Loading...
Searching...
No Matches
knot.h
1//
2// Copyright 2024 Pixar
3//
4// Licensed under the terms set forth in the LICENSE.txt file available at
5// https://openusd.org/license.
6//
7
8#ifndef PXR_BASE_TS_KNOT_H
9#define PXR_BASE_TS_KNOT_H
10
11#include "pxr/pxr.h"
12#include "pxr/base/ts/api.h"
13#include "pxr/base/ts/knotData.h"
14#include "pxr/base/ts/types.h"
15#include "pxr/base/ts/typeHelpers.h"
17#include "pxr/base/vt/value.h"
18#include "pxr/base/gf/half.h"
20#include "pxr/base/tf/preprocessorUtilsLite.h"
21#include "pxr/base/tf/type.h"
22
23#include <iosfwd>
24#include <memory>
25#include <optional>
26#include <string>
27#include <type_traits>
28
29PXR_NAMESPACE_OPEN_SCOPE
30
31
40class TsKnot
41{
42public:
53
55 TS_API
57
59 TS_API
61 TfType valueType);
62
68 TS_API
70 TfType valueType,
71 TsCurveType curveType);
72
73 TS_API
74 TsKnot(const TsKnot &other);
75
76 TS_API
77 TsKnot(TsKnot &&other);
78
79 TS_API
80 ~TsKnot();
81
82 TS_API
83 TsKnot& operator=(const TsKnot &other);
84
85 TS_API
86 TsKnot& operator=(TsKnot &&other);
87
88 TS_API
89 bool operator==(const TsKnot &other) const;
90
91 TS_API
92 bool operator!=(const TsKnot &other) const;
93
97
98 TS_API
99 bool SetTime(
100 TsTime time);
101
102 TS_API
103 TsTime GetTime() const;
104
108
110 TS_API
111 bool SetNextInterpolation(TsInterpMode mode);
112
113 TS_API
114 TsInterpMode GetNextInterpolation() const;
115
119
120 TS_API
121 TfType GetValueType() const;
122
123 template <typename T>
124 bool IsHolding() const;
125
126 TS_API
127 bool SetValue(
128 VtValue value);
129
130 template <typename T>
131 bool SetValue(
132 const T value);
133
134 TS_API
135 bool GetValue(
136 VtValue *valueOut) const;
137
138 template <typename T>
139 bool GetValue(
140 T *valueOut) const;
141
145
146 TS_API
147 bool IsDualValued() const;
148
149 TS_API
150 bool SetPreValue(
151 VtValue value);
152
153 template <typename T>
154 bool SetPreValue(
155 const T value);
156
157 TS_API
158 bool GetPreValue(
159 VtValue *valueOut) const;
160
161 template <typename T>
162 bool GetPreValue(
163 T *valueOut) const;
164
165 TS_API
166 bool ClearPreValue();
167
177
178 TS_API
179 bool SetCurveType(TsCurveType curveType);
180
181 TS_API
182 TsCurveType GetCurveType() const;
183
196
197 TS_API
198 bool SetPreTanWidth(TsTime width);
199
200 TS_API
201 TsTime GetPreTanWidth() const;
202
203 TS_API
204 bool SetPreTanSlope(VtValue slope);
205
206 template <typename T>
207 bool SetPreTanSlope(T slope);
208
209 TS_API
210 bool GetPreTanSlope(VtValue *slopeOut) const;
211
212 template <typename T>
213 bool GetPreTanSlope(T *slopeOut) const;
214
223 TS_API
224 bool SetPreTanAlgorithm(TsTangentAlgorithm algorithm);
225
227 TS_API
228 TsTangentAlgorithm GetPreTanAlgorithm() const;
229
233
234 TS_API
235 bool SetPostTanWidth(TsTime width);
236
237 TS_API
238 TsTime GetPostTanWidth() const;
239
240 TS_API
241 bool SetPostTanSlope(VtValue slope);
242
243 template <typename T>
244 bool SetPostTanSlope(T slope);
245
246 TS_API
247 bool GetPostTanSlope(VtValue *slopeOut) const;
248
249 template <typename T>
250 bool GetPostTanSlope(T *slopeOut) const;
251
260 TS_API
261 bool SetPostTanAlgorithm(TsTangentAlgorithm algorithm);
262
264 TS_API
265 TsTangentAlgorithm GetPostTanAlgorithm() const;
266
270
293 TS_API
294 bool UpdateTangents(const std::optional<TsKnot> prevKnot,
295 const std::optional<TsKnot> nextKnot,
296 TsCurveType curveType = TsCurveTypeBezier);
297
312
313 TS_API
314 bool SetCustomData(
315 VtDictionary customData);
316
317 TS_API
318 VtDictionary GetCustomData() const;
319
320 TS_API
321 bool SetCustomDataByKey(
322 const std::string &keyPath,
323 VtValue value);
324
325 TS_API
326 VtValue GetCustomDataByKey(
327 const std::string &keyPath) const;
328
332
334 TS_API
335 bool IsC0Continuous() const;
336
338 TS_API
339 bool IsG1Continuous() const;
340
342 TS_API
343 bool IsC1Continuous() const;
344
346
347protected:
348 friend class TsSpline;
349 friend class TsKnotMap;
350 friend class TsRegressionPreventer;
351
352 // Constructor for copying knot data from SplineData. The data has been
353 // copied for us, and we take ownership of it.
354 TsKnot(
355 Ts_KnotData *data,
356 TfType valueType,
357 VtDictionary &&customData);
358
359 // Accessors for low-level knot data.
360 Ts_KnotData* _GetData() { return _data; }
361 const Ts_KnotData* _GetData() const { return _data; }
362
363private:
364 template <typename T>
365 bool _CheckInParam(T value) const;
366
367 template <typename T>
368 bool _CheckOutParam(T *valueOut) const;
369
370 bool _CheckSetWidth(TsTime width) const;
371 bool _CheckInParamVt(VtValue value) const;
372 bool _CheckOutParamVt(VtValue* value) const;
373
374 template <typename T>
375 Ts_TypedKnotData<T>* _TypedData() const;
376
377 template <typename T>
378 const Ts_TypedKnotData<T>* _ConstTypedData() const;
379
380private:
381 // Main knot fields. Never null. The data is on the heap, and we own it
382 // exclusively, but we don't use unique_ptr because we need to deallocate in
383 // a type-aware way; see the destructor.
384 Ts_KnotData* _data;
385
386 // Proxy object, for typed data access. Never null.
387 //
388 // XXX: it would be possible to eliminate this member by encoding value type
389 // in a bitfield in Ts_KnotData; there are only three possible value types,
390 // and there are plenty of unused bits in the Ts_KnotData padding. Then we
391 // could create proxy objects on the fly, or make them singletons.
392 //
393 std::unique_ptr<Ts_KnotDataProxy> _proxy;
394
395 // Custom data. Optional; may be empty.
396 VtDictionary _customData;
397};
398
400TS_API
401std::ostream& operator<<(std::ostream& out, const TsKnot &knot);
402
403
422template <typename T,
423 typename = std::enable_if_t<Ts_IsSupportedValueType<T>::value>>
424class TsTypedKnot : public TsKnot
425{
426public:
427 TsTypedKnot() : TsKnot(Ts_GetType<T>()) {}
428};
429
433
437
441
442// Make sure we have coverage for all allowed types.
443#define _MAKE_CLAUSE(unused, tuple) \
444 static_assert(std::is_same_v<TF_PP_CAT(TF_PP_CAT(Ts, \
445 TS_SPLINE_VALUE_TYPE_NAME(tuple)), Knot), \
446 TsTypedKnot<TS_SPLINE_VALUE_CPP_TYPE(tuple)>>, \
447 "Incorrect type alias for TsKnot type: " #tuple);
448TF_PP_SEQ_FOR_EACH(_MAKE_CLAUSE, ~, TS_SPLINE_SUPPORTED_VALUE_TYPES)
449#undef _MAKE_CLAUSE
450
451
452
454// TEMPLATE HELPERS
455
456template <typename T>
457bool TsKnot::_CheckInParam(const T value) const
458{
459 if constexpr (!Ts_IsSupportedValueType<T>::value)
460 {
461 static_assert(Ts_IsSupportedValueType<T>::value,
462 "Cannot pass non-floating-point type as T-typed knot parameter");
463 return false;
464 }
465 else
466 {
467 if (GetValueType() != Ts_GetType<T>())
468 {
470 "Cannot set '%s' value into knot of type '%s'",
471 Ts_GetType<T>().GetTypeName().c_str(),
472 GetValueType().GetTypeName().c_str());
473 return false;
474 }
475
476 if (!Ts_IsFinite(value))
477 {
478 TF_CODING_ERROR("Set values must be finite.");
479 return false;
480 }
481
482 return true;
483 }
484}
485
486template <typename T>
487bool TsKnot::_CheckOutParam(T *valueOut) const
488{
489 if constexpr (!Ts_IsSupportedValueType<T>::value)
490 {
491 static_assert(Ts_IsSupportedValueType<T>::value,
492 "Cannot pass non-floating-point type as T-typed knot parameter");
493 return false;
494 }
495 else
496 {
497 if (!valueOut)
498 {
499 TF_CODING_ERROR("Null pointer");
500 return false;
501 }
502
503 if (GetValueType() != Ts_GetType<T>())
504 {
506 "Cannot read from knot of type '%s' into '%s'",
507 GetValueType().GetTypeName().c_str(),
508 Ts_GetType<T>().GetTypeName().c_str());
509 return false;
510 }
511
512 return true;
513 }
514}
515
516template <typename T>
517Ts_TypedKnotData<T>*
518TsKnot::_TypedData() const
519{
520 return static_cast<Ts_TypedKnotData<T>*>(_data);
521}
522
523template <typename T>
524const Ts_TypedKnotData<T>*
525TsKnot::_ConstTypedData() const
526{
527 return static_cast<const Ts_TypedKnotData<T>*>(_data);
528}
529
531// TEMPLATE IMPLEMENTATIONS
532
533template <typename T>
534bool TsKnot::IsHolding() const
535{
536 return GetValueType() == Ts_GetType<T>();
537}
538
539template <typename T>
540bool TsKnot::SetValue(const T value)
541{
542 if (!_CheckInParam(value))
543 {
544 return false;
545 }
546
547 _TypedData<T>()->value = value;
548 return true;
549}
550
551template <typename T>
552bool TsKnot::GetValue(T *valueOut) const
553{
554 if (!_CheckOutParam(valueOut))
555 {
556 return false;
557 }
558
559 *valueOut = _ConstTypedData<T>()->value;
560 return true;
561}
562
563template <typename T>
564bool TsKnot::SetPreValue(const T value)
565{
566 if (!_CheckInParam(value))
567 {
568 return false;
569 }
570
571 _data->dualValued = true;
572 _TypedData<T>()->preValue = value;
573 return true;
574}
575
576template <typename T>
577bool TsKnot::GetPreValue(T* const valueOut) const
578{
579 if (!_CheckOutParam(valueOut))
580 {
581 return false;
582 }
583
584 if (_data->dualValued)
585 {
586 *valueOut = _ConstTypedData<T>()->preValue;
587 }
588 else
589 {
590 *valueOut = _ConstTypedData<T>()->value;
591 }
592
593 return true;
594}
595
597// Pre-Tangent
598
599template <typename T>
600bool TsKnot::SetPreTanSlope(const T slope)
601{
602 if (!_CheckInParam(slope))
603 {
604 return false;
605 }
606
607 _TypedData<T>()->preTanSlope = slope;
608 return true;
609}
610
611template <typename T>
612bool TsKnot::GetPreTanSlope(T* const slopeOut) const
613{
614 if (!_CheckOutParam(slopeOut))
615 {
616 return false;
617 }
618
619 *slopeOut = _ConstTypedData<T>()->GetPreTanSlope();
620 return true;
621}
622
624// Post-Tangent
625
626template <typename T>
627bool TsKnot::SetPostTanSlope(const T slope)
628{
629 if (!_CheckInParam(slope))
630 {
631 return false;
632 }
633
634 _TypedData<T>()->postTanSlope = slope;
635 return true;
636}
637
638template <typename T>
639bool TsKnot::GetPostTanSlope(T* const slopeOut) const
640{
641 if (!_CheckOutParam(slopeOut))
642 {
643 return false;
644 }
645
646 *slopeOut = _ConstTypedData<T>()->GetPostTanSlope();
647 return true;
648}
649
650
651PXR_NAMESPACE_CLOSE_SCOPE
652
653#endif
Low-level utilities for informing users of various internal and external diagnostic conditions.
TfType represents a dynamic runtime type.
Definition: type.h:48
A knot-construction convenience.
A knot-construction convenience.
A knot-construction convenience.
A knot belonging to a TsSpline.
Definition: knot.h:41
TS_API TsKnot()
Default constructor creates a double-typed knot.
TS_API TsTangentAlgorithm GetPreTanAlgorithm() const
Get the pre-tangent algorithm.
TS_API TsKnot(TfType valueType)
Creates a knot with a specified value type.
TS_API bool IsG1Continuous() const
Not yet implemented.
TS_API TsTangentAlgorithm GetPostTanAlgorithm() const
Get the post-tangent algorithm.
TS_API bool SetPostTanAlgorithm(TsTangentAlgorithm algorithm)
Set the post-tangent algorithm.
TS_API bool UpdateTangents(const std::optional< TsKnot > prevKnot, const std::optional< TsKnot > nextKnot, TsCurveType curveType=TsCurveTypeBezier)
Update tangent values algorithmically.
TS_API bool IsC1Continuous() const
Not yet implemented.
TS_API bool SetPreTanAlgorithm(TsTangentAlgorithm algorithm)
Set the pre-tangent algorithm.
TS_API TsKnot(TfType valueType, TsCurveType curveType)
Creates a knot with a specified value type and curve type.
TS_API bool SetNextInterpolation(TsInterpMode mode)
Sets the interpolation mode of the spline segment following this knot.
TS_API bool IsC0Continuous() const
Not yet implemented.
The knots in a spline.
Definition: knotMap.h:37
An authoring helper class that enforces non-regression in splines.
A mathematical description of a curved function from time to value.
Definition: spline.h:59
A convenience for constructing knots with specified types.
Definition: knot.h:425
A map with string keys and VtValue values.
Definition: dictionary.h:43
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:152
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
Output a GfBBox3d using the format [(range) matrix zeroArea].
#define TF_CODING_ERROR(fmt, args)
Issue an internal programming error, but continue execution.
Definition: diagnostic.h:68
This header serves to simply bring in the half float datatype and provide a hash_value function.