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