【问题标题】:Generating fractal Swirl [closed]产生分形漩涡[关闭]
【发布时间】:2012-12-10 06:05:39
【问题描述】:

我需要使用算法Iterated Function System 绘制分形漩涡。

这个分形有系数:

0.745455 -0.459091  0.406061  0.887121 1.460279 0.691072 0.912675
-0.424242 -0.065152 -0.175758 -0.218182 3.809567 6.741476 0.087325

这是我的代码:

import java.awt.Graphics;
import javax.swing.JPanel;

public class Surface extends JPanel {
double a1 = 0.745455;
double b1 = -0.459091;
double d1 = 0.406061;
double e1 = 0.887121;
double c1 = 1.460279;
double f1 = 0.691072;
double p1 = 0.912675;

double a2 = -0.424242;
double b2 = -0.065152;
double d2 = -0.175758;
double e2 = -0.218182;
double c2 = 3.809567;
double f2 = 6.741476;
double p2 = 0.087325;

double x1(double x, double y) {
    return a1 * x + b1 * y + c1;
}

double y1(double x, double y) {
    return d1 * x + e1 * y + f1;
}

double x2(double x, double y) {
    return a2 * x + b2 * y + c2;
}

double y2(double x, double y) {
    return d2 * x + e2 * y + f2;
}

public void paint(Graphics g) {
    drawFractal(g);
}

void drawFractal(Graphics g) {
    double x1 = 300;
    double y1 = 300;
    double x2 = 0;
    double y2 = 0;
    g.fillOval(300 + (int) x1, 300 + (int) y1, 3, 3);
    for (int i = 0; i < 10000; i++) {
        double p = Math.random();
        if (p < 0.91675) {
            x2 = x1(x1, y1);
            y2 = y1(x1, y1);
            g.fillOval(300 + (int) x2, 300 + (int) y2, 3, 3);
            x1 = x2;
            y1 = y2;
        } else {
            x2 = x2(x1, y1);
            y2 = y2(x1, y1);
            g.fillOval(300 + (int) x2, 300 + (int) y2, 3, 3);
            x1 = x2;
            y1 = y2;
        }
    }
}
}

不幸的是,这段代码我得到了一张错误的图片:

如果有人能指出我的错误,那就太好了。

【问题讨论】:

标签: java algorithm graph fractals


【解决方案1】:

您的这一代似乎是正确的(即不要做x1 = x2 +300; y1 = y2 +300;),但您的问题是您的渲染目的远远超出了规模。这意味着很少有点落在图像的中心之外。

您的窗口是[0..600]x[0..600]。尝试将x2y2 与50 相乘,这样您将渲染[-6..6]x[-6..6] 区域而不是[-300..300]x[-300..300] 空间区域。

请注意,绘制单个像素(作为自身的线)而不是 3x3 椭圆应该就足够了。

int xp = 300 + (int) (x2 * scale);
int yp = 300 + (int) (y2 * scale);
g.drawLine(xp, yp, xp, yp);

根据渲染的内容,您可能需要稍微调整比例以使整个图像具有合理的边界。注意第二个变换偏移了-6.7,所以30的比例应该是正确的。

另请注意,通过使用x1 = x2 +300; y1 = y2 +300;,您可以更改转换并获得不同分形(以您期望的比例)。

【讨论】:

  • 最后我得到了正确的分形! :) 感谢您的解释,现在我看到了我的错误
  • 一月好!我也想过这个问题,但我犯了一个错误,继续使用缩放值xp, yp 来表示分形并放弃解决这个问题:)。
【解决方案2】:

这太好了,我错误地认为需要指数运行时间!分形看起来比我想象的更立体!

感谢@Jan Dvorak!

以下也有效(在我的坐标中,xcenter=300ycenter=100radius=50 是全局绘图参数)并且运行速度更快:

void drawFractal2(Graphics g) {

        double x1 = 0;
        double y1 = 0;
        double x2 = 0;
        double y2 = 0;
        double p;

        g.fillOval(xcenter + (int) (x1 * radius), ycenter + (int) (y1 * radius), 3, 3);

        for(int i=0; i<100000; ++i) {
            p = Math.random();

            if (p < p1) {
                x2 = x1(x1, y1);
                y2 = y1(x1, y1);

            }
            else {
                x2 = x2(x1, y1);
                y2 = y2(x1, y1);

            }

            g.fillOval(xcenter + (int) (x2 * radius), ycenter + (int) (y2 * radius), 3, 3);
            x1 = x2;
            y1 = y2;
        }

    }

而且画面更好

【讨论】:

  • 感谢您测试我的修复,伙计 :-)
  • 请注意,“树状运行时”在技术上是无稽之谈。您可以进行“树状递归”,然后体验“指数运行时”;)
  • 你介意给我一些答案吗?
  • 当然我已经加分了
  • 我的意思是,在答案中说明提问者的代码到底有什么问题以及是谁发现了问题 ;-)
【解决方案3】:

以下是我的错误答案

但它表明分形比直觉更大,所以我保留它。

我猜你的算法应该是树状的(递归的),而你的算法是线性的。你只是画了一连串的点,一个接一个地变换它。所以你得到了一些螺旋状的链。它原则上不能生成任何分形图。

我有你的照片

你有两个错误:

1) 您将 300 传递给迭代和绘图转换。这是次要的。

2) 你的算法是线性的。线性算法不能画出树状图。如果您使用随机值,您应该多次运行算法。一条链仅绘制图片的一个随机部分。

我用以下递归算法得到了你的照片。它运行缓慢,但你要改进它。

  void drawFractal(Graphics g, double x1, double y1, int depth) {

        double x2 = 0;
        double y2 = 0;

        if( depth > 20 ) {
            return;
        }

        g.fillOval(xcenter + (int) (x1 * radius), ycenter + (int) (y1 * radius), 3, 3);

        x2 = x1(x1, y1);
        y2 = y1(x1, y1);
        drawFractal(g, x2, y2, depth+1);



        x2 = x2(x1, y1);
        y2 = y2(x1, y1);
        drawFractal(g, x2, y2, depth+1);






    }

我用它来运行它

    public void paint(Graphics g) {
        //drawFractal(g);
        drawFractal(g, 0, 0, 0);
    }

参数是

    int xcenter = 300;
    int ycenter = 100;

    int radius = 50;

图片如下:

【讨论】:

  • 这就是 IFS 的工作方式。请注意,转换是从一组两个中随机选择的 - 一个转换确实是不够的。
  • 不,你错了。随机选择无济于事。
  • 阅读IFS 或做一些手部模拟。这就是迭代函数系统的美妙之处。
  • "你的算法是线性的。线性算法不能画树状图。" -- 还是错了。
  • 您声称需要手动分支的说法不正确。您通过应用正确的比例(提问者没有这样做)解决了这个问题,而不是通过切换到树状递归。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-12
  • 2016-10-27
相关资源
最近更新 更多