11#include " axis.h"
22
33#include < algorithm>
4+ #include < cmath>
5+ #include < limits>
46#include < map>
57#include < optional>
68#include < string>
@@ -42,7 +44,13 @@ MeasureAxis::MeasureAxis(Math::Range<double> interval,
4244 unit (std::string{unit}),
4345 origMeasureName (std::string{measName}),
4446 step (step ? *step : Math::Renard::R5().ceil(range.size() / 5.0 ))
45- {}
47+ {
48+ if (Math::Floating::is_zero (range.size ()))
49+ this ->step ->value = 0 ;
50+ else if (std::signbit (this ->step ->value )
51+ != std::signbit (range.size ()))
52+ this ->step ->value *= -1 ;
53+ }
4654
4755bool MeasureAxis::operator ==(const MeasureAxis &other) const
4856{
@@ -68,8 +76,66 @@ MeasureAxis interpolate(const MeasureAxis &op0,
6876 interpolate (op0.origMeasureName , op1.origMeasureName , factor);
6977
7078 if (op0.enabled .get () && op1.enabled .get ()) {
71- res.range = Math::interpolate (op0.range , op1.range , factor);
72- res.step = interpolate (op0.step , op1.step , factor);
79+ constexpr auto MAX = std::numeric_limits<double >::max () / 2 ;
80+ using Math::Floating::is_zero;
81+
82+ const auto s0 = op0.range .size ();
83+ const auto s1 = op1.range .size ();
84+
85+ if (auto s0Zero = is_zero (s0); s0Zero || is_zero (s1)) {
86+ res.range = Math::Range<double >::Raw (
87+ Math::interpolate (op0.range .getMin (),
88+ op1.range .getMin (),
89+ factor),
90+ Math::interpolate (op0.range .getMax (),
91+ op1.range .getMax (),
92+ factor));
93+ res.step = s0Zero ? op1.step : op0.step ;
94+ }
95+ else {
96+ auto s0Inv = 1 / s0;
97+ auto s1Inv = 1 / s1;
98+
99+ const auto interp =
100+ Math::interpolate (s0Inv, s1Inv, factor);
101+
102+ const auto s = is_zero (interp) ? MAX : 1 / interp;
103+
104+ res.range = Math::Range<double >::Raw (
105+ Math::interpolate (op0.range .getMin () * s0Inv,
106+ op1.range .getMin () * s1Inv,
107+ factor)
108+ * s,
109+ Math::interpolate (op0.range .getMax () * s0Inv,
110+ op1.range .getMax () * s1Inv,
111+ factor)
112+ * s);
113+
114+ auto step = Math::interpolate (op0.step .get () * s0Inv,
115+ op1.step .get () * s1Inv,
116+ factor)
117+ * s;
118+
119+ if (auto op0sign = std::signbit (op0.step .get ());
120+ op0sign == std::signbit (op1.step .get ()))
121+ res.step = interpolate (op0.step ,
122+ op1.step ,
123+ Math::Range<double >::Raw (op0.step .get (),
124+ op1.step .get ())
125+ .rescale (step));
126+ else if (auto max = std::copysign (MAX, step);
127+ op0sign == std::signbit (step))
128+ res.step = interpolate (op0.step ,
129+ Anim::Interpolated{max},
130+ Math::Range<double >::Raw (op0.step .get (), max)
131+ .rescale (step));
132+ else
133+ res.step = interpolate (op1.step ,
134+ Anim::Interpolated{max},
135+ Math::Range<double >::Raw (op1.step .get (), max)
136+ .rescale (step));
137+ }
138+
73139 res.unit = interpolate (op0.unit , op1.unit , factor);
74140 }
75141 else if (op0.enabled .get ()) {
0 commit comments