MeshLib C++ Docs
Loading...
Searching...
No Matches
MRUnits.h
Go to the documentation of this file.
1#pragma once
2
3#include "MRViewer/exports.h"
5#include "MRMesh/MRUnitInfo.h"
6
7#include <string>
8#include <variant>
9
10// Read the manual at: docs/measurement_units.md
11
12namespace MR
13{
14
15namespace detail::Units
16{
17 struct Empty {};
18}
19
20template <UnitEnum E>
22
23// Returns the default parameters for converting a specific unit type to a string.
24// You can modify those with `setDefaultUnitParams()`.
25template <UnitEnum E>
27
28#define MR_X(E) extern template MRVIEWER_API const UnitToStringParams<E>& getDefaultUnitParams();
30#undef MR_X
31
32// Modifies the default parameters for converting a specific unit type to a string.
33template <UnitEnum E>
35
36#define MR_X(E) extern template MRVIEWER_API void setDefaultUnitParams( const UnitToStringParams<E>& newParams );
38#undef MR_X
39
40enum class NumberStyle
41{
42 normal, // Like %f.
43 distributePrecision, // Like %f, but the precision digits are spread across both decimal and integral parts.
44 exponential, // Like %e.
45 maybeExponential, // Like %g.
46};
47
48// This controls how the degrees are printed.
49enum class DegreesMode
50{
51 degrees, // Fractional degrees.
52 degreesMinutes, // Integral degrees, fractional arcminutes.
53 degreesMinutesSeconds, // Integral degrees and minutes, fractional arcseconds.
54 _count [[maybe_unused]],
55};
56[[nodiscard]] MRVIEWER_API std::string_view toString( DegreesMode mode );
57
58enum class ZeroMode
59{
60 asIs, // Print as is.
61 alwaysPositive, // Treat negative zero as positive zero.
62 alwaysNegative, // Treat positive zero as negative zero.
63};
64
65// Controls how a value with a unit is converted to a string.
66template <UnitEnum E>
68{
69 // The resulting string is wrapped in this.
70 // Do NOT use this for custom unit suffixes! Add them as actual units instead.
71 std::string_view decorationFormatString = "{}";
72
73 // --- Units:
74
75 // The measurement unit of the input value. If null, no conversion is performed.
77 // The measurement unit of the resulting string. If null, no conversion is performed, and the unit name is taken from `sourceUnit` if any.
78 std::optional<E> targetUnit = getDefaultUnitParams<E>().targetUnit;
79
80 // Whether to show the unit suffix.
82
83 // --- Precision:
84
85 // The output style. (Scientific notation or not, fixed-precision or not.)
87
88 // How many digits of precision.
90
91 // --- Other:
92
93 // Show the `+` sign on positive numbers.
95
96 // How to deal with zeroes.
98
99 // Use a pretty Unicode minus sign instead of the ASCII `-`.
100 bool unicodeMinusSign = getDefaultUnitParams<E>().unicodeMinusSign;
101
102 // If non-zero, this character is inserted between every three digits to the left of the decimal point.
103 char thousandsSeparator = getDefaultUnitParams<E>().thousandsSeparator;
104 // If non-zero, this character is inserted between every three digits to the right of the decimal point.
105 char thousandsSeparatorFrac = getDefaultUnitParams<E>().thousandsSeparatorFrac;
106
107 // If false, remove zero before the fractional point (`.5` instead of `0.5`).
109
110 // Remove trailing zeroes after the fractional point. If the point becomes the last symbol, remove the point too.
111 bool stripTrailingZeroes = getDefaultUnitParams<E>().stripTrailingZeroes;
112
113 // When printing degrees, this lets you display arcminutes and possibly arcseconds. Ignored for everything else.
114 std::conditional_t<std::is_same_v<E, AngleUnit>, DegreesMode, detail::Units::Empty> degreesMode = getDefaultUnitParams<E>().degreesMode;
115
116 // If you add new fields there, update the initializer for `defaultUnitToStringParams` in `MRUnits.cpp`.
117
118 friend bool operator==( const UnitToStringParams&, const UnitToStringParams& ) = default;
119};
120
121// The `std::variant` of `UnitToStringParams<E>` for all known `E`s (unit kinds).
122using VarUnitToStringParams = std::variant<
123 #define MR_X(E) , UnitToStringParams<E>
125 #undef MR_X
126>;
127
128// Converts value to a string, possibly converting it to a different unit.
129// By default, length is kept as is, while angles are converted from radians to the current UI unit.
130template <UnitEnum E, detail::Units::Scalar T>
131[[nodiscard]] MRVIEWER_API std::string valueToString( T value, const UnitToStringParams<E>& params = getDefaultUnitParams<E>() );
132
133#define MR_Y(T, E) extern template MRVIEWER_API std::string valueToString<E, T>( T value, const UnitToStringParams<E>& params );
134#define MR_X(E) DETAIL_MR_UNIT_VALUE_TYPES(MR_Y, E)
136#undef MR_X
137#undef MR_Y
138
139// This overload lets you select the unit kind at runtime.
140template <detail::Units::Scalar T>
141[[nodiscard]] MRVIEWER_API std::string valueToString( T value, const VarUnitToStringParams& params );
142
143#define MR_X(T, unused) extern template MRVIEWER_API std::string valueToString( T value, const VarUnitToStringParams& params );
145#undef MR_X
146
147// Guesses the number of digits of precision for fixed-point formatting of `value`.
148// Mostly for internal use.
149template <detail::Units::Scalar T>
150[[nodiscard]] MRVIEWER_API int guessPrecision( T value );
151
152// Guesses the number of digits of precision for fixed-point formatting of the min-max range.
153// If `min >= max`, always returns zero. Ignores min and/or max if they are the smallest of the largest representable value respectively.
154// Mostly for internal use.
155template <detail::Units::Scalar T>
156[[nodiscard]] MRVIEWER_API int guessPrecision( T min, T max );
157
158// Same but for vectors.
159template <typename T>
161[[nodiscard]] int guessPrecision( T value )
162{
163 int ret = 0;
164 for ( int i = 0; i < VectorTraits<T>::size; i++ )
165 ret = std::max( ret, guessPrecision( VectorTraits<T>::getElem( i, value ) ) );
166 return ret;
167}
168template <typename T>
169requires (VectorTraits<T>::size > 1 && detail::Units::Scalar<typename VectorTraits<T>::BaseType>)
170[[nodiscard]] int guessPrecision( T min, T max )
171{
172 int ret = 0;
173 for ( int i = 0; i < VectorTraits<T>::size; i++ )
174 ret = std::max( ret, guessPrecision( VectorTraits<T>::getElem( i, min ), VectorTraits<T>::getElem( i, max ) ) );
175 return ret;
176}
177
178#define MR_X(T, unused) \
179 extern template MRVIEWER_API int guessPrecision( T value ); \
180 extern template MRVIEWER_API int guessPrecision( T min, T max );
182#undef MR_X
183
184// Generates a printf-style format string for `value`, for use with ImGui widgets.
185// It has form "123.45 mm##%.6f" (the baked number, then `##` and some format string).
186// The `##...` part isn't printed, but we need it when ctrl+clicking the number, to show the correct number of digits.
187template <UnitEnum E, detail::Units::Scalar T>
188[[nodiscard]] MRVIEWER_API std::string valueToImGuiFormatString( T value, const UnitToStringParams<E>& params = getDefaultUnitParams<E>() );
189
190#define MR_Y(T, E) extern template MRVIEWER_API std::string valueToImGuiFormatString( T value, const UnitToStringParams<E>& params );
191#define MR_X(E) DETAIL_MR_UNIT_VALUE_TYPES(MR_Y, E)
193#undef MR_X
194#undef MR_Y
195
196// This overload lets you select the unit kind at runtime.
197template <detail::Units::Scalar T>
198[[nodiscard]] MRVIEWER_API std::string valueToImGuiFormatString( T value, const VarUnitToStringParams& params );
199
200#define MR_X(T, unused) extern template MRVIEWER_API std::string valueToImGuiFormatString( T value, const VarUnitToStringParams& params );
202#undef MR_X
203
204}
#define MR_TRIM_LEADING_COMMA(...)
Definition MRMacros.h:58
#define MR_X(E)
Definition MRUnitInfo.h:157
#define DETAIL_MR_UNIT_VALUE_TYPES(X,...)
Definition MRUnitInfo.h:118
#define DETAIL_MR_UNIT_ENUMS(X)
Definition MRUnitInfo.h:110
Definition MRUnitInfo.h:177
Definition MRCameraOrientationPlugin.h:8
NumberStyle
Definition MRUnits.h:41
MRVIEWER_API int guessPrecision(T value)
Definition MRUnits.h:161
MRVIEWER_API std::string valueToString(T value, const UnitToStringParams< E > &params=getDefaultUnitParams< E >())
const UnitToStringParams< E > & getDefaultUnitParams()
void setDefaultUnitParams(const UnitToStringParams< E > &newParams)
MRVIEWER_API std::string valueToImGuiFormatString(T value, const UnitToStringParams< E > &params=getDefaultUnitParams< E >())
ZeroMode
Definition MRUnits.h:59
DegreesMode
Definition MRUnits.h:50
MRMESH_API std::string_view toString(DimensionsVisualizePropertyType value)
std::variant< > VarUnitToStringParams
Definition MRUnits.h:122
Definition MRUnits.h:68
bool leadingZero
Definition MRUnits.h:108
int precision
Definition MRUnits.h:89
std::conditional_t< std::is_same_v< E, AngleUnit >, DegreesMode, detail::Units::Empty > degreesMode
Definition MRUnits.h:114
NumberStyle style
Definition MRUnits.h:86
std::optional< E > sourceUnit
Definition MRUnits.h:76
ZeroMode zeroMode
Definition MRUnits.h:97
std::string_view decorationFormatString
Definition MRUnits.h:71
char thousandsSeparator
Definition MRUnits.h:103
bool unitSuffix
Definition MRUnits.h:81
char thousandsSeparatorFrac
Definition MRUnits.h:105
std::optional< E > targetUnit
Definition MRUnits.h:78
friend bool operator==(const UnitToStringParams &, const UnitToStringParams &)=default
bool stripTrailingZeroes
Definition MRUnits.h:111
bool plusSign
Definition MRUnits.h:94
bool unicodeMinusSign
Definition MRUnits.h:100
Definition MRMesh/MRVectorTraits.h:15
static constexpr int size
Definition MRMesh/MRVectorTraits.h:19
static constexpr auto && getElem(int i, U &&value)
Definition MRMesh/MRVectorTraits.h:29
Definition MRUnits.h:17