用Java语言来绘制向量场

本文介绍了一个使用Java绘制向量场的初步实现方案。通过定义等势线和向量场的相关数学模型,实现了向量场的可视化。尽管程序中存在一些bug,但该方案为理解和展示向量场提供了一种直观的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天晚上看了微分方程课程的视频,了解到了向量场的概念,所以产生了用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、付费专栏及课程。

余额充值