aboutsummaryrefslogtreecommitdiff
path: root/libjava/java/awt/geom/Line2D.java
diff options
context:
space:
mode:
authorBryce McKinlay <bryce@waitaki.otago.ac.nz>2002-08-09 04:26:17 +0000
committerBryce McKinlay <bryce@gcc.gnu.org>2002-08-09 05:26:17 +0100
commit7bde45b2eb84502b62e77e46d947e46dcbd333d6 (patch)
treecdf9958b411887bead2263ea8ef0bdfc8eae6319 /libjava/java/awt/geom/Line2D.java
parent097684ce62b505168739fc98e952f92a8719a1fa (diff)
downloadgcc-7bde45b2eb84502b62e77e46d947e46dcbd333d6.zip
gcc-7bde45b2eb84502b62e77e46d947e46dcbd333d6.tar.gz
gcc-7bde45b2eb84502b62e77e46d947e46dcbd333d6.tar.bz2
AWT/Swing merge from GNU Classpath.
From-SVN: r56147
Diffstat (limited to 'libjava/java/awt/geom/Line2D.java')
-rw-r--r--libjava/java/awt/geom/Line2D.java1190
1 files changed, 850 insertions, 340 deletions
diff --git a/libjava/java/awt/geom/Line2D.java b/libjava/java/awt/geom/Line2D.java
index 608b566..9e55110 100644
--- a/libjava/java/awt/geom/Line2D.java
+++ b/libjava/java/awt/geom/Line2D.java
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000, 2001, 2002 Free Software Foundation
+/* Line2D.java -- represents a line in 2-D space, plus operations on a line
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation
This file is part of GNU Classpath.
@@ -38,325 +39,769 @@ package java.awt.geom;
import java.awt.Rectangle;
import java.awt.Shape;
+import java.util.NoSuchElementException;
/**
+ * Represents a directed line bewteen two points in (x,y) Cartesian space.
+ * Remember, on-screen graphics have increasing x from left-to-right, and
+ * increasing y from top-to-bottom. The storage is left to subclasses.
+ *
* @author Tom Tromey <tromey@cygnus.com>
- * @date April 21, 2001
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @since 1.2
+ * @status updated to 1.4
*/
-
public abstract class Line2D implements Shape, Cloneable
{
- protected Line2D ()
+ /**
+ * The default constructor.
+ */
+ protected Line2D()
{
}
- public Object clone ()
+ /**
+ * Return the x coordinate of the first point.
+ *
+ * @return the starting x coordinate
+ */
+ public abstract double getX1();
+
+ /**
+ * Return the y coordinate of the first point.
+ *
+ * @return the starting y coordinate
+ */
+ public abstract double getY1();
+
+ /**
+ * Return the first point.
+ *
+ * @return the starting point
+ */
+ public abstract Point2D getP1();
+
+ /**
+ * Return the x coordinate of the second point.
+ *
+ * @return the ending x coordinate
+ */
+ public abstract double getX2();
+
+ /**
+ * Return the y coordinate of the second point.
+ *
+ * @return the ending y coordinate
+ */
+ public abstract double getY2();
+
+ /**
+ * Return the second point.
+ *
+ * @return the ending point
+ */
+ public abstract Point2D getP2();
+
+ /**
+ * Set the coordinates of the line to the given coordinates. Loss of
+ * precision may occur due to rounding issues.
+ *
+ * @param x1 the first x coordinate
+ * @param y1 the first y coordinate
+ * @param x2 the second x coordinate
+ * @param y2 the second y coordinate
+ */
+ public abstract void setLine(double x1, double y1, double x2, double y2);
+
+ /**
+ * Set the coordinates to the given points.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public void setLine(Point2D p1, Point2D p2)
{
- try
- {
- return super.clone ();
- }
- catch (CloneNotSupportedException _)
- {
- // Can't happen.
- return null;
- }
+ setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY());
}
- public boolean contains (double x, double y)
+ /**
+ * Set the coordinates to those of the given line.
+ *
+ * @param l the line to copy
+ * @throws NullPointerException if l is null
+ */
+ public void setLine(Line2D l)
{
- double x1 = getX1 ();
- double t1 = (x - x1) / (getX2 () - x1);
- if (t1 < 0 || t1 > 1)
- return false;
- double y1 = getY1 ();
- double t2 = (y - y1) / (getY2 () - y1);
- // FIXME: use of == here is bogus
- return t2 >= 0 && t2 <= 1 && t1 == t2;
+ setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
}
- public boolean contains (double x, double y, double w, double h)
+ /**
+ * Computes the relative rotation direction needed to pivot the line about
+ * the first point in order to have the second point colinear with point p.
+ * Because of floating point rounding, don't expect this to be a perfect
+ * measure of colinearity. The answer is 1 if the line has a shorter rotation
+ * in the direction of the positive X axis to the negative Y axis
+ * (counter-clockwise in the default Java coordinate system), or -1 if the
+ * shortest rotation is in the opposite direction (clockwise). If p
+ * is already colinear, the return value is -1 if it lies beyond the first
+ * point, 0 if it lies in the segment, or 1 if it lies beyond the second
+ * point. If the first and second point are coincident, this returns 0.
+ *
+ * @param x1 the first x coordinate
+ * @param y1 the first y coordinate
+ * @param x2 the second x coordinate
+ * @param y2 the second y coordinate
+ * @param px the reference x coordinate
+ * @param py the reference y coordinate
+ * @return the relative rotation direction
+ */
+ public static int relativeCCW(double x1, double y1, double x2, double y2,
+ double px, double py)
{
- return false;
+ if ((x1 == x2 && y1 == y2)
+ || (x1 == px && y1 == py))
+ return 0; // Coincident points.
+ // Translate to the origin.
+ x2 -= x1;
+ y2 -= y1;
+ px -= x1;
+ py -= y1;
+ double slope2 = y2 / x2;
+ double slopep = py / px;
+ if (slope2 == slopep || (x2 == 0 && px == 0))
+ return y2 > 0 // Colinear.
+ ? (py < 0 ? -1 : py > y2 ? 1 : 0)
+ : (py > 0 ? -1 : py < y2 ? 1 : 0);
+ if (x2 >= 0 && slope2 >= 0)
+ return px >= 0 // Quadrant 1.
+ ? (slope2 > slopep ? 1 : -1)
+ : (slope2 < slopep ? 1 : -1);
+ if (y2 > 0)
+ return px < 0 // Quadrant 2.
+ ? (slope2 > slopep ? 1 : -1)
+ : (slope2 < slopep ? 1 : -1);
+ if (slope2 >= 0.0)
+ return px >= 0 // Quadrant 3.
+ ? (slope2 < slopep ? 1 : -1)
+ : (slope2 > slopep ? 1 : -1);
+ return px < 0 // Quadrant 4.
+ ? (slope2 < slopep ? 1 : -1)
+ : (slope2 > slopep ? 1 : -1);
}
- public boolean contains (Point2D p)
+ /**
+ * Computes the relative rotation direction needed to pivot this line about
+ * the first point in order to have the second point colinear with point p.
+ * Because of floating point rounding, don't expect this to be a perfect
+ * measure of colinearity. The answer is 1 if the line has a shorter rotation
+ * in the direction of the positive X axis to the negative Y axis
+ * (counter-clockwise in the default Java coordinate system), or -1 if the
+ * shortest rotation is in the opposite direction (clockwise). If p
+ * is already colinear, the return value is -1 if it lies beyond the first
+ * point, 0 if it lies in the segment, or 1 if it lies beyond the second
+ * point. If the first and second point are coincident, this returns 0.
+ *
+ * @param px the reference x coordinate
+ * @param py the reference y coordinate
+ * @return the relative rotation direction
+ * @see #relativeCCW(double, double, double, double, double, double)
+ */
+ public int relativeCCW(double px, double py)
{
- return contains (p.getX (), p.getY ());
+ return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py);
}
- public boolean contains (Rectangle2D r)
+ /**
+ * Computes the relative rotation direction needed to pivot this line about
+ * the first point in order to have the second point colinear with point p.
+ * Because of floating point rounding, don't expect this to be a perfect
+ * measure of colinearity. The answer is 1 if the line has a shorter rotation
+ * in the direction of the positive X axis to the negative Y axis
+ * (counter-clockwise in the default Java coordinate system), or -1 if the
+ * shortest rotation is in the opposite direction (clockwise). If p
+ * is already colinear, the return value is -1 if it lies beyond the first
+ * point, 0 if it lies in the segment, or 1 if it lies beyond the second
+ * point. If the first and second point are coincident, this returns 0.
+ *
+ * @param p the reference point
+ * @return the relative rotation direction
+ * @throws NullPointerException if p is null
+ * @see #relativeCCW(double, double, double, double, double, double)
+ */
+ public int relativeCCW(Point2D p)
{
- return false;
+ return relativeCCW(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
}
- public Rectangle getBounds ()
+ /**
+ * Test if the line segment (x1,y1)-&gt;(x2,y2) intersects the line segment
+ * (x3,y3)-&gt;(x4,y4).
+ *
+ * @param x1 the first x coordinate of the first segment
+ * @param y1 the first y coordinate of the first segment
+ * @param x2 the second x coordinate of the first segment
+ * @param y2 the second y coordinate of the first segment
+ * @param x3 the first x coordinate of the second segment
+ * @param y3 the first y coordinate of the second segment
+ * @param x4 the second x coordinate of the second segment
+ * @param y4 the second y coordinate of the second segment
+ * @return true if the segments intersect
+ */
+ public static boolean linesIntersect(double x1, double y1,
+ double x2, double y2,
+ double x3, double y3,
+ double x4, double y4)
{
- double x1 = getX1 ();
- double y1 = getY1 ();
- double x2 = getX2 ();
- double y2 = getY2 ();
-
- double x = Math.min (x1, x2);
- double y = Math.min (y1, y2);
- double w = Math.abs (x1 - x2);
- double h = Math.abs (y1 - y2);
-
- return new Rectangle ((int) x, (int) y, (int) w, (int) h);
+ double beta = (((y1 - y3) * (x4 - x3) + (x1 - x3) * (y4 - y3))
+ / ((y2 - y1) * (x4 - x3) + (x2 - x1) * (y4 - y3)));
+ if (beta < 0.0 || beta > 1.0)
+ return false;
+ double alpha = (x1 + beta * (x2 - x1) - x3) / (x4 - x3);
+ return alpha >= 0.0 && alpha <= 1.0;
}
- public abstract Point2D getP1 ();
- public abstract Point2D getP2 ();
-
- public PathIterator getPathIterator (AffineTransform at)
+ /**
+ * Test if this line intersects the line given by (x1,y1)-&gt;(x2,y2).
+ *
+ * @param x1 the first x coordinate of the other segment
+ * @param y1 the first y coordinate of the other segment
+ * @param x2 the second x coordinate of the other segment
+ * @param y2 the second y coordinate of the other segment
+ * @return true if the segments intersect
+ * @see #linesIntersect(double, double, double, double,
+ * double, double, double, double)
+ */
+ public boolean intersectsLine(double x1, double y1, double x2, double y2)
{
- return getPathIterator (at, 0);
+ return linesIntersect(getX1(), getY1(), getX2(), getY2(),
+ x1, y1, x2, y2);
}
- public PathIterator getPathIterator (AffineTransform at, double flatness)
+ /**
+ * Test if this line intersects the given line.
+ *
+ * @param l the other segment
+ * @return true if the segments intersect
+ * @throws NullPointerException if l is null
+ * @see #linesIntersect(double, double, double, double,
+ * double, double, double, double)
+ */
+ public boolean intersectsLine(Line2D l)
{
- return at.new Iterator (new Iterator ());
+ return linesIntersect(getX1(), getY1(), getX2(), getY2(),
+ l.getX1(), l.getY1(), l.getX2(), l.getY2());
}
- public abstract double getX1 ();
- public abstract double getY1 ();
- public abstract double getX2 ();
- public abstract double getY2 ();
-
- public boolean intersects (double x, double y, double w, double h)
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the line segment. If the point is on the segment, the
+ * result will be 0.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the segment
+ * @see #ptSegDist(double, double, double, double, double, double)
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ */
+ public static double ptSegDistSq(double x1, double y1, double x2, double y2,
+ double px, double py)
{
- double x1 = getX1 ();
- double y1 = getY1 ();
- double x2 = getX2 ();
- double y2 = getY2 ();
-
- if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y +h)
- return true;
- if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y +h)
- return true;
-
- double x3 = x + w;
- double y3 = y + h;
-
- return (linesIntersect (x1, y1, x2, y2, x, y, x, y3)
- || linesIntersect (x1, y1, x2, y2, x, y3, x3, y3)
- || linesIntersect (x1, y1, x2, y2, x3, y3, x3, y)
- || linesIntersect (x1, y1, x2, y2, x3, y, x, y));
- }
-
- public boolean intersects (Rectangle2D r)
- {
- return intersects (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
- }
+ double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
- public boolean intersectsLine (double x1, double y1, double x2, double y2)
- {
- return linesIntersect (getX1 (), getY1 (), getX2 (), getY2(),
- x1, y1, x2, y2);
- }
+ double x, y;
+ if (pd2 == 0)
+ {
+ // Points are coincident.
+ x = x1;
+ y = y2;
+ }
+ else
+ {
+ double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
+
+ if (u < 0)
+ {
+ // "Off the end"
+ x = x1;
+ y = y1;
+ }
+ else if (u > 1.0)
+ {
+ x = x2;
+ y = y2;
+ }
+ else
+ {
+ x = x1 + u * (x2 - x1);
+ y = y1 + u * (y2 - y1);
+ }
+ }
- public boolean intersectsLine (Line2D l)
- {
- return linesIntersect (getX1 (), getY1 (), getX2 (), getY2(),
- l.getX1 (), l.getY1 (), l.getX2 (), l.getY2 ());
+ return (x - px) * (x - px) + (y - py) * (y - py);
}
- public static boolean linesIntersect (double x1, double y1,
- double x2, double y2,
- double x3,double y3,
- double x4, double y4)
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the line segment. If the point is on the segment, the result will be 0.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the segment
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ * @see #ptLineDist(double, double, double, double, double, double)
+ */
+ public static double ptSegDist(double x1, double y1, double x2, double y2,
+ double px, double py)
{
- double beta = (((y1 - y3) * (x4 - x3) + (x1 - x3) * (y4 - y3))
- / ((y2 - y1) * (x4 - x3) + (x2 - x1) * (y4 - y3)));
- if (beta < 0.0 || beta > 1.0)
- return false;
- double alpha = (x1 + beta * (x2 - x1) - x3) / (x4 - x3);
- return alpha >= 0.0 && alpha <= 1.0;
+ return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py));
}
- public double ptLineDist (double px, double py)
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on this line segment. If the point is on the segment, the
+ * result will be 0.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the segment
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ */
+ public double ptSegDistSq(double px, double py)
{
- return ptLineDist (getX1 (), getY1 (), getX2 (), getY2 (),
- px, py);
+ return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
}
- public static double ptLineDist (double x1, double y1,
- double x2, double y2,
- double px, double py)
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on this line segment. If the point is on the segment, the
+ * result will be 0.
+ *
+ * @param p the point
+ * @return the square of the distance from the point to the segment
+ * @throws NullPointerException if p is null
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ */
+ public double ptSegDistSq(Point2D p)
{
- return Math.sqrt (ptLineDistSq (x1, y1, x2, y2, px, py));
+ return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
}
- public double ptLineDist (Point2D p)
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * this line segment. If the point is on the segment, the result will be 0.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the segment
+ * @see #ptSegDist(double, double, double, double, double, double)
+ */
+ public double ptSegDist(double px, double py)
{
- return ptLineDist (getX1 (), getY1 (), getX2 (), getY2 (),
- p.getX (), p.getY ());
+ return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py);
}
- public double ptLineDistSq (double px, double py)
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * this line segment. If the point is on the segment, the result will be 0.
+ *
+ * @param p the point
+ * @return the distance from the point to the segment
+ * @throws NullPointerException if p is null
+ * @see #ptSegDist(double, double, double, double, double, double)
+ */
+ public double ptSegDist(Point2D p)
{
- return ptLineDistSq (getX1 (), getY1 (), getX2 (), getY2 (),
- px, py);
+ return ptSegDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
}
- public static double ptLineDistSq (double x1, double y1,
- double x2, double y2,
- double px, double py)
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the infinite line extended from the segment. If the point
+ * is on the segment, the result will be 0. If the segment is length 0,
+ * the distance is to the common endpoint.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the extended line
+ * @see #ptLineDist(double, double, double, double, double, double)
+ * @see #ptSegDistSq(double, double, double, double, double, double)
+ */
+ public static double ptLineDistSq(double x1, double y1, double x2, double y2,
+ double px, double py)
{
double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
double x, y;
if (pd2 == 0)
{
- // Points are coincident.
- x = x1;
- y = y2;
+ // Points are coincident.
+ x = x1;
+ y = y2;
}
else
{
- double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
- x = x1 + u * (x2 - x1);
- y = y1 + u * (y2 - y1);
+ double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
+ x = x1 + u * (x2 - x1);
+ y = y1 + u * (y2 - y1);
}
return (x - px) * (x - px) + (y - py) * (y - py);
}
- public double ptLineDistSq (Point2D p)
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the infinite line extended from the segment. If the point is on the
+ * segment, the result will be 0. If the segment is length 0, the distance
+ * is to the common endpoint.
+ *
+ * @param x1 the first x coordinate of the segment
+ * @param y1 the first y coordinate of the segment
+ * @param x2 the second x coordinate of the segment
+ * @param y2 the second y coordinate of the segment
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the extended line
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ * @see #ptSegDist(double, double, double, double, double, double)
+ */
+ public static double ptLineDist(double x1, double y1,
+ double x2, double y2,
+ double px, double py)
{
- return ptLineDistSq (getX1 (), getY1 (), getX2 (), getY2 (),
- p.getX (), p.getY ());
+ return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py));
}
- public double ptSegDist (double px, double py)
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the infinite line extended from this segment. If the point
+ * is on the segment, the result will be 0. If the segment is length 0,
+ * the distance is to the common endpoint.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the square of the distance from the point to the extended line
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ */
+ public double ptLineDistSq(double px, double py)
{
- return ptSegDist (getX1 (), getY1 (), getX2 (), getY2 (),
- px, py);
+ return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py);
}
- public static double ptSegDist (double x1, double y1,
- double x2, double y2,
- double px, double py)
+ /**
+ * Measures the square of the shortest distance from the reference point
+ * to a point on the infinite line extended from this segment. If the point
+ * is on the segment, the result will be 0. If the segment is length 0,
+ * the distance is to the common endpoint.
+ *
+ * @param p the point
+ * @return the square of the distance from the point to the extended line
+ * @throws NullPointerException if p is null
+ * @see #ptLineDistSq(double, double, double, double, double, double)
+ */
+ public double ptLineDistSq(Point2D p)
{
- return Math.sqrt (ptSegDistSq (x1, y1, x2, y2, px, py));
+ return ptLineDistSq(getX1(), getY1(), getX2(), getY2(),
+ p.getX(), p.getY());
}
- public double ptSegDist (Point2D p)
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the infinite line extended from this segment. If the point is on the
+ * segment, the result will be 0. If the segment is length 0, the distance
+ * is to the common endpoint.
+ *
+ * @param px the x coordinate of the point
+ * @param py the y coordinate of the point
+ * @return the distance from the point to the extended line
+ * @see #ptLineDist(double, double, double, double, double, double)
+ */
+ public double ptLineDist(double px, double py)
{
- return ptSegDist (getX1 (), getY1 (), getX2 (), getY2 (),
- p.getX (), p.getY ());
+ return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py);
}
- public double ptSegDistSq (double px, double py)
+ /**
+ * Measures the shortest distance from the reference point to a point on
+ * the infinite line extended from this segment. If the point is on the
+ * segment, the result will be 0. If the segment is length 0, the distance
+ * is to the common endpoint.
+ *
+ * @param p the point
+ * @return the distance from the point to the extended line
+ * @throws NullPointerException if p is null
+ * @see #ptLineDist(double, double, double, double, double, double)
+ */
+ public double ptLineDist(Point2D p)
{
- return ptSegDistSq (getX1 (), getY1 (), getX2 (), getY2 (),
- px, py);
+ return ptLineDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY());
}
- public static double ptSegDistSq (double x1, double y1,
- double x2, double y2,
- double px, double py)
+ /**
+ * Test if a point is contained inside the line. Since a line has no area,
+ * this returns false.
+ *
+ * @param x the x coordinate
+ * @param y the y coordinate
+ * @return false; the line does not contain points
+ */
+ public boolean contains(double x, double y)
{
- double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2);
+ return false;
+ }
- double x, y;
- if (pd2 == 0)
- {
- // Points are coincident.
- x = x1;
- y = y2;
- }
- else
- {
- double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2;
-
- if (u < 0)
- {
- // "Off the end"
- x = x1;
- y = y1;
- }
- else if (u > 1.0)
- {
- x = x2;
- y = y2;
- }
- else
- {
- x = x1 + u * (x2 - x1);
- y = y1 + u * (y2 - y1);
- }
- }
+ /**
+ * Test if a point is contained inside the line. Since a line has no area,
+ * this returns false.
+ *
+ * @param p the point
+ * @return false; the line does not contain points
+ */
+ public boolean contains(Point2D p)
+ {
+ return false;
+ }
- return (x - px) * (x - px) + (y - py) * (y - py);
+ /**
+ * Tests if this line intersects the interior of the specified rectangle.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @return true if the line intersects the rectangle
+ */
+ public boolean intersects(double x, double y, double w, double h)
+ {
+ if (w <= 0 || h <= 0)
+ return false;
+ double x1 = getX1();
+ double y1 = getY1();
+ double x2 = getX2();
+ double y2 = getY2();
+
+ if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h)
+ return true;
+ if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h)
+ return true;
+
+ double x3 = x + w;
+ double y3 = y + h;
+
+ return (linesIntersect(x1, y1, x2, y2, x, y, x, y3)
+ || linesIntersect(x1, y1, x2, y2, x, y3, x3, y3)
+ || linesIntersect(x1, y1, x2, y2, x3, y3, x3, y)
+ || linesIntersect(x1, y1, x2, y2, x3, y, x, y));
}
- public double ptSegDistSq (Point2D p)
+ /**
+ * Tests if this line intersects the interior of the specified rectangle.
+ *
+ * @param r the rectangle
+ * @return true if the line intersects the rectangle
+ * @throws NullPointerException if r is null
+ */
+ public boolean intersects(Rectangle2D r)
{
- return ptSegDistSq (getX1 (), getY1 (), getX2 (), getY2 (),
- p.getX (), p.getY ());
+ return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
+ }
+
+ /**
+ * Tests if the line contains a rectangle. Since lines have no area, this
+ * always returns false.
+ *
+ * @param x the x coordinate of the rectangle
+ * @param y the y coordinate of the rectangle
+ * @param w the width of the rectangle
+ * @param h the height of the rectangle
+ * @return false; the line does not contain points
+ */
+ public boolean contains(double x, double y, double w, double h)
+ {
+ return false;
+ }
+
+ /**
+ * Tests if the line contains a rectangle. Since lines have no area, this
+ * always returns false.
+ *
+ * @param r the rectangle
+ * @return false; the line does not contain points
+ */
+ public boolean contains(Rectangle2D r)
+ {
+ return false;
}
- public int relativeCCW (double px, double py)
+ /**
+ * Gets a bounding box (not necessarily minimal) for this line.
+ *
+ * @return the integer bounding box
+ * @see #getBounds2D()
+ */
+ public Rectangle getBounds()
{
- return relativeCCW (getX1 (), getY1 (),
- getX2 (), getY2 (),
- px, py);
+ return getBounds2D().getBounds();
}
- public static int relativeCCW (double x1, double y1,
- double x2, double y2,
- double px, double py)
+ /**
+ * Return a path iterator, possibly applying a transform on the result. This
+ * iterator is not threadsafe.
+ *
+ * @param at the transform, or null
+ * @return a new path iterator
+ */
+ public PathIterator getPathIterator(final AffineTransform at)
{
- // 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);
+ return new PathIterator()
+ {
+ /** Current coordinate. */
+ private int current;
+
+ public int getWindingRule()
+ {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone()
+ {
+ return current < 2;
+ }
+
+ public void next()
+ {
+ current++;
+ }
- double a = (a1 - a2) % (2 * Math.PI);
- if (a == 0 || a == Math.PI)
+ public int currentSegment(float[] coords)
{
- double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1));
- if (u < 0.0)
- return 1;
- else if (u > 1.0)
- return -1;
- else
- return 0;
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = (float) getX1();
+ coords[1] = (float) getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = (float) getX2();
+ coords[1] = (float) getY2();
+ result = SEG_LINETO;
+ break;
+ default:
+ throw new NoSuchElementException("line iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return result;
}
- return (a > 0 && a < Math.PI) ? 1 : -1;
+ public int currentSegment(double[] coords)
+ {
+ int result;
+ switch (current)
+ {
+ case 0:
+ coords[0] = getX1();
+ coords[1] = getY1();
+ result = SEG_MOVETO;
+ break;
+ case 1:
+ coords[0] = getX2();
+ coords[1] = getY2();
+ result = SEG_LINETO;
+ break;
+ default:
+ throw new NoSuchElementException("line iterator out of bounds");
+ }
+ if (at != null)
+ at.transform(coords, 0, coords, 0, 1);
+ return result;
+ }
+ };
}
- public int relativeCCW (Point2D p)
+ /**
+ * Return a flat path iterator, possibly applying a transform on the result.
+ * This iterator is not threadsafe.
+ *
+ * @param at the transform, or null
+ * @param flatness ignored, since lines are already flat
+ * @return a new path iterator
+ * @see #getPathIterator(AffineTransform)
+ */
+ public PathIterator getPathIterator(AffineTransform at, double flatness)
{
- return relativeCCW (getX1 (), getY1 (),
- getX2 (), getY2 (),
- p.getX (), p.getY ());
+ return getPathIterator(at);
}
- public abstract void setLine (double x1, double y1, double x2, double y2);
-
- public void setLine (Line2D l)
+ /**
+ * Create a new line of the same run-time type with the same contents as
+ * this one.
+ *
+ * @return the clone
+ */
+ public Object clone()
{
- setLine (l.getX1 (), l.getY1 (), l.getX2 (), l.getY2 ());
+ try
+ {
+ return super.clone();
+ }
+ catch (CloneNotSupportedException e)
+ {
+ throw (Error) new InternalError().initCause(e); // Impossible
+ }
}
- public void setLine (Point2D p1, Point2D p2)
+ /**
+ * This class defines a point in <code>double</code> precision.
+ *
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Double extends Line2D
{
- setLine (p1.getX (), p1.getY (), p2.getX (), p2.getY ());
- }
+ /** The x coordinate of the first point. */
+ public double x1;
- public static class Float extends Line2D
- {
- float x1, y1, x2, y2;
+ /** The y coordinate of the first point. */
+ public double y1;
+
+ /** The x coordinate of the second point. */
+ public double x2;
+
+ /** The y coordinate of the second point. */
+ public double y2;
- public Float ()
+ /**
+ * Construct the line segment (0,0)-&gt;(0,0).
+ */
+ public Double()
{
- this (0.0F, 0.0F, 0.0F, 0.0F);
}
- public Float (float x1, float y1, float x2, float y2)
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param x1 the x coordinate of the first point
+ * @param y1 the y coordinate of the first point
+ * @param x2 the x coordinate of the second point
+ * @param y2 the y coordinate of the second point
+ */
+ public Double(double x1, double y1, double x2, double y2)
{
this.x1 = x1;
this.y1 = y1;
@@ -364,80 +809,149 @@ public abstract class Line2D implements Shape, Cloneable
this.y2 = y2;
}
- public Float (Point2D p1, Point2D p2)
- {
- this.x1 = (float) p1.getX ();
- this.y1 = (float) p1.getY ();
- this.x2 = (float) p2.getX ();
- this.y2 = (float) p2.getY ();
- }
-
- public Rectangle2D getBounds2D ()
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public Double(Point2D p1, Point2D p2)
{
- float x = Math.min (x1, x2);
- float w = Math.abs (x1 - x2);
- float y = Math.min (y1, y2);
- float h = Math.abs (y1 - y2);
- return new Rectangle2D.Float (x, y, w, h);
+ x1 = p1.getX();
+ y1 = p1.getY();
+ x2 = p2.getX();
+ y2 = p2.getY();
}
- public Point2D getP1 ()
+ /**
+ * Return the x coordinate of the first point.
+ *
+ * @return the value of x1
+ */
+ public double getX1()
{
- return new Point2D.Float (x1, y1);
- }
-
- public Point2D getP2 ()
- {
- return new Point2D.Float (x2, y2);
+ return x1;
}
- public double getX1 ()
+ /**
+ * Return the y coordinate of the first point.
+ *
+ * @return the value of y1
+ */
+ public double getY1()
{
- return x1;
+ return y1;
}
- public double getY1 ()
+ /**
+ * Return the first point.
+ *
+ * @return the point (x1,y1)
+ */
+ public Point2D getP1()
{
- return y1;
+ return new Point2D.Double(x1, y1);
}
- public double getX2 ()
+ /**
+ * Return the x coordinate of the second point.
+ *
+ * @return the value of x2
+ */
+ public double getX2()
{
return x2;
}
- public double getY2 ()
+ /**
+ * Return the y coordinate of the second point.
+ *
+ * @return the value of y2
+ */
+ public double getY2()
{
return y2;
}
- public void setLine (double x1, double y1, double x2, double y2)
+ /**
+ * Return the second point.
+ *
+ * @return the point (x2,y2)
+ */
+ public Point2D getP2()
{
- this.x1 = (float) x1;
- this.y1 = (float) y1;
- this.x2 = (float) x2;
- this.y2 = (float) y2;
+ return new Point2D.Double(x2, y2);
}
- public void setLine (float x1, float y1, float x2, float y2)
+ /**
+ * Set this line to the given points.
+ *
+ * @param x1 the new x coordinate of the first point
+ * @param y1 the new y coordinate of the first point
+ * @param x2 the new x coordinate of the second point
+ * @param y2 the new y coordinate of the second point
+ */
+ public void setLine(double x1, double y1, double x2, double y2)
{
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
- }
- public static class Double extends Line2D
+ /**
+ * Return the exact bounds of this line segment.
+ *
+ * @return the bounding box
+ */
+ public Rectangle2D getBounds2D()
+ {
+ double x = Math.min(x1, x2);
+ double y = Math.min(y1, y2);
+ double w = Math.abs(x1 - x2);
+ double h = Math.abs(y1 - y2);
+ return new Rectangle2D.Double(x, y, w, h);
+ }
+ } // class Double
+
+ /**
+ * This class defines a point in <code>float</code> precision.
+ *
+ * @author Eric Blake <ebb9@email.byu.edu>
+ * @since 1.2
+ * @status updated to 1.4
+ */
+ public static class Float extends Line2D
{
- double x1, y1, x2, y2;
+ /** The x coordinate of the first point. */
+ public float x1;
+
+ /** The y coordinate of the first point. */
+ public float y1;
+
+ /** The x coordinate of the second point. */
+ public float x2;
- public Double ()
+ /** The y coordinate of the second point. */
+ public float y2;
+
+ /**
+ * Construct the line segment (0,0)-&gt;(0,0).
+ */
+ public Float()
{
- this (0.0, 0.0, 0.0, 0.0);
}
- public Double (double x1, double y1, double x2, double y2)
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param x1 the x coordinate of the first point
+ * @param y1 the y coordinate of the first point
+ * @param x2 the x coordinate of the second point
+ * @param y2 the y coordinate of the second point
+ */
+ public Float(float x1, float y1, float x2, float y2)
{
this.x1 = x1;
this.y1 = y1;
@@ -445,129 +959,125 @@ public abstract class Line2D implements Shape, Cloneable
this.y2 = y2;
}
- public Double (Point2D p1, Point2D p2)
+ /**
+ * Construct the line segment with the specified points.
+ *
+ * @param p1 the first point
+ * @param p2 the second point
+ * @throws NullPointerException if either point is null
+ */
+ public Float(Point2D p1, Point2D p2)
{
- this.x1 = (double) p1.getX ();
- this.y1 = p1.getY ();
- this.x2 = p2.getX ();
- this.y2 = p2.getY ();
+ x1 = (float) p1.getX();
+ y1 = (float) p1.getY();
+ x2 = (float) p2.getX();
+ y2 = (float) p2.getY();
}
- public Rectangle2D getBounds2D ()
+ /**
+ * Return the x coordinate of the first point.
+ *
+ * @return the value of x1
+ */
+ public double getX1()
{
- double x = Math.min (x1, x2);
- double w = Math.abs (x1 - x2);
- double y = Math.min (y1, y2);
- double h = Math.abs (y1 - y2);
- return new Rectangle2D.Double (x, y, w, h);
+ return x1;
}
- public Point2D getP1 ()
+ /**
+ * Return the y coordinate of the first point.
+ *
+ * @return the value of y1
+ */
+ public double getY1()
{
- return new Point2D.Double (x1, y1);
+ return y1;
}
- public Point2D getP2 ()
+ /**
+ * Return the first point.
+ *
+ * @return the point (x1,y1)
+ */
+ public Point2D getP1()
{
- return new Point2D.Double (x2, y2);
+ return new Point2D.Float(x1, y1);
}
- public double getX1 ()
+ /**
+ * Return the x coordinate of the second point.
+ *
+ * @return the value of x2
+ */
+ public double getX2()
{
- return x1;
+ return x2;
}
- public double getY1 ()
+ /**
+ * Return the y coordinate of the second point.
+ *
+ * @return the value of y2
+ */
+ public double getY2()
{
- return y1;
+ return y2;
}
- public double getX2 ()
+ /**
+ * Return the second point.
+ *
+ * @return the point (x2,y2)
+ */
+ public Point2D getP2()
{
- return x2;
+ return new Point2D.Float(x2, y2);
}
- public double getY2 ()
+ /**
+ * Set this line to the given points.
+ *
+ * @param x1 the new x coordinate of the first point
+ * @param y1 the new y coordinate of the first point
+ * @param x2 the new x coordinate of the second point
+ * @param y2 the new y coordinate of the second point
+ */
+ public void setLine(double x1, double y1, double x2, double y2)
{
- return y2;
+ this.x1 = (float) x1;
+ this.y1 = (float) y1;
+ this.x2 = (float) x2;
+ this.y2 = (float) y2;
}
- public void setLine (double x1, double y1, double x2, double y2)
+ /**
+ * Set this line to the given points.
+ *
+ * @param x1 the new x coordinate of the first point
+ * @param y1 the new y coordinate of the first point
+ * @param x2 the new x coordinate of the second point
+ * @param y2 the new y coordinate of the second point
+ */
+ public void setLine(float x1, float y1, float x2, float y2)
{
this.x1 = x1;
this.y1 = y1;
this.x2 = x2;
this.y2 = y2;
}
- }
-
- // 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)
+ /**
+ * Return the exact bounds of this line segment.
+ *
+ * @return the bounding box
+ */
+ public Rectangle2D getBounds2D()
{
- 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;
-
- return r;
+ float x = Math.min(x1, x2);
+ float y = Math.min(y1, y2);
+ float w = Math.abs(x1 - x2);
+ float h = Math.abs(y1 - y2);
+ return new Rectangle2D.Float(x, y, w, h);
}
-
- public int currentSegment (float[] coords)
- {
- 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;
- }
- }
-}
+ } // class Float
+} // class Line2D