/**************************************************************************** * cartesian.h * Shared stuff for dealing with Cartesian coordinates * Also contains quaternion structures and operations * * Cartesian point of doubles: cPt * Cartesian point of integers: iPt * Vector of doubles: vectorPt * Color of doubles: colorPt * Quaternion: Quaternion * * Can be accessed as cPt.x, cPt[X], colorPt[GREEN], iPt[I], etc. * * * W. Michael Brown ****************************************************************************/ /*! \file */ #ifndef CARTESIAN_H #define CARTESIAN_H #include "miscm.h" #include "m_constants.h" #include "spherical.h" #include #include #include #include using namespace std; enum { X, ///<0 Y, ///<1 Z ///<2 }; enum { I, ///<0 J, ///<1 K, ///<2 W ///<3 }; enum { RED, ///<0 GREEN, ///<1 BLUE ///<2 }; // Other coordinates template class Ball; // Template friend declarations template class TwoD; template ostream & operator<< (ostream &out, const TwoD &t); template istream & operator>> (istream &in, TwoD &t); template class ThreeD; template ostream & operator<< (ostream &out, const ThreeD &t); template istream & operator>> (istream &in, ThreeD &t); template ThreeD operator+ (const numtyp, const ThreeD &two); template ThreeD operator- (const numtyp, const ThreeD &two); template ThreeD operator* (const numtyp, const ThreeD &two); template ThreeD operator/ (const numtyp, const ThreeD &two); /// Two dimensional vector /** The elements can be accessed directly .x or .y * or by using the operator [] ( [X], [Y] or [I], [J] ) * * The following operators are currently overloaded: * +,-,* * * operators *,/ returns a vector with each element multiplied * times the corresponding element in the other vector (Matlab .* ) * * the member function dot can be used to compute dot products * * Input and output are overloaded for element I/O of the form "x y" * <<, >> * * \sa cartesian.h for typedefs and defines*/ template class TwoD { public: /// Empty construct. Not necessarily initialized to [0 0] TwoD(); /// Assign both x and y the value TwoD(numtyp x); /// Assignment Constructor TwoD(numtyp cx, numtyp cy); /// Type conversion TwoD(const TwoD &two); /// Ball projection (onto xy-plane) TwoD(const Ball &ball); numtyp x; ///< First element numtyp y; ///< Last element numtyp &operator[](unsigned i); friend ostream & operator<< <>(ostream &out, const TwoD &t); friend istream & operator>> <>(istream &in, TwoD &t); TwoD operator + (const TwoD &two) const; void operator += (const TwoD &two); TwoD operator + (const numtyp two) const; TwoD operator - (const TwoD &two) const; TwoD operator - (const numtyp two) const; TwoD operator * (const numtyp two) const; TwoD operator * (const TwoD &two) const; void operator /= (const numtyp two); bool operator != (const TwoD &two) const; /// Dot Product numtyp dot(const TwoD &two) const; /// Distance between two points numtyp dist(const TwoD &two) const; /// Distance squared between two points numtyp dist2(const TwoD &two) const; /// Returns one of two normals to a line represented by vector TwoD normal(); /// Move coordinates into array void to_array(numtyp *array); /// Set coordinates from array void from_array(numtyp *array); // -------------- Weird functions that help with coord templating unsigned dimensionality(); /// Returns the index of *this (for unsigned) in a square 3D array /** \param s_size s_size[0]=1Dsize **/ numtyp array_index(vector &s_size); /// Increment a 2D index from min to max (same as nested for) /** Returns false when increment is complete **/ bool increment_index(TwoD &minp,TwoD &maxp); /// Return false if x or y is not within the inclusive range bool check_bounds(numtyp min,numtyp max); private: }; ///\var typedef TwoD c2DPt /// Two dimensional vector of doubles typedef TwoD c2DPt; /// Three dimensional vector /** The elements can be accessed directly .x or .y or .z * or by using the operator [] ( [X], [Y], [Z] or [I], [J], [K] or * [RED], [GREEN], [BLUE] ) * * The following operators are currently overloaded: * +,-,*,/,+=,-=,*=,/=,==,!= * * operators *,/,*=,/= returns a vector with each element multiplied * times the corresponding element in the other vector (Matlab .* ) * or with each element multiplied by a scalar * * the member function dot can be used to compute dot products * * Input and output are overloaded for element I/O of the form "x y z" * <<, >> * * \sa cartesian.h for typedefs and defines*/ template class ThreeD { public: /// Assignment Constructor ThreeD(numtyp cx, numtyp cy, numtyp cz); /// Assign all the value ThreeD(numtyp in); /// Type Conversion ThreeD(const ThreeD&); /// Type Conversion ThreeD(const ThreeD&); /// Type Conversion ThreeD(const ThreeD&); /// Type Conversion ThreeD(const ThreeD&); /// TwoD with (z-coordinate set to zero) ThreeD(const TwoD&); /// Spherical Conversion ThreeD(const Ball&); /// Spherical Conversion ThreeD(const Ball&); /// Empty construct (Not necessarily initialized to zero) ThreeD(); numtyp x; ///< First Element numtyp y; ///< Second Element numtyp z; ///< Last Element friend ostream & operator<< <>(ostream &out, const ThreeD &t); friend istream & operator>> <>(istream &in, ThreeD &t); friend ThreeD operator+ <>(const numtyp, const ThreeD &two); friend ThreeD operator- <>(const numtyp, const ThreeD &two); friend ThreeD operator* <>(const numtyp, const ThreeD &two); friend ThreeD operator/ <>(const numtyp, const ThreeD &two); inline numtyp &operator[](unsigned i) { switch(i) { case X: return x; case Y: return y; case Z: return z; } return x; } inline numtyp operator[](unsigned i) const { switch(i) { case X: return x; case Y: return y; case Z: return z; } return x; } bool operator == (const ThreeD &two) const; bool operator != (const ThreeD &two) const; ThreeD operator + (const ThreeD &two) const; ThreeD operator + (const numtyp &two) const; ThreeD operator - (const ThreeD &two) const; ThreeD operator - (const numtyp &two) const; ThreeD operator * (const numtyp &two) const; ThreeD operator * (const ThreeD &two) const; ThreeD operator / (const numtyp &two) const; ThreeD operator / (const ThreeD &two) const; void operator = (const ThreeD &two); void operator += (const numtyp &two); void operator += (const ThreeD &two); void operator -= (const numtyp &two); void operator -= (const ThreeD &two); inline void operator *= (const numtyp &two) { x*=two; y*=two; z*=two; } void operator /= (const numtyp &two); /// Move coordinates into array void to_array(numtyp *array); /// Set coordinates from array void from_array(numtyp *array); /// Returns the dot product of *this and two numtyp dot(const ThreeD &two) const; /// Returns the cross product of \b *this and \b two /** The input vectors do not need to be normalized, however, the output * vector will not be */ ThreeD cross(const ThreeD &two) const; /// Returns the angle between \b *this and \b two numtyp angle(const ThreeD &two) const; /// Returns an arbitrary vector that is perpendicular to the input /** The output vector is not normalized */ ThreeD perpendicular(); /// Rotate a vector in xz-plane by t radians ThreeD rotatey(double t) const; /// Rotate a vector in xy-plane by t radians ThreeD rotatez(double t) const; /// Magnitude of vector numtyp norm() const; /// Squared norm of a vector numtyp norm2() const; /// Magnitude of vector numtyp hypot() const; /// Distance between two points inline numtyp dist(const ThreeD &two) { return (*this-two).norm(); } /// Distance squared between two points numtyp dist2(const ThreeD &two); /// Converts \b *this to the unit vector inline void normalize() { numtyp temp=norm(); #ifdef NANCHECK assert(temp!=0); #endif *this/=temp; } /// Return the unit vector of \b *this ThreeD unit(); /// Returns the projection of the point or vector onto Z-plane c2DPt projz(); /// Set this to be the max of one and two for each dimension void max(ThreeD &one, ThreeD &two); /// Set this to be the min of one and two for each dimension void min(ThreeD &one, ThreeD &two); // -------------- Weird functions that help with coord templating /// Returns 3 unsigned dimensionality(); /// Returns the index of *this (for unsigned) in a square 3D array /** \param s_size s_size[0]=1Dsize, and s_size[1]=1D size*1Dsize **/ numtyp array_index(vector &s_size); /// Increment a 3D index from min to max (same as nested for) /** \note This is currently only implemented for unsigned numbers * Returns false when increment is complete **/ bool increment_index(ThreeD &minp,ThreeD &maxp); /// Return false if x,y, or z is not within the inclusive range bool check_bounds(numtyp min,numtyp max); private: }; ///\var typedef ThreeD iPt; /// Three dimensional vector of integers typedef ThreeD iPt; ///\var typedef ThreeD uPt; /// Three dimensional vector of unsigned typedef ThreeD uPt; ///\var typedef ThreeD cPt; /// Three dimensional vector of doubles typedef ThreeD cPt; ///\var typedef ThreeD vectorPt; /// Three dimensional vector of doubles typedef ThreeD vectorPt; ///\var typedef ThreeD colorPt; /// Three dimensional vector of doubles typedef ThreeD colorPt; ///\def ORIGIN /// Point at origin #define ORIGIN cPt(0.0,0.0,0.0) ///\def XAXIS /// Unit vector for x-axis #define XAXIS vectorPt(1.0,0.0,0.0) ///\def YAXIS /// Unit vector for y-axis #define YAXIS vectorPt(0.0,1.0,0.0) ///\def ZAXIS /// Unit vector for z-axis #define ZAXIS vectorPt(0.0,0.0,1.0) class RotMat; /// Euler Rotation class EulerRot { public: EulerRot(); EulerRot(double theta,double psi,double phi); /// Rotate the rotation axis by a given rotation matrix void rotate_axis(const RotMat &rotmat); void operator= (const EulerRot &two); friend ostream & operator<<(ostream &out, const EulerRot &rot); double theta; double psi; double phi; }; ///\def EU_NOROTATE /// EulerRot with no rotation #define EU_NOROTATE EulerRot(0.0,0.0,0.0) //---------------------------Quaternion Stuff ------------------------- /// Class for handling Quaternion vectors /** The elements can be accessed directly .w .i .j or .k * or by using the operator[] ( [W], [X], [Y], [Z] or [W], [I], [J], [K] ) * * The following operators are currently overloaded: * +=,*,*=,=,== * * Overloaded * concatenates two successive rotations \n * \e It \e is \e not \e communative \n * For \e join=q1*q2, \e join is equivalent to performing rotation \e q1 * \b followed by \e q2. * * Input and output are overloaded for element I/O of the form "w i j k" * <<, >> * * \sa cartesian.h for typedefs and defines*/ class Quaternion { public: Quaternion(); ~Quaternion(); double w; ///>(istream &in, Quaternion &q); }; /// Rotation matrix (about origin) /** Rotation of ThreeD can be applied via overloaded * operator **/ class RotMat { public: /// Unspecified matrix! RotMat(); /// Initialize with quaternion RotMat(const Quaternion &q); /// Set based on quaternion void set(const Quaternion &q); /// Assert that the rotation is proper void proper(); cPt operator*(const cPt &in) const; double x_x,x_y,x_z,y_x,y_y,y_z,z_x,z_y,z_z; }; ///\def NOROTATE /// Quaternion with no rotation #define NOROTATE Quaternion(1.0,0.0,0.0,0.0) /// Global geometry functions namespace c { /// Returns point on a line closest to an outside point /** The line is described by a directional vector and a point on the line *\param v Vector describing the line direction *\param v_point Point on the line *\param point The Outside point */ cPt point_to_line(const vectorPt &v, const cPt &v_point, const cPt &point); /// Return the closest distance between two line segments input as end points /**\param l1_1 End point of segment 1 *\param l1_2 End point of segment 1 *\param l2_1 End point of segment 2 *\param l2_2 End point of segment 2 */ double closest_approach(const cPt &l1_1, const cPt &l1_2, const cPt &l2_1, const cPt &l2_2); /// Calculates the points where two line segments are closest /**\param l1_1 End point of segment 1 *\param l1_2 End point of segment 1 *\param l2_1 End point of segment 2 *\param l2_2 End point of segment 2 *\param close_l1 Calculated closest point on line segment 1 *\param close_l2 Calculated closest point on line segment 2 */ void closest_approach_points(const cPt &l1_1, const cPt &l1_2, const cPt &l2_1, const cPt &l2_2, cPt &close_l1, cPt &close_l2); /// Returns true if two line segments intersect bool intersect(const c2DPt &line1_start, const c2DPt &line1_end, const c2DPt &line2_start, const c2DPt &line2_end); /// Liang-Barsky Intersection between line segment and line bool sline_intersect(const c2DPt &line1_start, const c2DPt &line1_end, const c2DPt &line2normal, const c2DPt &line2_point); /// Average position cPt mean(vector &vec); } #endif