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). */