用Java语言来绘制向量场

昨天晚上看了微分方程课程的视频,了解到了向量场的概念,所以产生了用Java来绘制向量场的想法。目前给出了初步的实现方案,程序有bug,回去继续改。

修改了一会,觉得太麻烦了

下面是代码:

package com.math;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Graphics;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JToggleButton;

class PainterPanel extends JPanel {

    private static final long serialVersionUID = 1L;

    public PainterPanel() {
        super(); // 调用父类构造函数
        this.setBackground(Color.white); // 设置背景颜色
        repaint();
    }

    public void paint(Graphics g) {
        setSize(1000, 400);
        g.translate(800, 200);
        Range range = new Range(-200.0, 20.0);
        List<Equipotent> el = new ArrayList<Equipotent>();
        DirectorField df = new DirectorField(el);
        addEp1(el, range);
        addEp2(el, range);
        addEp3(el, range);
        addEp4(el, range);

        df.paint(g);
    }
    
    private void addEp1(List<Equipotent> el, Range range){
        Calculater director = new Calculater() { 
            public double getValue(Object[] val) { return 3; }};
            
        Calculater equipotential = new Calculater() {
            public double getValue(Object[] val) {
                double x = (Double)val[0];
                return x+5;
            }
        };
        Calculater equipotential_1d = new Calculater() {
            public double getValue(Object[] val) {
                double x = (Double)val[0];
                return 1;
            }
        };
        Calculater equipotential_2d = new Calculater() { 
            public double getValue(Object[] val) {return 0;}};
            
        Equipotent ep = new Equipotent(range, director, equipotential,
                equipotential_1d, equipotential_2d);
        
        el.add(ep);
    }

    private void addEp2(List<Equipotent> el, Range range){
        Calculater director = new Calculater() { 
            public double getValue(Object[] val) { return 0; }};
            
        Calculater equipotential = new Calculater() {
            public double getValue(Object[] val) {
                double x = (Double)val[0];
                return x+1;
            }
        };
        Calculater equipotential_1d = new Calculater() {
            public double getValue(Object[] val) {
                double x = (Double)val[0];
                return 1;
            }
        };
        Calculater equipotential_2d = new Calculater() { 
            public double getValue(Object[] val) {return 0;}};
            
        Equipotent ep = new Equipotent(range, director, equipotential,
                equipotential_1d, equipotential_2d);
        
        el.add(ep);
    }
    
    private void addEp3(List<Equipotent> el, Range range){
        Calculater director = new Calculater() { 
            public double getValue(Object[] val) { return 1; }};
            
        Calculater equipotential = new Calculater() {
            public double getValue(Object[] val) {
                double x = (Double)val[0];
                return x;
            }
        };
        Calculater equipotential_1d = new Calculater() {
            public double getValue(Object[] val) {
                double x = (Double)val[0];
                return 1;
            }
        };
        Calculater equipotential_2d = new Calculater() { 
            public double getValue(Object[] val) {return 0;}};
            
        Equipotent ep = new Equipotent(range, director, equipotential,
                equipotential_1d, equipotential_2d);
        
        el.add(ep);
    }
    
    private void addEp4(List<Equipotent> el, Range range){
        Calculater director = new Calculater() { 
            public double getValue(Object[] val) { return 0; }};
            
        Calculater equipotential = new Calculater() {
            public double getValue(Object[] val) {
                double x = (Double)val[0];
                return x-1;
            }
        };
        Calculater equipotential_1d = new Calculater() {
            public double getValue(Object[] val) {
                double x = (Double)val[0];
                return 1;
            }
        };
        Calculater equipotential_2d = new Calculater() { 
            public double getValue(Object[] val) {return 0;}};
            
        Equipotent ep = new Equipotent(range, director, equipotential,
                equipotential_1d, equipotential_2d);
        
        el.add(ep);
    }

}

class Point {
    public double x, y;
    
    public Point(){};

    public Point(double _x, double _y) {
        this.x = _x;
        this.y = _y;
    }

    public String toString() {
        return "<x:" + x + ", y:" + y + ">";
    }
}

class Range {
    public double x1, x2;

    public Range(double _x1, double _x2) {
        this.x1 = _x1;
        this.x2 = _x2;
    }
    
    public String toString() {
        return "<x1:" + x1 + ", x2:" + x2 + ">";
    }
}

interface ICalculater {
    public double getValue(Object[] val);
    public double getValue(Object val);
}
abstract class Calculater implements ICalculater {
    public double getValue(Object[] val){
        return 0.0;
    }
    public double getValue(Object val) {
        return getValue(new Object[] {val});
    }
}

class DirectorField{
    List<Equipotent> el;
    public DirectorField(List<Equipotent> _el) {
        this.el = _el;
    }
    public void paint(Graphics g) {
        for(Equipotent e : el) {
            e.paint(g);
        }
    }
}

class Equipotent {
    Calculater director;
    Calculater equipotential; // 等势线
    Calculater equipotential_1d; // //等势线的向量
    Calculater equipotential_2d;
    Point first, current;
    double distance = 0.3; // 间隔
    double length = 20; // 向量的长度
    double e = 0.0001;
    Range range;
    ArrayList<Point> pl;
    int pos = -1;

    public Equipotent(Range _range, Calculater _director,
            Calculater _equipotential, Calculater _equipotential_1d,
            Calculater _equipotential_2d) {
        this.director = _director;
        this.equipotential = _equipotential;
        this.equipotential_1d = _equipotential_1d;
        this.equipotential_2d = _equipotential_2d;
        this.range = _range;
    }


