2017-02-05 9 views
6

이것은 Pygame 모듈을 사용하여 Python 3.5에서 Mandelbrot 세트를 프로그래밍하려는 시도입니다.Mandelbrot 설정이 잘못 표시됩니다.

import math, pygame 
pygame.init() 

def mapMandelbrot(c,r,dim,xRange,yRange): 
    x = (dim-c)/dim 
    y = (dim-r)/dim 
    #print([x,y]) 
    x = x*(xRange[1]-xRange[0]) 
    y = y*(yRange[1]-yRange[0]) 
    x = xRange[0] + x 
    y = yRange[0] + y 
    return [x,y] 

def checkDrawBox(surface): 
    for i in pygame.event.get(): 
     if i.type == pygame.QUIT: 
      pygame.quit() 
     elif i.type == pygame.MOUSEBUTTONDOWN: 
      startXY = pygame.mouse.get_pos() 
      boxExit = False 
      while boxExit == False: 
       for event in pygame.event.get(): 
        if event.type == pygame.MOUSEBUTTONUP: 
         boxExit = True 
       if boxExit == True: 
        return [startXY,pygame.mouse.get_pos()] 
       pygame.draw.rect(surface,[255,0,0],[startXY,[pygame.mouse.get_pos()[0]-startXY[0],pygame.mouse.get_pos()[1]-startXY[1]]],1) 
       pygame.display.update() 

def setup(): 
    dimensions = 500 
    white = [255,255,255] 
    black = [0,0,0] 
    checkIterations = 100 
    canvas = pygame.display.set_mode([dimensions,dimensions]) 
    canvas.fill(black) 
    xRange = [-2,2] 
    yRange = [-2,2] 
    xRangePrev = [0,0] 
    yRangePrev = [0,0] 
    newxRange = [0,0] 
    newyRange = [0,0] 
    while True: 
     if not ([xRange,yRange] == [xRangePrev,yRangePrev]): 
      draw(dimensions, canvas, xRange, yRange, checkIterations) 
      pygame.display.update() 
      xRangePrev = xRange 
      yRangePrev = yRange 
     box = checkDrawBox(canvas) 
     if box != None: 
      maxX = max([box[0][0],box[1][0]]) 
      maxY = max([box[0][1],box[1][1]]) 
      newxRange[0] = mapMandelbrot(box[0][0],0,dimensions,xRange,yRange)[0] 
      newxRange[1] = mapMandelbrot(box[1][0],0,dimensions,xRange,yRange)[0] 
      newyRange[0] = mapMandelbrot(0,box[0][1],dimensions,xRange,yRange)[1] 
      newyRange[1] = mapMandelbrot(0,box[1][1],dimensions,xRange,yRange)[1] 
      xRange = newxRange 
      yRange = newyRange 

def draw(dim, surface, xRange, yRange, checkIterations): 
    for column in range(dim): 
     for row in range(dim): 
      greyVal = iteration(0,0,mapMandelbrot(column,row,dim,xRange,yRange),checkIterations,checkIterations)  
      surface.set_at([dim-column,row],greyVal) 

def iteration(a, b, c, iterCount, maxIter): 
    a = (a*a) - (b*b) + c[0] 
    b = (2*a*b) + c[1] 
    iterCount = iterCount - 1 
    if iterCount == 0: 
     return [0,0,0] 
    elif abs(a+b) > 17: 
     b = (iterCount/maxIter)*255 
     return [b,b,b] 
    else: 
     return iteration(a,b,c,iterCount,maxIter) 


setup() 

나는 반복 알고리즘이 올바른지 생각하지만, 출력이 제대로 보이지 않습니다 :

enter image description here

문제가 무엇인지 궁금하십니까? 죄송합니다 코드 덤프, 그냥 어떤 부분을 그렇게 보이게 발생할 수 있습니다 확실하지 않습니다.

+0

별도 : 'abs (a + b)> 17'을 사용하는 것이 비정상적인 탈출입니다. 더 평범한 것은'a * a + b * b> = 2'이며 다음 반복에서 그 사각형이 필요하기 때문에 값이 싸다. –

+0

죄송합니다, 나는'> = 4'라고 말했습니다. –

답변

9

매혹적인 버그 - 그것은 말 그대로 숙청 버그 :처럼 보이는

문제는 두 줄에있다

: 따라서 사용

a = (a*a) - (b*b) + c[0] 
b = (2*a*b) + c[1] 

당신은 첫 번째 줄에 a의 의미를 변화 두 번째로 잘못된 a입니다. a 동일한 값을 야기한다

a, b = (a*a) - (b*b) + c[0], (2*a*b) + c[1] 

가 우측을 계산하는데 사용될 :

픽스는만큼 간단하다.

