Почему изображение (Мандельброт) будет искажено и обернуто? - PullRequest
7 голосов
/ 02 июня 2010

Итак, я просто написал небольшой фрагмент кода, чтобы сгенерировать фрактал Мандельброта, и представляю себе мое удивление, когда он получился уродливым и искаженным (как вы можете видеть внизу). Я был бы признателен за то, что это могло произойти. Это опыт обучения, и я не ищу никого, кто бы сделал это для меня, но я вроде как в тупике отлаживаю его. Неправильный код генерации:

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

И код изображения (в котором я вполне уверен):

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

Ответы [ 2 ]

15 голосов
/ 02 июня 2010

Ну, изображение искажено, потому что размеры неправильные, но это очевидно. Вы указываете размер изображения, а затем выплевываете список пикселей, но с неправильным количеством пикселей в строке где-то.

В частности, обратите внимание, что изображение оборачивается почти ровно один раз: другими словами, skew per line * height of the image = width of the image. Поскольку изображение имеет квадратную форму, это означает, что вы генерируете дополнительный пиксель на строку - старая добрая ошибка "один на один".

Очевидное место для этого - когда вы генерируете координаты для повторения. Давайте попробуем небольшой набор и посмотрим, что он нам даст:

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

И так. Я подозреваю, что ошибка в том, что вы вычисляете приращение как реальное расстояние, деленное на размер в пикселях, что генерирует правильное количество интервалов , но дополнительную точку. Рассмотрим интервал от 0,0 до 1,0. Используя ваш расчет шириной 4, мы получим:

> 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

Итак, чтобы получить правильное количество точек, просто уменьшите размер на 1 при генерации координат.

4 голосов
/ 02 июня 2010

Это опыт обучения, и я не ищу, чтобы кто-нибудь сделал это для меня, но я вроде как в тупике отлаживаю его

Я знаю, что Камкканн уже решил вашу проблему, но он вроде "дал вам рыбу", а "научить вас ловить рыбу" может быть более полезным.

Итак, я поделюсь тем, что, по моему мнению, может быть полезным способом достижения решения.

Итак, ваше изображение Мандельброта искажено. Некоторые вероятные возможные причины:

  • У вас есть ошибка в формуле Мандельброта
  • У вас есть ошибка в представлении / сохранении вашей картинки

Вы можете провести эксперимент, чтобы узнать больше, если какое-либо из приведенных выше объяснений является уместным или нет. Таким экспериментом может быть, например, рисование тривиальных изображений, скажем, горизонтальных и вертикальных линий.

После этого эксперимента вы увидите, что ваши вертикальные линии не такие вертикальные. Возвращаясь к вероятным возможным причинам, ясно, что у вас есть ошибка в представлении / сохранении вашего изображения, и это все объясняет. Возможно, у вас все еще есть ошибка в формуле Мандельброта, но, возможно, ее нет, и это не имеет отношения к рассматриваемой проблеме.

Теперь вы должны подумать, какая ошибка сохранения изображения приведет к диагонали вертикальных линий. Если не появляется никакой идеи, вы можете сделать свой простой пример все меньше и меньше, пока результат PPM не станет достаточно маленьким, чтобы вы могли проверить его вручную. Тогда вы наверняка поймаете ошибку.

...