java – 仅渲染与主圆相交的圆的线段/区域

前端之家收集整理的这篇文章主要介绍了java – 仅渲染与主圆相交的圆的线段/区域前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

我绝对喜欢数学(或者你们大多数人都会说’数学’!)但是我还没有达到我知道这个问题答案的水平.我有一个主圆,可以在显示屏上的任何x和y处有一个中心点.其他圆圈将随意在显示器周围移动,但在任何给定的渲染方法调用中,我不仅要渲染与主圆相交的圆,而且只渲染在主圆内可见的圆的线段.类比将是对现实生活对象的阴影,我只想绘制那个被“照亮”的对象的一部分.

我想最好用Java做这个,但如果你有一个原始的公式,将不胜感激.我想知道如何绘制形状并用Java填充它,我确定曲线上的折线必须有一些变化吗?

非常感谢

最佳答案
设A和B为2 intersection points(当没有或1个截取点时,你可以忽略它).

然后计算A和B之间circular line segment的长度.

有了这些信息,您应该能够使用Graphics' drawArc(...)方法绘制弧线(如果我没有弄错……).

编辑

好吧,你甚至不需要圆形线段的长度.我有线交叉代码,所以我围绕它构建了一个小GUI,你可以如何绘制/查看这些相交圆的ARC(代码中有一些注释):

  1. import javax.swing.*;
  2. import java.awt.*;
  3. import java.awt.event.*;
  4. import java.awt.geom.Arc2D;
  5. /**
  6. * @author: Bart Kiers
  7. */
  8. public class GUI extends JFrame {
  9. private GUI() {
  10. super("Circle Intersection Demo");
  11. initGUI();
  12. }
  13. private void initGUI() {
  14. super.setSize(600,640);
  15. super.setDefaultCloSEOperation(EXIT_ON_CLOSE);
  16. super.setLayout(new BorderLayout(5,5));
  17. final Grid grid = new Grid();
  18. grid.addMouseMotionListener(new MouseMotionAdapter() {
  19. @Override
  20. public void mouseDragged(MouseEvent e) {
  21. Point p = new Point(e.getX(),e.getY()).toCartesianPoint(grid.getWidth(),grid.getHeight());
  22. grid.showDraggedCircle(p);
  23. }
  24. });
  25. grid.addMouseListener(new MouseAdapter() {
  26. @Override
  27. public void mouseReleased(MouseEvent e) {
  28. Point p = new Point(e.getX(),grid.getHeight());
  29. grid.released(p);
  30. }
  31. @Override
  32. public void mousePressed(MouseEvent e) {
  33. Point p = new Point(e.getX(),grid.getHeight());
  34. grid.pressed(p);
  35. }
  36. });
  37. super.add(grid,BorderLayout.CENTER);
  38. super.setVisible(true);
  39. }
  40. public static void main(String[] args) {
  41. SwingUtilities.invokeLater(new Runnable() {
  42. @Override
  43. public void run() {
  44. new GUI();
  45. }
  46. });
  47. }
  48. private static class Grid extends JPanel {
  49. private Circle c1 = null;
  50. private Circle c2 = null;
  51. private Point screenClick = null;
  52. private Point currentPosition = null;
  53. public void released(Point p) {
  54. if (c1 == null || c2 != null) {
  55. c1 = new Circle(screenClick,screenClick.distance(p));
  56. c2 = null;
  57. } else {
  58. c2 = new Circle(screenClick,screenClick.distance(p));
  59. }
  60. screenClick = null;
  61. repaint();
  62. }
  63. public void pressed(Point p) {
  64. if(c1 != null && c2 != null) {
  65. c1 = null;
  66. c2 = null;
  67. }
  68. screenClick = p;
  69. repaint();
  70. }
  71. @Override
  72. public void paintComponent(Graphics g) {
  73. Graphics2D g2d = (Graphics2D) g;
  74. g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
  75. g2d.setColor(Color.WHITE);
  76. g2d.fillRect(0,super.getWidth(),super.getHeight());
  77. final int W = super.getWidth();
  78. final int H = super.getHeight();
  79. g2d.setColor(Color.LIGHT_GRAY);
  80. g2d.drawLine(0,H / 2,W,H / 2); // x-axis
  81. g2d.drawLine(W / 2,W / 2,H); // y-axis
  82. if (c1 != null) {
  83. g2d.setColor(Color.RED);
  84. c1.drawOn(g2d,H);
  85. }
  86. if (c2 != null) {
  87. g2d.setColor(Color.ORANGE);
  88. c2.drawOn(g2d,H);
  89. }
  90. if (screenClick != null && currentPosition != null) {
  91. g2d.setColor(Color.DARK_GRAY);
  92. g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f));
  93. Circle temp = new Circle(screenClick,screenClick.distance(currentPosition));
  94. temp.drawOn(g2d,H);
  95. currentPosition = null;
  96. }
  97. if (c1 != null && c2 != null) {
  98. g2d.setColor(Color.BLUE);
  99. g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.4f));
  100. Point[] ips = c1.intersections(c2);
  101. for (Point ip : ips) {
  102. ip.drawOn(g,H);
  103. }
  104. g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.2f));
  105. if (ips.length == 2) {
  106. g2d.setStroke(new BasicStroke(10.0f));
  107. c1.highlightArc(g2d,ips[0],ips[1],H);
  108. }
  109. }
  110. g2d.dispose();
  111. }
  112. public void showDraggedCircle(Point p) {
  113. currentPosition = p;
  114. repaint();
  115. }
  116. }
  117. private static class Circle {
  118. public final Point center;
  119. public final double radius;
  120. public Circle(Point center,double radius) {
  121. this.center = center;
  122. this.radius = radius;
  123. }
  124. public void drawOn(Graphics g,int width,int height) {
  125. // translate Cartesian(x,y) to Screen(x,y)
  126. Point screenP = center.toScreenPoint(width,height);
  127. int r = (int) Math.rint(radius);
  128. g.drawOval((int) screenP.x - r,(int) screenP.y - r,r + r,r + r);
  129. // draw the center
  130. Point screenCenter = center.toScreenPoint(width,height);
  131. r = 4;
  132. g.drawOval((int) screenCenter.x - r,(int) screenCenter.y - r,r + r);
  133. }
  134. public void highlightArc(Graphics2D g2d,Point p1,Point p2,int height) {
  135. double a = center.degrees(p1);
  136. double b = center.degrees(p2);
  137. // translate Cartesian(x,height);
  138. int r = (int) Math.rint(radius);
  139. // find the point to start drawing our arc
  140. double start = Math.abs(a - b) < 180 ? Math.min(a,b) : Math.max(a,b);
  141. // find the minimum angle to go from `start`-angle to the other angle
  142. double extent = Math.abs(a - b) < 180 ? Math.abs(a - b) : 360 - Math.abs(a - b);
  143. // draw the arc
  144. g2d.draw(new Arc2D.Double((int) screenP.x - r,start,extent,Arc2D.OPEN));
  145. }
  146. public Point[] intersections(Circle that) {
  147. // see: http://mathworld.wolfram.com/Circle-CircleIntersection.html
  148. double d = this.center.distance(that.center);
  149. double d1 = ((this.radius * this.radius) - (that.radius * that.radius) + (d * d)) / (2 * d);
  150. double h = Math.sqrt((this.radius * this.radius) - (d1 * d1));
  151. double x3 = this.center.x + (d1 * (that.center.x - this.center.x)) / d;
  152. double y3 = this.center.y + (d1 * (that.center.y - this.center.y)) / d;
  153. double x4_i = x3 + (h * (that.center.y - this.center.y)) / d;
  154. double y4_i = y3 - (h * (that.center.x - this.center.x)) / d;
  155. double x4_ii = x3 - (h * (that.center.y - this.center.y)) / d;
  156. double y4_ii = y3 + (h * (that.center.x - this.center.x)) / d;
  157. if (Double.isNaN(x4_i)) {
  158. // no intersections
  159. return new Point[0];
  160. }
  161. // create the intersection points
  162. Point i1 = new Point(x4_i,y4_i);
  163. Point i2 = new Point(x4_ii,y4_ii);
  164. if (i1.distance(i2) < 0.0000000001) {
  165. // i1 and i2 are (more or less) the same: a single intersection
  166. return new Point[]{i1};
  167. }
  168. // two unique intersections
  169. return new Point[]{i1,i2};
  170. }
  171. @Override
  172. public String toString() {
  173. return String.format("{center=%s,radius=%.2f}",center,radius);
  174. }
  175. }
  176. private static class Point {
  177. public final double x;
  178. public final double y;
  179. public Point(double x,double y) {
  180. this.x = x;
  181. this.y = y;
  182. }
  183. public double degrees(Point that) {
  184. double deg = Math.toDegrees(Math.atan2(that.y - this.y,that.x - this.x));
  185. return deg < 0.0 ? deg + 360 : deg;
  186. }
  187. public double distance(Point that) {
  188. double dX = this.x - that.x;
  189. double dY = this.y - that.y;
  190. return Math.sqrt(dX * dX + dY * dY);
  191. }
  192. public void drawOn(Graphics g,y)
  193. Point screenP = toScreenPoint(width,height);
  194. int r = 7;
  195. g.fillOval((int) screenP.x - r,r + r);
  196. }
  197. public Point toCartesianPoint(int width,int height) {
  198. double xCart = x - (width / 2);
  199. double yCart = -(y - (height / 2));
  200. return new Point(xCart,yCart);
  201. }
  202. public Point toScreenPoint(int width,int height) {
  203. double screenX = x + (width / 2);
  204. double screenY = -(y - (height / 2));
  205. return new Point(screenX,screenY);
  206. }
  207. @Override
  208. public String toString() {
  209. return String.format("(%.2f,%.2f)",x,y);
  210. }
  211. }
  212. }

如果您启动上面的GUI,然后在文本框中键入100 0 130 -80 55 180并点击return,您将看到以下内容:…

更改了代码,以便通过按下并拖动鼠标来绘制圆圈.截图:

猜你在找的Java相关文章