Newer
Older
Russell Taylor
committed
#include <cmath>
Gigg, Martyn Anthony
committed
#include <math.h>
Gigg, Martyn Anthony
committed
#include "MantidKernel/V3D.h"
#include "MantidKernel/Tolerance.h"
Russell Taylor
committed
#include "MantidKernel/Exception.h"
Gigg, Martyn Anthony
committed
namespace Kernel
Russell Taylor
committed
x(xx),y(yy),z(zz)
/**
Sets the vector position based on spherical coordinates
Janik Zikovsky
committed
@param R :: The R value (distance)
@param theta :: The theta value (in degrees) = the polar angle away from the +Z axis.
@param phi :: The phi value (in degrees) = the azimuthal angle, where 0 points along +X and rotates counter-clockwise in the XY plane
*/
void V3D::spherical(const double& R, const double& theta, const double& phi)
{
const double deg2rad=M_PI/180.0;
z=R*cos(theta*deg2rad);
const double ct=sin(theta*deg2rad);
x=R*ct*cos(phi*deg2rad);
y=R*ct*sin(phi*deg2rad);
// Setting this way can lead to very small values of x & y that should really be zero.
// This can cause confusion for the atan2 function used in getSpherical.
if (std::abs(x) < Tolerance) x = 0.0;
if (std::abs(y) < Tolerance) y = 0.0;
}
/**
Sets the vector position based on spherical coordinates, in radians
Janik Zikovsky
committed
@param R :: The R value (distance)
@param polar :: the polar angle (in radians) away from the +Z axis.
@param azimuth :: the azimuthal angle (in radians), where 0 points along +X and rotates counter-clockwise in the XY plane
void V3D::spherical_rad(const double& R, const double& polar, const double& azimuth)
z=R*cos(polar);
const double ct=R*sin(polar);
x=ct*cos(azimuth);
y=ct*sin(azimuth);
// Setting this way can lead to very small values of x & y that should really be zero.
// This can cause confusion for the atan2 function used in getSpherical.
if (std::abs(x) < Tolerance) x = 0.0;
if (std::abs(y) < Tolerance) y = 0.0;
/**
Sets the vector position based on azimuth and polar angle, in RADIANS, in the SNS instrument coordinate system,
where +Z = beam direction, +Y = vertical.
Janik Zikovsky
committed
@param R :: The R value (distance)
@param azimuth :: The azimuthal angle (in Radians)
@param polar :: The polar value (in Radians)
*/
void V3D::azimuth_polar_SNS(const double& R, const double& azimuth, const double& polar)
{
y=R*cos(polar);
const double ct=R*sin(polar);
x=ct*cos(azimuth);
z=ct*sin(azimuth);
// Setting this way can lead to very small values of x & y that should really be zero.
// This can cause confusion for the atan2 function used in getSpherical.
if (std::abs(x) < Tolerance) x = 0.0;
if (std::abs(y) < Tolerance) y = 0.0;
if (std::abs(z) < Tolerance) z = 0.0;
}
Janik Zikovsky
committed
@param rhs :: V3D to copy
@return *this
V3D& V3D::operator=(const V3D& rhs)
x = rhs.x;
y = rhs.y;
z = rhs.z;
Constructor from a pointer.
requires that the point is assigned after this has
been allocated since vPtr[x] may throw.
*/
Russell Taylor
committed
V3D::V3D(const double* vPtr)
{
if (vPtr)
{
x=vPtr[0];
y=vPtr[1];
z=vPtr[2];
}
}
/// Destructor
Janik Zikovsky
committed
@param v :: Vector to add
@return *this+v;
Russell Taylor
committed
V3D
Janik Zikovsky
committed
@param v :: Vector to sub.
@return *this-v;
Russell Taylor
committed
V3D
Janik Zikovsky
committed
@param v :: Vector to sub.
@return *this * v;
Russell Taylor
committed
V3D
Janik Zikovsky
committed
@param v :: Vector to divide
@return *this * v;
Russell Taylor
committed
V3D
Janik Zikovsky
committed
@param v :: Vector to add.
@return *this+=v;
Russell Taylor
committed
V3D&
V3D::operator+=(const V3D& v)
{
x+=v.x;
y+=v.y;
z+=v.z;
return *this;
}
Janik Zikovsky
committed
@param v :: Vector to sub.
@return *this-v;
Russell Taylor
committed
V3D&
V3D::operator-=(const V3D& v)
{
x-=v.x;
y-=v.y;
z-=v.z;
return *this;
}
Janik Zikovsky
committed
@param v :: Vector to multiply
@return *this*=v;
Russell Taylor
committed
V3D&
V3D::operator*=(const V3D& v)
{
x*=v.x;
y*=v.y;
z*=v.z;
return *this;
}
Janik Zikovsky
committed
@param v :: Vector to divide
@return *this*=v;
Russell Taylor
committed
V3D&
V3D::operator/=(const V3D& v)
{
x/=v.x;
y/=v.y;
z/=v.z;
return *this;
}
Janik Zikovsky
committed
@param D :: value to scale
@return this * D
Russell Taylor
committed
V3D
Janik Zikovsky
committed
@param D :: value to scale
@return this / D
Russell Taylor
committed
V3D
Janik Zikovsky
committed
@param D :: value to scale
@return this *= D
Russell Taylor
committed
V3D&
Janik Zikovsky
committed
@param D :: value to scale
@return this /= D
Russell Taylor
committed
V3D&
V3D::operator/=(const double D)
{
if (D!=0.0)
{
x/=D;
y/=D;
z/=D;
}
return *this;
}
Janik Zikovsky
committed
@param v :: V3D for comparison
@return true if the items are equal
Russell Taylor
committed
bool
using namespace std;
return (fabs(x-v.x)>Tolerance ||
fabs(y-v.y)>Tolerance ||
fabs(z-v.z)>Tolerance) ?
/** Not equals operator with tolerance factor.
Janik Zikovsky
committed
* @param other :: The V3D to compare against
* @returns True if the vectors are different
*/
bool V3D::operator!=(const V3D& other) const
{
return !(this->operator==(other));
}
Janik Zikovsky
committed
@return true if V is greater
Russell Taylor
committed
bool
{
if (x!=V.x)
return x<V.x;
if (y!=V.y)
return y<V.y;
return z<V.z;
}
Janik Zikovsky
committed
@param xx :: The X coordinate
@param yy :: The Y coordinate
@param zz :: The Z coordinate
Russell Taylor
committed
void
V3D::operator()(const double xx, const double yy, const double zz)
{
x=xx;
y=yy;
z=zz;
return;
}
Anders Markvardsen
committed
/**
Set is x position
Janik Zikovsky
committed
@param xx :: The X coordinate
Anders Markvardsen
committed
*/
void V3D::setX(const double xx)
{
x=xx;
}
/**
Set is y position
Janik Zikovsky
committed
@param yy :: The Y coordinate
Anders Markvardsen
committed
*/
void V3D::setY(const double yy)
{
y=yy;
}
/**
Set is z position
Janik Zikovsky
committed
@param zz :: The Z coordinate
Anders Markvardsen
committed
*/
void V3D::setZ(const double zz)
{
z=zz;
}
Janik Zikovsky
committed
@param Index :: 0=x, 1=y, 2=z
@return a double value of the requested axis
Gigg, Martyn Anthony
committed
V3D::operator[](const size_t Index) const
{
switch (Index)
{
case 0: return x;
case 1: return y;
case 2: return z;
default:
Russell Taylor
committed
throw Kernel::Exception::IndexError(Index,2,"V3D::operator[] range error");
Janik Zikovsky
committed
@param Index :: 0=x, 1=y, 2=z
@return a double value of the requested axis
Gigg, Martyn Anthony
committed
V3D::operator[](const size_t Index)
{
switch (Index)
{
case 0: return x;
case 1: return y;
case 2: return z;
default:
Russell Taylor
committed
throw Kernel::Exception::IndexError(Index,2,"V3D::operator[] range error");
/** Return the vector's position in spherical coordinates
Janik Zikovsky
committed
* @param R :: Returns the radial distance
* @param theta :: Returns the theta angle in degrees
* @param phi :: Returns the phi (azimuthal) angle in degrees
Russell Taylor
committed
void V3D::getSpherical(double& R, double& theta, double& phi) const
{
const double rad2deg = 180.0/M_PI;
R = norm();
theta = 0.0;
if ( R ) theta = acos(z/R) * rad2deg;
phi = atan2(y,x) * rad2deg;
return;
}
Janik Zikovsky
committed
@return vec.length()
Russell Taylor
committed
double
Janik Zikovsky
committed
@return vec.length()
Russell Taylor
committed
double
Alex Buts
committed
return (x*x+y*y+z*z);
Russell Taylor
committed
Normalises the vector and
Janik Zikovsky
committed
@return Norm
{
const double ND(norm());
this->operator/=(ND);
return ND;
}
Gigg, Martyn Anthony
committed
/** Round each component to the nearest integer */
void V3D::round()
{
x = double(long(x + (x<0?-0.5:+0.5)));
y = double(long(y + (y<0?-0.5:+0.5)));
z = double(long(z + (z<0?-0.5:+0.5)));
}
Janik Zikovsky
committed
@param V :: The second vector to include in the calculation
@return The scalar product of the two vectors
Russell Taylor
committed
double
V3D::scalar_prod(const V3D& V) const
{
return (x*V.x+y*V.y+z*V.z);
}
Janik Zikovsky
committed
Calculates the cross product. Returns (this * v).
Janik Zikovsky
committed
@param v :: The second vector to include in the calculation
@return The cross product of the two vectors (this * v)
Russell Taylor
committed
V3D
return V3D(y*v.z-z*v.y, z*v.x-x*v.z,x*v.y-y*v.x);
Janik Zikovsky
committed
@param v :: The second vector to include in the calculation
@return The distance between the two vectors
Russell Taylor
committed
double
V3D::distance(const V3D& v) const
{
V3D dif(*this);
dif-=v;
return dif.norm();
}
Russell Taylor
committed
/** Calculates the zenith angle (theta) of this vector with respect to another
Janik Zikovsky
committed
* @param v :: The other vector
* @return The azimuthal angle in radians (0 < theta < pi)
Russell Taylor
committed
*/
double V3D::zenith(const V3D& v) const
{
double R = distance(v);
double zOffset = z - v.z;
if ( R )
{
return acos( zOffset / R );
}
else
{
return 0.0;
}
}
Janik Zikovsky
committed
/** Calculates the angle between this and another vector.
*
Janik Zikovsky
committed
* @param v :: The other vector
* @return The angle between the vectors in radians (0 < theta < pi)
Russell Taylor
committed
*/
double V3D::angle(const V3D& v) const
{
return acos( this->scalar_prod(v) / (this->norm() * v.norm()) );
}
Russell Taylor
committed
V3D::reBase(const V3D& A,const V3D&B,const V3D& C)
Janik Zikovsky
committed
/**
Re-express this point components of A,B,C.
Assuming that A,B,C are form an basis set (which
does not have to be othonormal.
Janik Zikovsky
committed
@param A :: Unit vector in basis
@param B :: Unit vector in basis
@param C :: Unit vector in basis
@retval -1 :: The points do not form a basis set.
@retval 0 :: Vec3D has successfully been re-expressed.
*/
{
Matrix<double> T(3,3);
for(int i=0;i<3;i++)
{
T[i][0]=A[i];
T[i][1]=B[i];
T[i][2]=C[i];
}
const double det=T.Invert();
if (fabs(det)<1e-13) // failed
return -1;
rotate(T);
return 0;
}
void
Gigg, Martyn Anthony
committed
V3D::rotate(const Kernel::Matrix<double>& A)
Janik Zikovsky
committed
/**
Russell Taylor
committed
Rotate a point by a matrix
Janik Zikovsky
committed
@param A :: Rotation matrix (needs to be >3x3)
*/
{
Matrix<double> Pv(3,1);
Pv[0][0]=x;
Pv[1][0]=y;
Pv[2][0]=z;
Matrix<double> Po=A*Pv;
x=Po[0][0];
y=Po[1][0];
z=Po[2][0];
return;
}
Janik Zikovsky
committed
/**
Gigg, Martyn Anthony
committed
Determines if this,B,C are collinear
Janik Zikovsky
committed
@param Bv :: Vector to test
@param Cv :: Vector to test
@return false is no colinear and true if they are (within Ptolerance)
Gigg, Martyn Anthony
committed
bool
V3D::coLinear(const V3D& Bv,const V3D& Cv) const
{
const V3D& Av=*this;
const V3D Tmp((Bv-Av).cross_prod(Cv-Av));
Gigg, Martyn Anthony
committed
return (Tmp.norm()>Tolerance) ? false : true;
Gigg, Martyn Anthony
committed
bool
V3D::nullVector(const double Tol) const
Janik Zikovsky
committed
/**
Checks the size of the vector
Janik Zikovsky
committed
@param Tol :: size of the biggest zero vector allowed.
@retval 1 : the vector squared components
Russell Taylor
committed
magnitude are less than Tol
Janik Zikovsky
committed
@retval 0 :: Vector bigger than Tol
using namespace std;
if (fabs(x)>Tol)
Gigg, Martyn Anthony
committed
return false;
if (fabs(y)>Tol)
Gigg, Martyn Anthony
committed
return false;
if (fabs(z)>Tol)
Gigg, Martyn Anthony
committed
return false;
// Getting to this point means a null vector
return true;
Russell Taylor
committed
int
V3D::masterDir(const double Tol) const
Janik Zikovsky
committed
/**
Calculates the index of the primary direction (if there is one)
Janik Zikovsky
committed
@param Tol :: Tolerance accepted
@retval range -3,-2,-1 1,2,3 if the vector
is orientaged within Tol on the x,y,z direction (the sign
indecates the direction to the +ve side )
Janik Zikovsky
committed
@retval 0 :: No master direction
*/
{
// Calc max dist
Russell Taylor
committed
double max=x*x;
double other=max;
double u2=y*y;
int idx=(x>0) ? 1 : -1;
if (u2>max)
{
max=u2;
idx=(y>0) ? 2 : -2;
}
other+=u2;
u2=z*z;
if (u2>max)
{
max=u2;
idx=(z>0) ? 3 : -3;
}
other+=u2;
other-=max;
if ((other/max)>Tol) //doesn't have master direction
{
return 0;
}
return idx;
}
Janik Zikovsky
committed
/**
Russell Taylor
committed
\todo Check Error handling
Janik Zikovsky
committed
@param IX :: Input Stream
*/
void
V3D::read(std::istream& IX)
{
IX>>x>>y>>z;
return;
}
void
V3D::write(std::ostream& OX) const
Janik Zikovsky
committed
/**
Write out the point values
Janik Zikovsky
committed
@param OX :: Output stream
*/
{
OX<<x<<" "<<y<<" "<<z;
return;
}
Roman Tolchenov
committed
Prints a text representation of itself in format "[x,y,z]"
Janik Zikovsky
committed
@param os :: the Stream to output to
Russell Taylor
committed
void
V3D::printSelf(std::ostream& os) const
{
os << "[" << x << "," << y << "," << z << "]";
return;
}
Janik Zikovsky
committed
/**
Roman Tolchenov
committed
Read data from a stream in the format returned by printSelf ("[x,y,z]").
Janik Zikovsky
committed
@param IX :: Input Stream
@throw std::runtime_error if the input is of wrong format
Roman Tolchenov
committed
*/
void
V3D::readPrinted(std::istream& IX)
{
std::string in;
std::getline(IX,in);
size_t i = in.find_first_of('[');
if (i == std::string::npos) throw std::runtime_error("Wrong format for V3D input: "+in);
size_t j = in.find_last_of(']');
if (j == std::string::npos || j < i + 6) throw std::runtime_error("Wrong format for V3D input: "+in);
size_t c1 = in.find_first_of(',');
size_t c2 = in.find_first_of(',',c1+1);
if (c1 == std::string::npos || c2 == std::string::npos) throw std::runtime_error("Wrong format for V3D input: ["+in+"]");
x = atof(in.substr(i+1,c1-i-1).c_str());
y = atof(in.substr(c1+1,c2-c1-1).c_str());
z = atof(in.substr(c2+1,j-c2-1).c_str());
return;
}
Janik Zikovsky
committed
@param os :: the Stream to output to
@param v :: the vector to output
@return the output stream
Russell Taylor
committed
std::ostream&
operator<<(std::ostream& os, const V3D& v)
{
v.printSelf(os);
return os;
}
Russell Taylor
committed
std::istream&
Janik Zikovsky
committed
/**
Janik Zikovsky
committed
@param IX :: Input Stream
@param A :: Vec3D to write
@return Current state of stream
Gigg, Martyn Anthony
committed
} // Namespace Kernel