package edu.stanford.rsl.conrad.geometry.shapes.simple;
import java.io.Serializable;
import edu.stanford.rsl.conrad.geometry.General;
import edu.stanford.rsl.conrad.geometry.transforms.Transform;
import edu.stanford.rsl.conrad.geometry.transforms.Transformable;
import edu.stanford.rsl.conrad.numerics.SimpleOperators;
import edu.stanford.rsl.conrad.numerics.SimpleVector;
import edu.stanford.rsl.conrad.utils.CONRAD;
/**
* Class to model points of arbitrary dimension. Compatible with numerics.
*
* @author akmaier
*
*/
public class PointND implements Serializable, Transformable {
protected SimpleVector coordinates;
/**
* @param coordinates the coordinates to set
*/
public void setCoordinates(SimpleVector coordinates) {
this.coordinates = coordinates;
}
/**
*
*/
private static final long serialVersionUID = -1747968959310910786L;
/**
* Creates a new point of the specified dimension
* @param knotVector the dimension
*/
public PointND(SimpleVector knotVector){
coordinates = knotVector;
}
public PointND(){
}
/**
* Copy constructor
* @param point
*/
public PointND(PointND point){
coordinates = point.coordinates.clone();
}
public PointND clone(){
return new PointND(coordinates.clone());
}
/**
* Creates a new point of a given array or list of double values.<br>
* <pre>
* PointND p = new PointND(1.5, 2.5);
* ArbitrayrPoint p2 = new PointND(new double [] {1.5, 2.5});
* </pre>
* will create two 2D points at the same location.<br>
*
* @param point
*/
public PointND(double ... point) {
coordinates = new SimpleVector(point);
}
/**
* Returns a copy of the point as double array.
* @return the coordinates as double []
*/
public double [] getCoordinates(){
double [] revan = new double [coordinates.getLen()];
coordinates.copyTo(revan);
return revan;
}
/**
* Method to retrieve coordinate entries
* @param i the index of the coordinate [0, dim[
* @return the coordinate
*/
public double get(int i){
return coordinates.getElement(i);
}
/**
* Methods to set individual entries of the coordinates
* @param i the index of the coordinate [0, dim[
* @param d the value of the coordinate
*/
public void set(int i, double d){
coordinates.setElementValue(i, d);
}
/**
* Returns the internal abstract vector to enable computations via the numerics library.<BR>
* <b>Changes to the vector will affect the point</b>
* @return the internal abstract vector
*/
public SimpleVector getAbstractVector(){
return coordinates;
}
/**
* Returns the dimension of the point
* @return the dimension
*/
public int getDimension() {
return coordinates.getLen();
}
/**
* computes the Euclidean distance between the current point {@latex.inline $\\mathbf{x_1} = (x_1, y_1)$} the the point "two" {@latex.inline $\\mathbf{x_2} = (x_2, y_2)$} as
* {@latex.ilb
$|| \\mathbf{x_1} - \\mathbf{x_2} || = \\sqrt{\\sum_n(x_1(n) - x_2(n))^2}$.
}
* @param two the other point
* @return the distance
*/
public double euclideanDistance(PointND two){
return General.euclideanDistance(this.coordinates, two.coordinates);
// assert(two.getDimension() == getDimension());
// double revan = 0;
// double [] other = two.getCoordinates();
// for (int i=0; i< coordinates.getLen(); i++){
// revan += Math.pow(other[i] - coordinates.getElement(i), 2);
// }
// return Math.sqrt(revan);
}
/**
* Updates the vector at entries which are higher in p. Used to scan for a maximum in an iterative process.
* Search for a bounding box can be performed like this:
* <pre>
* ArrayList<PointND> list = ...
* PointND max = new PointND(-Double.MAX_VALUE, -Double.MAX_VALUE, -Double.MAX_VALUE);
* for (PointND p : list){
* max.updateIfHigher(p);
* }
* <pre>
*
* @param p the other point
*/
public void updateIfHigher(PointND p) {
if (p == null)
return;
for (int i = 0; i < coordinates.getLen(); i++) {
if (p.coordinates.getElement(i) > coordinates.getElement(i)) {
coordinates.setElementValue(i, p.coordinates.getElement(i));
}
}
}
/**
* Updates the vector at entries which are higher in p. Used to scan for a minimum in an iterative process.
* Search for a bounding box can be performed like this:
* <pre>
* ArrayList<PointND> list = ...
* PointND min = new PointND(Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE);
* for (PointND p : list){
* min.updateIfLower(p);
* }
* <pre>
*
* @param p the other point
*/
public void updateIfLower(PointND p) {
if (p == null)
return;
for (int i = 0; i < coordinates.getLen(); i++) {
if (p.coordinates.getElement(i) < coordinates.getElement(i)) {
coordinates.setElementValue(i, p.coordinates.getElement(i));
}
}
}
@Override
public boolean equals(Object o) {
if (o instanceof PointND) {
PointND p = (PointND) o;
return (SimpleOperators.subtract(coordinates, p.coordinates).normL2() < CONRAD.FLOAT_EPSILON);
} else {
return false;
}
}
@Override
public void applyTransform(Transform t) {
coordinates = t.transform(this).coordinates;
}
public double innerProduct(PointND pointND) { // suwest
double innerProduct = 0.0;
for(int i = 0; i < pointND.getDimension(); ++i){
innerProduct += this.get(i) * pointND.get(i);
}
return innerProduct;
}
/////////////////////////////////////////////////
// Serialization and Persistence //
/////////////////////////////////////////////////
public String getVectorSerialization() {
return (coordinates != null) ? coordinates.toString() : null;
}
public void setVectorSerialization(final String str) {
if(str == null) coordinates = null;
else{
if (coordinates == null)
coordinates = new SimpleVector();
coordinates.init(str);
}
}
@Override
public String toString(){
return (coordinates != null) ? coordinates.toString() : null;
}
}
/*
* Copyright (C) 2010-2014 Andreas Maier, Rotimi X Ojo
* CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
*/