    public void paint(Graphics g) {
        try {
            init();
        } catch (Exception e) {
            e.printStackTrace();
        }
        double px = length / (2 * Math.sqrt(1 + director.getValue(pos)));
        double py = director.getValue(pos)*px;
        int rate=100;
        for (Point p : pl) {
            p.x = p.x*rate;
            p.y = p.y*rate;
            g.drawLine((int) Math.round(p.x - px), (int) Math.round(p.y - py),
                    (int) Math.round(p.x + px), (int) Math.round(p.y + py));
        }
    }

    private void init() throws Exception {
        pl = calcPoint();
        Collections.sort(pl, new Comparator<Point>() {
            public int compare(Point o1, Point o2) {
                return (int) (o1.x - o2.x) * 1000;
            }
        });
    }

    private ArrayList<Point> calcPoint() throws Exception {
        ArrayList<Point> pl = new ArrayList<Point>();
        double p;
        try {
            p = calcPoint(new Object[]{range.x1}, new Object[]{range.x2}, equipotential_1d, e);
            ArrayList<Point> pl1 = calcXXX(new Range(range.x1, p),
                    equipotential_1d.getValue(range.x1),
                    equipotential_2d.getValue(range.x1));
            ArrayList<Point> pl2 = calcXXX(new Range(p, range.x2),
                    equipotential_1d.getValue(range.x2),
                    equipotential_2d.getValue(range.x2));
            pl.addAll(pl1);
            pl.addAll(pl2);
        } catch (Exception e) {
            pl = calcXXX(new Range(range.x1, range.x2),
                    equipotential_1d.getValue(range.x1),
                    equipotential_2d.getValue(range.x1));
            
        }
        return pl;
    }
    
    private ArrayList<Point> calcXXX(Range range, double e1d, double e2d) {
        Calculater upper = new Calculater() {
            public double getValue(Object[] val) {
                double x = (Double)val[0];
                double b = (Double)val[1];
                return equipotential.getValue(x)
                        - (equipotential.getValue(b)+Math.sqrt(distance*distance - (x-b)*(x-b)));
            }
        };
        Calculater down = new Calculater() {
            public double getValue(Object[] val) {
                double x = (Double)val[0];
                double b = (Double)val[1];
                return equipotential.getValue(x)
                        - (equipotential.getValue(b)-Math.sqrt(distance*distance - (x-b)*(x-b)));
            }
        };
        Calculater calc = e2d > 0 ? upper : down;
        boolean isLeft = e1d * e2d > 0;
        ArrayList<Point> pl = new ArrayList<Point>();
        try {
            double b = isLeft ? range.x1 : range.x2;
            double t = calcTmp(b, isLeft);

            int i = 0;
            while (isLeft ? t <= range.x2 : t >= range.x1) {
                if(i++%30==0) {
                    System.out.print("" + i);
                }
                if(isLeft){
                    if(t<b-distance){
                        t = b-distance;
                    }
                }else{
                    if(t>b+distance){
                        t = b+distance;
                    }
                }
                double x = calcPoint(new Object[]{b, b}, new Object[]{t, b}, calc, this.e);
                pl.add(new Point(x, equipotential.getValue(x)));
                b = x;
                t = calcTmp(b, isLeft);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return pl;
    }

    private double calcTmp(double x, boolean isLeft) {
        double v = equipotential_1d.getValue(x);
        double t = isLeft ? x + distance / Math.sqrt(1 + v * v) 
                : x - distance / Math.sqrt(1 + v * v);
        return t;
    }


    // 高斯逼近法的变种
    private double calcPoint(Object[] params1, Object[] params2, Calculater c, double e)
            throws Exception {
        double xa = (Double)params1[0], xb = (Double)params2[0];
        double ya = c.getValue(params1);
        double yb = c.getValue(params2);
        if(ya<=e) {
            return xa;
        }else if(yb<=e) {
            return xb;
        }
        if (!isNeg(ya, yb)) {
            throw new Exception("there is no result exists");
        }
        Object[] params = new Object[params1.length];
        System.arraycopy(params1, 0, params, 0, params1.length);
        double x = (xa + xb) / 2;
        params[0] = x;
        double y = c.getValue(params);
        int i = 0;
        while (abs(y) >= e) {
            if(i%30==0){
                System.out.println("hhh");
            }
            if (isNeg(y, ya)) {
                xb = x;
                yb = y;
            } else {
                xa = x;
                ya = y;
            }
            x = (xa + xb) / 2;
            params[0] = x;
            y = c.getValue(params);
        }
        return x;
    }

    private double abs(double v) {
        return v > 0 ? v : -v;
    }

    private boolean isNeg(double a, double b) {
        return a * b <= 0;
    }

}

public class PainterDemo extends JFrame {
    JToggleButton[] button = new JToggleButton[3]; // 按钮组
    PainterPanel painter = new PainterPanel(); // 绘图面板

    public PainterDemo() {
        super("Java 向量场"); // 调用父类构造函数
        Container container = getContentPane(); // 得到窗口容器
        container.add(painter, BorderLayout.CENTER);
        setSize(1000, 600); // 设置窗口尺寸
        setVisible(true); // 设置窗口为可视
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); // 关闭窗口时退出程序
    }

    public static void main(String[] args) {
        new PainterDemo();
        System.out.println("Hello World");

    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值