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
004This file is part of GNU Classpath.
005
006GNU Classpath is free software; you can redistribute it and/or modify
007it under the terms of the GNU General Public License as published by
008the Free Software Foundation; either version 2, or (at your option)
009any later version.
010
011GNU Classpath is distributed in the hope that it will be useful, but
012WITHOUT ANY WARRANTY; without even the implied warranty of
013MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014General Public License for more details.
015
016You should have received a copy of the GNU General Public License
017along with GNU Classpath; see the file COPYING.  If not, write to the
018Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
01902110-1301 USA.
020
021Linking this library statically or dynamically with other modules is
022making a combined work based on this library.  Thus, the terms and
023conditions of the GNU General Public License cover the whole
024combination.
025
026As a special exception, the copyright holders of this library give you
027permission to link this library with independent modules to produce an
028executable, regardless of the license terms of these independent
029modules, and to copy and distribute the resulting executable under
030terms of your choice, provided that you also meet, for each linked
031independent module, the terms and conditions of the license of that
032module.  An independent module is a module which is not derived from
033or based on this library.  If you modify this library, you may extend
034this exception to your version of the library, but you are not
035obligated to do so.  If you do not wish to do so, delete this
036exception statement from your version. */
037
038package java.awt.geom;
039
040import java.awt.Rectangle;
041import java.awt.Shape;
042import 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 */
055public 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