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