/[classpath]/classpath/java/awt/geom/Line2D.java
ViewVC logotype

Diff of /classpath/java/awt/geom/Line2D.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.2 by mark, Tue Jan 22 22:26:59 2002 UTC revision 1.3 by ericb, Thu Mar 21 07:58:00 2002 UTC
# Line 1  Line 1 
1  /* Copyright (C) 2000, 2001, 2002  Free Software Foundation  /* Line2D.java -- represents a line in 2-D space, plus operations on a line
2       Copyright (C) 2000, 2001, 2002 Free Software Foundation
3    
4  This file is part of GNU Classpath.  This file is part of GNU Classpath.
5    
# Line 38  package java.awt.geom; Line 39  package java.awt.geom;
39    
40  import java.awt.Rectangle;  import java.awt.Rectangle;
41  import java.awt.Shape;  import java.awt.Shape;
42    import java.util.NoSuchElementException;
43    
44  /**  /**
45     * Represents a directed line bewteen two points in (x,y) Cartesian space.
46     * Remember, on-screen graphics have increasing x from left-to-right, and
47     * increasing y from top-to-bottom. The storage is left to subclasses.
48     *
49   * @author Tom Tromey <tromey@cygnus.com>   * @author Tom Tromey <tromey@cygnus.com>
50   * @date April 21, 2001   * @author Eric Blake <ebb9@email.byu.edu>
51     * @since 1.2
52     * @status updated to 1.4
53   */   */
   
