2010-06-02 15 views
7

Así que acabo de escribir un pequeño fragmento para generar el fractal de Mandelbrot e imaginar mi sorpresa cuando salió todo feo y sesgado (como se puede ver en la parte inferior). Apreciaría un punto en la dirección de por qué esto sucedería. Es una experiencia de aprendizaje y no estoy buscando a nadie que lo haga por mí, pero estoy en un callejón sin salida para depurarlo. El código de generación infractor es:¿Por qué una imagen (el Mandelbrot) estaría sesgada y envuelta?

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 

Y el código de la imagen (que estoy bastante confiado en) es:

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

¿Quiso agregar un enlace al archivo de imagen? – jchl

+0

Mi opinión sobre Mandelbrot: http://gist.github.com/291074 – jrockway

Respuesta

15

Bueno, la imagen es sesgada porque las dimensiones son mal, pero eso es obvio. Está especificando el tamaño de la imagen y luego escupiendo una lista de píxeles, pero con un número incorrecto de píxeles por línea en algún lugar.

Más específicamente, tenga en cuenta que la imagen se ajusta casi exactamente una vez: en otras palabras, skew per line * height of the image = width of the image. Dado que la imagen es cuadrada, eso significa que está generando un píxel extra por línea, un buen error antiguo.

El lugar obvio para que esto suceda es cuando está generando las coordenadas para iterar. Probemos un conjunto pequeño y veamos qué nos ofrece:

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

Y así sucesivamente. Sospecho que el error se debe a que está calculando el incremento como la distancia real dividida por el tamaño del píxel, que genera la cantidad correcta de intervalos, pero un punto extra. Considere el intervalo de 0.0 a 1.0. Usando el cálculo con una anchura de 4, obtenemos:

> 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 

Por lo tanto, para obtener el número correcto de puntos, simplemente reducir el tamaño de 1 hora de generar las coordenadas.

+1

No se pudo pedir una mejor respuesta. Muchas gracias señor. –

+1

@Sean: si ese es el caso, entonces creo que es correcto marcar la respuesta como aceptada. :) –

+0

Por supuesto que usar (ancho-1) tiene mucho más sentido, inicialmente después de leer tu respuesta acabo de utilizar la cola –

4

Es una experiencia de aprendizaje y no estoy buscando a alguien que lo haga por mí, pero estoy un poco en un callejón sin salida de depuración que

Sé camccann ya resuelto su problema, pero él tipo de "te dio el pescado", mientras que "enseñarte a pescar" podría ser más útil.

Así que compartiré lo que creo que podría ser una forma útil de llegar a la solución.

Por lo tanto, su imagen de mandelbrot está sesgada. Algunas de las causas probables posibles:

  • Usted tiene un error en su fórmula de Mandelbrot
  • ha encontrado un error en la presentación/guardar la imagen

Se podría hacer un experimento para aprender aún más si alguna de las las explicaciones anteriores son relevantes o no. Tal experimento podría ser, por ejemplo, dibujar imágenes triviales de, por ejemplo, líneas horizontales y verticales.

Después de hacer ese experimento, verá que sus líneas verticales no son tan verticales. Volviendo a las posibles causas posibles, está claro que tiene un error al presentar/guardar su imagen, y eso explica todo.Es posible que todavía tengas un error en la fórmula de mandelbrot, pero probablemente no, y eso no es relevante para el problema actual.

Ahora debe reflexionar sobre qué tipo de error de guardado de imagen provocará que las líneas verticales sean diagonales. Si no aparece ninguna idea, puede hacer que su ejemplo simple sea cada vez más pequeño hasta que el resultado PPM sea lo suficientemente pequeño como para poder examinarlo a mano. Entonces seguramente atraparás el error.

+1

Intenté al menos hablar sobre la solución más o menos en la secuencia que seguí para llegar a ella, pero tenía prisa y no la deletreé con tanto detalle como lo había hecho, gracias por hacerlo. En particular, observar el "un píxel extra por línea" fue como lo reduje a la generación de coordenadas, y el fragmento de GHCi fue un experimento para probar la hipótesis. –

+0

Muchas gracias, tendré en cuenta estas cosas la próxima vez que esté atascado. Entre su respuesta y la de Camccann, creo que obtuve todo lo que podría haber deseado. –

Cuestiones relacionadas