001    /* Line2D.java -- represents a line in 2-D space, plus operations on a line
002       Copyright (C) 2000, 2001, 2002 Free Software Foundation
003    
004    This file is part of GNU Classpath.
005    
006    GNU Classpath is free software; you can redistribute it and/or modify
007    it under the terms of the GNU General Public License as published by
008    the Free Software Foundation; either version 2, or (at your option)
009    any later version.
010    
011    GNU Classpath is distributed in the hope that it will be useful, but
012    WITHOUT ANY WARRANTY; without even the implied warranty of
013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014    General Public License for more details.
015    
016    You should have received a copy of the GNU General Public License
017    along with GNU Classpath; see the file COPYING.  If not, write to the
018    Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
019    02110-1301 USA.
020    
021    Linking this library statically or dynamically with other modules is
022    making a combined work based on this library.  Thus, the terms and
023    conditions of the GNU General Public License cover the whole
024    combination.
025    
026    As a special exception, the copyright holders of this library give you
027    permission to link this library with independent modules to produce an
028    executable, regardless of the license terms of these independent
029    modules, and to copy and distribute the resulting executable under
030    terms of your choice, provided that you also meet, for each linked
031    independent module, the terms and conditions of the license of that
032    module.  An independent module is a module which is not derived from
033    or based on this library.  If you modify this library, you may extend
034    this exception to your version of the library, but you are not
035    obligated to do so.  If you do not wish to do so, delete this
036    exception statement from your version. */
037    
038    package java.awt.geom;
039    
040    import java.awt.Rectangle;
041    import java.awt.Shape;
042    import java.util.NoSuchElementException;
043    
044    /**
045     * Represents a directed line bewteen two points in (x,y) Cartesian space.
046     * Remember, on-screen graphics have increasing x from left-to-right, and
047     * increasing y from top-to-bottom. The storage is left to subclasses.
048     *
049     * @author Tom Tromey (tromey@cygnus.com)
050     * @author Eric Blake (ebb9@email.byu.edu)
051     * @author David Gilbert
052     * @since 1.2
053     * @status updated to 1.4
054     */
055    public abstract class Line2D implements Shape, Cloneable
056    {
057      /**
058       * The default constructor.
059       */
060      protected Line2D()
061      {
062      }
063    
064      /**
065       * Return the x coordinate of the first point.
066       *
067       * @return the starting x coordinate
068       */
069      public abstract double getX1();
070    
071      /**
072       * Return the y coordinate of the first point.
073       *
074       * @return the starting y coordinate
075       */
076      public abstract double getY1();
077    
078      /**
079       * Return the first point.
080       *
081       * @return the starting point
082       */
083      public abstract Point2D getP1();
084    
085      /**
086       * Return the x coordinate of the second point.
087       *
088       * @return the ending x coordinate
089       */
090      public abstract double getX2();
091    
092      /**
093       * Return the y coordinate of the second point.
094       *
095       * @return the ending y coordinate
096       */
097      public abstract double getY2();
098    
099      /**
100       * Return the second point.
101       *
102       * @return the ending point
103       */
104      public abstract Point2D getP2();
105    
106      /**
107       * Set the coordinates of the line to the given coordinates. Loss of
108       * precision may occur due to rounding issues.
109       *
110       * @param x1 the first x coordinate
111       * @param y1 the first y coordinate
112       * @param x2 the second x coordinate
113       * @param y2 the second y coordinate
114       */
115      public abstract void setLine(double x1, double y1, double x2, double y2);
116    
117      /**
118       * Set the coordinates to the given points.
119       *
120       * @param p1 the first point
121       * @param p2 the second point
122       * @throws NullPointerException if either point is null
123       */
124      public void setLine(Point2D p1, Point2D p2)
125      {
126        setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
127      }
128    
129      /**
130       * Set the coordinates to those of the given line.
131       *
132       * @param l the line to copy
133       * @throws NullPointerException if l is null
134       */
135      public void setLine(Line2D l)
136      {
137        setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
138      }
139    
140      /**
141       * Computes the relative rotation direction needed to pivot the line about
142       * the first point in order to have the second point colinear with point p.
143       * Because of floating point rounding, don't expect this to be a perfect
144       * measure of colinearity. The answer is 1 if the line has a shorter rotation
145       * in the direction of the positive X axis to the negative Y axis
146       * (counter-clockwise in the default Java coordinate system), or -1 if the
147       * shortest rotation is in the opposite direction (clockwise). If p
148       * is already colinear, the return value is -1 if it lies beyond the first
149       * point, 0 if it lies in the segment, or 1 if it lies beyond the second
150       * point. If the first and second point are coincident, this returns 0.
151       *
152       * @param x1 the first x coordinate
153       * @param y1 the first y coordinate
154       * @param x2 the second x coordinate
155       * @param y2 the second y coordinate
156       * @param px the reference x coordinate
157       * @param py the reference y coordinate
158       * @return the relative rotation direction
159       */
160      public static int relativeCCW(double x1, double y1, double x2, double y2,
161                                    double px, double py)
162      {
163        if ((x1 == x2 && y1 == y2)
164            || (x1 == px && y1 == py))
165          return 0; // Coincident points.
166        // Translate to the origin.
167        x2 -= x1;
168        y2 -= y1;
169        px -= x1;
170        py -= y1;
171        double slope2 = y2 / x2;
172        double slopep = py / px;
173        if (slope2 == slopep || (x2 == 0 && px == 0))
174          return y2 > 0 // Colinear.
175            ? (py < 0 ? -1 : py > y2 ? 1 : 0)
176            : (py > 0 ? -1 : py < y2 ? 1 : 0);
177        if (x2 >= 0 && slope2 >= 0)
178          return px >= 0 // Quadrant 1.
179            ? (slope2 > slopep ? 1 : -1)
180            : (slope2 < slopep ? 1 : -1);
181        if (y2 > 0)
182          return px < 0 // Quadrant 2.
183            ? (slope2 > slopep ? 1 : -1)
184            : (slope2 < slopep ? 1 : -1);
185        if (slope2 >= 0.0)
186          return px >= 0 // Quadrant 3.
187            ? (slope2 < slopep ? 1 : -1)
188            : (slope2 > slopep ? 1 : -1);
189        return px < 0 // Quadrant 4.
190          ? (slope2 < slopep ? 1 : -1)
191          : (slope2 > slopep ? 1 : -1);
192      }
193    
194      /**
195       * Computes the relative rotation direction needed to pivot this line about
196       * the first point in order to have the second point colinear with point p.
197       * Because of floating point rounding, don't expect this to be a perfect
198       * measure of colinearity. The answer is 1 if the line has a shorter rotation
199       * in the direction of the positive X axis to the negative Y axis
200       * (counter-clockwise in the default Java coordinate system), or -1 if the
201       * shortest rotation is in the opposite direction (clockwise). If p
202       * is already colinear, the return value is -1 if it lies beyond the first
203       * point, 0 if it lies in the segment, or 1 if it lies beyond the second
204       * point. If the first and second point are coincident, this returns 0.
205       *
206       * @param px the reference x coordinate
207       * @param py the reference y coordinate
208       * @return the relative rotation direction
209       * @see #relativeCCW(double, double, double, double, double, double)
210       */
211      public int relativeCCW(double px, double py)
212      {
213        return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py);
214      }
215    
216      /**
217       * Computes the relative rotation direction needed to pivot this line about
218       * the first point in order to have the second point colinear with point p.
219       * Because of floating point rounding, don't expect this to be a perfect
220       * measure of colinearity. The answer is 1 if the line has a shorter rotation
221       * in the direction of the positive X axis to the negative Y axis
222       * (counter-clockwise in the default Java coordinate system), or -1 if the
223       * shortest rotation is in the opposite direction (clockwise). If p
224       * is already colinear, the return value is -1 if it lies beyond the first
225       * point, 0 if it lies in the segment, or 1 if it lies beyond the second
226       * point. If the first and second point are coincident, this returns 0.
227       *
228       * @param p the reference point
229       * @return the relative rotation direction
230       * @throws NullPointerException if p is null
231       * @see #relativeCCW(double, double, double, double, double, double)
232       */
233      public int relativeCCW(Point2D p)
234      {
235        return relativeCCW(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
236      }
237    
238      /**
239       * Computes twice the (signed) area of the triangle defined by the three
240       * points.  This method is used for intersection testing.
241       * 
242       * @param x1  the x-coordinate of the first point.
243       * @param y1  the y-coordinate of the first point.
244       * @param x2  the x-coordinate of the second point.
245       * @param y2  the y-coordinate of the second point.
246       * @param x3  the x-coordinate of the third point.
247       * @param y3  the y-coordinate of the third point.
248       * 
249       * @return Twice the area.
250       */
251      private static double area2(double x1, double y1,
252                                 double x2, double y2,
253                                 double x3, double y3) 
254      {
255        return (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1);    
256      }
257    
258      /**
259       * Returns <code>true</code> if (x3, y3) lies between (x1, y1) and (x2, y2),
260       * and false otherwise,  This test assumes that the three points are 
261       * collinear, and is used for intersection testing.
262       * 
263       * @param x1  the x-coordinate of the first point.
264       * @param y1  the y-coordinate of the first point.
265       * @param x2  the x-coordinate of the second point.
266       * @param y2  the y-coordinate of the second point.
267       * @param x3  the x-coordinate of the third point.
268       * @param y3  the y-coordinate of the third point.
269       * 
270       * @return A boolean.
271       */
272      private static boolean between(double x1, double y1, 
273                                    double x2, double y2, 
274                                    double x3, double y3) 
275      {
276        if (x1 != x2) {
277          return (x1 <= x3 && x3 <= x2) || (x1 >= x3 && x3 >= x2);   
278        }
279        else {
280          return (y1 <= y3 && y3 <= y2) || (y1 >= y3 && y3 >= y2);   
281        }
282      }
283    
284      /**
285       * Test if the line segment (x1,y1)-&gt;(x2,y2) intersects the line segment 
286       * (x3,y3)-&gt;(x4,y4).
287       *
288       * @param x1 the first x coordinate of the first segment
289       * @param y1 the first y coordinate of the first segment 
290       * @param x2 the second x coordinate of the first segment
291       * @param y2 the second y coordinate of the first segment
292       * @param x3 the first x coordinate of the second segment
293       * @param y3 the first y coordinate of the second segment
294       * @param x4 the second x coordinate of the second segment
295       * @param y4 the second y coordinate of the second segment
296       * @return true if the segments intersect
297       */
298      public static boolean linesIntersect(double x1, double y1,
299                                          double x2, double y2,
300                                          double x3, double y3,
301                                          double x4, double y4)
302      {
303        double a1, a2, a3, a4;
304      
305        // deal with special cases
306        if ((a1 = area2(x1, y1, x2, y2, x3, y3)) == 0.0) 
307        {
308          // check if p3 is between p1 and p2 OR
309          // p4 is collinear also AND either between p1 and p2 OR at opposite ends
310          if (between(x1, y1, x2, y2, x3, y3)) 
311          {
312            return true;
313          }
314          else 
315          {
316            if (area2(x1, y1, x2, y2, x4, y4) == 0.0) 
317            {
318              return between(x3, y3, x4, y4, x1, y1) 
319                     || between (x3, y3, x4, y4, x2, y2);
320            }
321            else {
322              return false;
323            }
324          }
325        }
326        else if ((a2 = area2(x1, y1, x2, y2, x4, y4)) == 0.0) 
327        {
328          // check if p4 is between p1 and p2 (we already know p3 is not
329          // collinear)
330          return between(x1, y1, x2, y2, x4, y4);
331        }
332      
333        if ((a3 = area2(x3, y3, x4, y4, x1, y1)) == 0.0) {
334          // check if p1 is between p3 and p4 OR
335          // p2 is collinear also AND either between p1 and p2 OR at opposite ends
336          if (between(x3, y3, x4, y4, x1, y1)) {
337            return true;
338          }
339          else {
340            if (area2(x3, y3, x4, y4, x2, y2) == 0.0) {
341              return between(x1, y1, x2, y2, x3, y3) 
342                     || between (x1, y1, x2, y2, x4, y4);
343            }
344            else {
345              return false;
346            }
347          }
348        }
349        else if ((a4 = area2(x3, y3, x4, y4, x2, y2)) == 0.0) {
350          // check if p2 is between p3 and p4 (we already know p1 is not
351          // collinear)
352          return between(x3, y3, x4, y4, x2, y2);
353        }
354        else {  // test for regular intersection
355          return ((a1 > 0.0) ^ (a2 > 0.0)) && ((a3 > 0.0) ^ (a4 > 0.0));
356        } 
357      }
358    
359      /**
360       * Test if this line intersects the line given by (x1,y1)-&gt;(x2,y2).
361       *
362       * @param x1 the first x coordinate of the other segment
363       * @param y1 the first y coordinate of the other segment
364       * @param x2 the second x coordinate of the other segment
365       * @param y2 the second y coordinate of the other segment
366       * @return true if the segments intersect
367       * @see #linesIntersect(double, double, double, double,
368       *                      double, double, double, double)
369       */
370      public boolean intersectsLine(double x1, double y1, double x2, double y2)
371      {
372        return linesIntersect(getX1(), getY1(), getX2(), getY2(),
373                              x1, y1, x2, y2);
374      }
375    
376      /**
377       * Test if this line intersects the given line.
378       *
379       * @param l the other segment
380       * @return true if the segments intersect
381       * @throws NullPointerException if l is null
382       * @see #linesIntersect(double, double, double, double,
383       *                      double, double, double, double)
384       */
385      public boolean intersectsLine(Line2D l)
386      {
387        return linesIntersect(getX1(), getY1(), getX2(), getY2(),
388                              l.getX1(), l.getY1(), l.getX2(), l.getY2());
389      }
390    
391      /**
392       * Measures the square of the shortest distance from the reference point
393       * to a point on the line segment. If the point is on the segment, the
394       * result will be 0.
395       *
396       * @param x1 the first x coordinate of the segment
397       * @param y1 the first y coordinate of the segment
398       * @param x2 the second x coordinate of the segment
399       * @param y2 the second y coordinate of the segment
400       * @param px the x coordinate of the point
401       * @param py the y coordinate of the point
402       * @return the square of the distance from the point to the segment
403       * @see #ptSegDist(double, double, double, double, double, double)
404       * @see #ptLineDistSq(double, double, double, double, double, double)
405       */
406      public static double ptSegDistSq(double x1, double y1, double x2, double y2,
407                                       double px, double py)
408      {
409        double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
410    
411        double x, y;
412        if (pd2 == 0)
413          {
414            // Points are coincident.
415            x = x1;
416            y = y2;
417          }
418        else
419          {
420            double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
421    
422            if (u < 0)
423              {
424                // "Off the end"
425                x = x1;
426                y = y1;
427              }
428            else if (u > 1.0)
429              {
430                x = x2;
431                y = y2;
432              }
433            else
434              {
435                x = x1 + u * (x2 - x1);
436                y = y1 + u * (y2 - y1);
437              }
438          }
439    
440        return (x - px) * (x - px) + (y - py) * (y - py);
441      }
442    
443      /**
444       * Measures the shortest distance from the reference point to a point on
445       * the line segment. If the point is on the segment, the result will be 0.
446       *
447       * @param x1 the first x coordinate of the segment
448       * @param y1 the first y coordinate of the segment
449       * @param x2 the second x coordinate of the segment
450       * @param y2 the second y coordinate of the segment
451       * @param px the x coordinate of the point
452       * @param py the y coordinate of the point
453       * @return the distance from the point to the segment
454       * @see #ptSegDistSq(double, double, double, double, double, double)
455       * @see #ptLineDist(double, double, double, double, double, double)
456       */
457      public static double ptSegDist(double x1, double y1, double x2, double y2,
458                                     double px, double py)
459      {
460        return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py));
461      }
462    
463      /**
464       * Measures the square of the shortest distance from the reference point
465       * to a point on this line segment. If the point is on the segment, the
466       * result will be 0.
467       *
468       * @param px the x coordinate of the point
469       * @param py the y coordinate of the point
470       * @return the square of the distance from the point to the segment
471       * @see #ptSegDistSq(double, double, double, double, double, double)
472       */
473      public double ptSegDistSq(double px, double py)
474      {
475        return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
476      }
477    
478      /**
479       * Measures the square of the shortest distance from the reference point
480       * to a point on this line segment. If the point is on the segment, the
481       * result will be 0.
482       *
483       * @param p the point
484       * @return the square of the distance from the point to the segment
485       * @throws NullPointerException if p is null
486       * @see #ptSegDistSq(double, double, double, double, double, double)
487       */
488      public double ptSegDistSq(Point2D p)
489      {
490        return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
491      }
492    
493      /**
494       * Measures the shortest distance from the reference point to a point on
495       * this line segment. If the point is on the segment, the result will be 0.
496       *
497       * @param px the x coordinate of the point
498       * @param py the y coordinate of the point
499       * @return the distance from the point to the segment
500       * @see #ptSegDist(double, double, double, double, double, double)
501       */
502      public double ptSegDist(double px, double py)
503      {
504        return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py);
505      }
506    
507      /**
508       * Measures the shortest distance from the reference point to a point on
509       * this line segment. If the point is on the segment, the result will be 0.
510       *
511       * @param p the point
512       * @return the distance from the point to the segment
513       * @throws NullPointerException if p is null
514       * @see #ptSegDist(double, double, double, double, double, double)
515       */
516      public double ptSegDist(Point2D p)
517      {
518        return ptSegDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
519      }
520    
521      /**
522       * Measures the square of the shortest distance from the reference point
523       * to a point on the infinite line extended from the segment. If the point
524       * is on the segment, the result will be 0. If the segment is length 0,
525       * the distance is to the common endpoint.
526       *
527       * @param x1 the first x coordinate of the segment
528       * @param y1 the first y coordinate of the segment
529       * @param x2 the second x coordinate of the segment
530       * @param y2 the second y coordinate of the segment
531       * @param px the x coordinate of the point
532       * @param py the y coordinate of the point
533       * @return the square of the distance from the point to the extended line
534       * @see #ptLineDist(double, double, double, double, double, double)
535       * @see #ptSegDistSq(double, double, double, double, double, double)
536       */
537      public static double ptLineDistSq(double x1, double y1, double x2, double y2,
538                                        double px, double py)
539      {
540        double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
541    
542        double x, y;
543        if (pd2 == 0)
544          {
545            // Points are coincident.
546            x = x1;
547            y = y2;
548          }
549        else
550          {
551            double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
552            x = x1 + u * (x2 - x1);
553            y = y1 + u * (y2 - y1);
554          }
555    
556        return (x - px) * (x - px) + (y - py) * (y - py);
557      }
558    
559      /**
560       * Measures the shortest distance from the reference point to a point on
561       * the infinite line extended from the segment. If the point is on the
562       * segment, the result will be 0. If the segment is length 0, the distance
563       * is to the common endpoint.
564       *
565       * @param x1 the first x coordinate of the segment
566       * @param y1 the first y coordinate of the segment
567       * @param x2 the second x coordinate of the segment
568       * @param y2 the second y coordinate of the segment
569       * @param px the x coordinate of the point
570       * @param py the y coordinate of the point
571       * @return the distance from the point to the extended line
572       * @see #ptLineDistSq(double, double, double, double, double, double)
573       * @see #ptSegDist(double, double, double, double, double, double)
574       */
575      public static double ptLineDist(double x1, double y1,
576                                       double x2, double y2,
577                                       double px, double py)
578      {
579        return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py));
580      }
581    
582      /**
583       * Measures the square of the shortest distance from the reference point
584       * to a point on the infinite line extended from this segment. If the point
585       * is on the segment, the result will be 0. If the segment is length 0,
586       * the distance is to the common endpoint.
587       *
588       * @param px the x coordinate of the point
589       * @param py the y coordinate of the point
590       * @return the square of the distance from the point to the extended line
591       * @see #ptLineDistSq(double, double, double, double, double, double)
592       */
593      public double ptLineDistSq(double px, double py)
594      {
595        return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
596      }
597    
598      /**
599       * Measures the square of the shortest distance from the reference point
600       * to a point on the infinite line extended from this segment. If the point
601       * is on the segment, the result will be 0. If the segment is length 0,
602       * the distance is to the common endpoint.
603       *
604       * @param p the point
605       * @return the square of the distance from the point to the extended line
606       * @throws NullPointerException if p is null
607       * @see #ptLineDistSq(double, double, double, double, double, double)
608       */
609      public double ptLineDistSq(Point2D p)
610      {
611        return ptLineDistSq(getX1(), getY1(), getX2(), getY2(),
612                            p.getX(), p.getY());
613      }
614    
615      /**
616       * Measures the shortest distance from the reference point to a point on
617       * the infinite line extended from this segment. If the point is on the
618       * segment, the result will be 0. If the segment is length 0, the distance
619       * is to the common endpoint.
620       *
621       * @param px the x coordinate of the point
622       * @param py the y coordinate of the point
623       * @return the distance from the point to the extended line
624       * @see #ptLineDist(double, double, double, double, double, double)
625       */
626      public double ptLineDist(double px, double py)
627      {
628        return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py);
629      }
630    
631      /**
632       * Measures the shortest distance from the reference point to a point on
633       * the infinite line extended from this segment. If the point is on the
634       * segment, the result will be 0. If the segment is length 0, the distance
635       * is to the common endpoint.
636       *
637       * @param p the point
638       * @return the distance from the point to the extended line
639       * @throws NullPointerException if p is null
640       * @see #ptLineDist(double, double, double, double, double, double)
641       */
642      public double ptLineDist(Point2D p)
643      {
644        return ptLineDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
645      }
646    
647      /**
648       * Test if a point is contained inside the line. Since a line has no area,
649       * this returns false.
650       *
651       * @param x the x coordinate
652       * @param y the y coordinate
653       * @return false; the line does not contain points
654       */
655      public boolean contains(double x, double y)
656      {
657        return false;
658      }
659    
660      /**
661       * Test if a point is contained inside the line. Since a line has no area,
662       * this returns false.
663       *
664       * @param p the point
665       * @return false; the line does not contain points
666       */
667      public boolean contains(Point2D p)
668      {
669        return false;
670      }
671    
672      /**
673       * Tests if this line intersects the interior of the specified rectangle.
674       *
675       * @param x the x coordinate of the rectangle
676       * @param y the y coordinate of the rectangle
677       * @param w the width of the rectangle
678       * @param h the height of the rectangle
679       * @return true if the line intersects the rectangle
680       */
681      public boolean intersects(double x, double y, double w, double h)
682      {
683        if (w <= 0 || h <= 0)
684          return false;
685        double x1 = getX1();
686        double y1 = getY1();
687        double x2 = getX2();
688        double y2 = getY2();
689    
690        if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
691          return true;
692        if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
693          return true;
694    
695        double x3 = x + w;
696        double y3 = y + h;
697    
698        return (linesIntersect(x1, y1, x2, y2, x, y, x, y3)
699                || linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
700                || linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
701                || linesIntersect(x1, y1, x2, y2, x3, y, x, y));
702      }
703    
704      /**
705       * Tests if this line intersects the interior of the specified rectangle.
706       *
707       * @param r the rectangle
708       * @return true if the line intersects the rectangle
709       * @throws NullPointerException if r is null
710       */
711      public boolean intersects(Rectangle2D r)
712      {
713        return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
714      }
715    
716      /**
717       * Tests if the line contains a rectangle. Since lines have no area, this
718       * always returns false.
719       *
720       * @param x the x coordinate of the rectangle
721       * @param y the y coordinate of the rectangle
722       * @param w the width of the rectangle
723       * @param h the height of the rectangle
724       * @return false; the line does not contain points
725       */
726      public boolean contains(double x, double y, double w, double h)
727      {
728        return false;
729      }
730    
731      /**
732       * Tests if the line contains a rectangle. Since lines have no area, this
733       * always returns false.
734       *
735       * @param r the rectangle
736       * @return false; the line does not contain points
737       */
738      public boolean contains(Rectangle2D r)
739      {
740        return false;
741      }
742    
743      /**
744       * Gets a bounding box (not necessarily minimal) for this line.
745       *
746       * @return the integer bounding box
747       * @see #getBounds2D()
748       */
749      public Rectangle getBounds()
750      {
751        return getBounds2D().getBounds();
752      }
753    
754      /**
755       * Return a path iterator, possibly applying a transform on the result. This
756       * iterator is not threadsafe.
757       *
758       * @param at the transform, or null
759       * @return a new path iterator
760       */
761      public PathIterator getPathIterator(final AffineTransform at)
762      {
763        return new PathIterator()
764        {
765          /** Current coordinate. */
766          private int current = 0;
767    
768          public int getWindingRule()
769          {
770            return WIND_NON_ZERO;
771          }
772    
773          public boolean isDone()
774          {
775            return current >= 2;
776          }
777    
778          public void next()
779          {
780            current++;
781          }
782    
783          public int currentSegment(float[] coords)
784          {
785            int result;
786            switch (current)
787              {
788              case 0:
789                coords[0] = (float) getX1();
790                coords[1] = (float) getY1();
791                result = SEG_MOVETO;
792                break;
793              case 1:
794                coords[0] = (float) getX2();
795                coords[1] = (float) getY2();
796                result = SEG_LINETO;
797                break;
798              default:
799                throw new NoSuchElementException("line iterator out of bounds");
800              }
801            if (at != null)
802              at.transform(coords, 0, coords, 0, 1);
803            return result;
804          }
805    
806          public int currentSegment(double[] coords)
807          {
808            int result;
809            switch (current)
810              {
811              case 0:
812                coords[0] = getX1();
813                coords[1] = getY1();
814                result = SEG_MOVETO;
815                break;
816              case 1:
817                coords[0] = getX2();
818                coords[1] = getY2();
819                result = SEG_LINETO;
820                break;
821              default:
822                throw new NoSuchElementException("line iterator out of bounds");
823              }
824            if (at != null)
825              at.transform(coords, 0, coords, 0, 1);
826            return result;
827          }
828        };
829      }
830    
831      /**
832       * Return a flat path iterator, possibly applying a transform on the result.
833       * This iterator is not threadsafe.
834       *
835       * @param at the transform, or null
836       * @param flatness ignored, since lines are already flat
837       * @return a new path iterator
838       * @see #getPathIterator(AffineTransform)
839       */
840      public PathIterator getPathIterator(AffineTransform at, double flatness)
841      {
842        return getPathIterator(at);
843      }
844    
845      /**
846       * Create a new line of the same run-time type with the same contents as
847       * this one.
848       *
849       * @return the clone
850       *
851       * @exception OutOfMemoryError If there is not enough memory available.
852       *
853       * @since 1.2
854       */
855      public Object clone()
856      {
857        try
858          {
859            return super.clone();
860          }
861        catch (CloneNotSupportedException e)
862          {
863            throw (Error) new InternalError().initCause(e); // Impossible
864          }
865      }
866    
867      /**
868       * This class defines a point in <code>double</code> precision.
869       *
870       * @author Eric Blake (ebb9@email.byu.edu)
871       * @since 1.2
872       * @status updated to 1.4
873       */
874      public static class Double extends Line2D
875      {
876        /** The x coordinate of the first point. */
877        public double x1;
878    
879        /** The y coordinate of the first point. */
880        public double y1;
881    
882        /** The x coordinate of the second point. */
883        public double x2;
884    
885        /** The y coordinate of the second point. */
886        public double y2;
887    
888        /**
889         * Construct the line segment (0,0)-&gt;(0,0).
890         */
891        public Double()
892        {
893        }
894    
895        /**
896         * Construct the line segment with the specified points.
897         *
898         * @param x1 the x coordinate of the first point
899         * @param y1 the y coordinate of the first point
900         * @param x2 the x coordinate of the second point
901         * @param y2 the y coordinate of the second point
902         */
903        public Double(double x1, double y1, double x2, double y2)
904        {
905          this.x1 = x1;
906          this.y1 = y1;
907          this.x2 = x2;
908          this.y2 = y2;
909        }
910    
911        /**
912         * Construct the line segment with the specified points.
913         *
914         * @param p1 the first point
915         * @param p2 the second point
916         * @throws NullPointerException if either point is null
917         */
918        public Double(Point2D p1, Point2D p2)
919        {
920          x1 = p1.getX();
921          y1 = p1.getY();
922          x2 = p2.getX();
923          y2 = p2.getY();
924        }
925    
926        /**
927         * Return the x coordinate of the first point.
928         *
929         * @return the value of x1
930         */
931        public double getX1()
932        {
933          return x1;
934        }
935    
936        /**
937         * Return the y coordinate of the first point.
938         *
939         * @return the value of y1
940         */
941        public double getY1()
942        {
943          return y1;
944        }
945    
946        /**
947         * Return the first point.
948         *
949         * @return the point (x1,y1)
950         */
951        public Point2D getP1()
952        {
953          return new Point2D.Double(x1, y1);
954        }
955    
956        /**
957         * Return the x coordinate of the second point.
958         *
959         * @return the value of x2
960         */
961        public double getX2()
962        {
963          return x2;
964        }
965    
966        /**
967         * Return the y coordinate of the second point.
968         *
969         * @return the value of y2
970         */
971        public double getY2()
972        {
973          return y2;
974        }
975    
976        /**
977         * Return the second point.
978         *
979         * @return the point (x2,y2)
980         */
981        public Point2D getP2()
982        {
983          return new Point2D.Double(x2, y2);
984        }
985    
986        /**
987         * Set this line to the given points.
988         *
989         * @param x1 the new x coordinate of the first point
990         * @param y1 the new y coordinate of the first point
991         * @param x2 the new x coordinate of the second point
992         * @param y2 the new y coordinate of the second point
993         */
994        public void setLine(double x1, double y1, double x2, double y2)
995        {
996          this.x1 = x1;
997          this.y1 = y1;
998          this.x2 = x2;
999          this.y2 = y2;
1000        }
1001    
1002        /**
1003         * Return the exact bounds of this line segment.
1004         *
1005         * @return the bounding box
1006         */
1007        public Rectangle2D getBounds2D()
1008        {
1009          double x = Math.min(x1, x2);
1010          double y = Math.min(y1, y2);
1011          double w = Math.abs(x1 - x2);
1012          double h = Math.abs(y1 - y2);
1013          return new Rectangle2D.Double(x, y, w, h);
1014        }
1015      } // class Double
1016    
1017      /**
1018       * This class defines a point in <code>float</code> precision.
1019       *
1020       * @author Eric Blake (ebb9@email.byu.edu)
1021       * @since 1.2
1022       * @status updated to 1.4
1023       */
1024      public static class Float extends Line2D
1025      {
1026        /** The x coordinate of the first point. */
1027        public float x1;
1028    
1029        /** The y coordinate of the first point. */
1030        public float y1;
1031    
1032        /** The x coordinate of the second point. */
1033        public float x2;
1034    
1035        /** The y coordinate of the second point. */
1036        public float y2;
1037    
1038        /**
1039         * Construct the line segment (0,0)-&gt;(0,0).
1040         */
1041        public Float()
1042        {
1043        }
1044    
1045        /**
1046         * Construct the line segment with the specified points.
1047         *
1048         * @param x1 the x coordinate of the first point
1049         * @param y1 the y coordinate of the first point
1050         * @param x2 the x coordinate of the second point
1051         * @param y2 the y coordinate of the second point
1052         */
1053        public Float(float x1, float y1, float x2, float y2)
1054        {
1055          this.x1 = x1;
1056          this.y1 = y1;
1057          this.x2 = x2;
1058          this.y2 = y2;
1059        }
1060    
1061        /**
1062         * Construct the line segment with the specified points.
1063         *
1064         * @param p1 the first point
1065         * @param p2 the second point
1066         * @throws NullPointerException if either point is null
1067         */
1068        public Float(Point2D p1, Point2D p2)
1069        {
1070          x1 = (float) p1.getX();
1071          y1 = (float) p1.getY();
1072          x2 = (float) p2.getX();
1073          y2 = (float) p2.getY();
1074        }
1075    
1076        /**
1077         * Return the x coordinate of the first point.
1078         *
1079         * @return the value of x1
1080         */
1081        public double getX1()
1082        {
1083          return x1;
1084        }
1085    
1086        /**
1087         * Return the y coordinate of the first point.
1088         *
1089         * @return the value of y1
1090         */
1091        public double getY1()
1092        {
1093          return y1;
1094        }
1095    
1096        /**
1097         * Return the first point.
1098         *
1099         * @return the point (x1,y1)
1100         */
1101        public Point2D getP1()
1102        {
1103          return new Point2D.Float(x1, y1);
1104        }
1105    
1106        /**
1107         * Return the x coordinate of the second point.
1108         *
1109         * @return the value of x2
1110         */
1111        public double getX2()
1112        {
1113          return x2;
1114        }
1115    
1116        /**
1117         * Return the y coordinate of the second point.
1118         *
1119         * @return the value of y2
1120         */
1121        public double getY2()
1122        {
1123          return y2;
1124        }
1125    
1126        /**
1127         * Return the second point.
1128         *
1129         * @return the point (x2,y2)
1130         */
1131        public Point2D getP2()
1132        {
1133          return new Point2D.Float(x2, y2);
1134        }
1135    
1136        /**
1137         * Set this line to the given points.
1138         *
1139         * @param x1 the new x coordinate of the first point
1140         * @param y1 the new y coordinate of the first point
1141         * @param x2 the new x coordinate of the second point
1142         * @param y2 the new y coordinate of the second point
1143         */
1144        public void setLine(double x1, double y1, double x2, double y2)
1145        {
1146          this.x1 = (float) x1;
1147          this.y1 = (float) y1;
1148          this.x2 = (float) x2;
1149          this.y2 = (float) y2;
1150        }
1151    
1152        /**
1153         * Set this line to the given points.
1154         *
1155         * @param x1 the new x coordinate of the first point
1156         * @param y1 the new y coordinate of the first point
1157         * @param x2 the new x coordinate of the second point
1158         * @param y2 the new y coordinate of the second point
1159         */
1160        public void setLine(float x1, float y1, float x2, float y2)
1161        {
1162          this.x1 = x1;
1163          this.y1 = y1;
1164          this.x2 = x2;
1165          this.y2 = y2;
1166        }
1167    
1168        /**
1169         * Return the exact bounds of this line segment.
1170         *
1171         * @return the bounding box
1172         */
1173        public Rectangle2D getBounds2D()
1174        {
1175          float x = Math.min(x1, x2);
1176          float y = Math.min(y1, y2);
1177          float w = Math.abs(x1 - x2);
1178          float h = Math.abs(y1 - y2);
1179          return new Rectangle2D.Float(x, y, w, h);
1180        }
1181      } // class Float
1182    } // class Line2D