// Copyright 2004, FreeHEP.
package org.freehep.graphics2d;
import com.google.code.appengine.awt.Rectangle;
import com.google.code.appengine.awt.Shape;
import com.google.code.appengine.awt.geom.AffineTransform;
import com.google.code.appengine.awt.geom.PathIterator;
import com.google.code.appengine.awt.geom.Point2D;
import com.google.code.appengine.awt.geom.Rectangle2D;
/**
* This class can be used in a transient way to deal with the drawing or filling
* of an array of double points as a polyline/polygon. The class implements a
* shape and comes with an associated iterator.
*
* @author Mark Donszelmann
* @version $Id: ArrayPath.java 8584 2006-08-10 23:06:37Z duns $
*/
public class ArrayPath implements Shape {
private class ArrayPathIterator implements PathIterator {
private double[] xPoints, yPoints;
private double lastX, lastY;
private int nPoints;
private boolean closed;
private int resolution;
private int currentPoint;
private boolean isDone;
private ArrayPathIterator(double[] xPoints, double[] yPoints,
int nPoints, boolean closed, int resolution) {
this.xPoints = xPoints;
this.yPoints = yPoints;
this.nPoints = nPoints;
this.closed = closed;
this.resolution = resolution;
currentPoint = 0;
isDone = nPoints == 0;
}
public boolean isDone() {
return isDone;
}
public void next() {
currentPoint++;
while ((currentPoint < nPoints - 1)
&& (Math.abs(xPoints[currentPoint] - lastX) < resolution)
&& (Math.abs(yPoints[currentPoint] - lastY) < resolution)) {
currentPoint++;
}
if (closed
&& (currentPoint == nPoints - 1)
&& (Math.abs(xPoints[currentPoint] - xPoints[0]) < resolution)
&& (Math.abs(yPoints[currentPoint] - yPoints[0]) < resolution)) {
currentPoint++; // skip last point since it is same as first
}
isDone = (closed) ? currentPoint > nPoints
: currentPoint >= nPoints;
}
public int currentSegment(double[] coords) {
if (closed && (currentPoint == nPoints)) {
return PathIterator.SEG_CLOSE;
}
coords[0] = lastX = xPoints[currentPoint];
coords[1] = lastY = yPoints[currentPoint];
return (currentPoint == 0) ? PathIterator.SEG_MOVETO
: PathIterator.SEG_LINETO;
}
public int currentSegment(float[] coords) {
if (closed && (currentPoint == nPoints)) {
return PathIterator.SEG_CLOSE;
}
lastX = xPoints[currentPoint];
lastY = yPoints[currentPoint];
coords[0] = (float) lastX;
coords[1] = (float) lastY;
return (currentPoint == 0) ? PathIterator.SEG_MOVETO
: PathIterator.SEG_LINETO;
}
public int getWindingRule() {
return PathIterator.WIND_NON_ZERO;
}
}
private double[] xPoints, yPoints;
private int nPoints;
private boolean closed;
private int resolution;
public ArrayPath(double[] xPoints, double[] yPoints, int nPoints,
boolean closed, int resolution) {
this.xPoints = xPoints;
this.yPoints = yPoints;
this.nPoints = nPoints;
this.closed = closed;
this.resolution = resolution;
}
public boolean contains(double x, double y) {
// conservative guess
return false;
}
public boolean contains(double x, double y, double w, double h) {
// conservative guess
return false;
}
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 boolean intersects(double x, double y, double w, double h) {
// conservative guess
return true;
}
public boolean intersects(Rectangle2D r) {
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
}
public PathIterator getPathIterator(AffineTransform at, double flatness) {
return getPathIterator(at);
}
public Rectangle2D getBounds2D() {
double x1, y1, x2, y2;
int i = nPoints;
if (i > 0) {
i--;
y1 = y2 = yPoints[i];
x1 = x2 = xPoints[i];
while (i > 0) {
i--;
double y = yPoints[i];
double x = xPoints[i];
if (x < x1)
x1 = x;
if (y < y1)
y1 = y;
if (x > x2)
x2 = x;
if (y > y2)
y2 = y;
}
} else {
x1 = y1 = x2 = y2 = 0.0f;
}
return new Rectangle2D.Double(x1, y1, x2 - x1, y2 - y1);
}
public Rectangle getBounds() {
return getBounds2D().getBounds();
}
public PathIterator getPathIterator(AffineTransform t) {
double[] transformedXPoints = xPoints;
double[] transformedYPoints = yPoints;
if (t != null) {
// FIXME, this seems a silly slow way to deal with this.
transformedXPoints = new double[nPoints];
transformedYPoints = new double[nPoints];
Point2D s = new Point2D.Double();
Point2D d = new Point2D.Double();
for (int i = 0; i < nPoints; i++) {
s.setLocation(xPoints[i], yPoints[i]);
t.transform(s, d);
transformedXPoints[i] = d.getX();
transformedYPoints[i] = d.getY();
}
}
return new ArrayPathIterator(transformedXPoints, transformedYPoints,
nPoints, closed, resolution);
}
}