point.h

Go to the documentation of this file.
00001 //
00002 // Copyright (C) 2003-2006 Rational Discovery LLC
00003 //
00004 //   @@ All Rights Reserved  @@
00005 //
00006 
00007 
00008 #ifndef __RD_POINT_H__
00009 #define __RD_POINT_H__
00010 #include <iostream>
00011 #include <cmath>
00012 #include <vector>
00013 #include <map>
00014 
00015 #ifndef M_PI
00016 #define M_PI 3.14159265358979323846
00017 #endif
00018 
00019 
00020 #include <RDGeneral/Invariant.h>
00021 #include <Numerics/Vector.h>
00022 #include <boost/smart_ptr.hpp>
00023 
00024 namespace RDGeom {
00025   class Point3D;
00026   class Point2D;
00027   class Point;
00028   class PointND;
00029 }
00030 
00031 
00032 std::ostream & operator<<(std::ostream& target, const RDGeom::Point &pt);
00033 
00034 RDGeom::Point3D operator+ (const RDGeom::Point3D& p1, const RDGeom::Point3D& p2);
00035 RDGeom::Point3D operator- (const RDGeom::Point3D& p1, const RDGeom::Point3D& p2);
00036 RDGeom::Point3D operator* (const RDGeom::Point3D& p1, const double v);
00037 RDGeom::Point3D operator/ (const RDGeom::Point3D& p1, const double v);
00038 
00039 RDGeom::Point2D operator+ (const RDGeom::Point2D& p1, const RDGeom::Point2D& p2);
00040 RDGeom::Point2D operator- (const RDGeom::Point2D& p1, const RDGeom::Point2D& p2);
00041 RDGeom::Point2D operator* (const RDGeom::Point2D& p1, const double v);
00042 RDGeom::Point2D operator/ (const RDGeom::Point2D& p1, const double v);
00043 
00044 RDGeom::PointND operator+ (const RDGeom::PointND& p1, const RDGeom::PointND& p2);
00045 RDGeom::PointND operator- (const RDGeom::PointND& p1, const RDGeom::PointND& p2);
00046 RDGeom::PointND operator* (const RDGeom::PointND& p1, const double v);
00047 RDGeom::PointND operator/ (const RDGeom::PointND& p1, const double v);
00048 
00049 
00050 namespace RDGeom {
00051 
00052   class Point {
00053     // this is the virtual base class, mandating certain functions
00054   public:
00055     virtual ~Point() {};
00056     
00057     virtual double operator[](unsigned int i) const = 0;
00058     virtual double& operator[](unsigned int i) = 0;
00059 
00060     virtual void normalize() = 0;
00061     virtual double length() const = 0;
00062     virtual double lengthSq() const = 0;
00063     virtual unsigned int dimension() const = 0;
00064   };
00065    
00066   //typedef class Point3D Point;
00067   class Point3D : public Point {
00068 
00069   public:
00070     double x,
00071       y,
00072       z;
00073 
00074     Point3D() : x(0.0), y(0.0), z(0.0) {};
00075     Point3D(double xv,double yv,double zv): x(xv),y(yv),z(zv) {};
00076 
00077     ~Point3D() {};
00078 
00079     Point3D(const Point3D &other) :
00080       x(other.x), y(other.y), z(other.z) {
00081     }
00082 
00083     inline unsigned int dimension() const {return 3;}
00084 
00085     inline double operator[](unsigned int i) const {
00086       PRECONDITION(i < 3, "Invalid index on Point3D");
00087       if (i == 0) {
00088         return x;
00089       } else if (i == 1) {
00090         return y;
00091       } else {
00092         return z;
00093       }
00094     }
00095         
00096     inline double& operator[](unsigned int i) {
00097       PRECONDITION(i < 3, "Invalid index on Point3D");
00098       if (i == 0) {
00099         return x;
00100       } else if (i == 1) {
00101         return y;
00102       } else {
00103         return z;
00104       }
00105     }
00106 
00107     Point3D&
00108       operator=(const Point3D &other)
00109     {
00110       x = other.x;y=other.y;z=other.z;
00111       return *this;
00112     };
00113 
00114     Point3D& operator+=(const Point3D &other) {
00115       x += other.x;
00116       y += other.y;
00117       z += other.z;
00118       return *this;
00119     };
00120  
00121     Point3D& operator-=(const Point3D &other) {
00122       x -= other.x;
00123       y -= other.y;
00124       z -= other.z;
00125       return *this;
00126     };
00127     
00128     Point3D& operator*=(double scale) {
00129       x *= scale;
00130       y *= scale;
00131       z *= scale;
00132       return *this;
00133     };  
00134 
00135     Point3D& operator/=(double scale) {
00136       x /= scale;
00137       y /= scale;
00138       z /= scale;
00139       return *this;
00140     };  
00141 
00142     Point3D operator-() const {
00143       Point3D res(x, y, z);
00144       res.x *= -1.0;
00145       res.y *= -1.0;
00146       res.z *= -1.0;
00147       return res;
00148     }
00149 
00150     void normalize() {
00151       double l = this->length();
00152       x /= l;
00153       y /= l;
00154       z /= l;
00155     };
00156 
00157     double length() const {
00158       double res = x*x+y*y+z*z;
00159       return sqrt(res);
00160     };
00161 
00162     double lengthSq() const {
00163       double res = pow(x,2) + pow(y,2) + pow(z,2);
00164       return res;
00165     };
00166 
00167     double dotProduct(const Point3D &other) const {
00168       double res = x*(other.x) + y*(other.y) + z*(other.z);
00169       return res;
00170     };
00171 
00172     /*! \brief determines the angle between a vector to this point
00173      *   from the origin and a vector to the other point.
00174      * 
00175      *  The angle is unsigned: the results of this call will always
00176      *   be between 0 and M_PI
00177      */
00178     double angleTo(const Point3D &other) const {
00179       Point3D t1,t2;
00180       t1 = *this;
00181       t2 = other;
00182       t1.normalize();
00183       t2.normalize();
00184       double dotProd = t1.dotProduct(t2);
00185       // watch for roundoff error:
00186       if(dotProd<-1.0) dotProd = -1.0;
00187       else if(dotProd>1.0) dotProd = 1.0;
00188       return acos(dotProd);
00189     }
00190 
00191     /*! \brief determines the signed angle between a vector to this point
00192      *   from the origin and a vector to the other point.
00193      * 
00194      *  The results of this call will be between 0 and M_2_PI
00195      */
00196     double signedAngleTo(const Point3D &other) const {
00197       double res=this->angleTo(other);
00198       // check the sign of the z component of the cross product:
00199       if((this->x*other.y-this->y*other.x)<-1e-6) res = 2.0*M_PI-res;
00200       return res;
00201     }
00202 
00203     /*! \brief Returns a normalized direction vector from this
00204      *   point to another.
00205      * 
00206      */
00207     Point3D directionVector(const Point3D &other) const {
00208       Point3D res;
00209       res.x = other.x - x;
00210       res.y = other.y - y;
00211       res.z = other.z - z;
00212       res.normalize();
00213       return res;
00214         
00215     }
00216 
00217     
00218     /*! \brief Cross product of this point with the another point
00219      * 
00220      * The order is important here
00221      *  The result is "this" cross with "other" not (other x this)
00222      */
00223     Point3D crossProduct(const Point3D &other) const {
00224       Point3D res;
00225       res.x = y*(other.z) - z*(other.y);
00226       res.y = -x*(other.z) + z*(other.x);
00227       res.z = x*(other.y) - y*(other.x);
00228       return res;
00229     };
00230 
00231     /*! \brief Get a unit perpendicular from this point (treating it as a vector):
00232      *
00233      */
00234     Point3D getPerpendicular() const {
00235       Point3D res(0.0,0.0,0.0);
00236       if(x){
00237         if(y){
00238           res.y = -1*x;
00239           res.x = y;
00240         } else if(z) {
00241           res.z = -1*x;
00242           res.x = z;
00243         } else {
00244           res.y = 1;
00245         }
00246       } else if(y){
00247         if(z){
00248           res.z = -1*y;
00249           res.y = z;
00250         } else {
00251           res.x = 1;
00252         }
00253       } else if(z){
00254         res.x = 1;
00255       }
00256       double l=res.length();
00257       POSTCONDITION(l>0.0,"zero perpendicular");
00258       res = res/l;
00259       return res;
00260     }
00261   };
00262   
00263   // given a  set of four pts in 3D compute the dihedral angle between the
00264   // plane of the first three points (pt1, pt2, pt3) and the plane of the 
00265   // last three points (pt2, pt3, pt4)
00266   // the computed angle is between 0 and PI
00267   double computeDihedralAngle(Point3D pt1, Point3D pt2, Point3D pt3, Point3D pt4);
00268 
00269   class Point2D : public Point {
00270   public:
00271     double x,
00272       y;
00273 
00274     Point2D() : x(0.0), y(0.0) {};
00275     Point2D(double xv,double yv): x(xv),y(yv) {};
00276     
00277     ~Point2D() {}; 
00278 
00279     Point2D(const Point2D &other) : x(other.x), y(other.y) {
00280     }
00281 
00282     inline unsigned int dimension() const {return 2;}
00283 
00284     inline double operator[](unsigned int i) const {
00285       PRECONDITION(i < 2, "Invalid index on Point2D");
00286       if (i == 0) {
00287         return x;
00288       } else { 
00289         return y;
00290       } 
00291     }
00292 
00293     inline double& operator[](unsigned int i) {
00294       PRECONDITION(i < 2, "Invalid index on Point2D");
00295       if (i == 0) {
00296         return x;
00297       } else { 
00298         return y;
00299       } 
00300     }
00301 
00302     Point2D&
00303       operator=(const Point2D &other)
00304     {
00305       x = other.x;y=other.y;
00306       return *this;
00307     };
00308 
00309     Point2D& operator+=(const Point2D &other) {
00310       x += other.x;
00311       y += other.y;
00312       return *this;
00313     };
00314 
00315     Point2D& operator-=(const Point2D &other) {
00316       x -= other.x;
00317       y -= other.y;
00318       return *this;
00319     };
00320     
00321     Point2D& operator*=(double scale){
00322       x *= scale;
00323       y *= scale;
00324       return *this;
00325     };
00326 
00327     Point2D& operator/=(double scale){
00328       x /= scale;
00329       y /= scale;
00330       return *this;
00331     };
00332 
00333     Point2D operator-() const {
00334       Point2D res(x, y);
00335       res.x *= -1.0;
00336       res.y *= -1.0;
00337       return res;
00338     }
00339       
00340     void normalize() {
00341       double ln = this->length();
00342       x /= ln;
00343       y /= ln;
00344     };
00345 
00346     void rotate90() {
00347       double temp = x;
00348       x = -y;
00349       y = temp;
00350     }
00351 
00352     double length() const {
00353       double res = pow(x,2) + pow(y,2);
00354       return sqrt(res);
00355     };
00356 
00357     double lengthSq() const {
00358       double res = x*x+y*y;
00359       return res;
00360     };
00361 
00362     double dotProduct(const Point2D &other) const {
00363       double res = x*(other.x) + y*(other.y);
00364       return res;
00365     };
00366 
00367     double angleTo(const Point2D &other) const {
00368       Point2D t1,t2;
00369       t1 = *this;
00370       t2 = other;
00371       t1.normalize();
00372       t2.normalize();
00373       double dotProd = t1.dotProduct(t2);
00374       // watch for roundoff error:
00375       if(dotProd<-1.0) dotProd = -1.0;
00376       else if(dotProd>1.0) dotProd = 1.0;
00377       return acos(dotProd);
00378     }
00379 
00380     double signedAngleTo(const Point2D &other) const {
00381       double res=this->angleTo(other);
00382       if((this->x*other.y-this->y*other.x)<-1e-6) res = 2.0*M_PI-res;
00383       return res;
00384     }
00385 
00386     Point2D directionVector(const Point2D &other) const {
00387       Point2D res;
00388       res.x = other.x - x;
00389       res.y = other.y - y;
00390       res.normalize();
00391       return res;
00392         
00393     }
00394     
00395   };
00396   
00397   class PointND : public Point {
00398   public:
00399 
00400     typedef boost::shared_ptr<RDNumeric::Vector<double> > VECT_SH_PTR;
00401 
00402     PointND(unsigned int dim){
00403       RDNumeric::Vector<double> *nvec = new RDNumeric::Vector<double>(dim, 0.0);
00404       dp_storage.reset(nvec);
00405     };
00406 
00407     PointND(const PointND &other) {
00408       RDNumeric::Vector<double> *nvec = new RDNumeric::Vector<double>(*other.getStorage());
00409       dp_storage.reset(nvec);
00410     }
00411 
00412 #if 0
00413         template <typename T>
00414     PointND(const T &vals){
00415       RDNumeric::Vector<double> *nvec = new RDNumeric::Vector<double>(vals.size(), 0.0);
00416       dp_storage.reset(nvec);
00417       unsigned int idx=0;
00418       typename T::const_iterator it;
00419       for(it=vals.begin();
00420           it!=vals.end();
00421           ++it){
00422         nvec->setVal(idx,*it);
00423         ++idx;
00424       };
00425     };
00426 #endif
00427 
00428     ~PointND() {}
00429 
00430     inline double operator[](unsigned int i) const {
00431       return dp_storage.get()->getVal(i);
00432     }
00433 
00434     inline double& operator[](unsigned int i) {
00435       return (*dp_storage.get())[i];
00436     }
00437 
00438     inline void normalize() {
00439       dp_storage.get()->normalize();
00440     }
00441 
00442     inline double length() const {
00443       return dp_storage.get()->normL2();
00444     }
00445 
00446     inline double lengthSq() const {
00447       return dp_storage.get()->normL2Sq();
00448     }
00449     
00450     unsigned int dimension() const {
00451       return dp_storage.get()->size();
00452     }
00453     
00454     PointND& operator=(const PointND &other) {
00455       RDNumeric::Vector<double> *nvec = new RDNumeric::Vector<double>(*other.getStorage());
00456       dp_storage.reset(nvec);
00457       return *this;
00458     }
00459 
00460     PointND& operator+=(const PointND &other) {
00461       (*dp_storage.get()) += (*other.getStorage());
00462       return *this;
00463     }
00464     
00465     PointND& operator-=(const PointND &other) {
00466       (*dp_storage.get()) -= (*other.getStorage());
00467       return *this;
00468     }
00469 
00470     PointND& operator*=(double scale) {
00471       (*dp_storage.get()) *= scale;
00472       return *this;
00473     }
00474 
00475     PointND& operator/=(double scale) {
00476       (*dp_storage.get()) /= scale;
00477       return *this;
00478     }
00479     
00480     PointND directionVector(const PointND &other) {
00481       PRECONDITION(this->dimension() == other.dimension(), "Point dimensions do not match");
00482       PointND np(other);
00483       np -= (*this);
00484       np.normalize();
00485       return np;
00486     }
00487 
00488     double dotProduct(const PointND &other) const {
00489       return dp_storage.get()->dotProduct(*other.getStorage());
00490     }
00491     
00492     double angleTo(const PointND &other) const {
00493       double dp = this->dotProduct(other);
00494       double n1 = this->length();
00495       double n2 = other.length();
00496       if ((n1 > 1.e-8) && (n2 > 1.e-8)) {
00497         dp /= (n1*n2);
00498       }
00499       if (dp < -1.0) dp = -1.0;
00500       else if (dp > 1.0) dp = 1.0;
00501       return acos(dp);
00502     }
00503 
00504   private:
00505     VECT_SH_PTR dp_storage;
00506     inline const RDNumeric::Vector<double> * getStorage() const {
00507       return dp_storage.get();
00508     }
00509   };
00510 
00511   typedef std::vector<RDGeom::Point *> PointPtrVect;
00512   typedef PointPtrVect::iterator PointPtrVect_I;
00513   typedef PointPtrVect::const_iterator PointPtrVect_CI;
00514 
00515   typedef std::vector<RDGeom::Point3D *> Point3DPtrVect;
00516   typedef std::vector<RDGeom::Point2D *> Point2DPtrVect;
00517   typedef Point3DPtrVect::iterator Point3DPtrVect_I;
00518   typedef Point3DPtrVect::const_iterator Point3DPtrVect_CI;
00519   typedef Point2DPtrVect::iterator Point2DPtrVect_I;
00520   typedef Point2DPtrVect::const_iterator Point2DPtrVect_CI;
00521 
00522   typedef std::vector<const RDGeom::Point3D *> Point3DConstPtrVect;
00523   typedef Point3DConstPtrVect::iterator Point3DConstPtrVect_I;
00524   typedef Point3DConstPtrVect::const_iterator Point3DConstPtrVect_CI;
00525 
00526   typedef std::vector<Point3D>                 POINT3D_VECT;
00527   typedef std::vector<Point3D>::iterator       POINT3D_VECT_I;
00528   typedef std::vector<Point3D>::const_iterator POINT3D_VECT_CI;
00529 
00530   typedef std::map<int, Point2D> INT_POINT2D_MAP;
00531   typedef INT_POINT2D_MAP::iterator INT_POINT2D_MAP_I;
00532   typedef INT_POINT2D_MAP::const_iterator INT_POINT2D_MAP_CI;
00533 }
00534 
00535 
00536 
00537 
00538 #endif

Generated on Sat May 24 08:36:32 2008 for RDCode by  doxygen 1.5.3