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