package java.awt;
import java.awt.geom.*;
import java.io.Serializable;
import java.util.Arrays;
public class Polygon implements Shape, Serializable
{
protected Rectangle bounds;
public int npoints;
public int[] xpoints;
public int[] ypoints;
public Polygon ()
{
this.xpoints = new int[0];
this.ypoints = new int[0];
this.npoints = 0;
}
public Polygon (int[] xpoints, int[] ypoints, int npoints)
{
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);
}
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;
if (bounds != null)
computeBoundingBox ();
}
public boolean contains (double x, double y)
{
boolean inside = false;
for (int i = 0; i < npoints; ++i)
{
int x2 = (i == npoints) ? xpoints[0] : xpoints[i + 1];
int y2 = (i == npoints) ? ypoints[0] : ypoints[i + 1];
if (ypoints[i] == y2)
{
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;
}
public boolean contains (double x, double y, double w, double h)
{
return intersectOrContains (x, y, w, h, false);
}
public boolean contains (int x, int y)
{
return contains ((double) x, (double) y);
}
public boolean contains (Point p)
{
return contains (p.x, p.y);
}
public boolean contains (Point2D p)
{
return contains (p.getX (), p.getY ());
}
public boolean contains (Rectangle2D r)
{
return contains (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
}
public Rectangle getBoundingBox ()
{
if (bounds == null)
computeBoundingBox ();
return bounds;
}
public Rectangle getBounds ()
{
if (bounds == null)
computeBoundingBox ();
return bounds;
}
public Rectangle2D getBounds2D ()
{
if (bounds == null)
computeBoundingBox ();
return bounds; }
public PathIterator getPathIterator (AffineTransform at)
{
return new Iterator (at);
}
public PathIterator getPathIterator (AffineTransform at, double flatness)
{
return new Iterator (at);
}
public boolean inside (int x, int y)
{
return contains (x, y);
}
public boolean intersects (double x, double y, double w, double h)
{
return intersectOrContains (x, y, w, h, true);
}
public boolean intersects (Rectangle2D r)
{
return intersects (r.getX (), r.getY (), r.getWidth (), r.getHeight ());
}
private boolean intersectOrContains (double x, double y, double w, double h,
boolean intersect)
{
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)
{
int ins = 0;
for (int i = 0; i < npoints; ++i)
{
int x2 = (i == npoints) ? xpoints[0] : xpoints[i + 1];
int y2 = (i == npoints) ? ypoints[0] : ypoints[i + 1];
if (ypoints[i] == y2)
{
continue;
}
double t = (((double) miny - ypoints[i])
/ (double) (y2 - ypoints[i]));
double x3 = xpoints[i] + t * (x2 - xpoints[i]);
crosses[ins++] = x3;
}
Arrays.sort (crosses, 0, ins);
int i = intersect ? 0 : 1;
for (; i < ins - 1; i += 2)
{
if (crosses[i] == crosses[i + 1])
continue;
if ((crosses[i] >= x && crosses[i] < x + w)
|| (crosses[i + 1] >= x && crosses[i + 1] < x + w))
{
return intersect;
}
}
}
return false;
}
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;
}
}
private void computeBoundingBox ()
{
if (npoints == 0)
{
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;
}
}
}