为什么图像(曼德尔布罗特)会倾斜并环绕?

发布于 2024-09-03 20:34:14 字数 1445 浏览 6 评论 0原文

所以我只是写了一个小片段来生成曼德尔布罗分形,想象一下当它变得丑陋且扭曲时我的惊讶(正如你在底部看到的那样)。我希望能指出为什么会发生这种情况。这是一次学习经历,我并不是在寻找任何人为我做这件事,但我在调试它时有点陷入了死胡同。有问题的生成代码是:

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

So I just wrote a little snippet to generate the Mandelbrot fractal and imagine my surprise when it came out all ugly and skewed (as you can see at the bottom). I'd appreciate a point in the direction of why this would even happen. It's a learning experience and I'm not looking for anyone to do it for me, but I'm kinda at a dead end debugging it. The offending generation code is:

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

And the image code (which I'm fairly confident in) is:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

筱果果 2024-09-10 20:34:15

嗯,图像是倾斜的,因为尺寸错误,但这很明显。您指定图像大小,然后吐出像素列表,但某处每行的像素数不正确。

更具体地说,请注意图像几乎恰好环绕一次:换句话说,每行倾斜 * 图像高度 = 图像宽度。由于图像是正方形的,这意味着每行生成一个额外的像素——这是一个很好的旧的逐一错误。

发生这种情况的明显地方是当您生成要迭代的坐标时。让我们尝试一个小集合,看看它给我们带来了什么:

> 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 即可。

Well, the image is skewed because the dimensions are wrong, but that's obvious. You're specifying the image size and then spitting out a list of pixels, but with an incorrect number of pixels per line somewhere.

More specifically, note that the image wraps around almost exactly once: In other words, skew per line * height of the image = width of the image. Since the image is square, that means you're generating an extra pixel per line--a good old off-by-one error.

The obvious place for this to happen is when you're generating the coordinates to iterate on. Let's try a small set and see what it gives us:

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

And so. I suspect the error is because you're calculating the increment as real distance divided by pixel size, which generates the correct number of intervals, but an extra point. Consider the interval from 0.0 to 1.0. Using your calculation with a width of 4, we get:

> 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

So, to get the correct number of points, just reduce the size by 1 when generating the the coordinates.

々眼睛长脚气 2024-09-10 20:34:15

这是一次学习经历,我并不是在寻找任何人为我做这件事,但我在调试它时有点陷入困境

我知道 camccann 已经解决了你的问题,但他有点“授你鱼”,同时“教你”你如何钓鱼”可能更有用。

因此,我将分享我认为可能是达成解决方案的有用方法。

所以你的曼德尔布罗图像是倾斜的。一些可能的原因:

  • 您的曼德尔布罗公式中有错误
  • 您在呈现/保存图片时有错误

您可以做一个实验来进一步了解上述任何解释是否相关。例如,这样的实验可以是绘制水平线和垂直线等简单图像。

完成该实验后,您会发现您的垂直线不再那么垂直。回到可能的原因,很明显您在呈现/保存图像时遇到错误,这解释了一切。您的曼德尔布罗公式中可能仍然存在错误,但您可能没有,并且这与现在的问题无关。

现在你应该思考什么样的图像保存错误会导致垂直线成为对角线。如果没有出现任何想法,您可以让您的简单示例变得越来越小,直到 PPM 结果变得足够小,您可以手动检查它。那么你一定会发现这个错误。

It's a learning experience and I'm not looking for anyone to do it for me, but I'm kinda at a dead end debugging it

I know camccann already solved your problem, but he kind of "gave you the fish" while "teaching you how to fish" could be more useful.

So I'll share what I believe could be a useful way of reaching the solution.

So your mandelbrot image is skewed. Some likely possible causes:

  • You have a bug in your mandelbrot formula
  • You have a bug in presenting/saving your picture

You could do an experiment to learn further if any of the above explanations are relevant or not. Such an experiment could be for example drawing trivial images of, say, horizontal and vertical lines.

After doing that experiement you will see that your vertical lines are not so vertical. Going back to the likely possible causes, it's clear that you have a bug in presenting/saving your image, and that explains everything. You may still have a bug in your mandelbrot formula but you probably don't, and that's not relevant to the issue at hand now.

Now you should ponder what kind of image saving bug will cause vertical lines to be diagonal. If no idea pops up you can make your simple example smaller and smaller until the PPM result becomes small enough that you could examine it by hand. Then you'll surely catch the bug.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文