Visual Computing Library
Loading...
Searching...
No Matches
point.h
1/*****************************************************************************
2 * VCLib *
3 * Visual Computing Library *
4 * *
5 * Copyright(C) 2021-2025 *
6 * Visual Computing Lab *
7 * ISTI - Italian National Research Council *
8 * *
9 * All rights reserved. *
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the Mozilla Public License Version 2.0 as published *
13 * by the Mozilla Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 * This program is distributed in the hope that it will be useful, *
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
19 * Mozilla Public License Version 2.0 *
20 * (https://www.mozilla.org/en-US/MPL/2.0/) for more details. *
21 ****************************************************************************/
22
23#ifndef VCL_SPACE_CORE_POINT_H
24#define VCL_SPACE_CORE_POINT_H
25
26#include <vclib/concepts/space/point.h>
27#include <vclib/io/serialization.h>
28#include <vclib/math/base.h>
29#include <vclib/misc/hash.h>
30
31#include <Eigen/Core>
32#include <Eigen/Geometry>
33#include <compare>
34
35namespace vcl {
36
56template<typename Scalar, uint N>
57class Point : public Eigen::Matrix<Scalar, N, 1>
58{
59 using Base = Eigen::Matrix<Scalar, N, 1>;
60
61public:
62 using BaseMatrixType = Base;
63
64 // inherit Base operators
65 using Base::operator+;
66 using Base::operator-;
67 using Base::operator*;
68 using Base::operator/;
69 using Base::operator+=;
70 using Base::operator-=;
71 using Base::operator*=;
72 using Base::operator/=;
73
77 using ScalarType = Scalar;
78
82 static const uint DIM = N;
83
87 Point() { Base::setZero(); }
88
98 template<typename OtherDerived>
99 Point(const Eigen::MatrixBase<OtherDerived>& other) : Base(other)
100 {
101 }
102
116 template<typename... Scalars>
117 Point(Scalars... scalars) requires (sizeof...(scalars) == N)
118 {
119 set(scalars...);
120 }
121
131 ScalarType& x() requires (N >= 1) { return at(0); }
132
142 const ScalarType& x() const requires (N >= 1) { return at(0); }
143
153 ScalarType& y() requires (N >= 2) { return at(1); }
154
164 const ScalarType& y() const requires (N >= 2) { return at(1); }
165
175 ScalarType& z() requires (N >= 3) { return at(2); }
176
186 const ScalarType& z() const requires (N >= 3) { return at(2); }
187
197 ScalarType& w() requires (N >= 4) { return at(3); }
198
208 const ScalarType& w() const requires (N >= 4) { return at(3); }
209
210 ScalarType& at(uint i) { return Base::operator()(i); }
211
212 const ScalarType& at(uint i) const { return Base::operator()(i); }
213
225 template<typename S>
226 auto cast() const
227 {
228 if constexpr (std::is_same_v<Scalar, S>) {
229 return *this;
230 }
231 else {
232 return Point<S, N>(Base::template cast<S>());
233 }
234 }
235
247 bool isDegenerate() const
248 {
249 for (size_t i = 0; i < DIM; ++i)
250 if (vcl::isDegenerate(at(i)))
251 return true;
252 return false;
253 }
254
272 const Point& p1,
273 Scalar epsilon = std::numeric_limits<Scalar>::epsilon()) const
274 {
275 bool b = true;
276 for (size_t i = 0; i < DIM; ++i)
277 b = b && vcl::epsilonEquals(at(i), p1(i), epsilon);
278 return b;
279 }
280
294 Scalar angle(const Point& p1) const
295 {
296 Scalar w = Base::norm() * p1.norm();
297 if (w == 0)
298 return -1;
299 Scalar t = Base::dot(p1) / w;
300 if (t > 1)
301 t = 1;
302 else if (t < -1)
303 t = -1;
304 return (Scalar) acos(t);
305 }
306
319 Scalar dist(const Point& p1) const { return (*this - p1).norm(); }
320
333 Scalar squaredDist(const Point& p1) const
334 {
335 return (*this - p1).squaredNorm();
336 }
337
350 Point mul(const Point& p1) const
351 {
353 for (size_t i = 0; i < DIM; ++i)
354 tmp[i] = at(i) * p1[i];
355 return tmp;
356 }
357
374 Point div(const Point& p1) const
375 {
377 for (size_t i = 0; i < DIM; ++i) {
378 if (p1[i] == 0)
379 throw std::runtime_error(
380 "Math error: Attempted to divide by Zero\n");
381 tmp[i] = at(i) / p1[i];
382 }
383 return tmp;
384 }
385
394 constexpr uint size() const { return N; }
395
410 template<typename... Scalars>
411 void set(Scalars... scalars) requires (sizeof...(scalars) == N)
412 {
413 Scalar args[N] = {static_cast<Scalar>(scalars)...};
414 for (uint i = 0; i < N; i++)
415 at(i) = args[i];
416 }
417
430 auto outerProduct(const Point& p1) const
431 {
432 Eigen::Matrix<ScalarType, DIM, DIM> res;
433 for (uint i = 0; i < DIM; i++) {
434 for (uint j = 0; j < DIM; j++) {
435 res(i, j) = at(i) * p1(j);
436 }
437 }
438 return res;
439 }
440
461 void orthoBase(Point& u, Point& v) const requires (N == 3)
462 {
463 const double locEps = double(1e-7);
464
465 Point<Scalar, 3> up(0, 1, 0);
466 u = Base::cross(up);
467
468 double len = u.norm();
469 if (len < locEps) {
470 if (std::abs(at(0)) < std::abs(at(1))) {
471 if (std::abs(at(0)) < std::abs(at(2)))
472 up = Point<Scalar, 3>(1, 0, 0); // x is the min
473 else
474 up = Point<Scalar, 3>(0, 0, 1); // z is the min
475 }
476 else {
477 if (std::abs(at(1)) < std::abs(at(2)))
478 up = Point<Scalar, 3>(0, 1, 0); // y is the min
479 else
480 up = Point<Scalar, 3>(0, 0, 1); // z is the min
481 }
482 u = Base::cross(up);
483 }
484 v = Base::cross(u);
485 }
486
491 void serialize(std::ostream& os) const
492 {
493 vcl::serializeN(os, Base::data(), N);
494 }
495
500 void deserialize(std::istream& is)
501 {
502 vcl::deserializeN(is, Base::data(), N);
503 }
504
513 std::size_t hash() const
514 {
515 std::size_t h = 0;
516 for (size_t i = 0; i < DIM; ++i)
517 hashCombine(h, at(i));
518 return h;
519 }
520
526 template<typename OtherDerived>
527 Point& operator=(const Eigen::MatrixBase<OtherDerived>& other)
528 {
529 this->Base::operator=(other);
530 return *this;
531 }
532
547 auto operator<=>(const Point& p1) const
548 {
549 uint i = 0;
550 while (i < DIM && at(i) == p1[i]) {
551 ++i;
552 }
553 return i == DIM ? std::strong_ordering::equal : at(i) <=> p1[i];
554 }
555
567 Point operator+(const Scalar& s) const { return Base(Base::array() + s); }
568
580 Point operator-(const Scalar& s) const { return Base(Base::array() - s); }
581
593 Scalar operator*(const Point& p1) const { return Base::dot(p1); }
594
610 Point operator*(const Eigen::Matrix<Scalar, N + 1, N + 1>& m) const
611 requires (N == 3)
612 {
613 Eigen::Matrix<Scalar, 1, N> s;
614
615 s(0) = m(0, 0) * at(0) + m(0, 1) * at(1) + m(0, 2) * at(2) + m(0, 3);
616 s(1) = m(1, 0) * at(0) + m(1, 1) * at(1) + m(1, 2) * at(2) + m(1, 3);
617 s(2) = m(2, 0) * at(0) + m(2, 1) * at(1) + m(2, 2) * at(2) + m(2, 3);
618
619 Scalar w =
620 at(0) * m(3, 0) + at(1) * m(3, 1) + at(2) * m(3, 2) + m(3, 3);
621 if (w != 0) [[likely]]
622 s = s / w;
623 return Point(s);
624 }
625
636 Point& operator+=(const Scalar& s)
637 {
638 *this = *this + s;
639 return *this;
640 }
641
652 Point& operator-=(const Scalar& s)
653 {
654 *this = *this - s;
655 return *this;
656 }
657
671 Point& operator*=(const Eigen::Matrix<Scalar, N + 1, N + 1>& m)
672 requires (N == 3)
673 {
674 *this = *this * m;
675 return *this;
676 }
677
678private:
679 // hide Base begin and end members
680 using Base::begin;
681 using Base::end;
682};
683
697template<typename Scalar, uint N>
698bool epsilonEquals(
699 const Point<Scalar, N>& p1,
700 const Point<Scalar, N>& p2,
701 const Scalar& epsilon = std::numeric_limits<Scalar>::epsilon())
702{
703 return p1.epsilonEquals(p2, epsilon);
704}
705
706/* Specialization Aliases */
707
719template<typename Scalar>
721
732
744
756
768template<typename Scalar>
770
781
793
805
817template<typename Scalar>
819
830
842
854
855/* Deduction guides */
856
857template<typename S, typename... Scalars>
858Point(S, Scalars... scalars) -> Point<S, sizeof...(Scalars) + 1>;
859
860} // namespace vcl
861
862// inject vcl::Point hash function in std namespace
863namespace std {
864
865template<typename Scalar, unsigned int N>
866struct hash<vcl::Point<Scalar, N>>
867{
877 size_t operator()(const vcl::Point<Scalar, N>& id) const noexcept
878 {
879 return id.hash();
880 }
881};
882
883} // namespace std
884
885#endif // VCL_SPACE_CORE_POINT_H
The Point class represents an N-dimensional point containing N scalar values.
Definition point.h:58
auto outerProduct(const Point &p1) const
Returns the outer product between this point p and p1, which is p * p1^T.
Definition point.h:430
Point & operator*=(const Eigen::Matrix< Scalar, N+1, N+1 > &m)
Applies a TRS 4x4 matrix transformation to this point.
Definition point.h:671
Point & operator+=(const Scalar &s)
Adds a scalar value to this point.
Definition point.h:636
Point operator*(const Eigen::Matrix< Scalar, N+1, N+1 > &m) const
Returns a new 3D point/vector on which has been applied a TRS 4x4 matrix.
Definition point.h:610
Point(const Eigen::MatrixBase< OtherDerived > &other)
Constructs a Point object from an Eigen matrix.
Definition point.h:99
Scalar operator*(const Point &p1) const
Computes the dot product of this point with another point.
Definition point.h:593
Point operator-(const Scalar &s) const
Subtracts a scalar value from each coordinate of the point.
Definition point.h:580
Scalar squaredDist(const Point &p1) const
Computes the squared Euclidean distance between two Point objects.
Definition point.h:333
Point(Scalars... scalars)
Constructs a Point object from a set of scalar values.
Definition point.h:117
auto cast() const
Casts the Point object to a different scalar type.
Definition point.h:226
const ScalarType & y() const
Returns a const reference to the y-component of the Point object.
Definition point.h:164
Scalar ScalarType
The Scalar type of the Point.
Definition point.h:77
void orthoBase(Point &u, Point &v) const
Computes an Orthonormal Basis starting from this point n.
Definition point.h:461
constexpr uint size() const
Returns the size of the Point object.
Definition point.h:394
ScalarType & z()
Returns a reference to the z-component of the Point object.
Definition point.h:175
Scalar angle(const Point &p1) const
Computes the angle between two Point objects.
Definition point.h:294
Scalar dist(const Point &p1) const
Computes the Euclidean distance between two Point objects.
Definition point.h:319
Point operator+(const Scalar &s) const
Adds a scalar value to each coordinate of the point.
Definition point.h:567
Point()
Constructs a Point object with all components set to zero.
Definition point.h:87
Point div(const Point &p1) const
Divides the components of two Point objects.
Definition point.h:374
ScalarType & x()
Returns a reference to the x-component of the Point object.
Definition point.h:131
Point & operator=(const Eigen::MatrixBase< OtherDerived > &other)
Assigns the point to the given Eigen matrix.
Definition point.h:527
ScalarType & w()
Returns a reference to the w-component of the Point object.
Definition point.h:197
Point & operator-=(const Scalar &s)
Subtracts a scalar value from this point.
Definition point.h:652
void deserialize(std::istream &is)
Deserializes the point from the given input stream.
Definition point.h:500
auto operator<=>(const Point &p1) const
Compares the point with another point using the spaceship operator.
Definition point.h:547
void set(Scalars... scalars)
Sets all the components of the Point object from a set of scalar values.
Definition point.h:411
const ScalarType & z() const
Returns a const reference to the z-component of the Point object.
Definition point.h:186
void serialize(std::ostream &os) const
Serializes the point to the given output stream.
Definition point.h:491
std::size_t hash() const
Computes the hash value of the point.
Definition point.h:513
static const uint DIM
DIM: the number of dimensions of the Point.
Definition point.h:82
Point mul(const Point &p1) const
Multiplies the components of two Point objects.
Definition point.h:350
ScalarType & y()
Returns a reference to the y-component of the Point object.
Definition point.h:153
const ScalarType & w() const
Returns a const reference to the w-component of the Point object.
Definition point.h:208
const ScalarType & x() const
Returns a const reference to the x-component of the Point object.
Definition point.h:142
bool isDegenerate() const
Returns true if at least one of its components is NaN or inf.
Definition point.h:247
bool epsilonEquals(const Point &p1, Scalar epsilon=std::numeric_limits< Scalar >::epsilon()) const
Checks for the equality of two Point objects within a given epsilon tolerance.
Definition point.h:271
A class representing a line segment in n-dimensional space. The class is parameterized by a PointConc...
Definition segment.h:43
bool epsilonEquals(Scalar n1, Scalar n2, Scalar epsilon=std::numeric_limits< Scalar >::epsilon())
Checks if two floating point numbers are equal within an epsilon value.
Definition base.h:66
bool isDegenerate(Scalar number)
Checks if a floating point number is degenerate.
Definition base.h:45