MeshLib
 
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 <algorithm>
7#include <cmath>
8#if MR_HAS_REQUIRES
9#include <concepts>
10#endif
11
12namespace MR
13{
14
17template <typename T>
18struct Vector3
19{
20 using ValueType = T;
23 static constexpr int elements = 3;
24
25 T x, y, z;
26
27 constexpr Vector3() noexcept : x( 0 ), y( 0 ), z( 0 ) { }
28 explicit Vector3( NoInit ) noexcept { }
29 constexpr Vector3( T x, T y, T z ) noexcept : x( x ), y( y ), z( z ) { }
30 explicit constexpr Vector3( const Vector2<T> & v ) noexcept : x( v.x ), y( v.y ), z( 0 ) { }
31
32 static constexpr Vector3 diagonal( T a ) noexcept { return Vector3( a, a, a ); }
33 static constexpr Vector3 plusX() noexcept { return Vector3( 1, 0, 0 ); }
34 static constexpr Vector3 plusY() noexcept { return Vector3( 0, 1, 0 ); }
35 static constexpr Vector3 plusZ() noexcept { return Vector3( 0, 0, 1 ); }
36 static constexpr Vector3 minusX() noexcept { return Vector3( -1, 0, 0 ); }
37 static constexpr Vector3 minusY() noexcept { return Vector3( 0, -1, 0 ); }
38 static constexpr Vector3 minusZ() noexcept { return Vector3( 0, 0, -1 ); }
39
40 template <typename U>
41 constexpr explicit Vector3( const Vector3<U> & v ) noexcept : x( T( v.x ) ), y( T( v.y ) ), z( T( v.z ) ) { }
42
43 constexpr const T & operator []( int e ) const noexcept { return *( &x + e ); }
44 constexpr T & operator []( int e ) noexcept { return *( &x + e ); }
45
46 T lengthSq() const { return x * x + y * y + z * z; }
47 auto length() const
48 {
49 // Calling `sqrt` this way to hopefully support boost.multiprecision numbers.
50 // Returning `auto` to not break on integral types.
51 using std::sqrt;
52 return sqrt( lengthSq() );
53 }
54
55 [[nodiscard]] Vector3 normalized() const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
56 {
57 auto len = length();
58 if ( len <= 0 )
59 return {};
60 return ( 1 / len ) * (*this);
61 }
62
64 Vector3 furthestBasisVector() const MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, bool> );
65
68 std::pair<Vector3, Vector3> perpendicular() const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> );
69
71 Vector3 transformed( const AffineXf3<T>* xf ) const MR_REQUIRES_IF_SUPPORTED( !std::same_as<T, bool> )
72 {
73 return xf ? ( *xf )( *this ) : *this;
74 }
75
77 void unsignZeroValues() MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
78 {
79 for ( auto i = 0; i < elements; ++i )
80 if ( (*this)[i] == 0.f && std::signbit( (*this)[i] ) )
81 (*this)[i] = 0.f;
82 }
83
84 [[nodiscard]] bool isFinite() const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
85 {
86 return std::isfinite( x ) && std::isfinite( y ) && std::isfinite( z );
87 }
88};
89
92
93template <typename T>
94inline Vector3<T> & operator +=( Vector3<T> & a, const Vector3<T> & b ) { a.x += b.x; a.y += b.y; a.z += b.z; return a; }
95
96template <typename T>
97inline Vector3<T> & operator -=( Vector3<T> & a, const Vector3<T> & b ) { a.x -= b.x; a.y -= b.y; a.z -= b.z; return a; }
98
99template <typename T>
100inline Vector3<T> & operator *=( Vector3<T> & a, T b ) { a.x *= b; a.y *= b; a.z *= b; return a; }
101
102template <typename T>
103inline Vector3<T> & operator /=( Vector3<T> & a, T b )
104{
105 if constexpr ( std::is_integral_v<T> )
106 { a.x /= b; a.y /= b; a.z /= b; return a; }
107 else
108 return a *= ( 1 / b );
109}
110
111template <typename T>
112inline Vector3<T> operator -( const Vector3<T> & a ) { return Vector3<T>( -a.x, -a.y, -a.z ); }
113
114template <typename T>
115inline const Vector3<T> & operator +( const Vector3<T> & a ) { return a; }
116
118template <typename T>
119inline Vector3<T> cross( const Vector3<T> & a, const Vector3<T> & b )
120{
121 return {
122 a.y * b.z - a.z * b.y,
123 a.z * b.x - a.x * b.z,
124 a.x * b.y - a.y * b.x
125 };
126}
127
129template <typename T>
130inline T dot( const Vector3<T> & a, const Vector3<T> & b )
131{
132 return a.x * b.x + a.y * b.y + a.z * b.z;
133}
134
136template <typename T>
137inline T sqr( const Vector3<T> & a )
138{
139 return a.lengthSq();
140}
141
143template <typename T>
144inline T mixed( const Vector3<T> & a, const Vector3<T> & b, const Vector3<T> & c )
145{
146 return dot( a, cross( b, c ) );
147}
148
150template <typename T>
151inline Vector3<T> mult( const Vector3<T>& a, const Vector3<T>& b )
152{
153 return { a.x * b.x,a.y * b.y,a.z * b.z };
154}
155
157template <typename T>
158inline Vector3<T> div( const Vector3<T>& a, const Vector3<T>& b )
159{
160 return { a.x / b.x, a.y / b.y, a.z / b.z };
161}
162
163
166template <typename T>
167inline T angle( const Vector3<T> & a, const Vector3<T> & b )
168{
169 return std::atan2( cross( a, b ).length(), dot( a, b ) );
170 // this version is slower and less precise
171 //return std::acos( std::clamp( dot( a.normalized(), b.normalized() ), T(-1), T(1) ) );
172}
173
174template <typename T>
175inline Vector3<T> Vector3<T>::furthestBasisVector() const MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, bool> )
176{
177 using std::abs; // This should allow boost.multiprecision numbers here.
178 if ( abs( x ) < abs( y ) )
179 return ( abs( x ) < abs( z ) ) ? Vector3( 1, 0, 0 ) : Vector3( 0, 0, 1 );
180 else
181 return ( abs( y ) < abs( z ) ) ? Vector3( 0, 1, 0 ) : Vector3( 0, 0, 1 );
182}
183
184template <typename T>
185inline std::pair<Vector3<T>, Vector3<T>> Vector3<T>::perpendicular() const MR_REQUIRES_IF_SUPPORTED( std::floating_point<T> )
186{
187 std::pair<Vector3<T>, Vector3<T>> res;
188 auto c1 = furthestBasisVector();
189 res.first = cross( *this, c1 ).normalized();
190 res.second = cross( *this, res.first ).normalized();
191 return res;
192}
193
194template <typename T>
195[[nodiscard]] inline bool operator ==( const Vector3<T> & a, const Vector3<T> & b )
196 { return a.x == b.x && a.y == b.y && a.z == b.z; }
197
198template <typename T>
199[[nodiscard]] inline bool operator !=( const Vector3<T> & a, const Vector3<T> & b )
200 { return !( a == b ); }
201
202template <typename T>
203[[nodiscard]] inline constexpr Vector3<T> operator +( const Vector3<T> & a, const Vector3<T> & b )
204 { return { T( a.x + b.x ), T( a.y + b.y ), T( a.z + b.z ) }; }
205
206template <typename T>
207[[nodiscard]] inline Vector3<T> operator -( const Vector3<T> & a, const Vector3<T> & b )
208 { return { T( a.x - b.x ), T( a.y - b.y ), T( a.z - b.z ) }; }
209
210template <typename T>
211[[nodiscard]] inline Vector3<T> operator *( T a, const Vector3<T> & b )
212 { return { T( a * b.x ), T( a * b.y ), T( a * b.z ) }; }
213
214template <typename T>
215[[nodiscard]] inline Vector3<T> operator *( const Vector3<T> & b, T a )
216 { return { T( a * b.x ), T( a * b.y ), T( a * b.z ) }; }
217
218template <typename T>
219[[nodiscard]] inline Vector3<T> operator /( Vector3<T> b, T a )
220 { b /= a; return b; }
221
223template <typename T>
224Vector3<T> unitVector3( T azimuth, T altitude )
225{
226 const auto zenithAngle = T( PI2 ) - altitude;
227 return
228 {
229 std::sin( zenithAngle ) * std::cos( azimuth ),
230 std::sin( zenithAngle ) * std::sin( azimuth ),
231 std::cos( zenithAngle )
232 };
233}
234
235template <typename T>
236inline auto begin( const Vector3<T> & v ) { return &v[0]; }
237template <typename T>
238inline auto begin( Vector3<T> & v ) { return &v[0]; }
239
240template <typename T>
241inline auto end( const Vector3<T> & v ) { return &v[3]; }
242template <typename T>
243inline auto end( Vector3<T> & v ) { return &v[3]; }
244
246
247} // namespace MR
constexpr A & operator/=(A &a, B b)
Definition MRImGuiVectorOperators.h:115
#define MR_REQUIRES_IF_SUPPORTED(...)
Definition MRMacros.h:26
length
Definition MRObjectDimensionsEnum.h:14
BitSet operator-(const BitSet &a, const BitSet &b)
Definition MRMesh/MRBitSet.h:325
auto begin(const BitSet &a)
Definition MRMesh/MRBitSet.h:263
MRMESH_API bool operator==(const BitSet &a, const BitSet &b)
compare that two bit sets have the same set bits (they can be equal even if sizes are distinct but la...
auto end(const BitSet &)
Definition MRMesh/MRBitSet.h:265
bool operator!=(const SetBitIteratorT< T > &a, const SetBitIteratorT< T > &b)
Definition MRMesh/MRBitSet.h:259
MRMESH_API FloatGrid operator+=(FloatGrid &a, const FloatGrid &b)
MRMESH_API FloatGrid operator-=(FloatGrid &a, const FloatGrid &b)
MRMESH_API FloatGrid operator*=(FloatGrid &a, const FloatGrid &b)
Definition MRCameraOrientationPlugin.h:7
Color operator/(const Color &b, float a)
Definition MRColor.h:128
Color operator*(float a, const Color &b)
Definition MRColor.h:118
MRMESH_CLASS Vector3
Definition MRMesh/MRMeshFwd.h:136
Color operator+(const Color &a, const Color &b)
Definition MRColor.h:108
Definition MRMesh/MRAffineXf.h:14
Definition MRMesh/MRMatrix3.h:13
Definition MRMesh/MRMeshFwd.h:56
Definition MRSymMatrix3.h:15
Definition MRVector2.h:18
Definition MRMesh/MRVector3.h:19
static constexpr Vector3 plusX() noexcept
Definition MRMesh/MRVector3.h:33
void unsignZeroValues() MR_REQUIRES_IF_SUPPORTED(std
get rid of signed zero values to be sure that equal vectors have identical binary representation
Definition MRMesh/MRVector3.h:77
Vector3< T > unitVector3(T azimuth, T altitude)
returns a point on unit sphere given two angles
Definition MRMesh/MRVector3.h:224
Vector3< T > div(const Vector3< T > &a, const Vector3< T > &b)
per component division
Definition MRMesh/MRVector3.h:158
T dot(const Vector3< T > &a, const Vector3< T > &b)
dot product
Definition MRMesh/MRVector3.h:130
T x
Definition MRMesh/MRVector3.h:25
static constexpr Vector3 minusX() noexcept
Definition MRMesh/MRVector3.h:36
static constexpr Vector3 minusY() noexcept
Definition MRMesh/MRVector3.h:37
T y
Definition MRMesh/MRVector3.h:25
static constexpr int elements
Definition MRMesh/MRVector3.h:23
Vector3(NoInit) noexcept
Definition MRMesh/MRVector3.h:28
T ValueType
Definition MRMesh/MRVector3.h:20
constexpr const T & operator[](int e) const noexcept
Definition MRMesh/MRVector3.h:43
Vector3 furthestBasisVector() const MR_REQUIRES_IF_SUPPORTED(!std std::pair< Vector3, Vector3 > perpendicular() const MR_REQUIRES_IF_SUPPORTED(std Vector3 transformed(const AffineXf3< T > *xf) const MR_REQUIRES_IF_SUPPORTED(!std
returns one of 3 basis unit vector that makes the biggest angle with the direction specified by this
Definition MRMesh/MRVector3.h:71
auto length() const
Definition MRMesh/MRVector3.h:47
constexpr Vector3(T x, T y, T z) noexcept
Definition MRMesh/MRVector3.h:29
T mixed(const Vector3< T > &a, const Vector3< T > &b, const Vector3< T > &c)
mixed product
Definition MRMesh/MRVector3.h:144
static constexpr Vector3 plusZ() noexcept
Definition MRMesh/MRVector3.h:35
Vector3 normalized() const MR_REQUIRES_IF_SUPPORTED(std
Definition MRMesh/MRVector3.h:55
T sqr(const Vector3< T > &a)
squared length
Definition MRMesh/MRVector3.h:137
T angle(const Vector3< T > &a, const Vector3< T > &b)
Definition MRMesh/MRVector3.h:167
constexpr Vector3(const Vector2< T > &v) noexcept
Definition MRMesh/MRVector3.h:30
constexpr Vector3(const Vector3< U > &v) noexcept
Definition MRMesh/MRVector3.h:41
constexpr Vector3() noexcept
Definition MRMesh/MRVector3.h:27
static constexpr Vector3 minusZ() noexcept
Definition MRMesh/MRVector3.h:38
Vector3< T > mult(const Vector3< T > &a, const Vector3< T > &b)
per component multiplication
Definition MRMesh/MRVector3.h:151
T z
Definition MRMesh/MRVector3.h:25
T lengthSq() const
Definition MRMesh/MRVector3.h:46
static constexpr Vector3 plusY() noexcept
Definition MRMesh/MRVector3.h:34
bool isFinite() const MR_REQUIRES_IF_SUPPORTED(std
Definition MRMesh/MRVector3.h:84
static constexpr Vector3 diagonal(T a) noexcept
Definition MRMesh/MRVector3.h:32
Vector3< T > cross(const Vector3< T > &a, const Vector3< T > &b)
cross product
Definition MRMesh/MRVector3.h:119