54  public abstract class Line2D implements Shape, Cloneable  public abstract class Line2D implements Shape, Cloneable
55  {  {
56    protected Line2D ()    /**
57    {     * The default constructor.
58    }     */
59      protected Line2D()
60    public Object clone ()    {
61    {    }
62      try  
63        {    /**
64          return super.clone ();     * Return the x coordinate of the first point.
65        }     *
66      catch (CloneNotSupportedException _)     * @return the starting x coordinate
67        {     */
68          // Can't happen.    public abstract double getX1();
69          return null;  
70        }    /**
71    }     * Return the y coordinate of the first point.
72       *
73    public boolean contains (double x, double y)     * @return the starting y coordinate
74    {     */
75      double x1 = getX1 ();    public abstract double getY1();
76      double t1 = (x - x1) / (getX2 () - x1);  
77      if (t1 < 0 || t1 > 1)    /**
78        return false;     * Return the first point.
79      double y1 = getY1 ();     *
80      double t2 = (y - y1) / (getY2 () - y1);     * @return the starting point
81      // FIXME: use of == here is bogus     */
82      return t2 >= 0 && t2 <= 1 && t1 == t2;    public abstract Point2D getP1();
83    }  
84      /**
85    public boolean contains (double x, double y, double w, double h)     * Return the x coordinate of the second point.
86    {     *
87      return false;     * @return the ending x coordinate
88    }     */
89      public abstract double getX2();
90    public boolean contains (Point2D p)  
91    {    /**
92      return contains (p.getX (), p.getY ());     * Return the y coordinate of the second point.
93    }     *
94       * @return the ending y coordinate
95    public boolean contains (Rectangle2D r)     */
96    {    public abstract double getY2();
97      return false;  
98    }    /**
99       * Return the second point.
100    public Rectangle getBounds ()     *
101    {     * @return the ending point
102      double x1 = getX1 ();     */
103      double y1 = getY1 ();    public abstract Point2D getP2();
104      double x2 = getX2 ();  
105      double y2 = getY2 ();    /**
106       * Set the coordinates of the line to the given coordinates. Loss of
107      double x = Math.min (x1, x2);     * precision may occur due to rounding issues.
108      double y = Math.min (y1, y2);     *
109      double w = Math.abs (x1 - x2);     * @param x1 the first x coordinate
110      double h = Math.abs (y1 - y2);     * @param y1 the first y coordinate
111       * @param x2 the second x coordinate
112      return new Rectangle ((int) x, (int) y, (int) w, (int) h);     * @param y2 the second y coordinate
113    }     */
114      public abstract void setLine(double x1, double y1, double x2, double y2);
115    public abstract Point2D getP1 ();  
116    public abstract Point2D getP2 ();    /**
117       * Set the coordinates to the given points.
118    public PathIterator getPathIterator (AffineTransform at)     *
119    {     * @param p1 the first point
120      return getPathIterator (at, 0);     * @param p2 the second point
121    }     * @throws NullPointerException if either point is null
122       */
123    public PathIterator getPathIterator (AffineTransform at, double flatness)    public void setLine(Point2D p1, Point2D p2)
124    {    {
125      return at.new Iterator (new Iterator ());      setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
126    }    }
127    
128    public abstract double getX1 ();    /**
129    public abstract double getY1 ();     * Set the coordinates to those of the given line.
130    public abstract double getX2 ();     *
131    public abstract double getY2 ();     * @param l the line to copy
132       * @throws NullPointerException if l is null
133    public boolean intersects (double x, double y, double w, double h)     */
134    {    public void setLine(Line2D l)
135      double x1 = getX1 ();    {
136      double y1 = getY1 ();      setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
137      double x2 = getX2 ();    }
138      double y2 = getY2 ();  
139      /**
140      if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y +h)     * Computes the relative rotation direction needed to pivot the line about
141        return true;     * the first point in order to have the second point colinear with point p.
142      if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y +h)     * Because of floating point rounding, don't expect this to be a perfect
143        return true;     * measure of colinearity. The answer is 1 if the line has a shorter rotation
144       * in the direction of the positive X axis to the negative Y axis
145      double x3 = x + w;     * (counter-clockwise in the default Java coordinate system), or -1 if the
146      double y3 = y + h;     * shortest rotation is in the opposite direction (clockwise). If p
147       * is already colinear, the return value is -1 if it lies beyond the first
148      return (linesIntersect (x1, y1, x2, y2, x, y, x, y3)     * point, 0 if it lies in the segment, or 1 if it lies beyond the second
149              || linesIntersect (x1, y1, x2, y2, x, y3, x3, y3)     * point. If the first and second point are coincident, this returns 0.
150              || linesIntersect (x1, y1, x2, y2, x3, y3, x3, y)     *
151              || linesIntersect (x1, y1, x2, y2, x3, y, x, y));     * @param x1 the first x coordinate
152    }     * @param y1 the first y coordinate
153       * @param x2 the second x coordinate
154    public boolean intersects (Rectangle2D r)     * @param y2 the second y coordinate
155    {     * @param px the reference x coordinate
156      return intersects (r.getX (), r.getY (), r.getWidth (), r.getHeight ());     * @param py the reference y coordinate
157    }     * @return the relative rotation direction
158       */
159    public boolean intersectsLine (double x1, double y1, double x2, double y2)    public static int relativeCCW(double x1, double y1, double x2, double y2,
160    {                                  double px, double py)
161      return linesIntersect (getX1 (), getY1 (), getX2 (), getY2(),    {
162                             x1, y1, x2, y2);      if ((x1 == x2 && y1 == y2)
163    }          || (x1 == px && y1 == py))
164          return 0; // Coincident points.
165    public boolean intersectsLine (Line2D l)      // Translate to the origin.
166    {      x2 -= x1;
167      return linesIntersect (getX1 (), getY1 (), getX2 (), getY2(),      y2 -= y1;
168                             l.getX1 (), l.getY1 (), l.getX2 (), l.getY2 ());      px -= x1;
169    }      py -= y1;
170        double slope2 = y2 / x2;
171    public static boolean linesIntersect (double x1, double y1,      double slopep = py / px;
172                                          double x2, double y2,      if (slope2 == slopep || (x2 == 0 && px == 0))
173                                          double x3,double y3,        return y2 > 0 // Colinear.
174                                          double x4, double y4)          ? (py < 0 ? -1 : py > y2 ? 1 : 0)
175            : (py > 0 ? -1 : py < y2 ? 1 : 0);
176        if (x2 >= 0 && slope2 >= 0)
177          return px >= 0 // Quadrant 1.
178            ? (slope2 > slopep ? 1 : -1)
179            : (slope2 < slopep ? 1 : -1);
180        if (y2 > 0)
181          return px < 0 // Quadrant 2.
182            ? (slope2 > slopep ? 1 : -1)
183            : (slope2 < slopep ? 1 : -1);
184        if (slope2 >= 0.0)
185          return px >= 0 // Quadrant 3.
186            ? (slope2 < slopep ? 1 : -1)
187            : (slope2 > slopep ? 1 : -1);
188        return px < 0 // Quadrant 4.
189          ? (slope2 < slopep ? 1 : -1)
190          : (slope2 > slopep ? 1 : -1);
191      }
192    
193      /**
194       * Computes the relative rotation direction needed to pivot this line about
195       * the first point in order to have the second point colinear with point p.
196       * Because of floating point rounding, don't expect this to be a perfect
197       * measure of colinearity. The answer is 1 if the line has a shorter rotation
198       * in the direction of the positive X axis to the negative Y axis
199       * (counter-clockwise in the default Java coordinate system), or -1 if the
200       * shortest rotation is in the opposite direction (clockwise). If p
201       * is already colinear, the return value is -1 if it lies beyond the first
202       * point, 0 if it lies in the segment, or 1 if it lies beyond the second
203       * point. If the first and second point are coincident, this returns 0.
204       *
205       * @param px the reference x coordinate
206       * @param py the reference y coordinate
207       * @return the relative rotation direction
208       * @see #relativeCCW(double, double, double, double, double, double)
209       */
210      public int relativeCCW(double px, double py)
211      {
212        return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py);
213      }
214    
215      /**
216       * Computes the relative rotation direction needed to pivot this line about
217       * the first point in order to have the second point colinear with point p.
218       * Because of floating point rounding, don't expect this to be a perfect
219       * measure of colinearity. The answer is 1 if the line has a shorter rotation
220       * in the direction of the positive X axis to the negative Y axis
221       * (counter-clockwise in the default Java coordinate system), or -1 if the
222       * shortest rotation is in the opposite direction (clockwise). If p
223       * is already colinear, the return value is -1 if it lies beyond the first
224       * point, 0 if it lies in the segment, or 1 if it lies beyond the second
225       * point. If the first and second point are coincident, this returns 0.
226       *
227       * @param p the reference point
228       * @return the relative rotation direction
229       * @throws NullPointerException if p is null
230       * @see #relativeCCW(double, double, double, double, double, double)
231       */
232      public int relativeCCW(Point2D p)
233      {
234        return relativeCCW(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
235      }
236    
237      /**
238       * Test if the line segment (x1,y1)-&gt;(x2,y2) intersects the line segment
239       * (x3,y3)-&gt;(x4,y4).
240       *
241       * @param x1 the first x coordinate of the first segment
242       * @param y1 the first y coordinate of the first segment
243       * @param x2 the second x coordinate of the first segment
244       * @param y2 the second y coordinate of the first segment
245       * @param x3 the first x coordinate of the second segment
246       * @param y3 the first y coordinate of the second segment
247       * @param x4 the second x coordinate of the second segment
248       * @param y4 the second y coordinate of the second segment
249       * @return true if the segments intersect
250       */
251      public static boolean linesIntersect(double x1, double y1,
252                                           double x2, double y2,
253                                           double x3, double y3,
254                                           double x4, double y4)
255    {    {
256      double beta = (((y1 - y3) * (x4 - x3) + (x1 - x3) * (y4 - y3))      double beta = (((y1 - y3) * (x4 - x3) + (x1 - x3) * (y4 - y3))
257                     / ((y2 - y1) * (x4 - x3) + (x2 - x1) * (y4 - y3)));                     / ((y2 - y1) * (x4 - x3) + (x2 - x1) * (y4 - y3)));
258      if (beta < 0.0 || beta > 1.0)      if (beta < 0.0 || beta > 1.0)
259        return false;        return false;
260      double alpha = (x1 + beta * (x2 - x1) - x3) / (x4 - x3);      double alpha = (x1 + beta * (x2 - x1) - x3) / (x4 - x3);
261      return alpha >= 0.0 && alpha <= 1.0;      return alpha >= 0.0 && alpha <= 1.0;
262    }    }
263    
264    public double ptLineDist (double px, double py)    /**
265       * Test if this line intersects the line given by (x1,y1)-&gt;(x2,y2).
266       *
267       * @param x1 the first x coordinate of the other segment
268       * @param y1 the first y coordinate of the other segment
269       * @param x2 the second x coordinate of the other segment
270       * @param y2 the second y coordinate of the other segment
271       * @return true if the segments intersect
272       * @see #linesIntersect(double, double, double, double,
273       *                      double, double, double, double)
274       */
275      public boolean intersectsLine(double x1, double y1, double x2, double y2)
276      {
277        return linesIntersect(getX1(), getY1(), getX2(), getY2(),
278                              x1, y1, x2, y2);
279      }
280    
281      /**
282       * Test if this line intersects the given line.
283       *
284       * @param l the other segment
285       * @return true if the segments intersect
286       * @throws NullPointerException if l is null
287       * @see #linesIntersect(double, double, double, double,
288       *                      double, double, double, double)
289       */
290      public boolean intersectsLine(Line2D l)
291      {
292        return linesIntersect(getX1(), getY1(), getX2(), getY2(),
293                              l.getX1(), l.getY1(), l.getX2(), l.getY2());
294      }
295    
296      /**
297       * Measures the square of the shortest distance from the reference point
298       * to a point on the line segment. If the point is on the segment, the
299       * result will be 0.
300       *
301       * @param x1 the first x coordinate of the segment
302       * @param y1 the first y coordinate of the segment
303       * @param x2 the second x coordinate of the segment
304       * @param y2 the second y coordinate of the segment
305       * @param px the x coordinate of the point
306       * @param py the y coordinate of the point
307       * @return the square of the distance from the point to the segment
308       * @see #ptSegDist(double, double, double, double, double, double)
309       * @see #ptLineDistSq(double, double, double, double, double, double)
310       */
311      public static double ptSegDistSq(double x1, double y1, double x2, double y2,
312                                       double px, double py)
313    {    {
314      return ptLineDist (getX1 (), getY1 (), getX2 (), getY2 (),      double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
                        px, py);  
   }  
315    
316    public static double ptLineDist (double x1, double y1,      double x, y;
317                                     double x2, double y2,      if (pd2 == 0)
318                                     double px, double py)        {
319    {          // Points are coincident.
320      return Math.sqrt (ptLineDistSq (x1, y1, x2, y2, px, py));          x = x1;
321    }          y = y2;
322          }
323        else
324          {
325            double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
326    
327    public double ptLineDist (Point2D p)          if (u < 0)
328    {            {
329      return ptLineDist (getX1 (), getY1 (), getX2 (), getY2 (),              // "Off the end"
330                         p.getX (), p.getY ());              x = x1;
331    }              y = y1;
332              }
333            else if (u > 1.0)
334              {
335                x = x2;
336                y = y2;
337              }
338            else
339              {
340                x = x1 + u * (x2 - x1);
341                y = y1 + u * (y2 - y1);
342              }
343          }
344    
345    public double ptLineDistSq (double px, double py)      return (x - px) * (x - px) + (y - py) * (y - py);
   {  
     return ptLineDistSq (getX1 (), getY1 (), getX2 (), getY2 (),  
                          px, py);  
346    }    }
347    
348    public static double ptLineDistSq (double x1, double y1,    /**
349                                       double x2, double y2,     * Measures the shortest distance from the reference point to a point on
350                                       double px, double py)     * the line segment. If the point is on the segment, the result will be 0.
351       *
352       * @param x1 the first x coordinate of the segment
353       * @param y1 the first y coordinate of the segment
354       * @param x2 the second x coordinate of the segment
355       * @param y2 the second y coordinate of the segment
356       * @param px the x coordinate of the point
357       * @param py the y coordinate of the point
358       * @return the distance from the point to the segment
359       * @see #ptSegDistSq(double, double, double, double, double, double)
360       * @see #ptLineDist(double, double, double, double, double, double)
361       */
362      public static double ptSegDist(double x1, double y1, double x2, double y2,
363                                     double px, double py)
364      {
365        return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py));
366      }
367    
368      /**
369       * Measures the square of the shortest distance from the reference point
370       * to a point on this line segment. If the point is on the segment, the
371       * result will be 0.
372       *
373       * @param px the x coordinate of the point
374       * @param py the y coordinate of the point
375       * @return the square of the distance from the point to the segment
376       * @see #ptSegDistSq(double, double, double, double, double, double)
377       */
378      public double ptSegDistSq(double px, double py)
379      {
380        return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
381      }
382    
383      /**
384       * Measures the square of the shortest distance from the reference point
385       * to a point on this line segment. If the point is on the segment, the
386       * result will be 0.
387       *
388       * @param p the point
389       * @return the square of the distance from the point to the segment
390       * @throws NullPointerException if p is null
391       * @see #ptSegDistSq(double, double, double, double, double, double)
392       */
393      public double ptSegDistSq(Point2D p)
394      {
395        return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
396      }
397    
398      /**
399       * Measures the shortest distance from the reference point to a point on
400       * this line segment. If the point is on the segment, the result will be 0.
401       *
402       * @param px the x coordinate of the point
403       * @param py the y coordinate of the point
404       * @return the distance from the point to the segment
405       * @see #ptSegDist(double, double, double, double, double, double)
406       */
407      public double ptSegDist(double px, double py)
408      {
409        return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py);
410      }
411    
412      /**
413       * Measures the shortest distance from the reference point to a point on
414       * this line segment. If the point is on the segment, the result will be 0.
415       *
416       * @param p the point
417       * @return the distance from the point to the segment
418       * @throws NullPointerException if p is null
419       * @see #ptSegDist(double, double, double, double, double, double)
420       */
421      public double ptSegDist(Point2D p)
422      {
423        return ptSegDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
424      }
425    
426      /**
427       * Measures the square of the shortest distance from the reference point
428       * to a point on the infinite line extended from the segment. If the point
429       * is on the segment, the result will be 0. If the segment is length 0,
430       * the distance is to the common endpoint.
431       *
432       * @param x1 the first x coordinate of the segment
433       * @param y1 the first y coordinate of the segment
434       * @param x2 the second x coordinate of the segment
435       * @param y2 the second y coordinate of the segment
436       * @param px the x coordinate of the point
437       * @param py the y coordinate of the point
438       * @return the square of the distance from the point to the extended line
439       * @see #ptLineDist(double, double, double, double, double, double)
440       * @see #ptSegDistSq(double, double, double, double, double, double)
441       */
442      public static double ptLineDistSq(double x1, double y1, double x2, double y2,
443                                        double px, double py)
444    {    {
445      double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);      double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
446    
447      double x, y;      double x, y;
448      if (pd2 == 0)      if (pd2 == 0)
449        {        {
450          // Points are coincident.          // Points are coincident.
451          x = x1;          x = x1;
452          y = y2;          y = y2;
453        }        }
454      else      else
455        {        {
456          double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;          double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
457          x = x1 + u * (x2 - x1);          x = x1 + u * (x2 - x1);
458          y = y1 + u * (y2 - y1);          y = y1 + u * (y2 - y1);
459        }        }
460    
461      return (x - px) * (x - px) + (y - py) * (y - py);      return (x - px) * (x - px) + (y - py) * (y - py);
462    }    }
463    
464    public double ptLineDistSq (Point2D p)    /**
465       * Measures the shortest distance from the reference point to a point on
466       * the infinite line extended from the segment. If the point is on the
467       * segment, the result will be 0. If the segment is length 0, the distance
468       * is to the common endpoint.
469       *
470       * @param x1 the first x coordinate of the segment
471       * @param y1 the first y coordinate of the segment
472       * @param x2 the second x coordinate of the segment
473       * @param y2 the second y coordinate of the segment
474       * @param px the x coordinate of the point
475       * @param py the y coordinate of the point
476       * @return the distance from the point to the extended line
477       * @see #ptLineDistSq(double, double, double, double, double, double)
478       * @see #ptSegDist(double, double, double, double, double, double)
479       */
480      public static double ptLineDist(double x1, double y1,
481                                       double x2, double y2,
482                                       double px, double py)
483      {
484        return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py));
485      }
486    
487      /**
488       * Measures the square of the shortest distance from the reference point
489       * to a point on the infinite line extended from this segment. If the point
490       * is on the segment, the result will be 0. If the segment is length 0,
491       * the distance is to the common endpoint.
492       *
493       * @param px the x coordinate of the point
494       * @param py the y coordinate of the point
495       * @return the square of the distance from the point to the extended line
496       * @see #ptLineDistSq(double, double, double, double, double, double)
497       */
498      public double ptLineDistSq(double px, double py)
499      {
500        return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
501      }
502    
503      /**
504       * Measures the square of the shortest distance from the reference point
505       * to a point on the infinite line extended from this segment. If the point
506       * is on the segment, the result will be 0. If the segment is length 0,
507       * the distance is to the common endpoint.
508       *
509       * @param p the point
510       * @return the square of the distance from the point to the extended line
511       * @throws NullPointerException if p is null
512       * @see #ptLineDistSq(double, double, double, double, double, double)
513       */
514      public double ptLineDistSq(Point2D p)
515      {
516        return ptLineDistSq(getX1(), getY1(), getX2(), getY2(),
517                            p.getX(), p.getY());
518      }
519    
520      /**
521       * Measures the shortest distance from the reference point to a point on
522       * the infinite line extended from this segment. If the point is on the
523       * segment, the result will be 0. If the segment is length 0, the distance
524       * is to the common endpoint.
525       *
526       * @param px the x coordinate of the point
527       * @param py the y coordinate of the point
528       * @return the distance from the point to the extended line
529       * @see #ptLineDist(double, double, double, double, double, double)
530       */
531      public double ptLineDist(double px, double py)
532      {
533        return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py);
534      }
535    
536      /**
537       * Measures the shortest distance from the reference point to a point on
538       * the infinite line extended from this segment. If the point is on the
539       * segment, the result will be 0. If the segment is length 0, the distance
540       * is to the common endpoint.
541       *
542       * @param p the point
543       * @return the distance from the point to the extended line
544       * @throws NullPointerException if p is null
545       * @see #ptLineDist(double, double, double, double, double, double)
546       */
547      public double ptLineDist(Point2D p)
548      {
549        return ptLineDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
550      }
551    
552      /**
553       * Test if a point is contained inside the line. Since a line has no area,
554       * this returns false.
555       *
556       * @param x the x coordinate
557       * @param y the y coordinate
558       * @return false; the line does not contain points
559       */
560      public boolean contains(double x, double y)
561    {    {
562      return ptLineDistSq (getX1 (), getY1 (), getX2 (), getY2 (),      return false;
                          p.getX (), p.getY ());  
563    }    }
564    
565    public double ptSegDist (double px, double py)    /**
566       * Test if a point is contained inside the line. Since a line has no area,
567       * this returns false.
568       *
569       * @param p the point
570       * @return false; the line does not contain points
571       */
572      public boolean contains(Point2D p)
573    {    {
574      return ptSegDist (getX1 (), getY1 (), getX2 (), getY2 (),      return false;
                       px, py);  
575    }    }
576    
577    public static double ptSegDist (double x1, double y1,    /**
578                                     double x2, double y2,     * Tests if this line intersects the interior of the specified rectangle.
579                                     double px, double py)     *
580       * @param x the x coordinate of the rectangle
581       * @param y the y coordinate of the rectangle
582       * @param w the width of the rectangle
583       * @param h the height of the rectangle
584       * @return true if the line intersects the rectangle
585       */
586      public boolean intersects(double x, double y, double w, double h)
587    {    {
588      return Math.sqrt (ptSegDistSq (x1, y1, x2, y2, px, py));      if (w <= 0 || h <= 0)
589    }        return false;
590        double x1 = getX1();
591        double y1 = getY1();
592        double x2 = getX2();
593        double y2 = getY2();
594    
595        if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
596          return true;
597        if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
598          return true;
599    
600    public double ptSegDist (Point2D p)      double x3 = x + w;
601        double y3 = y + h;
602    
603        return (linesIntersect(x1, y1, x2, y2, x, y, x, y3)
604                || linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
605                || linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
606                || linesIntersect(x1, y1, x2, y2, x3, y, x, y));
607      }
608    
609      /**
610       * Tests if this line intersects the interior of the specified rectangle.
611       *
612       * @param r the rectangle
613       * @return true if the line intersects the rectangle
614       * @throws NullPointerException if r is null
615       */
616      public boolean intersects(Rectangle2D r)
617      {
618        return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
619      }
620    
621      /**
622       * Tests if the line contains a rectangle. Since lines have no area, this
623       * always returns false.
624       *
625       * @param x the x coordinate of the rectangle
626       * @param y the y coordinate of the rectangle
627       * @param w the width of the rectangle
628       * @param h the height of the rectangle
629       * @return false; the line does not contain points
630       */
631      public boolean contains(double x, double y, double w, double h)
632    {    {
633      return ptSegDist (getX1 (), getY1 (), getX2 (), getY2 (),      return false;
                       p.getX (), p.getY ());  
634    }    }
635    
636    public double ptSegDistSq (double px, double py)    /**
637       * Tests if the line contains a rectangle. Since lines have no area, this
638       * always returns false.
639       *
640       * @param r the rectangle
641       * @return false; the line does not contain points
642       */
643      public boolean contains(Rectangle2D r)
644    {    {
645      return ptSegDistSq (getX1 (), getY1 (), getX2 (), getY2 (),      return false;
                         px, py);  
646    }    }
647    
648    public static double ptSegDistSq (double x1, double y1,    /**
649                                       double x2, double y2,     * Gets a bounding box (not necessarily minimal) for this line.
650                                       double px, double py)     *
651       * @return the integer bounding box
652       * @see #getBounds2D()
653       */
654      public Rectangle getBounds()
655      {
656        double x1 = getX1();
657        double y1 = getY1();
658        double x2 = getX2();
659        double y2 = getY2();
660        double minx = Math.floor(Math.min(x1, x2));
661        double miny = Math.floor(Math.min(y1, y2));
662        double maxx = Math.ceil(Math.max(x1, x2));
663        double maxy = Math.ceil(Math.max(y1, y2));
664        return new Rectangle((int) minx, (int) miny,
665                             (int) (maxx - minx), (int) (maxy - miny));
666      }
667    
668      /**
669       * Return a path iterator, possibly applying a transform on the result. This
670       * iterator is not threadsafe.
671       *
672       * @param at the transform, or null
673       * @return a new path iterator
674       */
675      public PathIterator getPathIterator(final AffineTransform at)
676    {    {
677      double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);      return new PathIterator()
678        {
679          /** Current coordinate. */
680          private int current;
681    
682      double x, y;        public int getWindingRule()
     if (pd2 == 0)  
683        {        {
684          // Points are coincident.          return WIND_EVEN_ODD;
         x = x1;  
         y = y2;  
685        }        }
     else  
       {  
         double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;  
686    
687          if (u < 0)        public boolean isDone()
688            {        {
689              // "Off the end"          return current < 2;
             x = x1;  
             y = y1;  
           }  
         else if (u > 1.0)  
           {  
             x = x2;  
             y = y2;  
           }  
         else  
           {  
             x = x1 + u * (x2 - x1);  
             y = y1 + u * (y2 - y1);  
           }  
690        }        }
691    
692      return (x - px) * (x - px) + (y - py) * (y - py);        public void next()
693    }        {
694            current++;
695    public double ptSegDistSq (Point2D p)        }
   {  
     return ptSegDistSq (getX1 (), getY1 (), getX2 (), getY2 (),  
                         p.getX (), p.getY ());  
   }  
   
   public int relativeCCW (double px, double py)  
   {  
     return relativeCCW (getX1 (), getY1 (),  
                         getX2 (), getY2 (),  
                         px, py);  
   }  
   
   public static int relativeCCW (double x1, double y1,  
                                  double x2, double y2,  
                                  double px, double py)  
   {  
     // This is a somewhat silly way to compute this.  
     // Please write a better one.  
     double a1 = Math.atan2 (y2 - y1, x2 - x1);  
     double a2 = Math.atan2 (py - y1, px - x1);  
696    
697      double a = (a1 - a2) % (2 * Math.PI);        public int currentSegment(float[] coords)
     if (a == 0 || a == Math.PI)  
698        {        {
699          double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1));          int result;
700          if (u < 0.0)          switch (current)
701            return 1;            {
702          else if (u > 1.0)            case 0:
703            return -1;              coords[0] = (float) getX1();
704          else              coords[1] = (float) getY1();
705            return 0;              result = SEG_MOVETO;
706                break;
707              case 1:
708                coords[0] = (float) getX2();
709                coords[1] = (float) getY2();
710                result = SEG_LINETO;
711                break;
712              default:
713                throw new NoSuchElementException("line iterator out of bounds");
714              }
715            if (at != null)
716              at.transform(coords, 0, coords, 0, 1);
717            return result;
718        }        }
719    
720      return (a > 0 && a < Math.PI) ? 1 : -1;        public int currentSegment(double[] coords)
721          {
722            int result;
723            switch (current)
724              {
725              case 0:
726                coords[0] = getX1();
727                coords[1] = getY1();
728                result = SEG_MOVETO;
729                break;
730              case 1:
731                coords[0] = getX2();
732                coords[1] = getY2();
733                result = SEG_LINETO;
734                break;
735              default:
736                throw new NoSuchElementException("line iterator out of bounds");
737              }
738            if (at != null)
739              at.transform(coords, 0, coords, 0, 1);
740            return result;
741          }
742        };
743    }    }
744    
745    public int relativeCCW (Point2D p)    /**
746       * Return a flat path iterator, possibly applying a transform on the result.
747       * This iterator is not threadsafe.
748       *
749       * @param at the transform, or null
750       * @param flatness ignored, since lines are already flat
751       * @return a new path iterator
752       * @see #getPathIterator(AffineTransform)
753       */
754      public PathIterator getPathIterator(AffineTransform at, double flatness)
755      {
756        return getPathIterator(at);
757      }
758    
759      /**
760       * Create a new line of the same run-time type with the same contents as
761       * this one.
762       *
763       * @return the clone
764       */
765      public Object clone()
766    {    {
767      return relativeCCW (getX1 (), getY1 (),      try
768                          getX2 (), getY2 (),        {
769                          p.getX (), p.getY ());          return super.clone();
770          }
771        catch (CloneNotSupportedException e)
772          {
773            throw (Error) new InternalError().initCause(e); // Impossible
774          }
775    }    }
776    
777    public abstract void setLine (double x1, double y1, double x2, double y2);    /**
778       * This class defines a point in <code>double</code> precision.
779    public void setLine (Line2D l)     *
780       * @author Eric Blake <ebb9@email.byu.edu>
781       * @since 1.2
782       * @status updated to 1.4
783       */
784      public static class Double extends Line2D
785    {    {
786      setLine (l.getX1 (), l.getY1 (), l.getX2 (), l.getY2 ());      /** The x coordinate of the first point. */
787    }      public double x1;
788    
789    public void setLine (Point2D p1, Point2D p2)      /** The y coordinate of the first point. */
790    {      public double y1;
     setLine (p1.getX (), p1.getY (), p2.getX (), p2.getY ());  
   }                                            
791    
792    public static class Float extends Line2D      /** The x coordinate of the second point. */
793    {      public double x2;
     float x1, y1, x2, y2;  
794    
795      public Float ()      /** The y coordinate of the second point. */
796        public double y2;
797    
798        /**
799         * Construct the line segment (0,0)-&gt;(0,0).
800         */
801        public Double()
802      {      {
       this (0.0F, 0.0F, 0.0F, 0.0F);  
803      }      }
804    
805      public Float (float x1, float y1, float x2, float y2)      /**
806         * Construct the line segment with the specified points.
807         *
808         * @param x1 the x coordinate of the first point
809         * @param y1 the y coordinate of the first point
810         * @param x2 the x coordinate of the second point
811         * @param y2 the y coordinate of the second point
812         */
813        public Double(double x1, double y1, double x2, double y2)
814      {      {
815        this.x1 = x1;        this.x1 = x1;
816        this.y1 = y1;        this.y1 = y1;
# Line 364  public abstract class Line2D implements Line 818  public abstract class Line2D implements
818        this.y2 = y2;        this.y2 = y2;
819      }      }
820    
821      public Float (Point2D p1, Point2D p2)      /**
822      {       * Construct the line segment with the specified points.
823        this.x1 = (float) p1.getX ();       *
824        this.y1 = (float) p1.getY ();       * @param p1 the first point
825        this.x2 = (float) p2.getX ();       * @param p2 the second point
826        this.y2 = (float) p2.getY ();       * @throws NullPointerException if either point is null
827      }       */
828        public Double(Point2D p1, Point2D p2)
829      public Rectangle2D getBounds2D ()      {
830      {        x1 = p1.getX();
831        float x = Math.min (x1, x2);        y1 = p1.getY();
832        float w = Math.abs (x1 - x2);        x2 = p2.getX();
833        float y = Math.min (y1, y2);        y2 = p2.getY();
834        float h = Math.abs (y1 - y2);      }
835        return new Rectangle2D.Float (x, y, w, h);  
836      }      /**
837         * Return the x coordinate of the first point.
838      public Point2D getP1 ()       *
839      {       * @return the value of x1
840        return new Point2D.Float (x1, y1);       */
841      }      public double getX1()
   
     public Point2D getP2 ()  
     {  
       return new Point2D.Float (x2, y2);  
     }  
   
     public double getX1 ()  
842      {      {
843        return x1;        return x1;
844      }      }
845    
846      public double getY1 ()      /**
847         * Return the y coordinate of the first point.
848         *
849         * @return the value of y1
850         */
851        public double getY1()
852      {      {
853        return y1;        return y1;
854      }      }
855    
856      public double getX2 ()      /**
857         * Return the first point.
858         *
859         * @return the point (x1,y1)
860         */
861        public Point2D getP1()
862        {
863          return new Point2D.Double(x1, y1);
864        }
865    
866        /**
867         * Return the x coordinate of the second point.
868         *
869         * @return the value of x2
870         */
871        public double getX2()
872      {      {
873        return x2;        return x2;
874      }      }
875    
876      public double getY2 ()      /**
877         * Return the y coordinate of the second point.
878         *
879         * @return the value of y2
880         */
881        public double getY2()
882      {      {
883        return y2;        return y2;
884      }      }
885    
886      public void setLine (double x1, double y1, double x2, double y2)      /**
887      {       * Return the second point.
888        this.x1 = (float) x1;       *
889        this.y1 = (float) y1;       * @return the point (x2,y2)
890        this.x2 = (float) x2;       */
891        this.y2 = (float) y2;      public Point2D getP2()
892      }      {
893          return new Point2D.Double(x2, y2);
894      public void setLine (float x1, float y1, float x2, float y2)      }
895    
896        /**
897         * Set this line to the given points.
898         *
899         * @param x1 the new x coordinate of the first point
900         * @param y1 the new y coordinate of the first point
901         * @param x2 the new x coordinate of the second point
902         * @param y2 the new y coordinate of the second point
903         */
904        public void setLine(double x1, double y1, double x2, double y2)
905      {      {
906        this.x1 = x1;        this.x1 = x1;
907        this.y1 = y1;        this.y1 = y1;
908        this.x2 = x2;        this.x2 = x2;
909        this.y2 = y2;        this.y2 = y2;
910      }      }
   }  
