2013-03-24 34 views
5

Tôi đang vẽ một hình chữ nhật lên canvas và một đường thẳng từ giữa hình chữ nhật đến một số điểm ngẫu nhiên trong không gian tọa độ.Đường chéo Hình chữ nhật - cách tìm điểm giao nhau?

Bây giờ, tôi muốn cắt bớt đường theo độ dài bên trong hình chữ nhật sao cho dòng bắt đầu ở cạnh hình chữ nhật.

Tôi làm cách nào để thực hiện việc này?

Ví dụ

  • Hình chữ nhật có thể được xác định bởi 2 điểm: Pstart(1, 3), Pend(3, 1)
  • Điểm trung tâm có thể được tính đến: P(2, 2)
  • Bây giờ vẽ đường P(2, 2)-Q(10, 2).

Vì tôi biết chiều rộng của hình chữ nhật là 2, tôi có thể yêu cầu dòng bắt đầu tại P(4, 2) thay vì P(2, 2).

Điều này trở nên phức tạp hơn khi điểm không song song với một trong các trục XY. Hơn nữa chiều dài bên trong hình chữ nhật sẽ là số tiền khác nhau cho các đường chéo.

Làm cách nào tôi có thể tính toán độ lệch bắt đầu cho điểm dòng đối với tâm của hình chữ nhật và điểm kết thúc của đường?

Có lẽ tôi phải tìm điểm mà đường thẳng sẽ vượt qua hình chữ nhật, và sau đó chỉ để cho dòng bắt đầu tại điểm giao nhau. Nhưng làm thế nào tôi có thể nhận được điểm này?

+1

Có một loạt các giải pháp trên trang này: http: // stackoverflow.com/questions/1585525/how-to-find-the-intersection-point-between-a-line-và-a-rectangle Chọn giải pháp trên trang đó có ý nghĩa nhất đối với bạn và nhận được nó. – Michael

Trả lời

12

Thành thật mà nói, tôi không hiểu toán học, nhưng ...

Về cơ bản, bạn có 5 dòng. Dòng gốc và 4 dòng của hình chữ nhật. Vì vậy, nếu bạn phá vỡ nó xuống đến một ngã tư đường đơn giản của vấn đề dòng nó nên trở thành một chút dễ dàng hơn ...

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

Các hàm getIntersectionPoint() có thể được đơn giản hóa rất nhiều nếu bạn biết rằng một trong các dòng là dọc hoặc ngang, mà bạn làm. –

+1

câu trả lời hay! cảm ơn – user3197818

0

Đỉnh của hình chữ nhật: a, b, c, d. Đại diện cho x và y coord của mỗi người như rìu, ay vv

điểm cuối của đường: x, y

Dòng sau y = mx + b, và đi lên hoặc xuống, đúng hay trái. Điều đó thu hẹp các cạnh hình chữ nhật có thể của bạn để chuyển sang 2.

Sử dụng y = mx + b để xác định tọa độ dọc tại tọa độ ngang đường và thành phần nằm ngang nó đi qua đường thẳng đứng. Hoặc chỉ một trong số này thực sự nằm trên hình chữ nhật của bạn (tức là, được chứa trong một trong các cạnh hình chữ nhật), hoặc nó sẽ giao nhau ở một góc.

+0

thực sự bạn có thể sử dụng chỉ 'y = mx' bởi vì dòng bắt đầu ở giữa hình chữ nhật – Breavyn

+0

Tôi chưa hoàn thành toán học đầy đủ, nhưng tôi không * nghĩ * sẽ hoạt động. Chênh lệch 'b' cho bạn biết tọa độ 'y' cho một x = 0, tức là vị trí thẳng đứng của dòng có độ dốc 'm'. Điều đó chắc chắn sẽ ảnh hưởng đến cạnh hình chữ nhật được giao nhau bởi một dòng, trong trường hợp chung. Tôi không cho rằng bất kỳ điểm nào trong số này đều có nguồn gốc. – arcy

+0

Vâng, bạn chỉ có thể giả sử b = 0 nếu hình chữ nhật được căn giữa về gốc. –