2011-10-05 58 views
1

我正在研究一种Python脚本,它可以在通常的顺序中产生(包裹)菱形方形分形:而不是从外角和细分为更小的正方形,它从任意点开始递归地向外运行,只生成最终值依赖的点。下面是我写的,以确定如何处理每个点的功能:菱形方形分形的“内外”实现问题

def stepinfo(x, y): 
    y1 = y-(y&(y-1)) 
    x1 = x-(x&(x-1)) 
    sum = x1 + y1 
    return [((sum&(sum-1)) == 0), min(y1, x1)] 

返回的第一个值是一个布尔值,指定是否该点应被菱形或方形步骤中产生;第二个值指定步骤的网格大小。它很好用,除非x或y为零 - 那么返回的步长为零,脚本循环。但是,如果我将分形平铺到2x2网格中,并通过单击瓦片的右下角副本(即,远离窗口的零轴)来指定点,则整个分形将完美生成。但我似乎无法通过向鼠标坐标添加多个贴图大小或沿着这些行的任何内容来“伪造”此结果。

有什么建议吗?

下面是完整的脚本(我已经停止递归避免无端环,如果x或y = 0,但它仍然缺少点产生伪影):

MAPEXPONENT = 8 

import pygame 
import random 

MAPSIZE = 2**int(MAPEXPONENT) 
MAP = [[[None] for col in range(MAPSIZE)] for row in range(MAPSIZE)] 

def point(x, y): 
    return MAP[x%MAPSIZE][y%MAPSIZE] 

def displace(value, scale): 
    displaced = (value + (random.random()-.5) * scale * 12) 
    if displaced > 1 or displaced < 0: displaced = 1-displaced%1 
    return displaced 

def average(values): 
    realvalues = [] 
    for value in values: 
     if value <> None: realvalues.append(value) 
    if realvalues: return float(sum(realvalues, 0))/len(realvalues) 
    else: return 0 

def color_point(x, y, array): 
    pixel = point(x, y)[0] 
    green = pixel*255 
    red = pixel**.5*255 
    blue = 255-green 
    array[x%MAPSIZE][y%MAPSIZE] = [min(255, max(0, int(red))), 
            min(255, max(0, int(green))), 
            min(255, max(0, int(blue)))] 

def stepinfo(x, y): 
    y1 = y-(y&(y-1)) 
    x1 = x-(x&(x-1)) 
    sum = x1 + y1 
    return [((sum&(sum-1)) == 0), min(y1, x1)] 

def makepoint(x, y, map_array): 
    midpoint = point(x, y) 
    if midpoint[0] == None: 
     step = stepinfo(x, y) 
     size = step[1] 
     scale = float(size)/MAPSIZE 
     heights = [] 
     if step[0]: points = [[x-size, y-size], [x+size, y-size], 
           [x-size, y+size], [x+size, y+size]] 
     else:  points = [[x, y-size],  [x, y+size], 
           [x-size, y],  [x+size, y]] 
     for p in points: 
      if point(p[0], p[1])[0] == None and p[0] and p[1]: 
       makepoint(p[0], p[1], map_array) 
      heights.append(point(p[0], p[1])[0]) 
     midpoint[0] = displace(average(heights), scale) 
     color_point(x, y, map_array) 
    return midpoint 

pygame.init() 
screen = pygame.display.set_mode((2*MAPSIZE, 2*MAPSIZE)) 
map_surface = pygame.surface.Surface((MAPSIZE, MAPSIZE)) 
brush = 4+MAPSIZE/32 

map_surface_array = pygame.surfarray.pixels3d(map_surface) 
MAP[0][0][0] = random.random() 
color_point(0, 0, map_surface_array) 
del map_surface_array 

running = True 
while running: 
    event = pygame.event.wait() 
    if event.type == pygame.MOUSEBUTTONDOWN: 
     while event.type <> pygame.MOUSEBUTTONUP: 
      event = pygame.event.wait() 
      x0, y0 = pygame.mouse.get_pos() 
      map_surface_array = pygame.surfarray.pixels3d(map_surface) 
      for x in range(x0-brush, x0+brush): 
       for y in range(y0-brush, y0+brush): 
        if (x-x0)**2+(y-y0)**2 < brush**2: 
         makepoint(x, y, map_surface_array) 
      del map_surface_array 
      for x, y in [(0,0), (MAPSIZE,0), (0,MAPSIZE), (MAPSIZE,MAPSIZE)]: 
       screen.blit(map_surface, (x, y)) 
      pygame.display.update() 
    elif event.type == pygame.QUIT: 
     running = False 
pygame.quit() 

回答

1

基于在描述http://gameprogrammer.com/fractal.html#diamond我认为问题在于,如果x == 0或y == 0,那么您在Square与Diamond上做出错误决定。

我想你可以编写正确的决定:或

def stepinfo(x, y): 
    y1 = y-(y&(y-1)) 
    x1 = x-(x&(x-1)) 
    return [x1==y1, min(y1, x1)] 

更简单的:

def stepinfo(x, y): 
    y1 = y&-y 
    x1 = x&-x 
    return [x1==y1, min(y1, x1)]