RDKit
Open-source cheminformatics and machine learning.
Loading...
Searching...
No Matches
point.h
Go to the documentation of this file.
1//
2// Copyright (C) 2003-2021 Greg Landrum and other RDKit contributors
3//
4// @@ All Rights Reserved @@
5// This file is part of the RDKit.
6// The contents are covered by the terms of the BSD license
7// which is included in the file license.txt, found at the root
8// of the RDKit source tree.
9//
10
11#include <RDGeneral/export.h>
12#ifndef __RD_POINT_H__
13#define __RD_POINT_H__
14#include <iostream>
15#include <cmath>
16#include <vector>
17#include <map>
18
19#ifndef M_PI
20#define M_PI 3.14159265358979323846
21#endif
22
23#include <RDGeneral/Invariant.h>
24#include <Numerics/Vector.h>
25#include <boost/smart_ptr.hpp>
26
27namespace RDGeom {
28
30 // this is the virtual base class, mandating certain functions
31 public:
32 virtual ~Point() {}
33
34 virtual double operator[](unsigned int i) const = 0;
35 virtual double &operator[](unsigned int i) = 0;
36
37 virtual void normalize() = 0;
38 virtual double length() const = 0;
39 virtual double lengthSq() const = 0;
40 virtual unsigned int dimension() const = 0;
41
42 virtual Point *copy() const = 0;
43};
44#ifndef _MSC_VER
45// g++ (at least as of v9.3.0) generates some spurious warnings from here.
46// disable them
47#if !defined(__clang__) && defined(__GNUC__)
48#pragma GCC diagnostic push
49#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
50#endif
51#endif
52
53// typedef class Point3D Point;
55 public:
56 double x{0.0};
57 double y{0.0};
58 double z{0.0};
59
61 Point3D(double xv, double yv, double zv) : x(xv), y(yv), z(zv) {}
62
63 ~Point3D() override = default;
64
65 Point3D(const Point3D &other)
66 : Point(other), x(other.x), y(other.y), z(other.z) {}
67
68 Point *copy() const override { return new Point3D(*this); }
69
70 inline unsigned int dimension() const override { return 3; }
71
72 inline double operator[](unsigned int i) const override {
73 switch (i) {
74 case 0:
75 return x;
76 case 1:
77 return y;
78 case 2:
79 return z;
80 default:
81 throw ValueErrorException("Invalid index on Point3D");
82 break;
83 }
84 }
85
86 inline double &operator[](unsigned int i) override {
87 switch (i) {
88 case 0:
89 return x;
90 case 1:
91 return y;
92 case 2:
93 return z;
94 default:
95 throw ValueErrorException("Invalid index on Point3D");
96 break;
97 }
98 }
99
100 Point3D &operator=(const Point3D &other) {
101 if (&other == this) {
102 return *this;
103 }
104 x = other.x;
105 y = other.y;
106 z = other.z;
107 return *this;
108 }
109
110 Point3D &operator+=(const Point3D &other) {
111 x += other.x;
112 y += other.y;
113 z += other.z;
114 return *this;
115 }
116
117 Point3D &operator-=(const Point3D &other) {
118 x -= other.x;
119 y -= other.y;
120 z -= other.z;
121 return *this;
122 }
123
124 Point3D &operator*=(double scale) {
125 x *= scale;
126 y *= scale;
127 z *= scale;
128 return *this;
129 }
130
131 Point3D &operator/=(double scale) {
132 x /= scale;
133 y /= scale;
134 z /= scale;
135 return *this;
136 }
137
139 Point3D res(x, y, z);
140 res.x *= -1.0;
141 res.y *= -1.0;
142 res.z *= -1.0;
143 return res;
144 }
145
146 void normalize() override {
147 double l = this->length();
148 x /= l;
149 y /= l;
150 z /= l;
151 }
152
153 double length() const override {
154 double res = x * x + y * y + z * z;
155 return sqrt(res);
156 }
157
158 double lengthSq() const override {
159 // double res = pow(x,2) + pow(y,2) + pow(z,2);
160 double res = x * x + y * y + z * z;
161 return res;
162 }
163
164 double dotProduct(const Point3D &other) const {
165 double res = x * (other.x) + y * (other.y) + z * (other.z);
166 return res;
167 }
168
169 /*! \brief determines the angle between a vector to this point
170 * from the origin and a vector to the other point.
171 *
172 * The angle is unsigned: the results of this call will always
173 * be between 0 and M_PI
174 */
175 double angleTo(const Point3D &other) const {
176 double lsq = lengthSq() * other.lengthSq();
177 double dotProd = dotProduct(other);
178 dotProd /= sqrt(lsq);
179
180 // watch for roundoff error:
181 if (dotProd <= -1.0) {
182 return M_PI;
183 }
184 if (dotProd >= 1.0) {
185 return 0.0;
186 }
187
188 return acos(dotProd);
189 }
190
191 /*! \brief determines the signed angle between a vector to this point
192 * from the origin and a vector to the other point.
193 *
194 * The results of this call will be between 0 and M_2_PI
195 */
196 double signedAngleTo(const Point3D &other) const {
197 double res = this->angleTo(other);
198 // check the sign of the z component of the cross product:
199 if ((this->x * other.y - this->y * other.x) < -1e-6) {
200 res = 2.0 * M_PI - res;
201 }
202 return res;
203 }
204
205 /*! \brief Returns a normalized direction vector from this
206 * point to another.
207 *
208 */
209 Point3D directionVector(const Point3D &other) const {
210 Point3D res;
211 res.x = other.x - x;
212 res.y = other.y - y;
213 res.z = other.z - z;
214 res.normalize();
215 return res;
216 }
217
218 /*! \brief Cross product of this point with the another point
219 *
220 * The order is important here
221 * The result is "this" cross with "other" not (other x this)
222 */
223 Point3D crossProduct(const Point3D &other) const {
224 Point3D res;
225 res.x = y * (other.z) - z * (other.y);
226 res.y = -x * (other.z) + z * (other.x);
227 res.z = x * (other.y) - y * (other.x);
228 return res;
229 }
230
231 /*! \brief Get a unit perpendicular from this point (treating it as a vector):
232 *
233 */
235 Point3D res(0.0, 0.0, 0.0);
236 if (x) {
237 if (y) {
238 res.y = -1 * x;
239 res.x = y;
240 } else if (z) {
241 res.z = -1 * x;
242 res.x = z;
243 } else {
244 res.y = 1;
245 }
246 } else if (y) {
247 if (z) {
248 res.z = -1 * y;
249 res.y = z;
250 } else {
251 res.x = 1;
252 }
253 } else if (z) {
254 res.x = 1;
255 }
256 double l = res.length();
257 POSTCONDITION(l > 0.0, "zero perpendicular");
258 res /= l;
259 return res;
260 }
261};
262
263// given a set of four pts in 3D compute the dihedral angle between the
264// plane of the first three points (pt1, pt2, pt3) and the plane of the
265// last three points (pt2, pt3, pt4)
266// the computed angle is between 0 and PI
268 const Point3D &pt2,
269 const Point3D &pt3,
270 const Point3D &pt4);
271
272// given a set of four pts in 3D compute the signed dihedral angle between the
273// plane of the first three points (pt1, pt2, pt3) and the plane of the
274// last three points (pt2, pt3, pt4)
275// the computed angle is between -PI and PI
277 const Point3D &pt1, const Point3D &pt2, const Point3D &pt3,
278 const Point3D &pt4);
279
281 public:
282 double x{0.0};
283 double y{0.0};
284
286 Point2D(double xv, double yv) : x(xv), y(yv) {}
287 ~Point2D() override = default;
288
289 Point2D(const Point2D &other) : Point(other), x(other.x), y(other.y) {}
290 //! construct from a Point3D (ignoring the z coordinate)
291 Point2D(const Point3D &p3d) : Point(p3d), x(p3d.x), y(p3d.y) {}
292
293 Point *copy() const override { return new Point2D(*this); }
294
295 inline unsigned int dimension() const override { return 2; }
296
297 inline double operator[](unsigned int i) const override {
298 switch (i) {
299 case 0:
300 return x;
301 case 1:
302 return y;
303 default:
304 throw ValueErrorException("Invalid index on Point2D");
305 break;
306 }
307 }
308
309 inline double &operator[](unsigned int i) override {
310 switch (i) {
311 case 0:
312 return x;
313 case 1:
314 return y;
315 default:
316 throw ValueErrorException("Invalid index on Point2D");
317 break;
318 }
319 }
320
321 Point2D &operator=(const Point2D &other) {
322 x = other.x;
323 y = other.y;
324 return *this;
325 }
326
327 Point2D &operator+=(const Point2D &other) {
328 x += other.x;
329 y += other.y;
330 return *this;
331 }
332
333 Point2D &operator-=(const Point2D &other) {
334 x -= other.x;
335 y -= other.y;
336 return *this;
337 }
338
339 Point2D &operator*=(double scale) {
340 x *= scale;
341 y *= scale;
342 return *this;
343 }
344
345 Point2D &operator/=(double scale) {
346 x /= scale;
347 y /= scale;
348 return *this;
349 }
350
352 Point2D res(x, y);
353 res.x *= -1.0;
354 res.y *= -1.0;
355 return res;
356 }
357
358 void normalize() override {
359 double ln = this->length();
360 x /= ln;
361 y /= ln;
362 }
363
364 void rotate90() {
365 double temp = x;
366 x = -y;
367 y = temp;
368 }
369
370 double length() const override {
371 // double res = pow(x,2) + pow(y,2);
372 double res = x * x + y * y;
373 return sqrt(res);
374 }
375
376 double lengthSq() const override {
377 double res = x * x + y * y;
378 return res;
379 }
380
381 double dotProduct(const Point2D &other) const {
382 double res = x * (other.x) + y * (other.y);
383 return res;
384 }
385
386 double angleTo(const Point2D &other) const {
387 auto t1 = *this;
388 auto t2 = other;
389 t1.normalize();
390 t2.normalize();
391 double dotProd = t1.dotProduct(t2);
392 // watch for roundoff error:
393 if (dotProd < -1.0) {
394 dotProd = -1.0;
395 } else if (dotProd > 1.0) {
396 dotProd = 1.0;
397 }
398 return acos(dotProd);
399 }
400
401 double signedAngleTo(const Point2D &other) const {
402 double res = this->angleTo(other);
403 if ((this->x * other.y - this->y * other.x) < -1e-6) {
404 res = 2.0 * M_PI - res;
405 }
406 return res;
407 }
408
409 Point2D directionVector(const Point2D &other) const {
410 Point2D res;
411 res.x = other.x - x;
412 res.y = other.y - y;
413 res.normalize();
414 return res;
415 }
416};
417
419 public:
420 typedef boost::shared_ptr<RDNumeric::Vector<double>> VECT_SH_PTR;
421
422 PointND(unsigned int dim) {
424 dp_storage.reset(nvec);
425 }
426
427 PointND(const PointND &other) : Point(other) {
429 new RDNumeric::Vector<double>(*other.getStorage());
430 dp_storage.reset(nvec);
431 }
432
433 Point *copy() const override { return new PointND(*this); }
434
435#if 0
436 template <typename T>
437 PointND(const T &vals){
438 RDNumeric::Vector<double> *nvec = new RDNumeric::Vector<double>(vals.size(), 0.0);
439 dp_storage.reset(nvec);
440 unsigned int idx=0;
441 typename T::const_iterator it;
442 for(it=vals.begin();
443 it!=vals.end();
444 ++it){
445 nvec->setVal(idx,*it);
446 ++idx;
447 };
448 };
449#endif
450
451 ~PointND() override = default;
452
453 inline double operator[](unsigned int i) const override {
454 return dp_storage.get()->getVal(i);
455 }
456
457 inline double &operator[](unsigned int i) override {
458 return (*dp_storage.get())[i];
459 }
460
461 inline void normalize() override { dp_storage.get()->normalize(); }
462
463 inline double length() const override { return dp_storage.get()->normL2(); }
464
465 inline double lengthSq() const override {
466 return dp_storage.get()->normL2Sq();
467 }
468
469 unsigned int dimension() const override { return dp_storage.get()->size(); }
470
471 PointND &operator=(const PointND &other) {
472 if (this == &other) {
473 return *this;
474 }
475
477 new RDNumeric::Vector<double>(*other.getStorage());
478 dp_storage.reset(nvec);
479 return *this;
480 }
481
482 PointND &operator+=(const PointND &other) {
483 (*dp_storage.get()) += (*other.getStorage());
484 return *this;
485 }
486
487 PointND &operator-=(const PointND &other) {
488 (*dp_storage.get()) -= (*other.getStorage());
489 return *this;
490 }
491
492 PointND &operator*=(double scale) {
493 (*dp_storage.get()) *= scale;
494 return *this;
495 }
496
497 PointND &operator/=(double scale) {
498 (*dp_storage.get()) /= scale;
499 return *this;
500 }
501
503 PRECONDITION(this->dimension() == other.dimension(),
504 "Point dimensions do not match");
505 PointND np(other);
506 np -= (*this);
507 np.normalize();
508 return np;
509 }
510
511 double dotProduct(const PointND &other) const {
512 return dp_storage.get()->dotProduct(*other.getStorage());
513 }
514
515 double angleTo(const PointND &other) const {
516 double dp = this->dotProduct(other);
517 double n1 = this->length();
518 double n2 = other.length();
519 if ((n1 > 1.e-8) && (n2 > 1.e-8)) {
520 dp /= (n1 * n2);
521 }
522 if (dp < -1.0) {
523 dp = -1.0;
524 } else if (dp > 1.0) {
525 dp = 1.0;
526 }
527 return acos(dp);
528 }
529
530 private:
531 VECT_SH_PTR dp_storage;
532 inline const RDNumeric::Vector<double> *getStorage() const {
533 return dp_storage.get();
534 }
535};
536#ifndef _MSC_VER
537#if !defined(__clang__) && defined(__GNUC__)
538#pragma GCC diagnostic pop
539#endif
540#endif
541
542typedef std::vector<RDGeom::Point *> PointPtrVect;
543typedef PointPtrVect::iterator PointPtrVect_I;
544typedef PointPtrVect::const_iterator PointPtrVect_CI;
545
546typedef std::vector<RDGeom::Point3D *> Point3DPtrVect;
547typedef std::vector<RDGeom::Point2D *> Point2DPtrVect;
548typedef Point3DPtrVect::iterator Point3DPtrVect_I;
549typedef Point3DPtrVect::const_iterator Point3DPtrVect_CI;
550typedef Point2DPtrVect::iterator Point2DPtrVect_I;
551typedef Point2DPtrVect::const_iterator Point2DPtrVect_CI;
552
553typedef std::vector<const RDGeom::Point3D *> Point3DConstPtrVect;
554typedef Point3DConstPtrVect::iterator Point3DConstPtrVect_I;
555typedef Point3DConstPtrVect::const_iterator Point3DConstPtrVect_CI;
556
557typedef std::vector<Point3D> POINT3D_VECT;
558typedef std::vector<Point3D>::iterator POINT3D_VECT_I;
559typedef std::vector<Point3D>::const_iterator POINT3D_VECT_CI;
560
561typedef std::map<int, Point2D> INT_POINT2D_MAP;
562typedef INT_POINT2D_MAP::iterator INT_POINT2D_MAP_I;
563typedef INT_POINT2D_MAP::const_iterator INT_POINT2D_MAP_CI;
564
565RDKIT_RDGEOMETRYLIB_EXPORT std::ostream &operator<<(std::ostream &target,
566 const RDGeom::Point &pt);
567
569 const RDGeom::Point3D &p2);
571 const RDGeom::Point3D &p2);
573 double v);
575 double v);
576
578 const RDGeom::Point2D &p2);
580 const RDGeom::Point2D &p2);
582 double v);
584 double v);
585
587 const RDGeom::PointND &p2);
589 const RDGeom::PointND &p2);
591 double v);
593 double v);
594} // namespace RDGeom
595
596#endif
#define POSTCONDITION(expr, mess)
Definition Invariant.h:117
#define PRECONDITION(expr, mess)
Definition Invariant.h:109
#define M_PI
Definition MMFF/Params.h:26
unsigned int dimension() const override
Definition point.h:295
Point2D(double xv, double yv)
Definition point.h:286
Point2D(const Point2D &other)
Definition point.h:289
Point2D directionVector(const Point2D &other) const
Definition point.h:409
void rotate90()
Definition point.h:364
Point2D & operator*=(double scale)
Definition point.h:339
Point2D & operator=(const Point2D &other)
Definition point.h:321
Point2D & operator/=(double scale)
Definition point.h:345
Point2D & operator+=(const Point2D &other)
Definition point.h:327
Point2D & operator-=(const Point2D &other)
Definition point.h:333
Point2D(const Point3D &p3d)
construct from a Point3D (ignoring the z coordinate)
Definition point.h:291
~Point2D() override=default
Point2D operator-() const
Definition point.h:351
double dotProduct(const Point2D &other) const
Definition point.h:381
double lengthSq() const override
Definition point.h:376
Point * copy() const override
Definition point.h:293
void normalize() override
Definition point.h:358
double length() const override
Definition point.h:370
double operator[](unsigned int i) const override
Definition point.h:297
double & operator[](unsigned int i) override
Definition point.h:309
double signedAngleTo(const Point2D &other) const
Definition point.h:401
double angleTo(const Point2D &other) const
Definition point.h:386
Point3D(const Point3D &other)
Definition point.h:65
double lengthSq() const override
Definition point.h:158
Point3D operator-() const
Definition point.h:138
unsigned int dimension() const override
Definition point.h:70
Point3D & operator=(const Point3D &other)
Definition point.h:100
double dotProduct(const Point3D &other) const
Definition point.h:164
double signedAngleTo(const Point3D &other) const
determines the signed angle between a vector to this point from the origin and a vector to the other ...
Definition point.h:196
double operator[](unsigned int i) const override
Definition point.h:72
double angleTo(const Point3D &other) const
determines the angle between a vector to this point from the origin and a vector to the other point.
Definition point.h:175
Point3D & operator-=(const Point3D &other)
Definition point.h:117
Point3D crossProduct(const Point3D &other) const
Cross product of this point with the another point.
Definition point.h:223
~Point3D() override=default
double & operator[](unsigned int i) override
Definition point.h:86
double length() const override
Definition point.h:153
Point3D(double xv, double yv, double zv)
Definition point.h:61
double y
Definition point.h:57
double x
Definition point.h:56
Point * copy() const override
Definition point.h:68
double z
Definition point.h:58
void normalize() override
Definition point.h:146
Point3D & operator/=(double scale)
Definition point.h:131
Point3D directionVector(const Point3D &other) const
Returns a normalized direction vector from this point to another.
Definition point.h:209
Point3D & operator+=(const Point3D &other)
Definition point.h:110
Point3D getPerpendicular() const
Get a unit perpendicular from this point (treating it as a vector):
Definition point.h:234
Point3D & operator*=(double scale)
Definition point.h:124
PointND & operator+=(const PointND &other)
Definition point.h:482
PointND & operator/=(double scale)
Definition point.h:497
double & operator[](unsigned int i) override
Definition point.h:457
double length() const override
Definition point.h:463
unsigned int dimension() const override
Definition point.h:469
boost::shared_ptr< RDNumeric::Vector< double > > VECT_SH_PTR
Definition point.h:420
double dotProduct(const PointND &other) const
Definition point.h:511
~PointND() override=default
PointND & operator=(const PointND &other)
Definition point.h:471
double lengthSq() const override
Definition point.h:465
PointND(const PointND &other)
Definition point.h:427
void normalize() override
Definition point.h:461
double angleTo(const PointND &other) const
Definition point.h:515
PointND & operator*=(double scale)
Definition point.h:492
PointND & operator-=(const PointND &other)
Definition point.h:487
double operator[](unsigned int i) const override
Definition point.h:453
Point * copy() const override
Definition point.h:433
PointND(unsigned int dim)
Definition point.h:422
PointND directionVector(const PointND &other)
Definition point.h:502
virtual ~Point()
Definition point.h:32
virtual double lengthSq() const =0
virtual Point * copy() const =0
virtual double length() const =0
virtual void normalize()=0
virtual unsigned int dimension() const =0
virtual double operator[](unsigned int i) const =0
virtual double & operator[](unsigned int i)=0
A class to represent vectors of numbers.
Definition Vector.h:29
void setVal(unsigned int i, TYPE val)
sets the index at a particular value
Definition Vector.h:87
Class to allow us to throw a ValueError from C++ and have it make it back to Python.
Definition Exceptions.h:40
#define RDKIT_RDGEOMETRYLIB_EXPORT
Definition export.h:409
Point3DPtrVect::iterator Point3DPtrVect_I
Definition point.h:548
std::vector< RDGeom::Point * > PointPtrVect
Definition point.h:542
RDKIT_RDGEOMETRYLIB_EXPORT RDGeom::Point3D operator/(const RDGeom::Point3D &p1, double v)
PointPtrVect::const_iterator PointPtrVect_CI
Definition point.h:544
std::vector< const RDGeom::Point3D * > Point3DConstPtrVect
Definition point.h:553
std::map< int, Point2D > INT_POINT2D_MAP
Definition point.h:561
RDKIT_RDGEOMETRYLIB_EXPORT RDGeom::Point3D operator*(const RDGeom::Point3D &p1, double v)
Point3DConstPtrVect::iterator Point3DConstPtrVect_I
Definition point.h:554
std::vector< Point3D >::iterator POINT3D_VECT_I
Definition point.h:558
Point3DPtrVect::const_iterator Point3DPtrVect_CI
Definition point.h:549
std::vector< RDGeom::Point3D * > Point3DPtrVect
Definition point.h:546
RDKIT_RDGEOMETRYLIB_EXPORT RDGeom::Point3D operator-(const RDGeom::Point3D &p1, const RDGeom::Point3D &p2)
Point3DConstPtrVect::const_iterator Point3DConstPtrVect_CI
Definition point.h:555
Point2DPtrVect::iterator Point2DPtrVect_I
Definition point.h:550
RDKIT_RDGEOMETRYLIB_EXPORT std::ostream & operator<<(std::ostream &target, const RDGeom::Point &pt)
INT_POINT2D_MAP::const_iterator INT_POINT2D_MAP_CI
Definition point.h:563
RDKIT_RDGEOMETRYLIB_EXPORT double computeDihedralAngle(const Point3D &pt1, const Point3D &pt2, const Point3D &pt3, const Point3D &pt4)
std::vector< Point3D >::const_iterator POINT3D_VECT_CI
Definition point.h:559
INT_POINT2D_MAP::iterator INT_POINT2D_MAP_I
Definition point.h:562
std::vector< RDGeom::Point2D * > Point2DPtrVect
Definition point.h:547
Point2DPtrVect::const_iterator Point2DPtrVect_CI
Definition point.h:551
std::vector< Point3D > POINT3D_VECT
Definition point.h:557
RDKIT_RDGEOMETRYLIB_EXPORT double computeSignedDihedralAngle(const Point3D &pt1, const Point3D &pt2, const Point3D &pt3, const Point3D &pt4)
RDKIT_RDGEOMETRYLIB_EXPORT RDGeom::Point3D operator+(const RDGeom::Point3D &p1, const RDGeom::Point3D &p2)
PointPtrVect::iterator PointPtrVect_I
Definition point.h:543