2013-03-24 73 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