911    
912    public static class Double extends Line2D      /**
913         * Return the exact bounds of this line segment.
914         *
915         * @return the bounding box
916         */
917        public Rectangle2D getBounds2D()
918        {
919          double x = Math.min(x1, x2);
920          double y = Math.min(y1, y2);
921          double w = Math.abs(x1 - x2);
922          double h = Math.abs(y1 - y2);
923          return new Rectangle2D.Double(x, y, w, h);
924        }
925      } // class Double
926    
927      /**
928       * This class defines a point in <code>float</code> precision.
929       *
930       * @author Eric Blake <ebb9@email.byu.edu>
931       * @since 1.2
932       * @status updated to 1.4
933       */
934      public static class Float extends Line2D
935    {    {
936      double x1, y1, x2, y2;      /** The x coordinate of the first point. */
937        public float x1;
938    
939        /** The y coordinate of the first point. */
940        public float y1;
941    
942      public Double ()      /** The x coordinate of the second point. */
943        public float x2;
944    
945        /** The y coordinate of the second point. */
946        public float y2;
947    
948        /**
949         * Construct the line segment (0,0)-&gt;(0,0).
950         */
951        public Float()
952      {      {
       this (0.0, 0.0, 0.0, 0.0);  
953      }      }
954    
955      public Double (double x1, double y1, double x2, double y2)      /**
956         * Construct the line segment with the specified points.
957         *
958         * @param x1 the x coordinate of the first point
959         * @param y1 the y coordinate of the first point
960         * @param x2 the x coordinate of the second point
961         * @param y2 the y coordinate of the second point
962         */
963        public Float(float x1, float y1, float x2, float y2)
964      {      {
965        this.x1 = x1;        this.x1 = x1;
966        this.y1 = y1;        this.y1 = y1;
# Line 445  public abstract class Line2D implements Line 968  public abstract class Line2D implements
968        this.y2 = y2;        this.y2 = y2;
969      }      }
970    
971      public Double (Point2D p1, Point2D p2)      /**
972      {       * Construct the line segment with the specified points.
973        this.x1 = (double) p1.getX ();       *
974        this.y1 = p1.getY ();       * @param p1 the first point
975        this.x2 = p2.getX ();       * @param p2 the second point
976        this.y2 = p2.getY ();       * @throws NullPointerException if either point is null
977      }       */
978        public Float(Point2D p1, Point2D p2)
979      public Rectangle2D getBounds2D ()      {
980      {        x1 = (float) p1.getX();
981        double x = Math.min (x1, x2);        y1 = (float) p1.getY();
982        double w = Math.abs (x1 - x2);        x2 = (float) p2.getX();
983        double y = Math.min (y1, y2);        y2 = (float) p2.getY();
984        double h = Math.abs (y1 - y2);      }
985        return new Rectangle2D.Double (x, y, w, h);  
986      }      /**
987         * Return the x coordinate of the first point.
988      public Point2D getP1 ()       *
989      {       * @return the value of x1
990        return new Point2D.Double (x1, y1);       */
991      }      public double getX1()
   
     public Point2D getP2 ()  
     {  
       return new Point2D.Double (x2, y2);  
     }  
   
     public double getX1 ()  
992      {      {
993        return x1;        return x1;
994      }      }
995    
996      public double getY1 ()      /**
997         * Return the y coordinate of the first point.
998         *
999         * @return the value of y1
1000         */
1001        public double getY1()
1002      {      {
1003        return y1;        return y1;
1004      }      }
1005    
1006      public double getX2 ()      /**
1007         * Return the first point.
1008         *
1009         * @return the point (x1,y1)
1010         */
1011        public Point2D getP1()
1012        {
1013          return new Point2D.Float(x1, y1);
1014        }
1015    
1016        /**
1017         * Return the x coordinate of the second point.
1018         *
1019         * @return the value of x2
1020         */
1021        public double getX2()
1022      {      {
1023        return x2;        return x2;
1024      }      }
1025    
1026      public double getY2 ()      /**
1027         * Return the y coordinate of the second point.
1028         *
1029         * @return the value of y2
1030         */
1031        public double getY2()
1032      {      {
1033        return y2;        return y2;
1034      }      }
1035    
1036      public void setLine (double x1, double y1, double x2, double y2)      /**
1037         * Return the second point.
1038         *
1039         * @return the point (x2,y2)
1040         */
1041        public Point2D getP2()
1042        {
1043          return new Point2D.Float(x2, y2);
1044        }
1045    
1046        /**
1047         * Set this line to the given points.
1048         *
1049         * @param x1 the new x coordinate of the first point
1050         * @param y1 the new y coordinate of the first point
1051         * @param x2 the new x coordinate of the second point
1052         * @param y2 the new y coordinate of the second point
1053         */
1054        public void setLine(double x1, double y1, double x2, double y2)
1055        {
1056          this.x1 = (float) x1;
1057          this.y1 = (float) y1;
1058          this.x2 = (float) x2;
1059          this.y2 = (float) y2;
1060        }
1061    
1062        /**
1063         * Set this line to the given points.
1064         *
1065         * @param x1 the new x coordinate of the first point
1066         * @param y1 the new y coordinate of the first point
1067         * @param x2 the new x coordinate of the second point
1068         * @param y2 the new y coordinate of the second point
1069         */
1070        public void setLine(float x1, float y1, float x2, float y2)
1071      {      {
1072        this.x1 = x1;        this.x1 = x1;
1073        this.y1 = y1;        this.y1 = y1;
1074        this.x2 = x2;        this.x2 = x2;
1075        this.y2 = y2;        this.y2 = y2;
1076      }      }
   }  
   
   // This implements the PathIterator for all line objects that don't  
   // override getPathIterator.  
   private class Iterator implements PathIterator  
   {  
     // Current coordinate.  
     private int coord;  
   
     private static final int START = 0;  
     private static final int END_PLUS_ONE = 2;  
   
     public Iterator ()  
     {  
       coord = START;  
     }  
   
     public int currentSegment (double[] coords)  
     {  
       int r = SEG_MOVETO;  
       if (coord == 0)  
         {  
           coords[0] = getX1 ();  
           coords[1] = getY1 ();  
         }  
       else if (coord == 1)  
         {  
           coords[0] = getX2 ();  
           coords[1] = getY2 ();  
         }  
       else  
         r = SEG_CLOSE;  
1077    
1078        return r;      /**
1079         * Return the exact bounds of this line segment.
1080         *
1081         * @return the bounding box
1082         */
1083        public Rectangle2D getBounds2D()
1084        {
1085          float x = Math.min(x1, x2);
1086          float y = Math.min(y1, y2);
1087          float w = Math.abs(x1 - x2);
1088          float h = Math.abs(y1 - y2);
1089          return new Rectangle2D.Float(x, y, w, h);
1090      }      }
1091      } // class Float
1092      public int currentSegment (float[] coords)  } // class Line2D
     {  
       int r = SEG_MOVETO;  
       if (coord == 0)  
         {  
           coords[0] = (float) getX1 ();  
           coords[1] = (float) getY1 ();  
         }  
       else if (coord == 1)  
         {  
           coords[0] = (float) getX2 ();  
           coords[1] = (float) getY2 ();  
         }  
       else  
         r = SEG_CLOSE;  
   
       return r;  
     }  
   
     public int getWindingRule ()  
     {  
       return WIND_NON_ZERO;  
     }  
   
     public boolean isDone ()  
     {  
       return coord == END_PLUS_ONE;  
     }  
   
     public void next ()  
     {  
       if (coord < END_PLUS_ONE)  
         ++coord;  
     }  
   }  
 }  

Legend:
Removed from v.1.2  
changed lines
  Added in v.1.3

savannah-hackers-public@gnu.org
ViewVC Help
Powered by ViewVC 1.1.26