用Java语言来绘制向量场

来源:互联网 发布:java if else 缩写 编辑:程序博客网 时间:2024/05/16 13:50

昨天晚上看了微分方程课程的视频,了解到了向量场的概念,所以产生了用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");    }}