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