All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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/typeHelpers.h"
16#include "pxr/base/vt/value.h"
17#include "pxr/base/gf/half.h"
18#include "pxr/base/tf/type.h"
20
21#include <string>
22#include <memory>
23#include <iosfwd>
24#include <type_traits>
25
26PXR_NAMESPACE_OPEN_SCOPE
27
28
37class TsKnot
38{
39public:
50
52 TS_API
54
56 TS_API
58 TfType valueType,
59 TsCurveType curveType = TsCurveTypeBezier);
60
61 TS_API
62 TsKnot(const TsKnot &other);
63
64 TS_API
65 TsKnot(TsKnot &&other);
66
67 TS_API
68 ~TsKnot();
69
70 TS_API
71 TsKnot& operator=(const TsKnot &other);
72
73 TS_API
74 TsKnot& operator=(TsKnot &&other);
75
76 TS_API
77 bool operator==(const TsKnot &other) const;
78
79 TS_API
80 bool operator!=(const TsKnot &other) const;
81
85
86 TS_API
87 bool SetTime(
88 TsTime time);
89
90 TS_API
91 TsTime GetTime() const;
92
96
98 TS_API
99 bool SetNextInterpolation(TsInterpMode mode);
100
101 TS_API
102 TsInterpMode GetNextInterpolation() const;
103
107
108 TS_API
109 TfType GetValueType() const;
110
111 template <typename T>
112 bool IsHolding() const;
113
114 TS_API
115 bool SetValue(
116 VtValue value);
117
118 template <typename T>
119 bool SetValue(
120 const T value);
121
122 TS_API
123 bool GetValue(
124 VtValue *valueOut) const;
125
126 template <typename T>
127 bool GetValue(
128 T *valueOut) const;
129
133
134 TS_API
135 bool IsDualValued() const;
136
137 TS_API
138 bool SetPreValue(
139 VtValue value);
140
141 template <typename T>
142 bool SetPreValue(
143 const T value);
144
145 TS_API
146 bool GetPreValue(
147 VtValue *valueOut) const;
148
149 template <typename T>
150 bool GetPreValue(
151 T *valueOut) const;
152
153 TS_API
154 bool ClearPreValue();
155
166
167 TS_API
168 bool SetCurveType(TsCurveType curveType);
169
170 TS_API
171 TsCurveType GetCurveType() const;
172
185
186 TS_API
187 bool SetPreTanWidth(TsTime width);
188
189 TS_API
190 TsTime GetPreTanWidth() const;
191
192 TS_API
193 bool SetPreTanSlope(VtValue slope);
194
195 template <typename T>
196 bool SetPreTanSlope(T slope);
197
198 TS_API
199 bool GetPreTanSlope(VtValue *slopeOut) const;
200
201 template <typename T>
202 bool GetPreTanSlope(T *slopeOut) const;
203
207
208 TS_API
209 bool SetPostTanWidth(TsTime width);
210
211 TS_API
212 TsTime GetPostTanWidth() const;
213
214 TS_API
215 bool SetPostTanSlope(VtValue slope);
216
217 template <typename T>
218 bool SetPostTanSlope(T slope);
219
220 TS_API
221 bool GetPostTanSlope(VtValue *slopeOut) const;
222
223 template <typename T>
224 bool GetPostTanSlope(T *slopeOut) const;
225
240
241 TS_API
242 bool SetCustomData(
243 VtDictionary customData);
244
245 TS_API
246 VtDictionary GetCustomData() const;
247
248 TS_API
249 bool SetCustomDataByKey(
250 const std::string &keyPath,
251 VtValue value);
252
253 TS_API
254 VtValue GetCustomDataByKey(
255 const std::string &keyPath) const;
256
260
262 TS_API
263 bool IsC0Continuous() const;
264
266 TS_API
267 bool IsG1Continuous() const;
268
270 TS_API
271 bool IsC1Continuous() const;
272
274
275protected:
276 friend class TsSpline;
277 friend class TsKnotMap;
278 friend class TsRegressionPreventer;
279
280 // Constructor for copying knot data from SplineData. The data has been
281 // copied for us, and we take ownership of it.
282 TsKnot(
283 Ts_KnotData *data,
284 TfType valueType,
285 VtDictionary &&customData);
286
287 // Accessors for low-level knot data.
288 Ts_KnotData* _GetData() { return _data; }
289 const Ts_KnotData* _GetData() const { return _data; }
290
291private:
292 template <typename T>
293 bool _CheckInParam(T value) const;
294
295 template <typename T>
296 bool _CheckOutParam(T *valueOut) const;
297
298 bool _CheckGetWidth() const;
299 bool _CheckSetWidth(TsTime width) const;
300 bool _CheckInParamVt(VtValue value) const;
301 bool _CheckOutParamVt(VtValue* value) const;
302
303 template <typename T>
304 Ts_TypedKnotData<T>* _TypedData() const;
305
306 template <typename T>
307 const Ts_TypedKnotData<T>* _ConstTypedData() const;
308
309private:
310 // Main knot fields. Never null. The data is on the heap, and we own it
311 // exclusively, but we don't use unique_ptr because we need to deallocate in
312 // a type-aware way; see the destructor.
313 Ts_KnotData* _data;
314
315 // Proxy object, for typed data access. Never null.
316 //
317 // XXX: it would be possible to eliminate this member by encoding value type
318 // in a bitfield in Ts_KnotData; there are only three possible value types,
319 // and there are plenty of unused bits in the Ts_KnotData padding. Then we
320 // could create proxy objects on the fly, or make them singletons.
321 //
322 std::unique_ptr<Ts_KnotDataProxy> _proxy;
323
324 // Custom data. Optional; may be empty.
325 VtDictionary _customData;
326};
327
329TS_API
330std::ostream& operator<<(std::ostream& out, const TsKnot &knot);
331
332
351template <typename T,
352 typename = std::enable_if_t<Ts_IsSupportedValueType<T>::value>>
353class TsTypedKnot : public TsKnot
354{
355public:
356 TsTypedKnot() : TsKnot(Ts_GetType<T>()) {}
357};
358
362
366
370
371
373// TEMPLATE HELPERS
374
375template <typename T>
376bool TsKnot::_CheckInParam(const T value) const
377{
378 if constexpr (!Ts_IsSupportedValueType<T>::value)
379 {
380 static_assert(Ts_IsSupportedValueType<T>::value,
381 "Cannot pass non-floating-point type as T-typed knot parameter");
382 return false;
383 }
384 else
385 {
386 if (GetValueType() != Ts_GetType<T>())
387 {
389 "Cannot set '%s' value into knot of type '%s'",
390 Ts_GetType<T>().GetTypeName().c_str(),
391 GetValueType().GetTypeName().c_str());
392 return false;
393 }
394
395 if (!Ts_IsFinite(value))
396 {
397 TF_CODING_ERROR("Set values must be finite.");
398 return false;
399 }
400
401 return true;
402 }
403}
404
405template <typename T>
406bool TsKnot::_CheckOutParam(T *valueOut) const
407{
408 if constexpr (!Ts_IsSupportedValueType<T>::value)
409 {
410 static_assert(Ts_IsSupportedValueType<T>::value,
411 "Cannot pass non-floating-point type as T-typed knot parameter");
412 return false;
413 }
414 else
415 {
416 if (!valueOut)
417 {
418 TF_CODING_ERROR("Null pointer");
419 return false;
420 }
421
422 if (GetValueType() != Ts_GetType<T>())
423 {
425 "Cannot read from knot of type '%s' into '%s'",
426 GetValueType().GetTypeName().c_str(),
427 Ts_GetType<T>().GetTypeName().c_str());
428 return false;
429 }
430
431 return true;
432 }
433}
434
435template <typename T>
436Ts_TypedKnotData<T>*
437TsKnot::_TypedData() const
438{
439 return static_cast<Ts_TypedKnotData<T>*>(_data);
440}
441
442template <typename T>
443const Ts_TypedKnotData<T>*
444TsKnot::_ConstTypedData() const
445{
446 return static_cast<const Ts_TypedKnotData<T>*>(_data);
447}
448
450// TEMPLATE IMPLEMENTATIONS
451
452template <typename T>
453bool TsKnot::IsHolding() const
454{
455 return GetValueType() == Ts_GetType<T>();
456}
457
458template <typename T>
459bool TsKnot::SetValue(const T value)
460{
461 if (!_CheckInParam(value))
462 {
463 return false;
464 }
465
466 _TypedData<T>()->value = value;
467 return true;
468}
469
470template <typename T>
471bool TsKnot::GetValue(T *valueOut) const
472{
473 if (!_CheckOutParam(valueOut))
474 {
475 return false;
476 }
477
478 *valueOut = _ConstTypedData<T>()->value;
479 return true;
480}
481
482template <typename T>
483bool TsKnot::SetPreValue(const T value)
484{
485 if (!_CheckInParam(value))
486 {
487 return false;
488 }
489
490 _data->dualValued = true;
491 _TypedData<T>()->preValue = value;
492 return true;
493}
494
495template <typename T>
496bool TsKnot::GetPreValue(T* const valueOut) const
497{
498 if (!_CheckOutParam(valueOut))
499 {
500 return false;
501 }
502
503 if (_data->dualValued)
504 {
505 *valueOut = _ConstTypedData<T>()->preValue;
506 }
507 else
508 {
509 *valueOut = _ConstTypedData<T>()->value;
510 }
511
512 return true;
513}
514
516// Pre-Tangent
517
518template <typename T>
519bool TsKnot::SetPreTanSlope(const T slope)
520{
521 if (!_CheckInParam(slope))
522 {
523 return false;
524 }
525
526 _TypedData<T>()->preTanSlope = slope;
527 return true;
528}
529
530template <typename T>
531bool TsKnot::GetPreTanSlope(T* const slopeOut) const
532{
533 if (!_CheckOutParam(slopeOut))
534 {
535 return false;
536 }
537
538 *slopeOut = _ConstTypedData<T>()->GetPreTanSlope();
539 return true;
540}
541
543// Post-Tangent
544
545template <typename T>
546bool TsKnot::SetPostTanSlope(const T slope)
547{
548 if (!_CheckInParam(slope))
549 {
550 return false;
551 }
552
553 _TypedData<T>()->postTanSlope = slope;
554 return true;
555}
556
557template <typename T>
558bool TsKnot::GetPostTanSlope(T* const slopeOut) const
559{
560 if (!_CheckOutParam(slopeOut))
561 {
562 return false;
563 }
564
565 *slopeOut = _ConstTypedData<T>()->GetPostTanSlope();
566 return true;
567}
568
569
570PXR_NAMESPACE_CLOSE_SCOPE
571
572#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:38
TS_API TsKnot()
Default constructor creates a double-typed knot.
TS_API bool IsG1Continuous() const
Not yet implemented.
TS_API TsKnot(TfType valueType, TsCurveType curveType=TsCurveTypeBezier)
Creates a knot with a specified value type.
TS_API bool IsC1Continuous() const
Not yet implemented.
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:354
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:147
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.