钻石方形分形的“由内而外”实施的问题

时间:2011-10-05 06:41:57

标签: python algorithm graphics fractals

我正在研究一个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 个答案:

答案 0 :(得分:1)

基于http://gameprogrammer.com/fractal.html#diamond中的描述我认为问题是如果x == 0或y == 0,你就方形与钻石做出了错误的决定。

我认为你可以将正确的决定编码为:

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)]