首页 > 解决方案 > 我的 Mandelbrot 集不生成。我的方程式有什么问题?

问题描述

//Generator class
public class Generator {
double jump;
double sizeModifier;
int iterationRate,range;
ComplexNumber c;
public Generator(double jump) {
    this.jump=jump;
    this.sizeModifier=40;
    this.iterationRate=10;
    this.range=100;
    c=new ComplexNumber();
}
    public void generateSet(){
        DrawSet ds = new DrawSet();
        int ticker=0;
        for(double i=-2*range;i<=range;i+=jump){
            for(double j=-2*range;j<=range;j+=jump){
                c= new ComplexNumber((i/range),(j/range));
                double fz=c.square().mod()+c.mod();
                //System.out.println("c mod is: "+c.mod());
                //System.out.println("fz is: "+fz);
                if (fz < 2) {
                    for(int k=0;k<=iterationRate;k++) {
                        //System.out.println("nc:"+nc);
                        ticker++;
                        //System.out.println("ticker:"+ticker);
                        if(ticker==iterationRate) {
                            ds.addPoint(i + 450, j + 450);

                    }
                    if(fz>=2){
                        break;
                    }
                    else {
                        fz = Math.pow(fz, 2) + 1;
                    }
                }
            }
            ticker=0;
        }
    }
}
//Drawset class
public class DrawSet extends JPanel {
private ArrayList<Point> Points;
private ArrayList<Point> nPoints;


GraphicWindow gw;
public DrawSet(){
    this.Points=new ArrayList<>();
    this.nPoints=new ArrayList<>();
    gw = new GraphicWindow(1000,1000);
    gw.add(this);

}
public void addPoint(double x,double y){
    int ix=(int)x;
    int iy=(int)y;
    //int iwidth=(int)width*sizeModifier;
    //int iheight=(int)height*sizeModifier;
    Point a=new Point(ix,iy);
    Points.add(a);
    //System.out.println(Points.size());
}
public void paintComponent(Graphics g) {
        int pointSize = 1;
        super.paintComponents(g);
        System.out.println(Points.size());
        for (int i = 0; i < Points.size(); i++) {
            g.setColor(Color.BLACK);
            g.drawOval((int) Points.get(i).getX(), (int) Points.get(i).getY(), pointSize, pointSize);
        }
    }

基本问题是 fz 在 10 次迭代后永远不会小于 2,因此没有绘制点。为什么是这样?我应该执行什么等式?

我正在使用复数来生成值。我使用的类可以在这里看到: https ://github.com/abdulfatir/jcomplexnumber/ (或者在堆栈溢出论坛上Java有一个复数类吗?阿卜杜勒·法蒂尔先生)

标签: javaswingmathmandelbrot

解决方案


好的,观察

  • Generator不应该创建一个新的实例DrawSet
  • DrawSet不应该创建一个新的实例GraphicWindow

这些是这些类或方法的职责。这会高度耦合您的代码并产生副作用。

相反,generate应该传回它创建的点,然后这些点应该以你想要的任何方式应用,Generator不应该关心。

因为我无法访问您的完整代码,所以我只是将一系列随机点拼凑在一起来说明这一点。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test {

    public static void main(String[] args) {
        new Test();
    }

    public Test() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                DrawSet drawSet = new DrawSet();
                Generator generator = new Generator(100);
                drawSet.setPoints(generator.generateSet());

                JFrame frame = new JFrame();
                frame.add(drawSet);
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class DrawSet extends JPanel {

        private ArrayList<Point> points;
        private ArrayList<Point> nPoints;

        public DrawSet() {
            this.points = new ArrayList<>();
            this.nPoints = new ArrayList<>();
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(500, 500);
        }

        public void setPoints(ArrayList<Point> points) {
            this.points = points;
            repaint();
        }

//        public void addPoint(double x, double y) {
//            int ix = (int) x;
//            int iy = (int) y;
//            //int iwidth=(int)width*sizeModifier;
//            //int iheight=(int)height*sizeModifier;
//            Point a = new Point(ix, iy);
//            Points.add(a);
//            //System.out.println(Points.size());
//        }

        @Override
        protected void paintComponent(Graphics g) {
            int pointSize = 5;
            super.paintComponents(g);
            for (int i = 0; i < points.size(); i++) {
                g.setColor(Color.BLACK);
                g.drawOval((int) points.get(i).getX(), (int) points.get(i).getY(), pointSize, pointSize);
            }
        }
    }

    public class Generator {

        double jump;
        double sizeModifier;
        int iterationRate, range;
        //ComplexNumber c;

        public Generator(double jump) {
            this.jump = jump;
            this.sizeModifier = 40;
            this.iterationRate = 10;
            this.range = 100;
            //c = new ComplexNumber();
        }

        public ArrayList<Point> generateSet() {
            Random rnd = new Random();
            ArrayList<Point> points = new ArrayList<>(range);
            for (int index = 0; index < range; index++) {
                int x = (int)(490 * rnd.nextDouble());
                int  y = (int)(490 * rnd.nextDouble());
                points.add(new Point(x, y));
            }
            return points;

//            DrawSet ds = new DrawSet();
//            int ticker = 0;
//            for (double i = -2 * range; i <= range; i += jump) {
//                for (double j = -2 * range; j <= range; j += jump) {
//                    c = new ComplexNumber((i / range), (j / range));
//                    double fz = c.square().mod() + c.mod();
//                    //System.out.println("c mod is: "+c.mod());
//                    //System.out.println("fz is: "+fz);
//                    if (fz < 2) {
//                        for (int k = 0; k <= iterationRate; k++) {
//                            //System.out.println("nc:"+nc);
//                            ticker++;
//                            //System.out.println("ticker:"+ticker);
//                            if (ticker == iterationRate) {
//                                ds.addPoint(i + 450, j + 450);
//
//                            }
//                            if (fz >= 2) {
//                                break;
//                            } else {
//                                fz = Math.pow(fz, 2) + 1;
//                            }
//                        }
//                    }
//                    ticker = 0;
//                }
//            }
        }
    }
}

我也做了pointSize更大的,所以你实际上可以看到结果,虽然我会考虑填充点。

如果Generatoris 需要很长时间来执行其计算,您可以考虑使用 aSwingWorker来执行操作。这将允许将操作卸载到单独的线程,而不是阻塞主 UI 线程。然后,您可以使用SwingWorker来在计算时反馈每个单独的点,或者在整个生成完成时反馈所有点,以安全的方式返回到主 UI 线程。

有关更多详细信息,请参阅工作线程和 SwingWorker

为什么是这样?

摇摆是懒惰的。除非它认为需要,否则它不会对 UI 进行重绘或更新。因此,如果您更改 UI 所依赖的某些状态,则需要轻推 Swing 以鼓励它进行新的绘制。用最简单的话来说,这意味着调用repaint已更改的组件


推荐阅读