歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> 用Java實現一個向量場

用Java實現一個向量場

日期:2017/3/1 10:20:36   编辑:Linux編程

在學習微分方程的時候,以前也寫過類似的文章,可是效果不行,前幾天寫了一個,感覺不錯,分享之。

先看效果(x*x -y -2):


再來代碼:

  1. package com.math.slopfields;
  2. import java.awt.Color;
  3. import java.awt.Graphics;
  4. import javax.swing.JFrame;
  5. public class SlopFields extends JFrame {
  6. protected static final int WIDTH = 800;
  7. protected static final int HEIGHT = 600;
  8. private java.awt.Dimension dimension = java.awt.Toolkit.getDefaultToolkit().
  9. getScreenSize();
  10. public SlopFields(String title, Grid g) {
  11. super(title);
  12. this.setSize(WIDTH, HEIGHT);
  13. this.setLocation((dimension.width - WIDTH) / 2,
  14. (dimension.height - HEIGHT) / 2);
  15. HeartCanvas panel = new HeartCanvas(g);
  16. this.add(panel);
  17. }
  18. public static void main(String[] args) {
  19. double scale = 80;
  20. double aa = 3;
  21. double dd = 0.15;
  22. Area area = new Area(Vector.build(-aa, aa), Vector.build(aa, -aa));
  23. Vector grid = Vector.build(dd, dd);
  24. CanCalc c = new CanCalc(){
  25. public double doCalc(Vector v) {
  26. return v.x*v.x - v.y - 2;
  27. }
  28. };
  29. Grid g = new Grid(area, grid, c, scale);
  30. SlopFields hart = new SlopFields("向量場", g);
  31. hart.setVisible(true);
  32. hart.setDefaultCloseOperation(hart.EXIT_ON_CLOSE);
  33. }
  34. }
  35. class HeartCanvas extends javax.swing.JPanel {
  36. private Grid grid;
  37. public HeartCanvas(Grid g) {
  38. this.grid = g;
  39. this.grid.calcGrids();
  40. this.grid.preDraw();
  41. }
  42. public void paintComponent(Graphics g) {
  43. setBackground(Color.BLACK);
  44. super.paintComponent(g);
  45. g.setColor(Color.GREEN);
  46. this.grid.draw(g);
  47. }
  48. }
  49. class Grid {
  50. public double scale = 100;
  51. public double padding = 0.2;
  52. public Vector offect = Vector.build(0.25, 0.25);
  53. public Area area;
  54. public Area[][] areas;
  55. public Vector grid;
  56. public int nx, ny;
  57. private CanCalc calc;
  58. public Grid(Area _area, Vector _grid, CanCalc _calc, double _scale) {
  59. this.area = _area;
  60. this.grid = _grid;
  61. this.calc = _calc;
  62. this.scale = _scale;
  63. }
  64. public void draw(Graphics g) {
  65. int x = (int)area.ld.x;
  66. int y = (int)area.ld.y;
  67. Vector t = area.ru.add(area.ld.neg());
  68. int width = (int)t.x;
  69. int height = (int)t.y;
  70. g.drawRect(x, y, width, height);
  71. g.drawLine(x, (int)offect.y, x+width, (int)offect.y);
  72. g.drawLine((int)offect.x, y, (int)offect.x, y+height);
  73. for(Area[] al : areas) {
  74. for(Area a : al) {
  75. g.drawLine((int)a.ld.x, (int)a.ld.y, (int)a.ru.x, (int)a.ru.y);
  76. }
  77. }
  78. }
  79. public void preDraw() {
  80. offect = offect.dotMul(this.scale).add(Vector.build(-area.ld.x*scale, area.ru.y*scale));
  81. area = new Area(Vector.build(area.ld.x, -area.ru.y).dotMul(this.scale).add(offect),
  82. Vector.build(area.ru.x, -area.ld.x).dotMul(this.scale).add(offect));
  83. for(int i=0; i<ny; i++){
  84. for(int j=0; j<nx; j++) {
  85. Area tmp = areas[i][j];
  86. Vector va = Vector.build(tmp.ld.x, -tmp.ld.y).dotMul(this.scale).add(offect);
  87. Vector vb = Vector.build(tmp.ru.x, -tmp.ru.y).dotMul(this.scale).add(offect);
  88. areas[i][j] = new Area(va, vb);
  89. }
  90. }
  91. }
  92. private void fixArea() {
  93. Vector tn1 = area.ld.dotDiv(grid).intVal().abs();
  94. area.ld = grid.dotMul(tn1).neg();
  95. Vector tn2 = area.ru.dotDiv(grid).intVal().abs();
  96. area.ru = grid.dotMul(tn2);
  97. tn1 = tn1.add(tn2);
  98. nx = (int)tn1.x;
  99. ny = (int)tn1.y;
  100. }
  101. private Slop[][] initSlop(CanCalc calc) {
  102. fixArea();
  103. Slop[][] slops = new Slop[nx][ny];
  104. Vector now = area.ld.clone();
  105. now.y += grid.y/2;
  106. for(int i=0; i<ny; i++) {
  107. now.x = area.ld.x + grid.x/2;
  108. for(int j=0; j<nx; j++) {
  109. slops[i][j] = new Slop(now.clone(), calc.doCalc(now));
  110. now.x += grid.x;
  111. }
  112. now.y += grid.y;
  113. }
  114. return slops;
  115. }
  116. public Area[][] calcGrids() {
  117. Slop[][] slops = initSlop(calc);
  118. areas = new Area[nx][ny];
  119. for(int i=0; i<nx; i++) {
  120. for(int j=0; j<ny; j++) {
  121. Vector tmp = null;
  122. Slop s = slops[i][j];
  123. if(s.slop == grid.slop()) {
  124. tmp = grid.dotDiv(2);
  125. }else if(s.slop == -grid.slop()){
  126. tmp = grid.dotDiv(2).dotMul(Vector.dr);
  127. }else if(s.slop==0){
  128. tmp = Vector.build(grid.x/2, 0);
  129. }else if(s.slop<grid.slop() && s.slop>-grid.slop()) {
  130. tmp = Vector.build(grid.x/2, (grid.x/2)*s.slop);
  131. }else {
  132. tmp = Vector.build((grid.y/2)/s.slop, grid.y/2);
  133. }
  134. tmp = tmp.dotMul(1-this.padding);
  135. areas[i][j] = new Area(s.point.add(tmp.neg()), s.point.add(tmp));
  136. }
  137. }
  138. return areas;
  139. }
  140. }
  141. interface CanCalc {
  142. public double doCalc(Vector v);
  143. }
  144. class Slop{
  145. public Vector point;
  146. public double slop;
  147. public Slop(Vector _point, double _slop) {
  148. this.point = _point;
  149. this.slop = _slop;
  150. }
  151. public String toString() {
  152. return String.format("{%s, %.2f}", point, slop);
  153. }
  154. }
  155. class Area {
  156. public Vector ld;
  157. public Vector ru;
  158. public Area(Vector _ld, Vector _ru) {
  159. this.ld = _ld;
  160. this.ru = _ru;
  161. }
  162. public String toString() {
  163. return String.format("[%s-%s]", this.ld, this.ru);
  164. }
  165. public Area scale(double d) {
  166. return new Area(this.ld.dotMul(d), this.ru.dotMul(d));
  167. }
  168. public Area add(Vector v) {
  169. return new Area(this.ld.add(v), this.ru.add(v));
  170. }
  171. }
  172. class Vector {
  173. public static final double infinite = Double.MAX_VALUE;
  174. public double x;
  175. public double y;
  176. public static final Vector zero = Vector.build(0, 0);
  177. public static final Vector up = Vector.build(0, 1);
  178. public static final Vector down = Vector.build(0, -1);
  179. public static final Vector left = Vector.build(-1, 0);
  180. public static final Vector right = Vector.build(1, 0);
  181. public static final Vector ul = Vector.build(-1, 1);
  182. public static final Vector ur = Vector.build(1, 1);
  183. public static final Vector dl = Vector.build(-1, -1);
  184. public static final Vector dr = Vector.build(1, -1);
  185. public static Vector build(double x, double y) {
  186. return new Vector(x, y);
  187. }
  188. public Vector clone() {
  189. return Vector.build(this.x, this.y);
  190. }
  191. public double slop() {
  192. if(this.x == 0) {
  193. return Vector.infinite;
  194. }
  195. return this.y / this.x;
  196. }
  197. public Vector(double _x, double _y) {
  198. this.x = _x;
  199. this.y = _y;
  200. }
  201. public Vector intVal() {
  202. return new Vector((int)this.x, (int)this.y);
  203. }
  204. public Vector abs() {
  205. return Vector.build((x>=0?x:-x), (y>=0?y:-y));
  206. }
  207. public Vector add(Vector v) {
  208. return new Vector(this.x+v.x, this.y+v.y);
  209. }
  210. public Vector neg() {
  211. return new Vector(-this.x, -this.y);
  212. }
  213. public Vector mul(double m) {
  214. return new Vector(m*this.x, m*this.y);
  215. }
  216. public Vector dotMul(Vector m) {
  217. return new Vector(this.x * m.x, this.y * m.y);
  218. }
  219. public Vector dotMul(double m) {
  220. return Vector.build(this.x*m, this.y*m);
  221. }
  222. public Vector dotDiv(Vector m) {
  223. return new Vector(this.x/m.x, this.y/m.y);
  224. }
  225. public Vector dotDiv(double d) {
  226. return Vector.build(this.x/d, this.y/d);
  227. }
  228. public String toString() {
  229. return String.format("<%.2f, %.2f>", x, y);
  230. }
  231. }

配置代碼,可以查看不同的效果:

  1. double scale = 80;
  2. double aa = 3;
  3. double dd = 0.15;
  4. Area area = new Area(Vector.build(-aa, aa), Vector.build(aa, -aa));
  5. Vector grid = Vector.build(dd, dd);
  6. CanCalc c = new CanCalc(){
  7. public double doCalc(Vector v) {
  8. return v.x*v.x - v.y - 2;
  9. }
  10. };
Copyright © Linux教程網 All Rights Reserved