2017-02-05 11 views
6

यह Pygame मॉड्यूल का उपयोग कर पाइथन 3.5 में मंडेलब्रॉट सेट को प्रोग्राम करने का मेरा प्रयास है।मंडेलब्रॉट सेट गलत तरीके से प्रदर्शित करता है

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' का उपयोग करना असामान्य गेट-आउट है। अधिक सामान्य 'ए * ए + बी * बी> = 2' है और चूंकि आपको अगले पुनरावृत्ति में उन वर्गों की आवश्यकता होगी, यह सस्ता है। –

+0

क्षमा करें, मेरा मतलब था '> = 4' –

उत्तर

9

दिलचस्प बग - यह सचमुच एक कुचल बग :) की तरह लग रहा

समस्या दो पंक्तियों में निहित है:

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

आप पहली पंक्ति में a के अर्थ बदल रहे हैं इसलिए का उपयोग कर दूसरे में गलत a

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

जो a का एक ही मूल्य का कारण होगा दाहिने हाथ की ओर की गणना में प्रयोग की जाने वाली:

ठीक के रूप में सरल रूप में है।

यह बताने के लिए दिलचस्प होगा कि आपकी बग ने क्या बनाया है। हालांकि यह मंडेलब्रॉट सेट नहीं है, यह अपने ही अधिकार में एक दिलचस्प फ्रैक्टल लगता है। उस अर्थ में, आप बहुत भाग्यशाली बग था। 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

मैंने मंडलब्रॉट सेट के बारे में जानने का फैसला किया और अपना खुद का संस्करण लिखा! मैंने पायथन के 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

संबंधित मुद्दे