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 if (l < zero_tolerance) {
149 throw std::runtime_error("Cannot normalize a zero length vector");
150 }
151
152 x /= l;
153 y /= l;
154 z /= l;
155 }
156
157 double length() const override {
158 double res = x * x + y * y + z * z;
159 return sqrt(res);
160 }
161
162 double lengthSq() const override {
163 // double res = pow(x,2) + pow(y,2) + pow(z,2);
164 double res = x * x + y * y + z * z;
165 return res;
166 }
167
168 double dotProduct(const Point3D &other) const {
169 double res = x * (other.x) + y * (other.y) + z * (other.z);
170 return res;
171 }
172
173 /*! \brief determines the angle between a vector to this point
174 * from the origin and a vector to the other point.
175 *
176 * The angle is unsigned: the results of this call will always
177 * be between 0 and M_PI
178 */
179 double angleTo(const Point3D &other) const {
180 double lsq = lengthSq() * other.lengthSq();
181 double dotProd = dotProduct(other);
182 dotProd /= sqrt(lsq);
183
184 // watch for roundoff error:
185 if (dotProd <= -1.0) {
186 return M_PI;
187 }
188 if (dotProd >= 1.0) {
189 return 0.0;
190 }
191
192 return acos(dotProd);
193 }
194
195 /*! \brief determines the signed angle between a vector to this point
196 * from the origin and a vector to the other point.
197 *
198 * The results of this call will be between 0 and M_2_PI
199 */
200 double signedAngleTo(const Point3D &other) const {
201 double res = this->angleTo(other);
202 // check the sign of the z component of the cross product:
203 if ((this->x * other.y - this->y * other.x) < -zero_tolerance) {
204 res = 2.0 * M_PI - res;
205 }
206 return res;
207 }
208
209 /*! \brief Returns a normalized direction vector from this
210 * point to another.
211 *
212 */
213 Point3D directionVector(const Point3D &other) const {
214 Point3D res;
215 res.x = other.x - x;
216 res.y = other.y - y;
217 res.z = other.z - z;
218 res.normalize();
219 return res;
220 }
221
222 /*! \brief Cross product of this point with the another point
223 *
224 * The order is important here
225 * The result is "this" cross with "other" not (other x this)
226 */
227 Point3D crossProduct(const Point3D &other) const {
228 Point3D res;
229 res.x = y * (other.z) - z * (other.y);
230 res.y = -x * (other.z) + z * (other.x);
231 res.z = x * (other.y) - y * (other.x);
232 return res;
233 }
234
235 /*! \brief Get a unit perpendicular from this point (treating it as a vector):
236 *
237 */
239 Point3D res(0.0, 0.0, 0.0);
240 if (x) {
241 if (y) {
242 res.y = -1 * x;
243 res.x = y;
244 } else if (z) {
245 res.z = -1 * x;
246 res.x = z;
247 } else {
248 res.y = 1;
249 }
250 } else if (y) {
251 if (z) {
252 res.z = -1 * y;
253 res.y = z;
254 } else {
255 res.x = 1;
256 }
257 } else if (z) {
258 res.x = 1;
259 }
260 double l = res.length();
261 POSTCONDITION(l > 0.0, "zero perpendicular");
262 res /= l;
263 return res;
264 }
265};
266
267// given a set of four pts in 3D compute the dihedral angle between the
268// plane of the first three points (pt1, pt2, pt3) and the plane of the
269// last three points (pt2, pt3, pt4)
270// the computed angle is between 0 and PI
272 const Point3D &pt2,
273 const Point3D &pt3,
274 const Point3D &pt4);
275
276// given a set of four pts in 3D compute the signed dihedral angle between the
277// plane of the first three points (pt1, pt2, pt3) and the plane of the
278// last three points (pt2, pt3, pt4)
279// the computed angle is between -PI and PI
281 const Point3D &pt1, const Point3D &pt2, const Point3D &pt3,
282 const Point3D &pt4);
283
285 public:
286 double x{0.0};
287 double y{0.0};
288
290 Point2D(double xv, double yv) : x(xv), y(yv) {}
291 ~Point2D() override = default;
292
293 Point2D(const Point2D &other) : Point(other), x(other.x), y(other.y) {}
294 //! construct from a Point3D (ignoring the z coordinate)
295 Point2D(const Point3D &p3d) : Point(p3d), x(p3d.x), y(p3d.y) {}
296
297 Point *copy() const override { return new Point2D(*this); }
298
299 inline unsigned int dimension() const override { return 2; }
300
301 inline double operator[](unsigned int i) const override {
302 switch (i) {
303 case 0:
304 return x;
305 case 1:
306 return y;
307 default:
308 throw ValueErrorException("Invalid index on Point2D");
309 break;
310 }
311 }
312
313 inline double &operator[](unsigned int i) override {
314 switch (i) {
315 case 0:
316 return x;
317 case 1:
318 return y;
319 default:
320 throw ValueErrorException("Invalid index on Point2D");
321 break;
322 }
323 }
324
325 Point2D &operator=(const Point2D &other) {
326 x = other.x;
327 y = other.y;
328 return *this;
329 }
330
331 Point2D &operator+=(const Point2D &other) {
332 x += other.x;
333 y += other.y;
334 return *this;
335 }
336
337 Point2D &operator-=(const Point2D &other) {
338 x -= other.x;
339 y -= other.y;
340 return *this;
341 }
342
343 Point2D &operator*=(double scale) {
344 x *= scale;
345 y *= scale;
346 return *this;
347 }
348
349 Point2D &operator/=(double scale) {
350 x /= scale;
351 y /= scale;
352 return *this;
353 }
354
356 Point2D res(x, y);
357 res.x *= -1.0;
358 res.y *= -1.0;
359 return res;
360 }
361
362 void normalize() override {
363 double ln = this->length();
364 if (ln < zero_tolerance) {
365 throw std::runtime_error("Cannot normalize a zero length vector");
366 }
367
368 x /= ln;
369 y /= ln;
370 }
371
372 void rotate90() {
373 double temp = x;
374 x = -y;
375 y = temp;
376 }
377
378 double length() const override {
379 // double res = pow(x,2) + pow(y,2);
380 double res = x * x + y * y;
381 return sqrt(res);
382 }
383
384 double lengthSq() const override {
385 double res = x * x + y * y;
386 return res;
387 }
388
389 double dotProduct(const Point2D &other) const {
390 double res = x * (other.x) + y * (other.y);
391 return res;
392 }
393
394 double angleTo(const Point2D &other) const {
395 auto t1 = *this;
396 auto t2 = other;
397 t1.normalize();
398 t2.normalize();
399 double dotProd = t1.dotProduct(t2);
400 // watch for roundoff error:
401 if (dotProd < -1.0) {
402 dotProd = -1.0;
403 } else if (dotProd > 1.0) {
404 dotProd = 1.0;
405 }
406 return acos(dotProd);
407 }
408
409 double signedAngleTo(const Point2D &other) const {
410 double res = this->angleTo(other);
411 if ((this->x * other.y - this->y * other.x) < -zero_tolerance) {
412 res = 2.0 * M_PI - res;
413 }
414 return res;
415 }
416
417 Point2D directionVector(const Point2D &other) const {
418 Point2D res;
419 res.x = other.x - x;
420 res.y = other.y - y;
421 res.normalize();
422 return res;
423 }
424};
425
427 public:
428 typedef boost::shared_ptr<RDNumeric::Vector<double>> VECT_SH_PTR;
429
430 PointND(unsigned int dim) {
432 dp_storage.reset(nvec);
433 }
434
435 PointND(const PointND &other) : Point(other) {
437 new RDNumeric::Vector<double>(*other.getStorage());
438 dp_storage.reset(nvec);
439 }
440
441 Point *copy() const override { return new PointND(*this); }
442
443#if 0
444 template <typename T>
445 PointND(const T &vals){
446 RDNumeric::Vector<double> *nvec = new RDNumeric::Vector<double>(vals.size(), 0.0);
447 dp_storage.reset(nvec);
448 unsigned int idx=0;
449 typename T::const_iterator it;
450 for(it=vals.begin();
451 it!=vals.end();
452 ++it){
453 nvec->setVal(idx,*it);
454 ++idx;
455 };
456 };
457#endif
458
459 ~PointND() override = default;
460
461 inline double operator[](unsigned int i) const override {
462 return dp_storage.get()->getVal(i);
463 }
464
465 inline double &operator[](unsigned int i) override {
466 return (*dp_storage.get())[i];
467 }
468
469 inline void normalize() override { dp_storage.get()->normalize(); }
470
471 inline double length() const override { return dp_storage.get()->normL2(); }
472
473 inline double lengthSq() const override {
474 return dp_storage.get()->normL2Sq();
475 }
476
477 unsigned int dimension() const override { return dp_storage.get()->size(); }
478
479 PointND &operator=(const PointND &other) {
480 if (this == &other) {
481 return *this;
482 }
483
485 new RDNumeric::Vector<double>(*other.getStorage());
486 dp_storage.reset(nvec);
487 return *this;
488 }
489
490 PointND &operator+=(const PointND &other) {
491 (*dp_storage.get()) += (*other.getStorage());
492 return *this;
493 }
494
495 PointND &operator-=(const PointND &other) {
496 (*dp_storage.get()) -= (*other.getStorage());
497 return *this;
498 }
499
500 PointND &operator*=(double scale) {
501 (*dp_storage.get()) *= scale;
502 return *this;
503 }
504
505 PointND &operator/=(double scale) {
506 (*dp_storage.get()) /= scale;
507 return *this;
508 }
509
511 PRECONDITION(this->dimension() == other.dimension(),
512 "Point dimensions do not match");
513 PointND np(other);
514 np -= (*this);
515 np.normalize();
516 return np;
517 }
518
519 double dotProduct(const PointND &other) const {
520 return dp_storage.get()->dotProduct(*other.getStorage());
521 }
522
523 double angleTo(const PointND &other) const {
524 double dp = this->dotProduct(other);
525 double n1 = this->length();
526 double n2 = other.length();
527 if ((n1 > 1.e-8) && (n2 > 1.e-8)) {
528 dp /= (n1 * n2);
529 }
530 if (dp < -1.0) {
531 dp = -1.0;
532 } else if (dp > 1.0) {
533 dp = 1.0;
534 }
535 return acos(dp);
536 }
537
538 private:
539 VECT_SH_PTR dp_storage;
540 inline const RDNumeric::Vector<double> *getStorage() const {
541 return dp_storage.get();
542 }
543};
544#ifndef _MSC_VER
545#if !defined(__clang__) && defined(__GNUC__)
546#pragma GCC diagnostic pop
547#endif
548#endif
549
550typedef std::vector<RDGeom::Point *> PointPtrVect;
551typedef PointPtrVect::iterator PointPtrVect_I;
552typedef PointPtrVect::const_iterator PointPtrVect_CI;
553
554typedef std::vector<RDGeom::Point3D *> Point3DPtrVect;
555typedef std::vector<RDGeom::Point2D *> Point2DPtrVect;
556typedef Point3DPtrVect::iterator Point3DPtrVect_I;
557typedef Point3DPtrVect::const_iterator Point3DPtrVect_CI;
558typedef Point2DPtrVect::iterator Point2DPtrVect_I;
559typedef Point2DPtrVect::const_iterator Point2DPtrVect_CI;
560
561typedef std::vector<const RDGeom::Point3D *> Point3DConstPtrVect;
562typedef Point3DConstPtrVect::iterator Point3DConstPtrVect_I;
563typedef Point3DConstPtrVect::const_iterator Point3DConstPtrVect_CI;
564
565typedef std::vector<Point3D> POINT3D_VECT;
566typedef std::vector<Point3D>::iterator POINT3D_VECT_I;
567typedef std::vector<Point3D>::const_iterator POINT3D_VECT_CI;
568
569typedef std::map<int, Point2D> INT_POINT2D_MAP;
570typedef INT_POINT2D_MAP::iterator INT_POINT2D_MAP_I;
571typedef INT_POINT2D_MAP::const_iterator INT_POINT2D_MAP_CI;
572
573RDKIT_RDGEOMETRYLIB_EXPORT std::ostream &operator<<(std::ostream &target,
574 const RDGeom::Point &pt);
575
577 const RDGeom::Point3D &p2);
579 const RDGeom::Point3D &p2);
581 double v);
583 double v);
584
586 const RDGeom::Point2D &p2);
588 const RDGeom::Point2D &p2);
590 double v);
592 double v);
593
595 const RDGeom::PointND &p2);
597 const RDGeom::PointND &p2);
599 double v);
601 double v);
602} // namespace RDGeom
603
604#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
static constexpr double zero_tolerance
Definition Vector.h:25
unsigned int dimension() const override
Definition point.h:299
Point2D(double xv, double yv)
Definition point.h:290
Point2D(const Point2D &other)
Definition point.h:293
Point2D directionVector(const Point2D &other) const
Definition point.h:417
void rotate90()
Definition point.h:372
Point2D & operator*=(double scale)
Definition point.h:343
Point2D & operator=(const Point2D &other)
Definition point.h:325
Point2D & operator/=(double scale)
Definition point.h:349
Point2D & operator+=(const Point2D &other)
Definition point.h:331
Point2D & operator-=(const Point2D &other)
Definition point.h:337
Point2D(const Point3D &p3d)
construct from a Point3D (ignoring the z coordinate)
Definition point.h:295
~Point2D() override=default
Point2D operator-() const
Definition point.h:355
double dotProduct(const Point2D &other) const
Definition point.h:389
double lengthSq() const override
Definition point.h:384
Point * copy() const override
Definition point.h:297
void normalize() override
Definition point.h:362
double length() const override
Definition point.h:378
double operator[](unsigned int i) const override
Definition point.h:301
double & operator[](unsigned int i) override
Definition point.h:313
double signedAngleTo(const Point2D &other) const
Definition point.h:409
double angleTo(const Point2D &other) const
Definition point.h:394
Point3D(const Point3D &other)
Definition point.h:65
double lengthSq() const override
Definition point.h:162
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:168
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:200
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:179
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:227
~Point3D() override=default
double & operator[](unsigned int i) override
Definition point.h:86
double length() const override
Definition point.h:157
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:213
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:238
Point3D & operator*=(double scale)
Definition point.h:124
PointND & operator+=(const PointND &other)
Definition point.h:490
PointND & operator/=(double scale)
Definition point.h:505
double & operator[](unsigned int i) override
Definition point.h:465
double length() const override
Definition point.h:471
unsigned int dimension() const override
Definition point.h:477
boost::shared_ptr< RDNumeric::Vector< double > > VECT_SH_PTR
Definition point.h:428
double dotProduct(const PointND &other) const
Definition point.h:519
~PointND() override=default
PointND & operator=(const PointND &other)
Definition point.h:479
double lengthSq() const override
Definition point.h:473
PointND(const PointND &other)
Definition point.h:435
void normalize() override
Definition point.h:469
double angleTo(const PointND &other) const
Definition point.h:523
PointND & operator*=(double scale)
Definition point.h:500
PointND & operator-=(const PointND &other)
Definition point.h:495
double operator[](unsigned int i) const override
Definition point.h:461
Point * copy() const override
Definition point.h:441
PointND(unsigned int dim)
Definition point.h:430
PointND directionVector(const PointND &other)
Definition point.h:510
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:31
void setVal(unsigned int i, TYPE val)
sets the index at a particular value
Definition Vector.h:89
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:417
Point3DPtrVect::iterator Point3DPtrVect_I
Definition point.h:556
std::vector< RDGeom::Point * > PointPtrVect
Definition point.h:550
RDKIT_RDGEOMETRYLIB_EXPORT RDGeom::Point3D operator/(const RDGeom::Point3D &p1, double v)
PointPtrVect::const_iterator PointPtrVect_CI
Definition point.h:552
std::vector< const RDGeom::Point3D * > Point3DConstPtrVect
Definition point.h:561
std::map< int, Point2D > INT_POINT2D_MAP
Definition point.h:569
RDKIT_RDGEOMETRYLIB_EXPORT RDGeom::Point3D operator*(const RDGeom::Point3D &p1, double v)
Point3DConstPtrVect::iterator Point3DConstPtrVect_I
Definition point.h:562
std::vector< Point3D >::iterator POINT3D_VECT_I
Definition point.h:566
Point3DPtrVect::const_iterator Point3DPtrVect_CI
Definition point.h:557
std::vector< RDGeom::Point3D * > Point3DPtrVect
Definition point.h:554
RDKIT_RDGEOMETRYLIB_EXPORT RDGeom::Point3D operator-(const RDGeom::Point3D &p1, const RDGeom::Point3D &p2)
Point3DConstPtrVect::const_iterator Point3DConstPtrVect_CI
Definition point.h:563
Point2DPtrVect::iterator Point2DPtrVect_I
Definition point.h:558
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:571
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:567
INT_POINT2D_MAP::iterator INT_POINT2D_MAP_I
Definition point.h:570
std::vector< RDGeom::Point2D * > Point2DPtrVect
Definition point.h:555
Point2DPtrVect::const_iterator Point2DPtrVect_CI
Definition point.h:559
std::vector< Point3D > POINT3D_VECT
Definition point.h:565
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:551