2010-06-02 21 views
7

Po prostu napisałem mały fragment, by wygenerować fraktal Mandelbrota i wyobrazić sobie moje zdziwienie, gdy wyszło na jaw, że wszystko jest brzydkie i przekrzywione (jak widać na dole). Byłbym wdzięczny za wskazówkę, dlaczego tak się stało. To jest doświadczenie uczenia się i nie szukam dla nikogo, żeby to zrobił dla mnie, ale jestem trochę ślepy za to debugowanie. Kod generacja wykraczająca jest:Dlaczego obraz (Mandelbrot) byłby przekrzywiony i zawijany?

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 

I kod obrazu (którego jestem dość pewny) jest:

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

Czy chcesz dodać łącze do pliku obrazu? – jchl

+0

Moje podejście do Mandelbrota: http://gist.github.com/291074 – jrockway

Odpowiedz

15

dobrze, obraz jest przekrzywiony, ponieważ wymiary są źle, ale to oczywiste. Podajesz rozmiar obrazu, a następnie wypluwasz listę pikseli, ale gdzieś jest niepoprawna liczba pikseli na linię.

Dokładniej zauważ, że obraz zawija się prawie dokładnie raz: Innymi słowy, skew per line * height of the image = width of the image. Ponieważ obraz jest kwadratowy, oznacza to, że generujesz dodatkowy piksel na linię - stary, dobry błąd "z osobna".

Oczywistym miejscem, w którym to się dzieje, jest generowanie współrzędnych do iteracji. Wypróbujmy mały zestaw i zobaczmy, co nam to daje:

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

I tak. Podejrzewam, że błąd wynika z tego, że obliczasz przyrost jako rzeczywistą odległość podzieloną przez rozmiar piksela, który generuje prawidłową liczbę przedziałów , ale dodatkowy punkt. Rozważ przedział od 0,0 do 1,0. Korzystanie z obliczeń o szerokości 4, otrzymujemy:

> 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 

Tak więc, aby uzyskać odpowiednią liczbę punktów, po prostu zmniejszyć rozmiar o 1 podczas generowania współrzędnych.

+1

Nie można poprosić o lepszą odpowiedź. Dziękuję Panu bardzo. –

+1

@Sean: Jeśli tak jest, to myślę, że oznaczenie odpowiedzi jako zaakceptowanej jest w porządku. :) –

+0

Oczywiście używanie (szerokość-1) ma dużo więcej sensu, początkowo po przeczytaniu odpowiedzi użyłem po prostu ogona –

4

To doświadczenie uczenia się, a ja nie szukam nikogo to zrobić dla mnie, ale jestem trochę w ślepy zaułek debugowania to

wiem camccann już rozwiązany problem, ale w pewnym sensie "dał ci rybę", a "nauczenie cię, jak łowić ryby", może być bardziej przydatne.

Podzielę się tym, co według mnie może być użytecznym sposobem na znalezienie rozwiązania.

Twój obraz mandelbrota jest przekrzywiony. Niektóre prawdopodobnie możliwe przyczyny:

  • Masz błąd w formule Mandelbrot
  • Masz błąd w prezentacji/oszczędzając Twój obraz

można zrobić eksperyment w celu dalszego dowiedzieć się, czy którekolwiek z powyższe wyjaśnienia są istotne lub nie. Takim eksperymentem może być na przykład rysowanie banalnych obrazów, powiedzmy, linii poziomych i pionowych.

Po wykonaniu tego eksperymentu zobaczysz, że pionowe linie nie są tak pionowe. Wracając do prawdopodobnych możliwych przyczyn, jasne jest, że masz błąd w przedstawianiu/zapisywaniu obrazu, i to wszystko wyjaśnia.Nadal możesz mieć błąd w swojej formule mandelbrota, ale prawdopodobnie go nie masz, a to nie jest istotne dla danego problemu.

Teraz powinieneś zastanowić się, jaki rodzaj błędu przy zapisywaniu obrazu spowoduje przekątne pionowych linii. Jeśli nie pojawi się żaden pomysł, możesz uczynić swój prosty przykład mniejszym i mniejszym, dopóki wynik PPM nie będzie wystarczająco mały, abyś mógł go zbadać ręcznie. Wtedy na pewno złapiesz błąd.

+1

Próbowałem przynajmniej omówić rozwiązanie w przybliżeniu sekwencji, którą podążyłem, aby dostać się do niej osobiście, ale spieszyłem się i nie przeliterowałem tak szczegółowo, jak to zrobiliście - dziękuję za to. W szczególności, zwracając uwagę na "jeden dodatkowy piksel na linię", zawęziłem go do koordynacji generowania, a fragment kodu GHCi był eksperymentem do testowania hipotezy. –

+0

Wielkie dzięki, będę mieć te rzeczy na myśli następnym razem, gdy utknę. Pomiędzy twoją odpowiedzią a kamerą, myślę, że mam wszystko, czego mogłem chcieć. –