All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
spline.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_SPLINE_H
9#define PXR_BASE_TS_SPLINE_H
10
11#include "pxr/pxr.h"
12#include "pxr/base/ts/api.h"
13#include "pxr/base/ts/splineData.h"
14#include "pxr/base/ts/knotMap.h"
15#include "pxr/base/ts/knot.h"
16#include "pxr/base/ts/types.h"
17#include "pxr/base/ts/typeHelpers.h"
18#include "pxr/base/ts/eval.h"
19#include "pxr/base/vt/value.h"
21#include "pxr/base/tf/type.h"
22
23#include <string>
24#include <memory>
25#include <iosfwd>
26
27PXR_NAMESPACE_OPEN_SCOPE
28
29class VtDictionary;
30
31
59{
60public:
68
71 TS_API
73
75 TS_API
76 TsSpline(TfType valueType);
77
78 TS_API
79 TsSpline(const TsSpline &other);
80
81 TS_API
82 TsSpline& operator=(const TsSpline &other);
83
84 TS_API
85 bool operator==(const TsSpline &other) const;
86
87 TS_API
88 bool operator!=(const TsSpline &other) const;
89
93
94 TS_API
95 static bool IsSupportedValueType(TfType valueType);
96
97 TS_API
98 TfType GetValueType() const;
99
100 template <typename T>
101 bool IsHolding() const;
102
103 TS_API
104 void SetTimeValued(bool timeValued);
105
106 TS_API
107 bool IsTimeValued() const;
108
112
113 TS_API
114 void SetCurveType(TsCurveType curveType);
115
116 TS_API
117 TsCurveType GetCurveType() const;
118
122
123 TS_API
124 void SetPreExtrapolation(
125 const TsExtrapolation &extrap);
126
127 TS_API
128 TsExtrapolation GetPreExtrapolation() const;
129
130 TS_API
131 void SetPostExtrapolation(
132 const TsExtrapolation &extrap);
133
134 TS_API
135 TsExtrapolation GetPostExtrapolation() const;
136
155
156 TS_API
157 void SetInnerLoopParams(
158 const TsLoopParams &params);
159
160 TS_API
161 TsLoopParams GetInnerLoopParams() const;
162
166
167 TS_API
168 void SetKnots(
169 const TsKnotMap &knots);
170
171 TS_API
172 bool CanSetKnot(
173 const TsKnot &knot,
174 std::string *reasonOut = nullptr) const;
175
178 TS_API
180 const TsKnot &knot,
181 GfInterval *affectedIntervalOut = nullptr);
182
186 TS_API
188
192 TS_API
194 TsTime time,
195 TsKnot *knotOut) const;
196
200
201 TS_API
202 void ClearKnots();
203
206 TS_API
208 TsTime time,
209 GfInterval *affectedIntervalOut = nullptr);
210
212 TS_API
214 VtValue defaultValue = VtValue(),
215 const GfInterval &interval = GfInterval::GetFullInterval());
216
220
222 TS_API
224 const GfInterval &interval);
225
227 //
228 // Result cached
229 TS_API
231
233 //
234 // Bakes inner loops (finite) and extrapolating loops (infinite)
235 // Result cached, but only for last specified interval
236 TS_API
238 const GfInterval &interval) const;
239
243
248 TS_API
249 bool Split(
250 TsTime time,
251 GfInterval *affectedIntervalOut = nullptr);
252
262
267 TS_API
268 static TsAntiRegressionMode GetAntiRegressionAuthoringMode();
269
273 TS_API
275
279 TS_API
281
288
289 template <typename T>
290 bool Eval(
291 TsTime time,
292 T *valueOut) const;
293
294 template <typename T>
295 bool EvalPreValue(
296 TsTime time,
297 T *valueOut) const;
298
299 template <typename T>
300 bool EvalDerivative(
301 TsTime time,
302 T *valueOut) const;
303
304 template <typename T>
305 bool EvalPreDerivative(
306 TsTime time,
307 T *valueOut) const;
308
309 template <typename T>
310 bool EvalHeld(
311 TsTime time,
312 T *valueOut) const;
313
314 template <typename T>
315 bool EvalPreValueHeld(
316 TsTime time,
317 T *valueOut) const;
318
319 TS_API
320 bool DoSidesDiffer(
321 TsTime time) const;
322
326
327 TS_API
328 bool IsEmpty() const;
329
330 TS_API
331 bool HasValueBlocks() const;
332
334 TS_API
335 bool IsVarying() const;
336
338 TS_API
339 bool HasLoops() const;
340
341 TS_API
342 bool HasInnerLoops() const;
343
344 TS_API
345 bool HasExtrapolatingLoops() const;
346
348 TS_API
349 bool IsLinear() const;
350
352 TS_API
353 bool IsC0Continuous() const;
354
356 TS_API
357 bool IsG1Continuous() const;
358
360 TS_API
361 bool IsC1Continuous() const;
362
364 TS_API
366 const GfInterval &timeSpan,
367 std::pair<VtValue, VtValue> *rangeOut) const;
368
370 template <typename T>
372 const GfInterval &timeSpan,
373 std::pair<T, T> *rangeOut) const;
374
378
379 TS_API
380 bool HasValueBlockAtTime(
381 TsTime time) const;
382
384 TS_API
386 TsTime startTime) const;
387
389 TS_API
391 TsTime startTime) const;
392
394 TS_API
396 TsTime time,
397 VtValue defaultValue = VtValue()) const;
398
400
401public:
402 // Hash function. For now this is cheap, and only hashes by data pointer.
403 // If there are two identical but independent splines, they will hash
404 // unequal.
405 template <typename HashState>
406 friend void TfHashAppend(
407 HashState &h,
408 const TsSpline &spline)
409 {
410 h.Append(spline._data.get());
411 }
412
413private:
414 friend class TsRegressionPreventer;
415 void _SetKnotUnchecked(const TsKnot & knot);
416
417 // External helpers provide direct data access for Ts implementation.
418 friend Ts_SplineData* Ts_GetSplineData(TsSpline &spline);
419 friend const Ts_SplineData* Ts_GetSplineData(const TsSpline &spline);
420
421 friend struct Ts_BinaryDataAccess;
422 friend struct Ts_SplineOffsetAccess;
423
424private:
425 // Get data to read from. Will be either actual data or default data.
426 TS_API
427 const Ts_SplineData* _GetData() const;
428
429 // Ensure we have our own independent data, in preparation for writing. If
430 // a value type is passed, and we don't yet have typed data, ensure we have
431 // data of the specified type.
432 void _PrepareForWrite(TfType valueType = TfType());
433
434 template <typename T>
435 bool _Eval(
436 TsTime time,
437 T *valueOut,
438 Ts_EvalAspect aspect,
439 Ts_EvalLocation location) const;
440
441private:
442 // Our parameter data. Copy-on-write. Null only if we are in the default
443 // state, with no knots, and all overall parameters set to defaults. To
444 // deal with the possibility of null data, call _GetData for reading, and
445 // _PrepareForWrite before writing.
446 std::shared_ptr<Ts_SplineData> _data;
447};
448
450TS_API
451std::ostream& operator<<(std::ostream& out, const TsSpline &spline);
452
453// XXX: This should not be necessary. All it does is call std::swap. This is
454// here as a workaround for a downstream library that tries to call swap on
455// splines, with a "using namespace std" that doesn't appear to work when pxr
456// namespaces are in use.
457TS_API
458void swap(TsSpline &lhs, TsSpline &rhs);
459
460// For applying layer offsets.
461struct Ts_SplineOffsetAccess
462{
463 TS_API
464 static void ApplyOffsetAndScale(
465 TsSpline *spline,
466 const TsTime offset,
467 const double scale);
468};
469
470
472// TEMPLATE IMPLEMENTATIONS
473
474template <typename T>
475bool TsSpline::IsHolding() const
476{
477 if constexpr (!Ts_IsSupportedValueType<T>::value)
478 {
479 return false;
480 }
481
482 return GetValueType() == Ts_GetType<T>();
483}
484
485template <typename T>
486bool TsSpline::_Eval(
487 const TsTime time,
488 T* const valueOut,
489 const Ts_EvalAspect aspect,
490 const Ts_EvalLocation location) const
491{
492 const std::optional<double> result =
493 Ts_Eval(_GetData(), time, aspect, location);
494
495 if (!result)
496 {
497 return false;
498 }
499
500 *valueOut = T(*result);
501 return true;
502}
503
504template <typename T>
505bool TsSpline::Eval(const TsTime time, T* const valueOut) const
506{
507 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalAtTime);
508}
509
510template <typename T>
511bool TsSpline::EvalPreValue(const TsTime time, T* const valueOut) const
512{
513 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalPre);
514}
515
516template <typename T>
517bool TsSpline::EvalDerivative(const TsTime time, T* const valueOut) const
518{
519 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalAtTime);
520}
521
522template <typename T>
523bool TsSpline::EvalPreDerivative(const TsTime time, T* const valueOut) const
524{
525 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalPre);
526}
527
528template <typename T>
529bool TsSpline::EvalHeld(const TsTime time, T* const valueOut) const
530{
531 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalAtTime);
532}
533
534template <typename T>
535bool TsSpline::EvalPreValueHeld(const TsTime time, T* const valueOut) const
536{
537 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalPre);
538}
539
540
541PXR_NAMESPACE_CLOSE_SCOPE
542
543#endif
A basic mathematical interval class.
Definition: interval.h:33
static GfInterval GetFullInterval()
Returns the full interval (-inf, inf).
Definition: interval.h:325
TfType represents a dynamic runtime type.
Definition: type.h:48
Extrapolation parameters for the ends of a spline beyond the knots.
Definition: types.h:121
A knot belonging to a TsSpline.
Definition: knot.h:38
The knots in a spline.
Definition: knotMap.h:37
Inner-loop parameters.
Definition: types.h:94
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
TS_API const TsKnotMap & GetKnotsWithInnerLoopsBaked() const
Not yet implemented.
TS_API bool IsG1Continuous() const
Not yet implemented.
TS_API TsKnotMap GetKnots() const
Returns the spline's knots.
TS_API bool Split(TsTime time, GfInterval *affectedIntervalOut=nullptr)
Not yet implemented.
TS_API bool IsLinear() const
Not yet implemented.
TS_API bool SetKnot(const TsKnot &knot, GfInterval *affectedIntervalOut=nullptr)
Incompletely implemented; affectedIntervalOut is not yet populated.
bool GetValueRange(const GfInterval &timeSpan, std::pair< T, T > *rangeOut) const
Not yet implemented.
TS_API bool GetValueRange(const GfInterval &timeSpan, std::pair< VtValue, VtValue > *rangeOut) const
Not yet implemented.
TS_API bool IsC1Continuous() const
Not yet implemented.
TS_API TsSpline(TfType valueType)
Creates a spline with a specified value type.
TS_API bool ClearRedundantKnots(VtValue defaultValue=VtValue(), const GfInterval &interval=GfInterval::GetFullInterval())
Not yet implemented.
TS_API bool IsSegmentMonotonic(TsTime startTime) const
Not yet implemented.
TS_API void RemoveKnot(TsTime time, GfInterval *affectedIntervalOut=nullptr)
Incompletely implemented; affectedIntervalOut is not yet populated.
TS_API TsSpline()
Default constructor creates a spline without a value type.
TS_API bool AdjustRegressiveTangents()
Shorten any regressive tangents; or, if the current authoring mode is Contain, any tangents that exce...
TS_API bool HasLoops() const
Convenience for HasInnerLoops() || HasExtrapolatingLoops().
TS_API bool HasRegressiveTangents() const
Returns whether this spline has any tangents long enough to cause regression; or, if the current auth...
TS_API bool IsSegmentFlat(TsTime startTime) const
Not yet implemented.
TS_API bool IsVarying() const
Not yet implemented.
TS_API bool GetKnot(TsTime time, TsKnot *knotOut) const
Retrieves a copy of the knot at the specified time, if one exists.
TS_API bool IsKnotRedundant(TsTime time, VtValue defaultValue=VtValue()) const
Not yet implemented.
TS_API const TsKnotMap & GetKnotsWithLoopsBaked(const GfInterval &interval) const
Not yet implemented.
static TS_API TsAntiRegressionMode GetAntiRegressionAuthoringMode()
Returns the current effective anti-regression authoring mode.
TS_API bool BakeLoops(const GfInterval &interval)
Not yet implemented.
TS_API bool IsC0Continuous() const
Not yet implemented.
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].