MeshLib C++ Docs
Loading...
Searching...
No Matches
MRMesh/MRVector3.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRMacros.h"
4#include "MRMeshFwd.h"
5#include "MRConstants.h"
6#include "MRPch/MRBindingMacros.h"
7#include <algorithm>
8#include <cmath>
9#if MR_HAS_REQUIRES
10#include <concepts>
11#endif
12
13namespace MR
14{
15
16#ifdef _MSC_VER
17#pragma warning(push)
18#pragma warning(disable: 4804) // unsafe use of type 'bool' in operation
19#pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned
20#endif
21
24template <typename T>
25struct Vector3
26{
27 using ValueType = T;
30 static constexpr int elements = 3;
31
32 T x, y, z;
33
34 constexpr Vector3() noexcept : x( 0 ), y( 0 ), z( 0 ) { }
35 explicit Vector3( NoInit ) noexcept { }
36 constexpr Vector3( T x, T y, T z ) noexcept : x( x ), y( y ), z( z ) { }
37 explicit constexpr Vector3( const Vector2<T> & v ) noexcept : x( v.x ), y( v.y ), z( 0 ) { }
38
39 static constexpr Vector3 diagonal( T a ) noexcept { return Vector3( a, a, a ); }
40 static constexpr Vector3 plusX() noexcept { return Vector3( 1, 0, 0 ); }
41 static constexpr Vector3 plusY() noexcept { return Vector3( 0, 1, 0 ); }
42 static constexpr Vector3 plusZ() noexcept { return Vector3( 0, 0, 1 ); }
43 static constexpr Vector3 minusX() noexcept { return Vector3( -1, 0, 0 ); }
44 static constexpr Vector3 minusY() noexcept { return Vector3( 0, -1, 0 ); }
45 static constexpr Vector3 minusZ() noexcept { return Vector3( 0, 0, -1 ); }
46
47 template <typename U>
48 constexpr explicit Vector3( const Vector3<U> & v ) noexcept : x( T( v.x ) ), y( T( v.y ) ), z( T( v.z ) ) { }
49
50 constexpr const T & operator []( int e ) const noexcept { return *( &x + e ); }
51 constexpr T & operator []( int e ) noexcept { return *( &x + e ); }
52
53 T lengthSq() const { return x * x + y * y + z * z; }
54 auto length() const
55 {
56 // Calling `sqrt` this way to hopefully support boost.multiprecision numbers.
57 // Returning `auto` to not break on integral types.
58 using std::sqrt;
59 return sqrt( lengthSq() );
60 }
61
62 [[nodiscard]] Vector3 normalized() const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
63 {
64 auto len = length();
65 if ( len <= 0 )
66 return {};
67 return ( 1 / len ) * (*this);
68 }
69
71 Vector3 furthestBasisVector() const MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, bool> );
72
75 std::pair<Vector3, Vector3> perpendicular() const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> );
76
78 template <MR_SAME_TYPE_TEMPLATE_PARAM(T, TT)> // Need this, otherwise the bindings try to instantiate `AffineXf3` with non-FP arguments.
79 Vector3 transformed( const AffineXf3<TT>* xf ) const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
80 {
81 return xf ? ( *xf )( *this ) : *this;
82 }
83
85 void unsignZeroValues() MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
86 {
87 for ( auto i = 0; i < elements; ++i )
88 if ( (*this)[i] == 0.f && std::signbit( (*this)[i] ) )
89 (*this)[i] = 0.f;
90 }
91
92 [[nodiscard]] bool isFinite() const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
93 {
94 return std::isfinite( x ) && std::isfinite( y ) && std::isfinite( z );
95 }
96
97 [[nodiscard]] friend constexpr bool operator ==( const Vector3<T> & a, const Vector3<T> & b ) { return a.x == b.x && a.y == b.y && a.z == b.z; }
98 [[nodiscard]] friend constexpr bool operator !=( const Vector3<T> & a, const Vector3<T> & b ) { return !( a == b ); }
99
100 // NOTE: We use `std::declval()` in the operators below because libclang 18 in our binding generator is bugged and chokes on decltyping `a.x` and such. TODO fix this when we update libclang.
101
102 [[nodiscard]] friend constexpr const Vector3<T> & operator +( const Vector3<T> & a ) { return a; }
103 [[nodiscard]] friend constexpr auto operator -( const Vector3<T> & a ) -> Vector3<decltype( -std::declval<T>() )> { return { -a.x, -a.y, -a.z }; }
104
105 [[nodiscard]] friend constexpr auto operator +( const Vector3<T> & a, const Vector3<T> & b ) -> Vector3<decltype( std::declval<T>() + std::declval<T>() )> { return { a.x + b.x, a.y + b.y, a.z + b.z }; }
106 [[nodiscard]] friend constexpr auto operator -( const Vector3<T> & a, const Vector3<T> & b ) -> Vector3<decltype( std::declval<T>() - std::declval<T>() )> { return { a.x - b.x, a.y - b.y, a.z - b.z }; }
107 [[nodiscard]] friend constexpr auto operator *( T a, const Vector3<T> & b ) -> Vector3<decltype( std::declval<T>() * std::declval<T>() )> { return { a * b.x, a * b.y, a * b.z }; }
108 [[nodiscard]] friend constexpr auto operator *( const Vector3<T> & b, T a ) -> Vector3<decltype( std::declval<T>() * std::declval<T>() )> { return { a * b.x, a * b.y, a * b.z }; }
109 [[nodiscard]] friend constexpr auto operator /( Vector3<T> b, T a ) -> Vector3<decltype( std::declval<T>() / std::declval<T>() )>
110 {
111 if constexpr ( std::is_integral_v<T> )
112 return { b.x / a, b.y / a, b.z / a };
113 else
114 return b * ( 1 / a );
115 }
116
117 friend constexpr Vector3<T> & operator +=( Vector3<T> & a, const Vector3<T> & b ) MR_REQUIRES_IF_SUPPORTED( requires{ a + b; } ) { a.x += b.x; a.y += b.y; a.z += b.z; return a; }
118 friend constexpr Vector3<T> & operator -=( Vector3<T> & a, const Vector3<T> & b ) MR_REQUIRES_IF_SUPPORTED( requires{ a - b; } ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; return a; }
119 friend constexpr Vector3<T> & operator *=( Vector3<T> & a, T b ) MR_REQUIRES_IF_SUPPORTED( requires{ a * b; } ) { a.x *= b; a.y *= b; a.z *= b; return a; }
120 friend constexpr Vector3<T> & operator /=( Vector3<T> & a, T b ) MR_REQUIRES_IF_SUPPORTED( requires{ a / b; } )
121 {
122 if constexpr ( std::is_integral_v<T> )
123 { a.x /= b; a.y /= b; a.z /= b; return a; }
124 else
125 return a *= ( 1 / b );
126 }
127};
128
131
132
134template <typename T>
135inline T distanceSq( const Vector3<T> & a, const Vector3<T> & b )
136{
137 return ( a - b ).lengthSq();
138}
139
141template <typename T>
142inline T distance( const Vector3<T> & a, const Vector3<T> & b )
143{
144 return ( a - b ).length();
145}
146
148template <typename T>
149inline Vector3<T> cross( const Vector3<T> & a, const Vector3<T> & b )
150{
151 return {
152 a.y * b.z - a.z * b.y,
153 a.z * b.x - a.x * b.z,
154 a.x * b.y - a.y * b.x
155 };
156}
157
159template <typename T>
160inline auto dot( const Vector3<T> & a, const Vector3<T> & b ) -> decltype( a.x * b.x )
161{
162 return a.x * b.x + a.y * b.y + a.z * b.z;
163}
164
166template <typename T>
167inline T sqr( const Vector3<T> & a )
168{
169 return a.lengthSq();
170}
171
173template <typename T>
174inline T mixed( const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c )
175{
176 return dot( a, cross( b, c ) );
177}
178
180template <typename T>
181inline Vector3<T> mult( const Vector3<T>& a, const Vector3<T>& b )
182{
183 return { a.x * b.x,a.y * b.y,a.z * b.z };
184}
185
187template <typename T>
188inline Vector3<T> div( const Vector3<T>& a, const Vector3<T>& b )
189{
190 return { a.x / b.x, a.y / b.y, a.z / b.z };
191}
192
193
196template <typename T>
197inline T angle( const Vector3<T> & a, const Vector3<T> & b )
198{
199 return std::atan2( cross( a, b ).length(), dot( a, b ) );
200 // this version is slower and less precise
201 //return std::acos( std::clamp( dot( a.normalized(), b.normalized() ), T(-1), T(1) ) );
202}
203
204template <typename T>
205inline Vector3<T> Vector3<T>::furthestBasisVector() const MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, bool> )
206{
207 using std::abs; // This should allow boost.multiprecision numbers here.
208 if ( abs( x ) < abs( y ) )
209 return ( abs( x ) < abs( z ) ) ? Vector3( 1, 0, 0 ) : Vector3( 0, 0, 1 );
210 else
211 return ( abs( y ) < abs( z ) ) ? Vector3( 0, 1, 0 ) : Vector3( 0, 0, 1 );
212}
213
214template <typename T>
215inline std::pair<Vector3<T>, Vector3<T>> Vector3<T>::perpendicular() const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
216{
217 std::pair<Vector3<T>, Vector3<T>> res;
218 auto c1 = furthestBasisVector();
219 res.first = cross( *this, c1 ).normalized();
220 res.second = cross( *this, res.first ).normalized();
221 return res;
222}
223
225template <typename T>
226Vector3<T> unitVector3( T azimuth, T altitude )
227{
228 const auto zenithAngle = T( PI2 ) - altitude;
229 return
230 {
231 std::sin( zenithAngle ) * std::cos( azimuth ),
232 std::sin( zenithAngle ) * std::sin( azimuth ),
233 std::cos( zenithAngle )
234 };
235}
236
237
238// We don't need to bind those functions themselves. This doesn't prevent `__iter__` from being generated for the type.
239
240template <typename T>
241MR_BIND_IGNORE inline auto begin( const Vector3<T> & v ) { return &v[0]; }
242template <typename T>
243MR_BIND_IGNORE inline auto begin( Vector3<T> & v ) { return &v[0]; }
244
245template <typename T>
246MR_BIND_IGNORE inline auto end( const Vector3<T> & v ) { return &v[3]; }
247template <typename T>
248MR_BIND_IGNORE inline auto end( Vector3<T> & v ) { return &v[3]; }
249
251
252#ifdef _MSC_VER
253#pragma warning(pop)
254#endif
255
256} // namespace MR
#define MR_SAME_TYPE_TEMPLATE_PARAM(target_, name_)
Definition MRMacros.h:32
#define MR_REQUIRES_IF_SUPPORTED(...)
Definition MRMacros.h:31
length
Definition MRObjectDimensionsEnum.h:14
MR_BIND_IGNORE auto begin(const BitSet &a)
Definition MRMesh/MRBitSet.h:295
MR_BIND_IGNORE auto end(const BitSet &)
Definition MRMesh/MRBitSet.h:297
MRMESH_CLASS Vector3
Definition MRMesh/MRMeshFwd.h:170
Definition MRMesh/MRAffineXf.h:14
Definition MRMesh/MRMatrix3.h:19
Definition MRMesh/MRMeshFwd.h:89
Definition MRSymMatrix3.h:15
Definition MRVector2.h:25
Definition MRMesh/MRVector3.h:26
static constexpr Vector3 plusX() noexcept
Definition MRMesh/MRVector3.h:40
auto dot(const Vector3< T > &a, const Vector3< T > &b) -> decltype(a.x *b.x)
dot product
Definition MRMesh/MRVector3.h:160
Vector3< T > unitVector3(T azimuth, T altitude)
returns a point on unit sphere given two angles
Definition MRMesh/MRVector3.h:226
T distanceSq(const Vector3< T > &a, const Vector3< T > &b)
squared distance between two points, which is faster to compute than just distance
Definition MRMesh/MRVector3.h:135
friend constexpr bool operator!=(const Vector3< T > &a, const Vector3< T > &b)
Definition MRMesh/MRVector3.h:98
Vector3< T > div(const Vector3< T > &a, const Vector3< T > &b)
per component division
Definition MRMesh/MRVector3.h:188
friend constexpr auto operator*(T a, const Vector3< T > &b) -> Vector3< decltype(std::declval< T >() *std::declval< T >())>
Definition MRMesh/MRVector3.h:107
friend constexpr auto operator-(const Vector3< T > &a) -> Vector3< decltype(-std::declval< T >())>
Definition MRMesh/MRVector3.h:103
T x
Definition MRMesh/MRVector3.h:32
static constexpr Vector3 minusX() noexcept
Definition MRMesh/MRVector3.h:43
static constexpr Vector3 minusY() noexcept
Definition MRMesh/MRVector3.h:44
bool isFinite() const
Definition MRMesh/MRVector3.h:92
T y
Definition MRMesh/MRVector3.h:32
static constexpr int elements
Definition MRMesh/MRVector3.h:30
friend constexpr const Vector3< T > & operator+(const Vector3< T > &a)
Definition MRMesh/MRVector3.h:102
friend constexpr Vector3< T > & operator/=(Vector3< T > &a, T b)
Definition MRMesh/MRVector3.h:120
std::pair< Vector3, Vector3 > perpendicular() const
void unsignZeroValues()
get rid of signed zero values to be sure that equal vectors have identical binary representation
Definition MRMesh/MRVector3.h:85
Vector3(NoInit) noexcept
Definition MRMesh/MRVector3.h:35
T ValueType
Definition MRMesh/MRVector3.h:27
constexpr const T & operator[](int e) const noexcept
Definition MRMesh/MRVector3.h:50
auto length() const
Definition MRMesh/MRVector3.h:54
constexpr Vector3(T x, T y, T z) noexcept
Definition MRMesh/MRVector3.h:36
friend constexpr bool operator==(const Vector3< T > &a, const Vector3< T > &b)
Definition MRMesh/MRVector3.h:97
friend constexpr Vector3< T > & operator*=(Vector3< T > &a, T b)
Definition MRMesh/MRVector3.h:119
T distance(const Vector3< T > &a, const Vector3< T > &b)
distance between two points, better use distanceSq for higher performance
Definition MRMesh/MRVector3.h:142
T mixed(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
mixed product
Definition MRMesh/MRVector3.h:174
static constexpr Vector3 plusZ() noexcept
Definition MRMesh/MRVector3.h:42
friend constexpr auto operator/(Vector3< T > b, T a) -> Vector3< decltype(std::declval< T >()/std::declval< T >())>
Definition MRMesh/MRVector3.h:109
T sqr(const Vector3< T > &a)
squared length
Definition MRMesh/MRVector3.h:167
Vector3 normalized() const
Definition MRMesh/MRVector3.h:62
T angle(const Vector3< T > &a, const Vector3< T > &b)
Definition MRMesh/MRVector3.h:197
constexpr Vector3(const Vector2< T > &v) noexcept
Definition MRMesh/MRVector3.h:37
constexpr Vector3(const Vector3< U > &v) noexcept
Definition MRMesh/MRVector3.h:48
constexpr Vector3() noexcept
Definition MRMesh/MRVector3.h:34
static constexpr Vector3 minusZ() noexcept
Definition MRMesh/MRVector3.h:45
Vector3< T > mult(const Vector3< T > &a, const Vector3< T > &b)
per component multiplication
Definition MRMesh/MRVector3.h:181
T z
Definition MRMesh/MRVector3.h:32
friend constexpr Vector3< T > & operator-=(Vector3< T > &a, const Vector3< T > &b)
Definition MRMesh/MRVector3.h:118
T lengthSq() const
Definition MRMesh/MRVector3.h:53
static constexpr Vector3 plusY() noexcept
Definition MRMesh/MRVector3.h:41
Vector3 furthestBasisVector() const
returns one of 3 basis unit vector that makes the biggest angle with the direction specified by this
Vector3 transformed(const AffineXf3< TT > *xf) const
returns this vector transformed by xf if it is
Definition MRMesh/MRVector3.h:79
static constexpr Vector3 diagonal(T a) noexcept
Definition MRMesh/MRVector3.h:39
Vector3< T > cross(const Vector3< T > &a, const Vector3< T > &b)
cross product
Definition MRMesh/MRVector3.h:149
friend constexpr Vector3< T > & operator+=(Vector3< T > &a, const Vector3< T > &b)
Definition MRMesh/MRVector3.h:117