package net.sf.openrocket.optimization.general;
import java.util.Arrays;
import net.sf.openrocket.util.MathUtil;
/**
* An immutable n-dimensional coordinate point.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public final class Point {
private final double[] point;
private double length = -1;
private double length2 = -1;
/**
* Create a new point with all values zero.
*
* @param dim the dimensionality of the point
*/
public Point(int dim) {
if (dim <= 0) {
throw new IllegalArgumentException("Invalid dimensionality " + dim);
}
point = new double[dim];
}
/**
* Create a new point filled with a specific value.
*
* @param dim the dimensionality of the point
* @param value the value for all dimensions
*/
public Point(int dim, double value) {
this(dim);
Arrays.fill(point, value);
}
/**
* Create a new point with specific values.
*
* @param value the values of the dimensions.
*/
public Point(double... value) {
if (value.length == 0) {
throw new IllegalArgumentException("Zero-dimensional point not allowed");
}
point = value.clone();
}
/**
* Create a copy of a point. Used locally to create copies.
*
* @param p the point to copy.
*/
private Point(Point p) {
point = p.point.clone();
}
/**
* Return the point dimensionality.
*
* @return the point dimensionality
*/
public int dim() {
return point.length;
}
public double get(int i) {
return point[i];
}
public Point set(int i, double v) {
Point p = new Point(this);
p.point[i] = v;
return p;
}
/**
* Return a new point that is the sum of two points.
*
* @param other the point to add to this point.
* @return the sum of these points.
*/
public Point add(Point other) {
Point p = new Point(this);
for (int i = 0; i < point.length; i++) {
p.point[i] += other.point[i];
}
return p;
}
/**
* Return a new point that is the subtraction of two points.
*
* @param other the point to subtract from this point.
* @return the value of this - other.
*/
public Point sub(Point other) {
Point p = new Point(this);
for (int i = 0; i < point.length; i++) {
p.point[i] -= other.point[i];
}
return p;
}
/**
* Return this point multiplied by a scalar value.
*
* @param v the scalar to multiply with
* @return the scaled point
*/
public Point mul(double v) {
Point p = new Point(this);
for (int i = 0; i < point.length; i++) {
p.point[i] *= v;
}
return p;
}
/**
* Return the length of this coordinate.
*
* @return the length.
*/
public double length() {
if (length < 0) {
length = MathUtil.safeSqrt(length2());
}
return length;
}
/**
* Return the squared length of this coordinate.
*
* @return the square of the length of thie coordinate.
*/
public double length2() {
if (length2 < 0) {
length2 = 0;
for (double p : point) {
length2 += p * p;
}
}
return length2;
}
/**
* Return the point as an array.
*
* @return the point as an array.
*/
public double[] asArray() {
return point.clone();
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!(obj instanceof Point))
return false;
Point other = (Point) obj;
if (this.point.length != other.point.length)
return false;
for (int i = 0; i < point.length; i++) {
if (!MathUtil.equals(this.point[i], other.point[i]))
return false;
}
return true;
}
@Override
public int hashCode() {
int n = 0;
for (double d : point) {
n *= 37;
n += (int) (d * 1000);
}
return n;
}
@Override
public String toString() {
return "Point" + Arrays.toString(point);
}
}