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 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
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
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
00173
00174
00175
00176
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
00186 if(dotProd<-1.0) dotProd = -1.0;
00187 else if(dotProd>1.0) dotProd = 1.0;
00188 return acos(dotProd);
00189 }
00190
00191
00192
00193
00194
00195
00196 double signedAngleTo(const Point3D &other) const {
00197 double res=this->angleTo(other);
00198
00199 if((this->x*other.y-this->y*other.x)<-1e-6) res = 2.0*M_PI-res;
00200 return res;
00201 }
00202
00203
00204
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
00219
00220
00221
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
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
00264
00265
00266
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
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