polygon.java

来自「gcc3.2.1源代码」· Java 代码 · 共 423 行

JAVA
423
字号
/* Copyright (C) 2001  Free Software Foundation   This file is part of libjava.This software is copyrighted work licensed under the terms of theLibjava License.  Please consult the file "LIBJAVA_LICENSE" fordetails.  */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;    }  }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?