code: package util.geom;
  /**
   * This class represents a 3D point. This class is immutable, that means that it
   * can't be changed after its construction.
   * 
   * @author Institute of Stochastics, Ulm University
   */
  public class Point3D {
  	
  	/** A constant for the point located at the origin. */
  	public static final Point3D ORIGIN = new Point3D(0.0, 0.0, 0.0);
  	
  	/** the coordinates defining this point */
  	private final double[] coordinates;
  	
  	/**
  	 * Constructs a new point with the coordinates given by
  	 * <code>coordinates</code>.
  	 * 
  	 * @param coordinates the coordinates defining the point
  	 */
  	public Point3D(double[] coordinates) {
  		this.coordinates = coordinates.clone();
  	}
  	
  	/**
  	 * Constructs a new point with the coordinates given by
  	 * <code>(coord1,coord2,coord3)</code>.
  	 * 
  	 * @param coord1 the first coordinate of the point
  	 * @param coord2 the second coordinate of the point
  	 * @param coord3 the third coordinate of the point
  	 */
  	public Point3D(double coord1, double coord2, double coord3) {
  		this.coordinates = new double[] { coord1, coord2, coord3 };
  	}
  	
  	/**
  	 * Constructs a new point with the same coordinates as the given point.
  	 * 
  	 * @param point the point which will be copied to define this point
  	 */
  	public Point3D(Point3D point) {
  		this.coordinates = point.getCoordinates();
  	}
  	
  	/**
  	 * Checks if the point is very close or equal to <code>geom</code>.
  	 * 
  	 * @param geom the Geometry3D which shall be compared to the point
  	 * @return <code>true</code> if the Geometry3D <code>geom</code> is
  	 *         very close or equal to the point
  	 */
  	public boolean isSimilar(Point3D geom) {
  		double[] coordsO = ((Point3D) geom).getCoordinates();
  		for (int i = 0; i < 3; i++) {
  			if ((coordsO[i] != coordinates[i]) && !Utilities3D.isEqual(coordsO[i], coordinates[i])) 
  				return false;
  		}
  		return true;
  	}
  	
  	/**
  	 * Returns the coordinates of the point.
  	 * 
  	 * @return the coordinates of the point
  	 */
  	public double[] getCoordinates() {
  		return coordinates.clone();
  	}
  	
  	/**
  	 * Translates the point by a point <code>translateVector</code> without
  	 * changing the original point.
  	 * 
  	 * @param translateVector the point or vector by which the object shall be translated
  	 * @return the resulting translated point
  	 */
  	public Point3D translateBy(Point3D translateVector) {
  		double[] newCoords = translateVector.getCoordinates().clone();
  		for (int i = 0; i < 3; i++) {
  			newCoords[i] += coordinates[i];
  		}
  		return new Point3D(newCoords);
  	}
  	
  	/**
  	 * Gets the vector from a point <code>fromPoint</code> to this point.
  	 * 
  	 * @param fromPoint the other point
  	 * @return the resulting vector as a point
  	 */
  	public Point3D getVectorTo(Point3D fromPoint){
  		return this.translateBy(fromPoint.reflectOrigin());
  	}
  	
  	/**
  	 * Calculates the vector product of a given vector and this point.
  	 * 
  	 * @param vector the given vector represented by a point
  	 * @return the vector product represented by a point
  	 */
  	public Point3D getVectorProduct(Point3D vector){
  		double[]coordinates2=vector.getCoordinates();
  		double[]coordinates3=new double[3];
  		for (int i = 0; i < 3; i++){
  			coordinates3[i]= coordinates[(i+1)%3]*coordinates2[(i+2)%3] - coordinates[(i+2)%3]*coordinates2[(i+1)%3];
  		}
  		return new Point3D(coordinates3);
  	}
  	
  	/**
  	 * Calculates the scalar product between a given vector and this point.
  	 * 
  	 * @param vector the given vector represented by a point
  	 * @return the scalar product as a double
  	 */
  	public double getScalarProduct(Point3D vector){
  		double[]coordinates2=vector.getCoordinates();
  		double result=0;
  		for (int i = 0; i < 3; i++){
  			result += coordinates[i]*coordinates2[i];
  		}
  		return result;
  	}
  	
  	/**
  	 * Reflects the point at the origin without changing the original point.
  	 * 
  	 * @return the resulting reflected point
  	 */
  	public Point3D reflectOrigin() {
  		return new Point3D(new double[]{-coordinates[0], -coordinates[1], -coordinates[2]});
  	}
  	
  	/**
  	 * Applies a real scale to the point without changing the original point.
  	 * 
  	 * @param scale the scale for this operation
  	 * @return the scaled point
  	 */
  	public Point3D scaleBy(double scale) {
  		return new Point3D(new double[]{ scale * coordinates[0],
  		                                 scale * coordinates[1],
  		                                 scale * coordinates[2]});
  	}
  	
  	/**
  	 * Scales the point a three-dimensional scale in each direction without
  	 * changing the original point.
  	 * 
  	 * @param scale the 3D scale for this operation
  	 * @return the resulting scaled point
  	 */
  	public Point3D scaleBy(double[] scale) {
  		return new Point3D(new double[]{ coordinates[0] * scale[0],
  		                                 coordinates[1] * scale[1],
  		                                 coordinates[2] * scale[2] });
  	}
  	
  	/**
  	 * Get the length of the vector.
  	 * 
  	 * @return the length as double
  	 */
  	public double getLength() {
  		return Math.sqrt(coordinates[0] * coordinates[0]
  		                 + coordinates[1] * coordinates[1]
  		                 + coordinates[2] * coordinates[2]);
  	}
  	
  	/**
  	 * Norms the point without changing the original point.
  	 * 
  	 * @return the normed point
  	 */
  	public Point3D norm() {
  		double norm = this.getLength();
  		return new Point3D(new double[]{ coordinates[0] / norm,
  		                                 coordinates[1] / norm,
  		                                 coordinates[2] / norm }); 
  	}
  	
  	/**
  	 * Returns a string representation of this point for debugging purposes.
  	 * 
  	 * @return a string representation of this point
  	 */
  	@Override
  	public String toString() {
  		return coordinates[0] + ", " + coordinates[1] + ", " + coordinates[2];
  	}
  	
  }
  