버그가 발생한 부분을 해결하는 것은 흥미로운 일입니다. Mandelbrot 세트는 아니지만 자체적으로 흥미로운 프랙탈 인 것 같습니다. 그런 의미에서, 당신에게는 매우 운이 좋은 버그가있었습니다. 시간의 99 %를 차지하는 버그는 쓰레기로 이어지지 만, 때로는 매우 흥미롭지 만 단순히 의도하지 않은 것이 있습니다.

편집에

: 만델 세트는 복잡한 다항식을 반복에 기초

:

f(z) = z^2 + c 
생산하고이 버그 함수

을 반복에 기반 의사 - 만델 설정

f(z) = Re(z^2 + c) + i*[2*Re(z^2 + c)*Im(z) + Im(c)] 

여기서 Re()Im()은 복소수의 실수 부와 허수 부. 이것은 z의 다항식이 아니지만 z,z* (z*z의 복소수 공백 임)의 다항식임을 쉽게 알 수 있습니다.꽤 자연스러운 버그이기 때문에 만델 브로트 (Mandelbrot) 세트의 문헌에서 어딘가에 등장했다는 것을 거의 확신합니다.

0

나는 만델 브로 세트에 대해 배우기로 마음 먹고 내 자신의 버전을 썼다. 파이썬의 complex 데이터 형식을 사용했기 때문에 각 픽셀마다 맨델 브로 계산이 조금 더 명확 해졌습니다. 여기

enter image description here

그리고 소스 코드/코드 덤프입니다 :

import pygame 
import sys 

def calc_complex_coord(x, y): 
    real = min_corner.real + x * (max_corner.real - min_corner.real)/(width - 1.0) 
    imag = min_corner.imag + y * (max_corner.imag - min_corner.imag)/(height - 1.0) 
    return complex(real, imag) 

def calc_mandelbrot(c): 
    z = c 
    for i in range(1, max_iterations+1): 
     if abs(z) > 2: 
      return i 
     z = z*z + c 
    return i 

def calc_color_score(i): 
    if i == max_iterations: 
     return black 
    frac = 255.0 - (255.0 * i/max_iterations) 
    return (frac, frac, frac) 

def update_mandelbrot(): 
    for y in range(height): 
     for x in range(width): 
      c = calc_complex_coord(x, y) 
      mandel_score = calc_mandelbrot(c) 
      color = calc_color_score(mandel_score) 
      mandel_surface.set_at((x, y), color) 

if __name__ == "__main__": 
    pygame.init() 
    (width, height) = (500, 500) 
    display = pygame.display.set_mode((width, height)) 
    pygame.display.set_caption("Mandelbrot Magic") 
    clock = pygame.time.Clock() 
    mandel_surface = pygame.Surface((width, height)) 
    black = (0, 0, 0) 
    red = (255, 0, 0) 
    max_iterations = 50 
    min_corner = complex(-2, -2) 
    max_corner = complex(2, 2) 
    box = pygame.Rect(0, 0, width, height) 
    update_mandel = True 
    draw_box = False 

    while True: 
     for event in pygame.event.get(): 
      if event.type == pygame.QUIT: 
       sys.exit() 
      elif event.type == pygame.MOUSEBUTTONDOWN: 
       x, y = event.pos 
       box = pygame.Rect(x, y, 0, 0) 
       draw_box = True 
      elif event.type == pygame.MOUSEMOTION: 
       x, y = event.pos 
       if draw_box: 
        box = pygame.Rect(box.left, box.top, x - box.left, y - box.top) 
      elif event.type == pygame.MOUSEBUTTONUP: 
       x, y = event.pos 
       update_mandel = True 

     display.blit(mandel_surface, (0, 0)) 
     if draw_box: 
      pygame.draw.rect(display, red, box, 1) 
     if update_mandel: 
      box.normalize() 
      new_min_corner = calc_complex_coord(box.left, box.top) 
      new_max_corner = calc_complex_coord(box.right, box.bottom) 
      min_corner, max_corner = new_min_corner, new_max_corner 
      update_mandelbrot() 
      update_mandel = False 
      draw_box = False 

     pygame.display.update() 
     clock.tick(60) 

이 코드를 가진 두 가지 문제는 하나, 그것은 업데이트가 상당히 낮다는 여기에 결과의 스크린 샷입니다 만델 브로 세트 및 두 개, 정사각형이 아닌 창이나 상자 선택을 사용하면 화면 비율이 왜곡됩니다. 어떤 코드가 불분명한지 알려주십시오!

+1

상자에 그림을 포함시켜 주셔서 감사합니다. 그러나 기술적으로는 복잡한 데이터 유형을 에뮬레이션 한 것으로 생각됩니다. 방법은 각 픽셀에 대해 동일한 값을 제공합니다. – lollingbirdz