2013-03-24 90 views
5

我正在绘制一个矩形到画布和从矩形中心到坐标空间中某个随机点的一条线。线穿过矩形 - 如何找到交叉点?

现在,我想通过矩形内部的长度截断线条,以便线条从矩形边缘开始。

我该怎么做?

  • 矩形可以通过2点来定义:Pstart(1, 3)Pend(3, 1)
  • 中心点可以被​​计算到:P(2, 2)
  • 现在画线从P(2, 2)Q(10, 2)

据我所知矩形的宽度是2,我可以告诉行开始在P(4, 2)而不是P(2, 2)

当点不平行于XY轴时,这会变得更加复杂。此外,矩形内的长度对于对角线将是不同的量。

如何计算线条点相对于矩形中心和线条终点的起始偏移量?

也许我必须找到线将穿过矩形的点,然后让线从交叉点开始。但我怎么能得到这一点?

+1

本页有很多解决方案: http:// stackoverflow。com/questions/1585525 /如何找到线与矩形之间的交点 在该页面上选择对您最有意义的解决方案并加以解决。 – Michael 2013-03-24 02:35:03

回答

12

说实话,我不懂数学,但是......

从本质上讲,你有5条线路。原始线和矩形的4行。所以,如果你打破它行问题的一个简单的交叉线应该成为一个轻松一点......

enter image description here

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.Graphics; 
import java.awt.Graphics2D; 
import java.awt.Point; 
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 IntersectPoint { 

    public static void main(String[] args) { 
     new IntersectPoint(); 
    } 

    public IntersectPoint() { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       try { 
        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); 
       } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) { 
       } 

       JFrame frame = new JFrame("Testing"); 
       frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
       frame.setLayout(new BorderLayout()); 
       frame.add(new TestPane()); 
       frame.pack(); 
       frame.setLocationRelativeTo(null); 
       frame.setVisible(true); 
      } 
     }); 
    } 

    public class TestPane extends JPanel { 

     @Override 
     public Dimension getPreferredSize() { 
      return new Dimension(200, 200); 
     } 

     @Override 
     protected void paintComponent(Graphics g) { 
      super.paintComponent(g); 

      int x = (int) (getWidth() * 0.2f); 
      int y = (int) (getHeight() * 0.2f); 
      int width = (int) (getWidth() * 0.6f); 
      int height = (int) (getHeight() * 0.6f); 

      int x1 = x; 
      int y1 = 0; 
      int x2 = x + width; 
      int y2 = getHeight(); 

      Line2D line = new Line2D.Double(x1, y1, x2, y2); 
      Rectangle2D rect = new Rectangle2D.Double(x, y, width, height); 

      Graphics2D g2d = (Graphics2D) g.create(); 
      g2d.draw(rect); 
      g2d.draw(line); 

      g2d.setColor(Color.RED); 
      Point2D[] ps = getIntersectionPoint(line, rect); 
      for (Point2D p : ps) { 
       if (p != null) { 
        g2d.fill(new Ellipse2D.Double(p.getX() - 4, p.getY() - 4, 8, 8)); 
       } 
      } 
      g2d.dispose(); 

     } 

     public Point2D[] getIntersectionPoint(Line2D line, Rectangle2D rectangle) { 

      Point2D[] p = new Point2D[4]; 

      // Top line 
      p[0] = getIntersectionPoint(line, 
          new Line2D.Double(
          rectangle.getX(), 
          rectangle.getY(), 
          rectangle.getX() + rectangle.getWidth(), 
          rectangle.getY())); 
      // Bottom line 
      p[1] = getIntersectionPoint(line, 
          new Line2D.Double(
          rectangle.getX(), 
          rectangle.getY() + rectangle.getHeight(), 
          rectangle.getX() + rectangle.getWidth(), 
          rectangle.getY() + rectangle.getHeight())); 
      // Left side... 
      p[2] = getIntersectionPoint(line, 
          new Line2D.Double(
          rectangle.getX(), 
          rectangle.getY(), 
          rectangle.getX(), 
          rectangle.getY() + rectangle.getHeight())); 
      // Right side 
      p[3] = getIntersectionPoint(line, 
          new Line2D.Double(
          rectangle.getX() + rectangle.getWidth(), 
          rectangle.getY(), 
          rectangle.getX() + rectangle.getWidth(), 
          rectangle.getY() + rectangle.getHeight())); 

      return p; 

     } 

     public Point2D getIntersectionPoint(Line2D lineA, Line2D lineB) { 

      double x1 = lineA.getX1(); 
      double y1 = lineA.getY1(); 
      double x2 = lineA.getX2(); 
      double y2 = lineA.getY2(); 

      double x3 = lineB.getX1(); 
      double y3 = lineB.getY1(); 
      double x4 = lineB.getX2(); 
      double y4 = lineB.getY2(); 

      Point2D p = null; 

      double d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4); 
      if (d != 0) { 
       double xi = ((x3 - x4) * (x1 * y2 - y1 * x2) - (x1 - x2) * (x3 * y4 - y3 * x4))/d; 
       double yi = ((y3 - y4) * (x1 * y2 - y1 * x2) - (y1 - y2) * (x3 * y4 - y3 * x4))/d; 

       p = new Point2D.Double(xi, yi); 

      } 
      return p; 
     } 
    } 
} 
+0

如果您知道其中一行是垂直或水平的,您可以将getIntersectionPoint()函数大大简化。 – 2013-06-25 07:58:09

+1

不错的答案!谢谢 – user3197818 2016-05-27 11:29:06

0

矩形的顶点:a,b,c,d。代表x和每一个像AX,AY的ÿ坐标等的线的

端点:X,Y

线如下:Y = mx + b中,并进入或上或下,右或剩下。这可以缩小可能的矩形边,使其交叉到2.

使用y = mx + b来确定它穿过水平线的垂直坐标,以及穿过垂直线的水平分量。只有其中一个实际上会在您的矩形上(即,包含在其中一个矩形边缘内),或者它们将相交于一个角落。

+0

你真的可以使用'y = mx',因为这条线开始于矩形的中心 – Breavyn 2013-03-24 02:35:10

+0

我还没有完全计算出数学,但我不认为*会起作用。 'b'偏移量告诉你x = 0的'y'坐标,即具有斜率'm'的线的垂直位置。在一般情况下,这肯定会影响哪条矩形边与线相交。我不假定这些点都在原点。 – arcy 2013-03-24 03:08:30

+0

是的,如果矩形以原点为中心,则只能假设b = 0。 – 2013-06-25 07:56:41