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 "MRMesh/MRUnsigned.h"
5#include "MRMeshFwd.h"
6#include "MRPch/MRBindingMacros.h"
7#include <cmath>
8#include <algorithm>
9#include <cstring>
10#include <utility>
11
12namespace MR
13{
14
15#ifdef _MSC_VER
16#pragma warning(push)
17#pragma warning(disable: 4804) // unsafe use of type 'bool' in operation
18#pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned
19#endif
20
23
26template <typename T>
27struct Vector2
28{
29 using ValueType = T;
32 static constexpr int elements = 2;
33
34 T x, y;
35
36 constexpr Vector2() noexcept : x( 0 ), y( 0 )
37 {
38 static_assert( sizeof( Vector2<ValueType> ) == elements * sizeof( ValueType ), "Struct size invalid" );
39 static_assert( elements == 2, "Invalid number of elements" );
40 }
41 explicit Vector2( NoInit ) noexcept { }
42 constexpr Vector2( T x, T y ) noexcept : x( x ), y( y ) { }
43
44 template <typename U> MR_REQUIRES_IF_SUPPORTED( std::constructible_from<T, U> )
45 explicit constexpr Vector2( const Vector3<U> & v ) noexcept : x( v.x ), y( v.y ) { }
46
47 static constexpr Vector2 diagonal( T a ) noexcept { return Vector2( a, a ); }
48 static constexpr Vector2 plusX() noexcept { return Vector2( 1, 0 ); }
49 static constexpr Vector2 plusY() noexcept { return Vector2( 0, 1 ); }
50 static constexpr Vector2 minusX() noexcept MR_REQUIRES_IF_SUPPORTED( !std::is_unsigned_v<T> ) { return Vector2( -1, 0 ); }
51 static constexpr Vector2 minusY() noexcept MR_REQUIRES_IF_SUPPORTED( !std::is_unsigned_v<T> ) { return Vector2( 0, -1 ); }
52
53 // 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
54 // when generating the bindings, and looks out of place there.
55 template <typename U> MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, U> )
56 constexpr explicit Vector2( const Vector2<U> & v ) noexcept : x( T( v.x ) ), y( T( v.y ) ) { }
57
58 constexpr const T & operator []( int e ) const noexcept { return *( ( ValueType *)this + e ); }
59 constexpr T & operator []( int e ) noexcept { return *( ( ValueType *)this + e ); }
60
61 T lengthSq() const { return x * x + y * y; }
62 auto length() const
63 {
64 // Calling `sqrt` this way to hopefully support boost.multiprecision numbers.
65 // Returning `auto` to not break on integral types.
66 using std::sqrt;
67 return sqrt( lengthSq() );
68 }
69
70 Vector2 normalized() const MR_REQUIRES_IF_SUPPORTED( !std::is_integral_v<T> )
71 {
72 auto len = length();
73 if ( len <= 0 )
74 return {};
75 return ( 1 / len ) * (*this);
76 }
77
79 Vector2 furthestBasisVector() const MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, bool> );
80
82 constexpr Vector2 perpendicular() const MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, bool> ) { return Vector2{ -y, x }; }
83
84 [[nodiscard]] bool isFinite() const MR_REQUIRES_IF_SUPPORTED( std::is_floating_point_v<T> )
85 {
86 return std::isfinite( x ) && std::isfinite( y );
87 }
88
89 [[nodiscard]] friend constexpr bool operator ==( const Vector2<T> & a, const Vector2<T> & b ) { return a.x == b.x && a.y == b.y; }
90 [[nodiscard]] friend constexpr bool operator !=( const Vector2<T> & a, const Vector2<T> & b ) { return !( a == b ); }
91
92 // 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.
93
94 [[nodiscard]] friend constexpr const Vector2<T> & operator +( const Vector2<T> & a ) { return a; }
95 [[nodiscard]] friend constexpr auto operator -( const Vector2<T> & a ) -> Vector2<decltype( -std::declval<T>() )> { return { -a.x, -a.y }; }
96
97 [[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 }; }
98 [[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 }; }
99 [[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 }; }
100 [[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 }; }
101 [[nodiscard]] friend constexpr auto operator /( Vector2<T> b, T a ) -> Vector2<decltype( std::declval<T>() / std::declval<T>() )>
102 {
103 if constexpr ( std::is_integral_v<T> )
104 return { b.x / a, b.y / a };
105 else
106 return b * ( 1 / a );
107 }
108
109 friend constexpr Vector2<T> & operator +=( Vector2<T> & a, const Vector2<T> & b ) { a.x += b.x; a.y += b.y; return a; }
110 friend constexpr Vector2<T> & operator -=( Vector2<T> & a, const Vector2<T> & b ) { a.x -= b.x; a.y -= b.y; return a; }
111 friend constexpr Vector2<T> & operator *=( Vector2<T> & a, T b ) { a.x *= b; a.y *= b; return a; }
112 friend constexpr Vector2<T> & operator /=( Vector2<T> & a, T b )
113 {
114 if constexpr ( std::is_integral_v<T> )
115 { a.x /= b; a.y /= b; return a; }
116 else
117 return a *= ( 1 / b );
118 }
119};
120
123
125template <typename T>
126inline T distanceSq( const Vector2<T> & a, const Vector2<T> & b )
127{
128 return ( a - b ).lengthSq();
129}
130
132template <typename T>
133inline T distance( const Vector2<T> & a, const Vector2<T> & b )
134{
135 return ( a - b ).length();
136}
137
139template <typename T>
140inline T cross( const Vector2<T> & a, const Vector2<T> & b )
141{
142 return a.x * b.y - a.y * b.x;
143}
144
146template <typename T>
147inline auto dot( const Vector2<T> & a, const Vector2<T> & b ) -> decltype( a.x * b.x )
148{
149 return a.x * b.x + a.y * b.y;
150}
151
153template <typename T>
154inline T sqr( const Vector2<T> & a )
155{
156 return a.lengthSq();
157}
158
160template <typename T>
161inline Vector2<T> mult( const Vector2<T>& a, const Vector2<T>& b )
162{
163 return { a.x * b.x,a.y * b.y };
164}
165
167template <typename T>
168inline Vector2<T> div( const Vector2<T>& a, const Vector2<T>& b )
169{
170 return { a.x / b.x, a.y / b.y };
171}
172
174template <typename T>
175inline T angle( const Vector2<T> & a, const Vector2<T> & b )
176{
177 return std::atan2( std::abs( cross( a, b ) ), dot( a, b ) );
178 // this version is slower and less precise
179 //return std::acos( std::clamp( dot( a.normalized(), b.normalized() ), T(-1), T(1) ) );
180}
181
182template <typename T>
183inline Vector2<T> Vector2<T>::furthestBasisVector() const MR_REQUIRES_IF_SUPPORTED( !std::is_same_v<T, bool> )
184{
185 using std::abs; // This allows boost.multiprecision numbers.
186 using Unsigned::abs; // This silences warnings on unsigned integers.
187 if ( abs( x ) < abs( y ) )
188 return Vector2( 1, 0 );
189 else
190 return Vector2( 0, 1 );
191}
192
193
194// We don't need to bind those functions themselves. This doesn't prevent `__iter__` from being generated for the type.
195
196template <typename T>
197MR_BIND_IGNORE inline auto begin( const Vector2<T> & v ) { return &v[0]; }
198template <typename T>
199MR_BIND_IGNORE inline auto begin( Vector2<T> & v ) { return &v[0]; }
200
201template <typename T>
202MR_BIND_IGNORE inline auto end( const Vector2<T> & v ) { return &v[2]; }
203template <typename T>
204MR_BIND_IGNORE inline auto end( Vector2<T> & v ) { return &v[2]; }
205
207
208#ifdef _MSC_VER
209#pragma warning(pop)
210#endif
211
212} // namespace MR
213
214template<>
215struct std::hash<MR::Vector2f>
216{
217 size_t operator()( MR::Vector2f const& p ) const noexcept
218 {
219 std::uint64_t xy;
220 static_assert( sizeof( float ) == sizeof( std::uint32_t ) );
221 std::memcpy( &xy, &p.x, sizeof( std::uint64_t ) );
222 return size_t( xy );
223 }
224};
#define MR_REQUIRES_IF_SUPPORTED(...)
Definition MRMacros.h:34
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
constexpr T abs(T value)
Definition MRUnsigned.h:18
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:28
T x
Definition MRVector2.h:34
Vector2(NoInit) noexcept
Definition MRVector2.h:41
Vector2< T > div(const Vector2< T > &a, const Vector2< T > &b)
per component division
Definition MRVector2.h:168
T cross(const Vector2< T > &a, const Vector2< T > &b)
cross product
Definition MRVector2.h:140
friend constexpr bool operator!=(const Vector2< T > &a, const Vector2< T > &b)
Definition MRVector2.h:90
static constexpr Vector2 plusY() noexcept
Definition MRVector2.h:49
friend constexpr Vector2< T > & operator-=(Vector2< T > &a, const Vector2< T > &b)
Definition MRVector2.h:110
friend constexpr Vector2< T > & operator+=(Vector2< T > &a, const Vector2< T > &b)
Definition MRVector2.h:109
friend constexpr auto operator*(T a, const Vector2< T > &b) -> Vector2< decltype(std::declval< T >() *std::declval< T >())>
Definition MRVector2.h:99
T ValueType
Definition MRVector2.h:29
friend constexpr Vector2< T > & operator/=(Vector2< T > &a, T b)
Definition MRVector2.h:112
T y
Definition MRVector2.h:34
constexpr const T & operator[](int e) const noexcept
Definition MRVector2.h:58
Vector2 normalized() const MR_REQUIRES_IF_SUPPORTED(!std
Definition MRVector2.h:70
friend constexpr bool operator==(const Vector2< T > &a, const Vector2< T > &b)
Definition MRVector2.h:89
constexpr Vector2() noexcept
Definition MRVector2.h:36
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:82
friend constexpr auto operator/(Vector2< T > b, T a) -> Vector2< decltype(std::declval< T >()/std::declval< T >())>
Definition MRVector2.h:101
static constexpr Vector2 diagonal(T a) noexcept
Definition MRVector2.h:47
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:126
T distance(const Vector2< T > &a, const Vector2< T > &b)
distance between two points, better use distanceSq for higher performance
Definition MRVector2.h:133
static constexpr Vector2 minusY() noexcept MR_REQUIRES_IF_SUPPORTED(!std
Definition MRVector2.h:51
MR_REQUIRES_IF_SUPPORTED(!std::is_same_v< T, U >) const expr explicit Vector2(const Vector2< U > &v) noexcept
Definition MRVector2.h:55
constexpr Vector2(T x, T y) noexcept
Definition MRVector2.h:42
T sqr(const Vector2< T > &a)
squared length
Definition MRVector2.h:154
static constexpr int elements
Definition MRVector2.h:32
auto length() const
Definition MRVector2.h:62
static constexpr Vector2 plusX() noexcept
Definition MRVector2.h:48
auto dot(const Vector2< T > &a, const Vector2< T > &b) -> decltype(a.x *b.x)
dot product
Definition MRVector2.h:147
MR_REQUIRES_IF_SUPPORTED(std::constructible_from< T, U >) explicit const expr Vector2(const Vector3< U > &v) noexcept
Definition MRVector2.h:44
Vector2< T > mult(const Vector2< T > &a, const Vector2< T > &b)
per component multiplication
Definition MRVector2.h:161
friend constexpr Vector2< T > & operator*=(Vector2< T > &a, T b)
Definition MRVector2.h:111
static constexpr Vector2 minusX() noexcept MR_REQUIRES_IF_SUPPORTED(!std
Definition MRVector2.h:50
friend constexpr auto operator-(const Vector2< T > &a) -> Vector2< decltype(-std::declval< T >())>
Definition MRVector2.h:95
T lengthSq() const
Definition MRVector2.h:61
friend constexpr const Vector2< T > & operator+(const Vector2< T > &a)
Definition MRVector2.h:94
T angle(const Vector2< T > &a, const Vector2< T > &b)
angle in radians between two vectors
Definition MRVector2.h:175
bool isFinite() const MR_REQUIRES_IF_SUPPORTED(std
Definition MRVector2.h:84
Definition MRMesh/MRVector3.h:29