2013-03-24 13 views
5

Sto disegnando un rettangolo su una tela e una linea dal centro del rettangolo su un punto casuale nello spazio delle coordinate.Line crosses Rectangle - come trovare i punti croce?

Ora, voglio troncare la linea in base alla lunghezza che si trova all'interno del rettangolo in modo che la linea inizi sul bordo del rettangolo.

Come posso fare questo?

Esempio

  • Il rettangolo potrebbe essere definita da 2 punti: Pstart(1, 3), Pend(3, 1)
  • Il punto centrale può essere calcolata per: P(2, 2)
  • Ora disegnare la linea da P(2, 2) a Q(10, 2).

Per quanto ne so la larghezza del rettangolo è 2, potrei dire la linea per iniziare a P(4, 2) invece di P(2, 2).

Questo diventa più complicato quando il punto non è parallelo a uno degli assi XY. Inoltre la lunghezza all'interno del rettangolo sarà diversa per le linee diagonali.

Come è possibile calcolare lo scostamento iniziale per il punto della linea rispetto al centro del rettangolo e al punto finale della linea?

Probabilmente dovrei trovare il punto in cui la linea dovrebbe attraversare il rettangolo e quindi lasciare che la linea inizi al punto di incrocio. Ma come potrei ottenere questo punto?

+1

Ci sono un sacco di soluzioni in questa pagina: http: // stackoverflow.it/questions/1585525/how-to-find-the-intersezione-point-between-a-line-and-a-rectangle Scegli la soluzione su quella pagina che ha più senso per te e prendi la cosa giusta. – Michael

risposta

12

Onestamente, non capisco la matematica, ma ...

In sostanza, si hanno 5 linee. La linea originale e le 4 linee del rettangolo. Quindi, se si rompe verso il basso per una semplice linea di intersezione della linea di problema dovrebbe diventare un po 'più facile ...

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

Le funzioni getIntersectionPoint() possono essere notevolmente semplificate se si sa che una delle linee è verticale o orizzontale, cosa che si fa. –

+1

bella risposta! Grazie – user3197818

0

Vertici del rettangolo: a, b, c, d. Rappresentare la xey coord di ognuno come ax, ay, ecc

estremità della linea: x, y

La linea segue y = mx + b, e va verso l'alto o verso il basso, a destra oa sinistra. Si restringe verso il basso i possibili bordi del rettangolo per il passaggio a 2.

Utilizzare y = mx + b per determinare la coordinata verticale a cui attraversa la linea orizzontale e il componente orizzontale su cui attraversa la linea verticale. O solo uno di questi sarà effettivamente sul tuo rettangolo (cioè, contenuto in uno dei bordi del rettangolo), o si intersecherà in un angolo.

+0

in realtà si potrebbe usare solo 'y = mx' perché la linea inizia al centro del rettangolo – Breavyn

+0

Non ho elaborato completamente la matematica, ma non penso * che funzioni. L'offset 'b' indica la coordinata 'y' per x = 0, cioè la posizione verticale della linea con pendenza 'm'. Ciò influirà sicuramente su quale bordo del rettangolo è intersecato da una linea, nel caso generale. Non sto assumendo che nessuno di questi punti sia all'origine. – arcy

+0

Sì, puoi assumere b = 0 solo se il rettangolo è centrato sull'origine. –