3 #include <ossia/detail/config.hpp>
5 #if defined(__cpp_exceptions)
6 #include <ossia/detail/flat_map.hpp>
7 #include <ossia/detail/optional.hpp>
12 #include <ossia/network/base/node.hpp>
13 #include <ossia/network/base/parameter.hpp>
15 #include <ossia/network/value/value.hpp>
31 #if defined(__clang__)
32 #define CLANG_BUGGY_STATIC_VARIABLE_TEMPLATE static
34 #define CLANG_BUGGY_STATIC_VARIABLE_TEMPLATE
37 static const constexpr std::nullptr_t curve_segment_type_map =
nullptr;
40 curve_segment_type_map<int>
41 = ossia::curve_segment_type::INT;
44 curve_segment_type_map<int64_t>
45 = ossia::curve_segment_type::INT64;
48 curve_segment_type_map<float>
49 = ossia::curve_segment_type::FLOAT;
52 curve_segment_type_map<double>
53 = ossia::curve_segment_type::DOUBLE;
56 curve_segment_type_map<bool>
57 = ossia::curve_segment_type::BOOL;
60 curve_segment_type_map<ossia::value>
61 = ossia::curve_segment_type::ANY;
63 template <
typename K,
typename V>
64 using curve_map = ossia::flat_map<K, V>;
66 template <
typename X,
typename Y>
73 class curve final :
public curve_abstract
76 using abscissa_type = X;
77 using ordinate_type = Y;
78 using curve_type = curve<X, Y>;
79 using map_type = curve_map<X, std::pair<Y, ossia::curve_segment<Y>>>;
82 curve(
const curve& other)
86 m_y0_destination = other.m_y0_destination;
88 m_points = other.m_points;
90 m_y0_cacheUsed =
false;
93 curve(curve&& other) noexcept
97 m_y0_destination = std::move(other.m_y0_destination);
99 m_points = std::move(other.m_points);
101 m_y0_cacheUsed =
false;
104 curve& operator=(
const curve& other)
108 m_y0_destination = other.m_y0_destination;
110 m_points = other.m_points;
112 m_y0_cacheUsed =
false;
115 curve& operator=(curve&& other) noexcept
119 m_y0_destination = std::move(other.m_y0_destination);
121 m_points = std::move(other.m_points);
123 m_y0_cacheUsed =
false;
127 virtual ~curve() =
default;
129 void reset()
override;
136 bool add_point(ossia::curve_segment<Y>&& segment, X abscissa, Y value);
141 bool remove_point(X abscissa);
146 Y value_at(X abscissa)
const;
148 ossia::curve_type get_type()
const override;
165 void set_x0(X value);
170 void set_y0(Y value);
174 std::optional<destination> get_y0_destination()
const;
178 void set_y0_destination(
const ossia::destination& destination);
184 map_type get_points()
const;
186 static Y convert_to_template_type_value(
187 const ossia::value& value, ossia::destination_index::const_iterator idx);
189 void reserve(std::size_t count) { m_points.reserve(count); }
194 mutable std::optional<ossia::destination> m_y0_destination;
196 mutable map_type m_points;
198 mutable Y m_y0_cache;
200 mutable bool m_y0_cacheUsed =
false;
203 template <
typename X,
typename Y>
204 inline void curve<X, Y>::reset()
206 m_y0_cacheUsed =
false;
209 template <
typename X,
typename Y>
211 curve<X, Y>::add_point(ossia::curve_segment<Y>&& segment, X abscissa, Y value)
213 m_points.emplace(abscissa, std::make_pair(value, std::move(segment)));
218 template <
typename X,
typename Y>
219 inline bool curve<X, Y>::remove_point(X abscissa)
221 return m_points.erase(abscissa) > 0;
224 template <
typename X,
typename Y>
225 inline Y curve<X, Y>::value_at(X abscissa)
const
227 X lastAbscissa = get_x0();
228 Y lastValue = get_y0();
230 auto end = m_points.end();
231 for(
auto it = m_points.begin(); it != end; ++it)
233 if(abscissa > lastAbscissa && abscissa <= it->first)
235 lastValue = it->second.second(
236 ((
double)abscissa - (
double)lastAbscissa)
237 / ((
double)it->first - (
double)lastAbscissa),
238 lastValue, it->second.first);
241 else if(abscissa > it->first)
243 lastAbscissa = it->first;
244 lastValue = it->second.first;
253 template <
typename X,
typename Y>
254 inline curve_type curve<X, Y>::get_type()
const
256 return std::make_pair(curve_segment_type_map<X>, curve_segment_type_map<Y>);
259 template <
typename X,
typename Y>
260 inline X curve<X, Y>::get_x0()
const
265 template <
typename X,
typename Y>
266 inline Y curve<X, Y>::get_y0()
const
268 if(!m_y0_destination)
275 const destination& dest = *m_y0_destination;
276 m_y0_cacheUsed =
true;
277 m_y0_cache = convert_to_template_type_value(
278 dest.address().fetch_value(), dest.index.begin());
284 template <
typename X,
typename Y>
285 inline void curve<X, Y>::set_x0(X value)
290 template <
typename X,
typename Y>
291 inline void curve<X, Y>::set_y0(Y value)
296 template <
typename X,
typename Y>
297 inline std::optional<destination> curve<X, Y>::get_y0_destination()
const
299 return m_y0_destination;
302 template <
typename X,
typename Y>
303 inline void curve<X, Y>::set_y0_destination(
const destination& destination)
305 m_y0_destination = destination;
308 template <
typename X,
typename Y>
309 inline typename curve<X, Y>::map_type curve<X, Y>::get_points()
const
314 template <
typename X,
typename Y>
315 inline Y curve<X, Y>::convert_to_template_type_value(
316 const value& v, ossia::destination_index::const_iterator idx)
318 using namespace ossia;
322 destination_index::const_iterator index;
323 Y operator()(int32_t i)
const {
return i; }
324 Y operator()(
float f)
const {
return f; }
325 Y operator()(
bool b)
const {
return b; }
326 Y operator()(
char c)
const {
return c; }
327 Y operator()(vec2f vec)
const {
return vec[*index]; }
328 Y operator()(vec3f vec)
const {
return vec[*index]; }
329 Y operator()(vec4f vec)
const {
return vec[*index]; }
330 Y operator()(
const std::vector<ossia::value>& t)
const
332 auto& val = t[*index];
333 return convert_to_template_type_value(val, index + 1);
335 Y operator()(
const value_map_type& t)
const
338 "curve_impl::convertToTemplateTypeValue: "
339 "Cannot convert Map to a numeric type");
343 Y operator()(impulse)
const
346 "curve_impl::convertToTemplateTypeValue: "
347 "Cannot convert Impulse to a numeric type");
350 Y operator()(
const std::string& str)
const
353 "curve_impl::convertToTemplateTypeValue: "
354 "Cannot convert String to a numeric type");
360 "curve_impl::convertToTemplateTypeValue: "
384 : mValue{std::move(v)}
387 ~constant_curve()
override;
388 constant_curve() =
default;
389 constant_curve(
const constant_curve&) =
delete;
390 constant_curve(constant_curve&&) =
delete;
391 constant_curve& operator=(
const constant_curve&) =
delete;
392 constant_curve& operator=(constant_curve&&) =
delete;
396 [[nodiscard]] curve_type get_type()
const override
398 return std::make_pair(
399 ossia::curve_segment_type::DOUBLE, ossia::curve_segment_type::ANY);
402 void reset()
override { }
The curve_abstract class.
Definition: curve_abstract.hpp:42
The value class.
Definition: value.hpp:173
curve_segment_type
The curve_segment_type enum.
Definition: curve_abstract.hpp:18
The invalid_value_type_error class.
Definition: network/exceptions.hpp:87