MeshLib C++ Docs
Loading...
Searching...
No Matches
MRUnitInfo.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRVectorTraits.h"
4#include "MRMacros.h"
5
6#include <cassert>
7#include <optional>
8
9namespace MR
10{
11
12// A stub measurement unit representing no unit.
13enum class NoUnit
14{
15 _count [[maybe_unused]]
16};
17
18// Measurement units of length.
19enum class LengthUnit
20{
21 microns,
24 meters,
25 inches,
26 feet,
27 _count [[maybe_unused]],
28};
29
30// Measurement units of angle.
31enum class AngleUnit
32{
33 radians,
34 degrees,
35 _count [[maybe_unused]],
36};
37
38// Measurement units of screen sizes.
39enum class PixelSizeUnit
40{
41 pixels,
42 _count [[maybe_unused]],
43};
44
45// Measurement units for factors / ratios.
46enum class RatioUnit
47{
48 factor, // 0..1 x
49 percents, // 0..100 %
50 _count [[maybe_unused]],
51};
52
53// Measurement units for time.
54enum class TimeUnit
55{
56 seconds,
58 _count [[maybe_unused]],
59};
60
61// Measurement units for movement speed.
72
73// Measurement units for surface area.
74enum class AreaUnit
75{
79 meters2,
80 inches2,
81 feet2,
82 _count [[maybe_unused]],
83};
84
85// Measurement units for body volume.
86enum class VolumeUnit
87{
91 meters3,
92 inches3,
93 feet3,
94 _count [[maybe_unused]],
95};
96
97// Measurement units for 1/length.
98enum class InvLengthUnit
99{
105 inv_feet,
106 _count [[maybe_unused]],
107};
108
109// A list of all unit enums, for internal use.
110#define DETAIL_MR_UNIT_ENUMS(X) X(NoUnit) X(LengthUnit) X(AngleUnit) X(PixelSizeUnit) X(RatioUnit) X(TimeUnit) X(MovementSpeedUnit) X(AreaUnit) X(VolumeUnit) X(InvLengthUnit)
111
112// All supported value types for `valueToString()`.
113// Not using `__VA_OPT__(,)` here to support legacy MSVC preprocessor.
114#define DETAIL_MR_UNIT_VALUE_TYPES(X, ...) \
115 X(float ,__VA_ARGS__) X(double ,__VA_ARGS__) X(long double ,__VA_ARGS__) \
116 X(signed char ,__VA_ARGS__) X(unsigned char ,__VA_ARGS__) \
117 X(short ,__VA_ARGS__) X(unsigned short ,__VA_ARGS__) \
118 X(int ,__VA_ARGS__) X(unsigned int ,__VA_ARGS__) \
119 X(long ,__VA_ARGS__) X(unsigned long ,__VA_ARGS__) \
120 X(long long ,__VA_ARGS__) X(unsigned long long ,__VA_ARGS__)
121
122// Whether `E` is one of the unit enums: NoUnit, LengthUnit, AngleUnit, ...
123template <typename T>
124concept UnitEnum =
125 #define MR_X(E) || std::same_as<T, E>
127 #undef MR_X
128
129// ---
130
131// Information about a single measurement unit.
133{
134 // This is used to convert between units.
135 // To convert from A to B, multiply by A's factor and divide by B's.
137
138 std::string_view prettyName;
139
140 // The short unit name that's placed after values.
141 // This may or may not start with a space.
142 std::string_view unitSuffix;
143};
144
145// Returns information about a single measurement unit.
146template <UnitEnum E>
147[[nodiscard]] const UnitInfo& getUnitInfo( E unit ) = delete;
148
149// ignore for bindings to prevent GCC14 error: undefined symbol: _ZN2MR11getUnitInfoITkNS_8UnitEnumENS_8TimeUnitEEERKNS_8UnitInfoET_
150#define MR_X(E) template <> [[nodiscard]] MRMESH_API MR_BIND_IGNORE const UnitInfo& getUnitInfo( E unit );
152#undef MR_X
153
154// Returns true if converting a value between units `a` and `b` doesn't change its value.
155template <UnitEnum E>
156[[nodiscard]] bool unitsAreEquivalent( E a, E b )
157{
158 return a == b || getUnitInfo( a ).conversionFactor == getUnitInfo( b ).conversionFactor;
159}
160// This version also returns true if `a` or `b` is null.
161template <UnitEnum E>
162[[nodiscard]] bool unitsAreEquivalent( const std::optional<E> &a, const std::optional<E> &b )
163{
164 return !a || !b || unitsAreEquivalent( *a, *b );
165}
166
167namespace detail::Units
168{
169 template <typename T>
170 concept Scalar = std::is_arithmetic_v<T> && !std::is_same_v<T, bool>;
171
172 template <typename T>
173 using MakeFloatingPoint = std::conditional_t<std::is_integral_v<typename VectorTraits<T>::BaseType>, typename VectorTraits<T>::template ChangeBaseType<float>, T>;
174}
175
176// Converts `value` from unit `from` to unit `to`. `value` is a scalar of a Vector2/3/4 or ImVec2/4 of them.
177// The return type matches `T` if it's not integral. If it's integral, its element type type is changed to `float`.
178// Returns min/max floating-point values unchanged.
179template <UnitEnum E, typename T>
180[[nodiscard]] detail::Units::MakeFloatingPoint<T> convertUnits( E from, E to, const T& value )
181{
182 using ReturnType = detail::Units::MakeFloatingPoint<T>;
183
184 bool needConversion = !unitsAreEquivalent( from, to );
185
186 if constexpr ( std::is_same_v<T, ReturnType> )
187 {
188 if ( !needConversion )
189 return value;
190 }
191
192 ReturnType ret{};
193
194 for ( int i = 0; i < VectorTraits<T>::size; i++ )
195 {
197
198 // Don't touch min/max floating-point values.
199 bool needElemConversion = needConversion;
200 if constexpr ( std::is_floating_point_v<typename VectorTraits<T>::BaseType> )
201 {
202 if ( needElemConversion &&
203 (
204 target <= std::numeric_limits<typename VectorTraits<T>::BaseType>::lowest() ||
205 target >= std::numeric_limits<typename VectorTraits<T>::BaseType>::max()
206 )
207 )
208 needElemConversion = false;
209 }
210
211 if ( needElemConversion )
212 target = target * getUnitInfo( from ).conversionFactor / getUnitInfo( to ).conversionFactor;
213 }
214
215 return ret;
216}
217
218// This version is a no-op if `from` or `to` is null.
219template <UnitEnum E, typename T>
220[[nodiscard]] detail::Units::MakeFloatingPoint<T> convertUnits( const std::optional<E> &from, const std::optional<E> &to, const T& value )
221{
222 if ( from && to )
223 return convertUnits( *from, *to, value );
224 else
226}
227
228} //namespace MR
#define MR_X(E)
Definition MRUnitInfo.h:150
#define DETAIL_MR_UNIT_ENUMS(X)
Definition MRUnitInfo.h:110
Definition MRUnitInfo.h:124
Definition MRUnitInfo.h:170
std::conditional_t< std::is_integral_v< typename VectorTraits< T >::BaseType >, typename VectorTraits< T >::template ChangeBaseType< float >, T > MakeFloatingPoint
Definition MRUnitInfo.h:173
Definition MRCameraOrientationPlugin.h:8
PixelSizeUnit
Definition MRUnitInfo.h:40
const UnitInfo & getUnitInfo(E unit)=delete
NoUnit
Definition MRUnitInfo.h:14
bool unitsAreEquivalent(E a, E b)
Definition MRUnitInfo.h:156
LengthUnit
Definition MRUnitInfo.h:20
RatioUnit
Definition MRUnitInfo.h:47
MovementSpeedUnit
Definition MRUnitInfo.h:63
detail::Units::MakeFloatingPoint< T > convertUnits(E from, E to, const T &value)
Definition MRUnitInfo.h:180
VolumeUnit
Definition MRUnitInfo.h:87
AreaUnit
Definition MRUnitInfo.h:75
TimeUnit
Definition MRUnitInfo.h:55
InvLengthUnit
Definition MRUnitInfo.h:99
AngleUnit
Definition MRUnitInfo.h:32
Definition MRUnitInfo.h:133
std::string_view unitSuffix
Definition MRUnitInfo.h:142
std::string_view prettyName
Definition MRUnitInfo.h:138
float conversionFactor
Definition MRUnitInfo.h:136
Definition MRMesh/MRVectorTraits.h:15
static constexpr auto && getElem(int i, U &&value)
Definition MRMesh/MRVectorTraits.h:29
T BaseType
Definition MRMesh/MRVectorTraits.h:18