+++ /dev/null
-/* Copyright (C) 2001 Free Software Foundation
-
- This file is part of libjava.
-
-This software is copyrighted work licensed under the terms of the
-Libjava License. Please consult the file "LIBJAVA_LICENSE" for
-details. */
-
-package java.awt;
-
-import java.awt.geom.*;
-import java.io.Serializable;
-import java.util.Arrays;
-
-/**
- * @author Tom Tromey <tromey@redhat.com>
- * @date May 10, 2001
- */
-
-/** The Polygon class represents a closed region whose boundary is
- made of line segments. The Polygon is defined by its vertices. */
-public class Polygon implements Shape, Serializable
-{
- /** The bounds of the polygon. This is null until the bounds have
- * been computed for the first time; then it is correctly
- * maintained whenever it is modified. */
- protected Rectangle bounds;
-
- /** The number of points in the polygon. */
- public int npoints;
-
- /** The x coordinates of the points. */
- public int[] xpoints;
-
- /** The y coordinates of the points. */
- public int[] ypoints;
-
- /** Create a new, empty Polygon. */
- public Polygon ()
- {
- this.xpoints = new int[0];
- this.ypoints = new int[0];
- this.npoints = 0;
- }
-
- /** Create a new Polygon from the given vertices.
- * @param xpoints The x coordinates
- * @param ypoints The y coordinates
- * @param npoints The number of points
- */
- public Polygon (int[] xpoints, int[] ypoints, int npoints)
- {
- // We make explicit copies instead of relying on clone so that we
- // ensure the new arrays are the same size.
- this.xpoints = new int[npoints];
- this.ypoints = new int[npoints];
- System.arraycopy (xpoints, 0, this.xpoints, 0, npoints);
- System.arraycopy (ypoints, 0, this.ypoints, 0, npoints);
- }
-
- /** Append the specified point to this Polygon.
- * @param x The x coordinate
- * @param y The y coordinate
- */
- public void addPoint (int x, int y)
- {
- int[] newx = new int[npoints + 1];
- System.arraycopy (xpoints, 0, newx, 0, npoints);
- int[] newy = new int[npoints + 1];
- System.arraycopy (ypoints, 0, newy, 0, npoints);
- newx[npoints] = x;
- newy[npoints] = y;
- ++npoints;
- xpoints = newx;
- ypoints = newy;
-
- // It is simpler to just recompute.
- if (bounds != null)
- computeBoundingBox ();
- }
-
- /** Return true if the indicated point is inside this Polygon.
- * This uses an even-odd rule to determine insideness.
- * @param x The x coordinate
- * @param y The y coordinate
- * @returns true if the point is contained by this Polygon.
- */
- public boolean contains (double x, double y)
- {
- // What we do is look at each line segment. If the line segment
- // crosses the "scan line" at y at a point x' < x, then we
- // increment our counter. At the end, an even number means the
- // point is outside the polygon. Instead of a number, though, we
- // use a boolean.
- boolean inside = false;
- for (int i = 0; i < npoints; ++i)
- {
- // Handle the wrap case.
- int x2 = (i == npoints) ? xpoints[0] : xpoints[i + 1];
- int y2 = (i == npoints) ? ypoints[0] : ypoints[i + 1];
-
- if (ypoints[i] == y2)
- {
- // We ignore horizontal lines. This might give weird
- // results in some situations -- ?
- continue;
- }
-
- double t = (y - ypoints[i]) / (double) (y2 - ypoints[i]);
- double x3 = xpoints[i] + t * (x2 - xpoints[i]);
- if (x3 < x)
- inside = ! inside;
- }
-
- return inside;
- }
-
- /** Return true if the indicated rectangle is entirely inside this
- * Polygon.
- * This uses an even-odd rule to determine insideness.
- * @param x The x coordinate
- * @param y The y coordinate
- * @param w The width
- * @param h The height
- * @returns true if the rectangle is contained by this Polygon.
- */
- public boolean contains (double x, double y, double w, double h)
- {
- return intersectOrContains (x, y, w, h, false);
- }
-
- /** Return true if the indicated point is inside this Polygon.
- * This uses an even-odd rule to determine insideness.
- * @param x The x coordinate
- * @param y The y coordinate
- * @returns true if the point is contained by this Polygon.
- */
- public boolean contains (int x, int y)
- {
- return contains ((double) x, (double) y);
- }
-
- /** Return true if the indicated point is inside this Polygon.
- * This uses an even-odd rule to determine insideness.
- * @param p The point
- * @returns true if the point is contained by this Polygon.
- */
- public boolean contains (Point p)
- {
- return contains (p.x, p.y);
- }
-
- /** Return true if the indicated point is inside this Polygon.
- * This uses an even-odd rule to determine insideness.
- * @param p The point
- * @returns true if the point is contained by this Polygon.
- */
- public boolean contains (Point2D p)
- {
- return contains (p.getX (), p.getY ());
- }
-
- /** Return true if the indicated rectangle is entirely inside this
- * Polygon. This uses an even-odd rule to determine insideness.
- * @param r The rectangle
- * @returns true if the rectangle is contained by this Polygon.
- */
- public boolean contains (Rectangle2D r)
- {
- return contains (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
- }
-
- /** Returns the bounds of this Polygon.
- * @deprecated Use getBounds() instead.
- */
- public Rectangle getBoundingBox ()
- {
- if (bounds == null)
- computeBoundingBox ();
- return bounds;
- }
-
- /** Returns the bounds of this Polygon. */
- public Rectangle getBounds ()
- {
- if (bounds == null)
- computeBoundingBox ();
- return bounds;
- }
-
- /** Returns the bounds of this Polygon. */
- public Rectangle2D getBounds2D ()
- {
- if (bounds == null)
- computeBoundingBox ();
- return bounds; // Why not?
- }
-
- /** Return an iterator for the boundary of this Polygon.
- * @param at A transform to apply to the coordinates.
- * @returns A path iterator for the Polygon's boundary.
- */
- public PathIterator getPathIterator (AffineTransform at)
- {
- return new Iterator (at);
- }
-
- /** Return an iterator for the boundary of this Polygon.
- * @param at A transform to apply to the coordinates.
- * @param flatness The flatness of the result; it is ignored by
- * this class.
- * @returns A path iterator for the Polygon's boundary.
- */
- public PathIterator getPathIterator (AffineTransform at, double flatness)
- {
- // We ignore the flatness.
- return new Iterator (at);
- }
-
- /** @deprecated use contains(int,int). */
- public boolean inside (int x, int y)
- {
- return contains (x, y);
- }
-
- /** Return true if this Polygon's interior intersects the given
- * rectangle's interior.
- * @param x The x coordinate
- * @param y The y coordinate
- * @param w The width
- * @param h The height
- */
- public boolean intersects (double x, double y, double w, double h)
- {
- return intersectOrContains (x, y, w, h, true);
- }
-
- /** Return true if this Polygon's interior intersects the given
- * rectangle's interior.
- * @param r The rectangle
- */
- public boolean intersects (Rectangle2D r)
- {
- return intersects (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
- }
-
- // This tests for intersection with or containment of a rectangle,
- // depending on the INTERSECT argument.
- private boolean intersectOrContains (double x, double y, double w, double h,
- boolean intersect)
- {
- // First compute the rectangle of possible intersection points.
- Rectangle r = getBounds ();
- int minx = Math.max (r.x, (int) x);
- int maxx = Math.min (r.x + r.width, (int) (x + w));
- int miny = Math.max (r.y, (int) y);
- int maxy = Math.min (r.y + r.height, (int) (y + h));
-
- if (miny > maxy)
- return false;
-
- double[] crosses = new double[npoints + 1];
-
- for (; miny < maxy; ++miny)
- {
- // First compute every place where the polygon might intersect
- // the scan line at Y.
- int ins = 0;
- for (int i = 0; i < npoints; ++i)
- {
- // Handle the wrap case.
- int x2 = (i == npoints) ? xpoints[0] : xpoints[i + 1];
- int y2 = (i == npoints) ? ypoints[0] : ypoints[i + 1];
-
- if (ypoints[i] == y2)
- {
- // We ignore horizontal lines. This might give weird
- // results in some situations -- ?
- continue;
- }
-
- double t = (((double) miny - ypoints[i])
- / (double) (y2 - ypoints[i]));
- double x3 = xpoints[i] + t * (x2 - xpoints[i]);
- crosses[ins++] = x3;
- }
-
- // Now we can sort into increasing order and look to see if
- // any point in the rectangle is in the polygon. We examine
- // every other pair due to our even-odd rule.
- Arrays.sort (crosses, 0, ins);
- int i = intersect ? 0 : 1;
- for (; i < ins - 1; i += 2)
- {
- // Pathological case.
- if (crosses[i] == crosses[i + 1])
- continue;
-
- // Found a point on the inside.
- if ((crosses[i] >= x && crosses[i] < x + w)
- || (crosses[i + 1] >= x && crosses[i + 1] < x + w))
- {
- // If we're checking containment then we just lost.
- // But if we're checking intersection then we just
- // won.
- return intersect;
- }
- }
- }
-
- return false;
- }
-
- /** Translates all the vertices of the polygon via a given vector.
- * @param deltaX The X offset
- * @param deltaY The Y offset
- */
- public void translate (int deltaX, int deltaY)
- {
- for (int i = 0; i < npoints; ++i)
- {
- xpoints[i] += deltaX;
- ypoints[i] += deltaY;
- }
-
- if (bounds != null)
- {
- bounds.x += deltaX;
- bounds.y += deltaY;
- }
- }
-
- // This computes the bounding box if required.
- private void computeBoundingBox ()
- {
- if (npoints == 0)
- {
- // This is wrong if the user adds a new point, but we
- // account for that in addPoint().
- bounds = new Rectangle (0, 0, 0, 0);
- }
- else
- {
- int maxx = xpoints[0];
- int minx = xpoints[0];
- int maxy = ypoints[0];
- int miny = ypoints[0];
-
- for (int i = 1; i < npoints; ++i)
- {
- maxx = Math.max (maxx, xpoints[i]);
- minx = Math.min (minx, xpoints[i]);
- maxy = Math.max (maxy, ypoints[i]);
- miny = Math.min (miny, ypoints[i]);
- }
-
- bounds = new Rectangle (minx, miny, maxx - minx, maxy - miny);
- }
- }
-
- private class Iterator implements PathIterator
- {
- public AffineTransform xform;
- public int where;
-
- public Iterator (AffineTransform xform)
- {
- this.xform = xform;
- where = 0;
- }
-
- public int currentSegment (double[] coords)
- {
- int r;
-
- if (where < npoints)
- {
- coords[0] = xpoints[where];
- coords[1] = ypoints[where];
- r = (where == 0) ? SEG_MOVETO : SEG_LINETO;
- xform.transform (coords, 0, coords, 0, 1);
- ++where;
- }
- else
- r = SEG_CLOSE;
-
- return r;
- }
-
- public int currentSegment (float[] coords)
- {
- int r;
-
- if (where < npoints)
- {
- coords[0] = xpoints[where];
- coords[1] = ypoints[where];
- r = (where == 0) ? SEG_MOVETO : SEG_LINETO;
- xform.transform (coords, 0, coords, 0, 1);
- }
- else
- r = SEG_CLOSE;
-
- return r;
- }
-
- public int getWindingRule ()
- {
- return WIND_EVEN_ODD;
- }
-
- public boolean isDone ()
- {
- return where == npoints + 1;
- }
-
- public void next ()
- {
- ++where;
- }
- }
-}