/*
* Copyright (c) 2008-2009, Piccolo2D project, http://piccolo2d.org
* Copyright (c) 1998-2008, University of Maryland
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided
* that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions
* and the following disclaimer in the documentation and/or other materials provided with the
* distribution.
*
* None of the name of the University of Maryland, the name of the Piccolo2D project, or the names of its
* contributors may be used to endorse or promote products derived from this software without specific
* prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package edu.umd.cs.piccolox.util;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
public class XYArray implements MutablePoints, Cloneable {
// the coordinates are stored as alternating x and y pairs
private double[] points = null;
// the number of valid x, y pairs,
// i.e. not the length of the points array
private int numPoints = 0;
public XYArray(double[] points) {
initPoints(points, points.length / 2);
}
public XYArray(int n) {
initPoints(null, n);
}
public XYArray() {
this(0);
}
public int getPointCount() {
return numPoints;
}
// normalize an index, negative counts from end
private int normalize(int i) {
if (i >= numPoints) {
throw new IllegalArgumentException("The point index " + i + " is not below " + numPoints);
}
return (i < 0) ? numPoints + i : i;
}
public double getX(int i) {
return points[normalize(i) * 2];
}
public double getY(int i) {
return points[normalize(i) * 2 + 1];
}
public Point2D getPoint(int i, Point2D dst) {
int pointIndex = normalize(i);
dst.setLocation(points[pointIndex * 2], points[pointIndex * 2 + 1]);
return dst;
}
public void setX(int i, double x) {
points[normalize(i) * 2] = x;
}
public void setY(int i, double y) {
points[normalize(i) * 2 + 1] = y;
}
public void setPoint(int i, double x, double y) {
int pointIndex = normalize(i);
points[pointIndex * 2] = x;
points[pointIndex * 2 + 1] = y;
}
public void setPoint(int i, Point2D pt) {
setPoint(i, pt.getX(), pt.getY());
}
public void transformPoints(AffineTransform t) {
t.transform(points, 0, points, 0, numPoints);
}
public Rectangle2D getBounds(Rectangle2D dst) {
int i = 0;
if (dst.isEmpty() && getPointCount() > 0) {
dst.setRect(getX(i), getY(i), 1.0d, 1.0d);
i++;
}
while (i < getPointCount()) {
dst.add(getX(i), getY(i));
i++;
}
return dst;
}
public static double[] initPoints(double[] points, int n, double[] old) {
if (points == null || n * 2 > points.length) {
points = new double[n * 2];
}
if (old != null && points != old) {
System.arraycopy(old, 0, points, 0, Math.min(old.length, n * 2));
}
return (points);
}
private void initPoints(double[] points, int n) {
this.points = initPoints(points, n, this.points);
numPoints = (points != null ? points.length / 2 : 0);
}
public void addPoints(int pos, Points pts, int start, int end) {
if (end < 0) {
end = pts.getPointCount() + end + 1;
}
int n = numPoints + end - start;
points = initPoints(points, n, points);
int pos1 = pos * 2;
int pos2 = (pos + end - start) * 2;
int len = (numPoints - pos) * 2;
System.arraycopy(points, pos1, points, pos2, len);
numPoints = n;
if (pts != null) {
for (int count = 0; start < end; count++, start++) {
setPoint(pos + count, pts.getX(start), pts.getY(start));
}
}
}
public void addPoints(int pos, Points pts) {
addPoints(pos, pts, 0, pts.getPointCount());
}
public void appendPoints(Points pts) {
addPoints(numPoints, pts);
}
public static XYArray copyPoints(Points pts) {
XYArray newList = new XYArray(pts.getPointCount());
newList.appendPoints(pts);
return newList;
}
public void addPoint(int pos, double x, double y) {
addPoints(pos, null, 0, 1);
setPoint(pos, x, y);
}
public void addPoint(int pos, Point2D pt) {
addPoint(pos, pt.getX(), pt.getY());
}
public void removePoints(int pos, int num) {
num = Math.min(num, numPoints - pos);
if (num <= 0)
return;
System.arraycopy(points, (pos + num) * 2, points, pos * 2, (numPoints - (pos + num)) * 2);
numPoints -= num;
}
public void removeAllPoints() {
removePoints(0, numPoints);
}
public Object clone() {
XYArray ps = null;
try {
ps = (XYArray) (super.clone());
ps.points = initPoints(ps.points, numPoints, points);
ps.numPoints = numPoints;
}
catch (CloneNotSupportedException e) {
}
return (ps);
}
}