RDCode: point.h Source File

- Main Page
- Namespaces
- Classes
- Files
- Directories

# 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