2010-06-02 2 views
7

Alors j'ai juste écrit un petit extrait pour générer la fractale de Mandelbrot et imaginez ma surprise quand elle est sortie laide et déformée (comme vous pouvez le voir en bas). J'apprécierais un point dans la direction de pourquoi cela arriverait même. C'est une expérience d'apprentissage et je ne cherche personne pour le faire pour moi, mais je suis un peu dans une impasse pour le déboguer. Le code de génération incriminée est:Pourquoi une image (le Mandelbrot) serait-elle faussée et entourée?

module Mandelbrot where 
import Complex 
import Image 

main = writeFile "mb.ppm" $ imageMB 1000 

mandelbrotPixel x y = mb (x:+y) (0:+0) 0 

mb c x iter | magnitude x > 2 = iter 
      | iter >= 255  = 255 
      | otherwise  = mb c (c+q^2) (iter+1) 
    where q = x -- Mandelbrot 
      -- q = (abs.realPart $ x) :+ (abs.imagPart $ x) --Burning Ship 

argandPlane x0 x1 y0 y1 width height = [ (x,y) | 
     y <- [y1, y1 - dy .. y0], --traverse from 
     x <- [x0, x0 + dx .. x1] ] --top-left to bottom-right 
    where dx = (x1 - x0)/width 
      dy = (y1 - y0)/height 

drawPicture :: (a -> b -> c) -> (c -> Colour) -> [(a, b)] -> Image 
drawPicture function colourFunction = map (colourFunction . uncurry function) 

imageMB s = createPPM s s 
     $ drawPicture mandelbrotPixel (replicate 3) 
     $ argandPlane (-1.8) (-1.7) (0.02) 0.055 s' s' 
    where s' = fromIntegral s 

Et le code d'image (que je suis assez confiant dans) est:

module Image where 

type Colour = [Int] 
type Image = [Colour] 

createPPM :: Int -> Int -> Image -> String 
createPPM w h i = concat ["P3 ", show w, " ", show h, " 255\n", 
    unlines.map (unwords.map show) $ i] 

Ugly Mandelskew thing

+0

Vouliez-vous ajouter un lien vers le fichier image? – jchl

+0

Ma prise sur Mandelbrot: http://gist.github.com/291074 – jrockway

Répondre

15

Eh bien, l'image est biaisée car les dimensions sont mal, mais c'est évident. Vous spécifiez la taille de l'image, puis crachant une liste de pixels, mais avec un nombre incorrect de pixels par ligne quelque part. Plus précisément, notez que l'image s'enroule presque exactement une fois: en d'autres termes, skew per line * height of the image = width of the image. Comme l'image est carrée, cela signifie que vous générez un pixel supplémentaire par ligne - une bonne vieille erreur par défaut.

L'endroit idéal pour que cela se produise est lorsque vous générez les coordonnées pour itérer. Essayons un petit ensemble et voyons ce qu'il nous donne:

> length $ argandPlane (-2.5) (-2) 1.5 2 10 10 
121 
> 10^2 
100 
> 11^2 
121 

Et ainsi. Je soupçonne que l'erreur est parce que vous calculez l'incrément comme la distance réelle divisée par la taille de pixel, qui génère le nombre correct de intervalles, mais un point supplémentaire. Considérons l'intervalle de 0,0 à 1,0. Utilisation de votre calcul avec une largeur de 4, nous obtenons:

> let x0 = 0.0 
> let x1 = 1.0 
> let width = 4.0 
> let dx = (x1 - x0)/width 
> dx 
0.25 
> let xs = [x0, x0 + dx .. x1] 
> xs 
[0.0, 0.25, 0.5, 0.75, 1.0] 
> length xs 
5 

Ainsi, pour obtenir le nombre correct de points, seulement réduire la taille de 1 lors de la génération des coordonnées.

+1

Impossible de demander une meilleure réponse. Merci beaucoup monsieur. –

+1

@Sean: Si tel est le cas, je pense que la réponse est acceptée comme étant acceptée. :) –

+0

Bien sûr, en utilisant (largeur-1) fait beaucoup plus de sens, d'abord après avoir lu votre réponse, j'ai juste utilisé la queue –

4

Il est une expérience d'apprentissage et je ne suis pas à la recherche de quelqu'un pour le faire pour moi, mais je suis un peu dans une impasse déboguer

Je sais camccann déjà résolu votre problème, mais Le genre «vous a donné le poisson» alors que «vous apprendre à pêcher» pourrait être plus utile. Je vais donc partager ce que je crois être un moyen utile d'atteindre la solution.

Votre image mandelbrot est donc inclinée. Certaines causes probables possibles:

  • Vous avez un bug dans votre formule de Mandelbrot
  • Vous avez un bug dans la présentation/enregistrer votre image

Vous pourriez faire une expérience pour apprendre davantage si l'un des Les explications ci-dessus sont pertinentes ou non. Une telle expérience pourrait être par exemple de dessiner des images triviales de, disons, des lignes horizontales et verticales.

Après avoir fait cette expérience, vous verrez que vos lignes verticales ne sont pas si verticales. Pour en revenir aux causes possibles probables, il est clair que vous avez un bug dans la présentation/la sauvegarde de votre image, et cela explique tout.Il se peut que vous ayez encore un bug dans votre formule Mandelbrot, mais vous ne l'avez probablement pas, et ce n'est pas pertinent pour le problème actuel.

Maintenant, vous devriez réfléchir à quel type de bogue de sauvegarde d'image entraînera des lignes verticales à diagonale. Si aucune idée n'apparaît, vous pouvez rendre votre exemple simple de plus en plus petit jusqu'à ce que le résultat du PPM devienne suffisamment petit pour que vous puissiez l'examiner à la main. Alors vous allez sûrement attraper le bug.

+1

J'ai essayé au moins de parler de la solution dans la séquence que j'ai suivie pour y arriver moi-même, mais j'étais pressé et je n'ai pas écrit autant de détails que vous l'avez fait - merci de le faire. En particulier, en notant le "un pixel de plus par ligne", je l'ai réduit à la génération de coordonnées, et l'extrait de GHCi était une expérience pour tester l'hypothèse. –

+0

Merci beaucoup, je vais garder ces choses à l'esprit la prochaine fois que je suis coincé. Entre ta réponse et celle de camccann, je pense avoir tout ce que je voulais. –

Questions connexes