2017-02-05 8 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)の多項式であることが分かります。それはかなり自然なバグであるので、マンデルブロセットの文献のどこかに現れていることはほぼ確実ですが、私はこれまで見たことがないのです。

0

マンデルブロセットについて学び、自分のバージョンを書きました!私はPythonの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) 

このコードには2つの問題は1、それは更新はかなり遅いことですマンデルブロセット、および2つの場合は、非正方形のウィンドウまたはボックス選択を使用すると、アスペクト比が歪んで表示されます。コードのいずれかが不明な場合は私に教えてください!

+1

ボックスの図を含めてもいい人に感謝します。しかし、私のコードで特定の問題を探していました。技術的に複雑なデータ型をあなたがしたときと同じように各ピクセルに同じ値を与えます。 – lollingbirdz

関連する問題