MeshLib C++ Docs
Loading...
Searching...
No Matches
MRVector2.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRMacros.h"
4#include "MRMeshFwd.h"
5#include "MRPch/MRBindingMacros.h"
6#include <cmath>
7#include <algorithm>
8#include <cstring>
9#include <utility>
10
11namespace MR
12{
13
14#ifdef _MSC_VER
15#pragma warning(push)
16#pragma warning(disable: 4804) // unsafe use of type 'bool' in operation
17#pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned
18#endif
19
22
25template <typename T>
26struct Vector2
27{
28 using ValueType = T;
31 static constexpr int elements = 2;
32
33 T x, y;
34
35 constexpr Vector2() noexcept : x( 0 ), y( 0 ) { }
36 explicit Vector2( NoInit ) noexcept { }
37 constexpr Vector2( T x, T y ) noexcept : x( x ), y( y ) { }
38
39 template <typename U> MR_REQUIRES_IF_SUPPORTED( std::constructible_from<T, U> )
40 explicit constexpr Vector2( const Vector3<U> & v ) noexcept : x( v.x ), y( v.y ) { }
41
42 static constexpr Vector2 diagonal( T a ) noexcept { return Vector2( a, a ); }
43 static constexpr Vector2 plusX() noexcept { return Vector2( 1, 0 ); }
44 static constexpr Vector2 plusY() noexcept { return Vector2( 0, 1 ); }
45 static constexpr Vector2 minusX() noexcept { return Vector2( -1, 0 ); }
46 static constexpr Vector2 minusY() noexcept { return Vector2( 0, -1 ); }
47
48 // Here `T == U` doesn't seem to cause any issues in the C++ code, but we're still disabling it because it somehow gets emitted
49 // when generating the bindings, and looks out of place there.
50 template <typename U> MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, U> )
51 constexpr explicit Vector2( const Vector2<U> & v ) noexcept : x( T( v.x ) ), y( T( v.y ) ) { }
52
53 constexpr const T & operator []( int e ) const noexcept { return *( &x + e ); }
54 constexpr T & operator []( int e ) noexcept { return *( &x + e ); }
55
56 T lengthSq() const { return x * x + y * y; }
57 auto length() const
58 {
59 // Calling `sqrt` this way to hopefully support boost.multiprecision numbers.
60 // Returning `auto` to not break on integral types.
61 using std::sqrt;
62 return sqrt( lengthSq() );
63 }
64
65 Vector2 normalized() const MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> )
66 {
67 auto len = length();
68 if ( len <= 0 )
69 return {};
70 return ( 1 / len ) * (*this);
71 }
72
74 Vector2 furthestBasisVector() const MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, bool> );
75
77 constexpr Vector2 perpendicular() const MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, bool> ) { return Vector2{ -y, x }; }
78
79 [[nodiscard]] bool isFinite() const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> )
80 {
81 return std::isfinite( x ) && std::isfinite( y );
82 }
83
84 [[nodiscard]] friend constexpr bool operator ==( const Vector2<T> & a, const Vector2<T> & b ) { return a.x == b.x && a.y == b.y; }
85 [[nodiscard]] friend constexpr bool operator !=( const Vector2<T> & a, const Vector2<T> & b ) { return !( a == b ); }
86
87 // 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.
88
89 [[nodiscard]] friend constexpr const Vector2<T> & operator +( const Vector2<T> & a ) { return a; }
90 [[nodiscard]] friend constexpr auto operator -( const Vector2<T> & a ) -> Vector2<decltype( -std::declval<T>() )> { return { -a.x, -a.y }; }
91
92 [[nodiscard]] friend constexpr auto operator +( const Vector2<T> & a, const Vector2<T> & b ) -> Vector2<decltype( std::declval<T>() + std::declval<T>() )> { return { a.x + b.x, a.y + b.y }; }
93 [[nodiscard]] friend constexpr auto operator -( const Vector2<T> & a, const Vector2<T> & b ) -> Vector2<decltype( std::declval<T>() - std::declval<T>() )> { return { a.x - b.x, a.y - b.y }; }
94 [[nodiscard]] friend constexpr auto operator *( T a, const Vector2<T> & b ) -> Vector2<decltype( std::declval<T>() * std::declval<T>() )> { return { a * b.x, a * b.y }; }
95 [[nodiscard]] friend constexpr auto operator *( const Vector2<T> & b, T a ) -> Vector2<decltype( std::declval<T>() * std::declval<T>() )> { return { a * b.x, a * b.y }; }
96 [[nodiscard]] friend constexpr auto operator /( Vector2<T> b, T a ) -> Vector2<decltype( std::declval<T>() / std::declval<T>() )>
97 {
98 if constexpr ( std::is_integral_v<T> )
99 return { b.x / a, b.y / a };
100 else
101 return b * ( 1 / a );
102 }
103
104 friend constexpr Vector2<T> & operator +=( Vector2<T> & a, const Vector2<T> & b ) { a.x += b.x; a.y += b.y; return a; }
105 friend constexpr Vector2<T> & operator -=( Vector2<T> & a, const Vector2<T> & b ) { a.x -= b.x; a.y -= b.y; return a; }
106 friend constexpr Vector2<T> & operator *=( Vector2<T> & a, T b ) { a.x *= b; a.y *= b; return a; }
107 friend constexpr Vector2<T> & operator /=( Vector2<T> & a, T b )
108 {
109 if constexpr ( std::is_integral_v<T> )
110 { a.x /= b; a.y /= b; return a; }
111 else
112 return a *= ( 1 / b );
113 }
114};
115
118
120template <typename T>
121inline T distanceSq( const Vector2<T> & a, const Vector2<T> & b )
122{
123 return ( a - b ).lengthSq();
124}
125
127template <typename T>
128inline T distance( const Vector2<T> & a, const Vector2<T> & b )
129{
130 return ( a - b ).length();
131}
132
134template <typename T>
135inline T cross( const Vector2<T> & a, const Vector2<T> & b )
136{
137 return a.x * b.y - a.y * b.x;
138}
139
141template <typename T>
142inline auto dot( const Vector2<T> & a, const Vector2<T> & b ) -> decltype( a.x * b.x )
143{
144 return a.x * b.x + a.y * b.y;
145}
146
148template <typename T>
149inline T sqr( const Vector2<T> & a )
150{
151 return a.lengthSq();
152}
153
155template <typename T>
156inline Vector2<T> mult( const Vector2<T>& a, const Vector2<T>& b )
157{
158 return { a.x * b.x,a.y * b.y };
159}
160
162template <typename T>
163inline Vector2<T> div( const Vector2<T>& a, const Vector2<T>& b )
164{
165 return { a.x / b.x, a.y / b.y };
166}
167
169template <typename T>
170inline T angle( const Vector2<T> & a, const Vector2<T> & b )
171{
172 return std::atan2( std::abs( cross( a, b ) ), dot( a, b ) );
173 // this version is slower and less precise
174 //return std::acos( std::clamp( dot( a.normalized(), b.normalized() ), T(-1), T(1) ) );
175}
176
177template <typename T>
178inline Vector2<T> Vector2<T>::furthestBasisVector() const MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, bool> )
179{
180 using std::abs; // This allows boost.multiprecision numbers.
181 if ( abs( x ) < abs( y ) )
182 return Vector2( 1, 0 );
183 else
184 return Vector2( 0, 1 );
185}
186
187
188// We don't need to bind those functions themselves. This doesn't prevent `__iter__` from being generated for the type.
189
190template <typename T>
191MR_BIND_IGNORE inline auto begin( const Vector2<T> & v ) { return &v[0]; }
192template <typename T>
193MR_BIND_IGNORE inline auto begin( Vector2<T> & v ) { return &v[0]; }
194
195template <typename T>
196MR_BIND_IGNORE inline auto end( const Vector2<T> & v ) { return &v[2]; }
197template <typename T>
198MR_BIND_IGNORE inline auto end( Vector2<T> & v ) { return &v[2]; }
199
201
202#ifdef _MSC_VER
203#pragma warning(pop)
204#endif
205
206} // namespace MR
207
208template<>
209struct std::hash<MR::Vector2f>
210{
211 size_t operator()( MR::Vector2f const& p ) const noexcept
212 {
213 std::uint64_t xy;
214 static_assert( sizeof( float ) == sizeof( std::uint32_t ) );
215 std::memcpy( &xy, &p.x, sizeof( std::uint64_t ) );
216 return size_t( xy );
217 }
218};
#define MR_REQUIRES_IF_SUPPORTED(...)
Definition MRMacros.h:31
MR_BIND_IGNORE auto begin(const BitSet &a)
Definition MRMesh/MRBitSet.h:308
MR_BIND_IGNORE auto end(const BitSet &)
Definition MRMesh/MRBitSet.h:310
Definition MRCameraOrientationPlugin.h:8
std::array< Vector3f, 3 > MR_BIND_IGNORE
Definition MRMeshBuilderTypes.h:10
Definition MRMatrix2.h:19
Definition MRMesh/MRMeshFwd.h:90
Definition MRSymMatrix2.h:14
Definition MRVector2.h:27
T x
Definition MRVector2.h:33
Vector2(NoInit) noexcept
Definition MRVector2.h:36
Vector2< T > div(const Vector2< T > &a, const Vector2< T > &b)
per component division
Definition MRVector2.h:163
T cross(const Vector2< T > &a, const Vector2< T > &b)
cross product
Definition MRVector2.h:135
friend constexpr bool operator!=(const Vector2< T > &a, const Vector2< T > &b)
Definition MRVector2.h:85
static constexpr Vector2 plusY() noexcept
Definition MRVector2.h:44
static constexpr Vector2 minusX() noexcept
Definition MRVector2.h:45
friend constexpr Vector2< T > & operator-=(Vector2< T > &a, const Vector2< T > &b)
Definition MRVector2.h:105
friend constexpr Vector2< T > & operator+=(Vector2< T > &a, const Vector2< T > &b)
Definition MRVector2.h:104
friend constexpr auto operator*(T a, const Vector2< T > &b) -> Vector2< decltype(std::declval< T >() *std::declval< T >())>
Definition MRVector2.h:94
T ValueType
Definition MRVector2.h:28
friend constexpr Vector2< T > & operator/=(Vector2< T > &a, T b)
Definition MRVector2.h:107
T y
Definition MRVector2.h:33
constexpr const T & operator[](int e) const noexcept
Definition MRVector2.h:53
Vector2 normalized() const MR_REQUIRES_IF_SUPPORTED(!std
Definition MRVector2.h:65
friend constexpr bool operator==(const Vector2< T > &a, const Vector2< T > &b)
Definition MRVector2.h:84
constexpr Vector2() noexcept
Definition MRVector2.h:35
Vector2 furthestBasisVector() const MR_REQUIRES_IF_SUPPORTED(!std constexpr Vector2 perpendicular() const MR_REQUIRES_IF_SUPPORTED(!std
returns one of 2 basis unit vector that makes the biggest angle with the direction specified by this
Definition MRVector2.h:77
friend constexpr auto operator/(Vector2< T > b, T a) -> Vector2< decltype(std::declval< T >()/std::declval< T >())>
Definition MRVector2.h:96
static constexpr Vector2 diagonal(T a) noexcept
Definition MRVector2.h:42
T distanceSq(const Vector2< T > &a, const Vector2< T > &b)
squared distance between two points, which is faster to compute than just distance
Definition MRVector2.h:121
T distance(const Vector2< T > &a, const Vector2< T > &b)
distance between two points, better use distanceSq for higher performance
Definition MRVector2.h:128
MR_REQUIRES_IF_SUPPORTED(!std::is_same_v< T, U >) const expr explicit Vector2(const Vector2< U > &v) noexcept
Definition MRVector2.h:50
constexpr Vector2(T x, T y) noexcept
Definition MRVector2.h:37
T sqr(const Vector2< T > &a)
squared length
Definition MRVector2.h:149
static constexpr int elements
Definition MRVector2.h:31
auto length() const
Definition MRVector2.h:57
static constexpr Vector2 plusX() noexcept
Definition MRVector2.h:43
auto dot(const Vector2< T > &a, const Vector2< T > &b) -> decltype(a.x *b.x)
dot product
Definition MRVector2.h:142
MR_REQUIRES_IF_SUPPORTED(std::constructible_from< T, U >) explicit const expr Vector2(const Vector3< U > &v) noexcept
Definition MRVector2.h:39
Vector2< T > mult(const Vector2< T > &a, const Vector2< T > &b)
per component multiplication
Definition MRVector2.h:156
friend constexpr Vector2< T > & operator*=(Vector2< T > &a, T b)
Definition MRVector2.h:106
friend constexpr auto operator-(const Vector2< T > &a) -> Vector2< decltype(-std::declval< T >())>
Definition MRVector2.h:90
T lengthSq() const
Definition MRVector2.h:56
static constexpr Vector2 minusY() noexcept
Definition MRVector2.h:46
friend constexpr const Vector2< T > & operator+(const Vector2< T > &a)
Definition MRVector2.h:89
T angle(const Vector2< T > &a, const Vector2< T > &b)
angle in radians between two vectors
Definition MRVector2.h:170
bool isFinite() const MR_REQUIRES_IF_SUPPORTED(std
Definition MRVector2.h:79
Definition MRMesh/MRVector3.h:28