栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

用线连接两个圆圈

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

用线连接两个圆圈

好的,基本上,我们可以将问题分解为基本问题:

  1. 获取两个圆之间的角度
  2. 从这个圆的圆周到另一个圆的圆周画一条线
    这两个问题都不难解决(而且花在
    互联网上的任何时间都会提供解决方案-因为那是我从中获得的;))

因此,两点之间的角度可以使用类似…的方法来计算

protected double angleBetween(Point2D from, Point2D to) {    double x = from.getX();    double y = from.getY();    // This is the difference between the anchor point    // and the mouse.  Its important that this is done    // within the local coordinate space of the component,    // this means either the MouseMotionListener needs to    // be registered to the component itself (preferably)    // or the mouse coordinates need to be converted into    // local coordinate space    double deltaX = to.getX() - x;    double deltaY = to.getY() - y;    // Calculate the angle...    // This is our "0" or start angle..    double rotation = -Math.atan2(deltaX, deltaY);    rotation = Math.toRadians(Math.toDegrees(rotation) + 180);    return rotation;}

And the point on a circle can be calculated using something like…

protected Point2D getPointonCircle(Point2D center, double radians, double radius) {    double x = center.getX();    double y = center.getY();    radians = radians - Math.toRadians(90.0); // 0 becomes the top    // Calculate the outter point of the line    double xPosy = Math.round((float) (x + Math.cos(radians) * radius));    double yPosy = Math.round((float) (y + Math.sin(radians) * radius));    return new Point2D.Double(xPosy, yPosy);}

请注意,对结果进行了一些内部修改,以允许数学解决方案与

GraphicsAPI
绘制圆圈的方式之间的差异

好的,您说的这么多,对我有什么帮助?好吧,我实际上很棒。

您可以计算到的圆之间的角度(来回之间,也许
可以简单地将一个角度反演,但是我有可用的计算方法,所以我
使用了它)。由此,您可以计算线将
在其上相交的每个圆的点,然后只需要绘制它,就像…

double from = angleBetween(circle1, circle2);double to = angleBetween(circle2, circle1);Point2D pointFrom = getPointonCircle(circle1, from);Point2D pointTo = getPointonCircle(circle2, to);Line2D line = new Line2D.Double(pointFrom, pointTo);g2d.draw(line);

可运行的例子

因为我将许多计算精简为公用属性,所以提供了测试代码作为可运行示例。所有的
计算都是基于动态值,没有什么是真正的硬编码。对于例如,你可以改变大小和圆的位置和计算应该继续工作......

import java.awt.Color;import java.awt.Dimension;import java.awt.EventQueue;import java.awt.Graphics;import java.awt.Graphics2D;import java.awt.Shape;import java.awt.geom.Ellipse2D;import java.awt.geom.Line2D;import java.awt.geom.Point2D;import java.awt.geom.Rectangle2D;import javax.swing.Jframe;import javax.swing.JPanel;import javax.swing.UIManager;import javax.swing.UnsupportedLookAndFeelException;public class Test {    public static void main(String[] args) {        new Test();    }    public Test() {        EventQueue.invokeLater(new Runnable() { @Override public void run() {     try {         UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());     } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {         ex.printStackTrace();     }     Jframe frame = new Jframe("Testing");     frame.setDefaultCloseOperation(Jframe.EXIT_ON_CLOSE);     frame.add(new TestPane());     frame.pack();     frame.setLocationRelativeTo(null);     frame.setVisible(true); }        });    }    public class TestPane extends JPanel {        private Ellipse2D circle1;        private Ellipse2D circle2;        private Point2D drawTo;        public TestPane() { circle1 = new Ellipse2D.Double(10, 10, 40, 40); circle2 = new Ellipse2D.Double(100, 150, 40, 40); //addMouseMotionListener(new MouseAdapter() { //  @Override //  public void mouseMoved(MouseEvent e) { //      drawTo = new Point2D.Double(e.getPoint().x, e.getPoint().y); //      repaint(); //  } //});        }        protected Point2D center(Rectangle2D bounds) { return new Point2D.Double(bounds.getCenterX(), bounds.getCenterY());        }        protected double angleBetween(Shape from, Shape to) { return angleBetween(center(from.getBounds2D()), center(to.getBounds2D()));        }        protected double angleBetween(Point2D from, Point2D to) { double x = from.getX(); double y = from.getY(); // This is the difference between the anchor point // and the mouse.  Its important that this is done // within the local coordinate space of the component, // this means either the MouseMotionListener needs to // be registered to the component itself (preferably) // or the mouse coordinates need to be converted into // local coordinate space double deltaX = to.getX() - x; double deltaY = to.getY() - y; // Calculate the angle... // This is our "0" or start angle.. double rotation = -Math.atan2(deltaX, deltaY); rotation = Math.toRadians(Math.toDegrees(rotation) + 180); return rotation;        }        protected Point2D getPointonCircle(Shape shape, double radians) { Rectangle2D bounds = shape.getBounds();//          Point2D point = new Point2D.Double(bounds.getX(), bounds.getY()); Point2D point = center(bounds); return getPointonCircle(point, radians, Math.max(bounds.getWidth(), bounds.getHeight()) / 2d);        }        protected Point2D getPointonCircle(Point2D center, double radians, double radius) { double x = center.getX(); double y = center.getY(); radians = radians - Math.toRadians(90.0); // 0 becomes th?e top // Calculate the outter point of the line double xPosy = Math.round((float) (x + Math.cos(radians) * radius)); double yPosy = Math.round((float) (y + Math.sin(radians) * radius)); return new Point2D.Double(xPosy, yPosy);        }        @Override        public Dimension getPreferredSize() { return new Dimension(200, 200);        }        protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = (Graphics2D) g.create(); g2d.draw(circle1); g2d.draw(circle2); // This was used for testing, it will draw a line from circle1 to the // drawTo point, which, if enabled, is the last known position of the // mouse //if (drawTo != null) { //  Point2D pointFrom = center(circle1.getBounds2D()); //  g2d.setColor(Color.RED); //  g2d.draw(new Line2D.Double(drawTo, pointFrom)); // //  double from = angleBetween(pointFrom, drawTo); //  System.out.println(NumberFormat.getNumberInstance().format(Math.toDegrees(from))); // //  Point2D poc = getPointonCircle(circle1, from); //  g2d.setColor(Color.BLUE); //  g2d.draw(new Line2D.Double(poc, drawTo)); //} double from = angleBetween(circle1, circle2); double to = angleBetween(circle2, circle1); Point2D pointFrom = getPointonCircle(circle1, from); Point2D pointTo = getPointonCircle(circle2, to); g2d.setColor(Color.RED); Line2D line = new Line2D.Double(pointFrom, pointTo); g2d.draw(line); g2d.dispose();        }    }}

Arrow head

The intention is to treat the arrow head as a separate entity. The reason is
because it’s just simpler that way, you also get a more consistent result
regardless of the distance between the objects.

So, to start with, I define a new

Shape

public class ArrowHead extends Path2D.Double {    public ArrowHead() {        int size = 10;        moveTo(0, size);        lineTo(size / 2, 0);        lineTo(size, size);    }}

Pretty simple really. It just creates two lines, which point up, meeting in
the middle of the available space.

Then in the

paintComponent
method, we perform some
AffineTransform
magic
using the available information we already have, namely

  • The point on our target circles circumference
  • The angle to our target circle

And transform the

ArrowHead
shape…

g2d.setColor(Color.MAGENTA);ArrowHead arrowHead = new ArrowHead();AffineTransform at = AffineTransform.getTranslateInstance(     pointTo.getX() - (arrowHead.getBounds2D().getWidth() / 2d),      pointTo.getY());at.rotate(from, arrowHead.getBounds2D().getCenterX(), 0);arrowHead.transform(at);g2d.draw(arrowHead);

Now, because I’m crazy, I also tested the pre by drawing an arrow pointing at
our source circle, just to prove that the calculations would work…

// This just proofs that the previous calculations weren't a fluke// and that the arrow can be painted pointing to the source object as wellg2d.setColor(Color.GREEN);arrowHead = new ArrowHead();at = AffineTransform.getTranslateInstance(     pointFrom.getX() - (arrowHead.getBounds2D().getWidth() / 2d),      pointFrom.getY());at.rotate(to, arrowHead.getBounds2D().getCenterX(), 0);arrowHead.transform(at);g2d.draw(arrowHead);


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/406344.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号