package hep.physics.vec;
import java.io.Serializable;
/**
* A Hep3Vector representing a point in space.
* Derived from work by Norman Graf, Jan Strube and Frank Gaede
* @version $Id: SpacePoint.java 12630 2007-06-10 16:32:10Z tonyj $
*/
// Fixme: This class has many problems.
// The v() method is not compatible with Hep3Vector or the magnitude method
// The equals method is not consistent with Object.equals() or hashcode()
// The not equals method is pointless
// The clone method should not trap and throw away exceptions
// There is no way to construct a space point with non-Cartesian representations
public class SpacePoint implements Serializable, Hep3Vector, Cloneable
{
private Representation _representation;
private double _x;
private double _y;
private double _z;
private double _xy;
private double _xyz;
private double _phi;
private double _theta;
/**
* Returns the space point as a double array <b>in its internal representation</b>
* @see SpacePoint#getRepresentation()
*/
public double[] v()
{
switch(_representation)
{
case Cartesian: return new double[] {_x, _y, _z};
case Spherical: return new double[] {_xyz, _phi, _theta};
case Cylindrical: return new double[] {_xy, _phi, _z};
default: return new double[3];
}
}
private void cartesianToCylindricalR()
{
_xy = Math.sqrt(_x*_x+_y*_y);
}
private void cartesianToPhi()
{
_phi = Math.atan2(_y,_x);
}
private void cartesianToTheta()
{
if (Double.isNaN(_xy))
cartesianToCylindricalR();
_theta = Math.atan2(_xy,_z);
}
public double magnitude()
{
return _xyz;
}
public double magnitudeSquared()
{
return _xyz*_xyz;
}
/**
* Default constructor.
* Sets point to be the origin (0,0,0)
*/
public SpacePoint()
{
_x = _y = _z = 0.0;
_xy = _xyz = 0.0;
_phi = _theta = 0.0;
}
/**
* Copy constructor
*
* @param spt SpacePoint to copy
*/
public SpacePoint( SpacePoint spt )
{
_representation = spt._representation;
_x = spt.x();
_y = spt.y();
_z = spt.z();
_xy = spt.rxy();
_xyz = spt.rxyz();
_phi = spt.phi();
_theta = spt.theta();
}
public SpacePoint(Hep3Vector vec)
{
_representation = Representation.Cartesian;
_x = vec.x();
_y = vec.y();
_z = vec.z();
_xyz = Math.sqrt(_x*_x + _y*_y + _z*_z);
_xy = _phi = _theta = Double.NaN;
}
private void cylindricalToCartesianX()
{
_x = _xy*Math.cos(_phi);
}
private void sphericalToCartesianX()
{
_x = _xyz*Math.cos(_phi)*Math.sin(_theta);
}
private void sphericalToCartesianY()
{
_y = _xyz*Math.sin(_phi)*Math.sin(_theta);
}
private void sphericalToCartesianZ()
{
_z = _xyz*Math.cos(_theta);
}
/**
* Cartesian x
*/
public double x()
{
if (Double.isNaN(_x))
switch(_representation)
{
case Spherical: sphericalToCartesianX(); break;
case Cylindrical: cylindricalToCartesianX(); break;
}
return _x;
}
private void cylindricalToCartesianY()
{
_y = _xy*Math.sin(_phi);
}
/**
* Cartesian y
*/
public double y()
{
if (Double.isNaN(_y))
switch(_representation)
{
case Spherical: sphericalToCartesianY(); break;
case Cylindrical: cylindricalToCartesianY(); break;
}
return _y;
}
/**
* Cartesian z
*/
public double z()
{
if (Double.isNaN(_z))
sphericalToCartesianZ();
return _z;
}
private void sphericalToCylindricalR()
{
_xy = _xyz*Math.sin(_theta);
}
/**
* Cylindrical r
* @return double
*/
public double rxy()
{
if (Double.isNaN(_xy))
switch(_representation)
{
case Spherical: sphericalToCylindricalR(); break;
case Cartesian: cartesianToCylindricalR(); break;
}
return _xy;
}
/**
* Cylindrical phi
* @return double
*/
public double phi()
{
if (Double.isNaN(_phi))
cartesianToPhi();
return _phi;
}
/**
* Spherical r
* @return double
*/
public double rxyz()
{
return _xyz;
}
/**
* Spherical theta
* @return double
*/
public double theta()
{
if (Double.isNaN(_theta))
switch(_representation)
{
case Cartesian: cartesianToTheta(); break;
case Cylindrical: cylindricalToTheta(); break;
}
return _theta;
}
private void cylindricalToTheta()
{
_theta = Math.atan2(_xy,_z);
}
/**
* cos(phi)
*/
public double cosPhi()
{
if ( !Double.isNaN(_x) && !Double.isNaN(_xy) && _xy != 0. )
return _x/_xy;
if (Double.isNaN(_phi))
cartesianToPhi();
return Math.cos(_phi);
}
/**
* sin(phi)
*/
public double sinPhi()
{
if (!Double.isNaN(_y) && !Double.isNaN(_xy) && _xy != 0. )
return _y/_xy;
if (Double.isNaN(_phi))
cartesianToPhi();
return Math.sin(_phi);
}
/**
* sin(theta)
* @return double
*/
public double sinTheta()
{
if ( !Double.isNaN(_xy) && _xyz != 0. )
return _xy/_xyz;
if (Double.isNaN(_theta))
switch(_representation)
{
case Cartesian: cartesianToTheta(); break;
case Cylindrical: cylindricalToTheta(); break;
}
return Math.sin(_theta);
}
/**
* cos(theta)
* @return double
*/
public double cosTheta()
{
if ( !Double.isNaN(_z) && _xyz != 0. )
return _z/_xyz;
if (Double.isNaN(_theta))
switch(_representation)
{
case Cartesian: cartesianToTheta(); break;
case Cylindrical: cylindricalToTheta(); break;
}
return Math.cos(_theta);
}
/**
* Output Stream
*
* @return String representation of object
*/
public String toString()
{
return _representation + " SpacePoint: " + "\n" +
" x: " + x() + "\n" +
" y: " + y() + "\n" +
" z: " + z() + "\n" +
" rxy: " + rxy() + "\n" +
" rxyz: " + rxyz() + "\n" +
" phi: " + phi() + "\n" +
"theta: " + theta() + "\n" ;
}
/**
* Tests for equality within errors
* @param spt a SpacePoint to compare against
* @param precision the precision of the comparison
* @return true if each of the components is within precision
* of the components of spt
*/
public boolean equals(SpacePoint spt, double precision)
{
return ( Math.abs(x() - spt.x()) < precision ) &&
( Math.abs(y() - spt.y()) < precision ) &&
( Math.abs(z() - spt.z()) < precision );
}
/**
* Tests for equality within errors
* @param spt a Hep3Vector to compare against
* @param precision the precision of the comparison
* @return true if each of the components is within precision
* of the components of spt
*/
public boolean equals(Hep3Vector spt, double precision)
{
return ( Math.abs(x() - spt.x()) < precision ) &&
( Math.abs(y() - spt.y()) < precision ) &&
( Math.abs(z() - spt.z()) < precision );
}
/**
* Tests for equality
* @param x SpacePoint to compare
* @return true if objects are equal
*/
public boolean equals(SpacePoint x)
{
return equals(x, 1e-14);
}
/**
*Inequality
*
* @param spt SpacePoint to compare
* @return true if objects are <em> not </em> equal
*/
public boolean notEquals(SpacePoint spt)
{
return ! (equals(spt));
}
/**
* Return the distance between two space points.
* @param spt1 SpacePoint 1
* @param spt2 SpacePoint 2
* @return Euclidean distance between points
*/
public static double distance(SpacePoint spt1, SpacePoint spt2)
{
double dx = spt2.x() - spt1.x();
double dy = spt2.y() - spt1.y();
double dz = spt2.z() - spt1.z();
return Math.sqrt( dx*dx + dy*dy + dz*dz );
}
/**
*Clone
*
* @return a copy of this object
*/
public Object clone()
{
Object o = null;
try
{
o = super.clone();
}
catch (CloneNotSupportedException e)
{
e.printStackTrace();
}
return o;
}
/**
* @return array of doubles, cartesian representation
*/
public double[] getCartesianArray()
{
return new double[] {_x, _y, _z};
}
/**
* @return the representations of the object
*/
public Representation getRepresentation()
{
return _representation;
}
public enum Representation
{
Cartesian, Cylindrical, Spherical
}
}