Loading...
Searching...
No Matches
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/traits.h"
20#include "pxr/base/vt/value.h"
22#include "pxr/base/tf/type.h"
23
24#include <string>
25#include <memory>
26#include <iosfwd>
27
28PXR_NAMESPACE_OPEN_SCOPE
29
30class VtDictionary;
31
32
60{
61public:
69
72 TS_API
74
76 TS_API
77 TsSpline(TfType valueType);
78
79 TS_API
80 TsSpline(const TsSpline &other);
81
82 TS_API
83 TsSpline& operator=(const TsSpline &other);
84
85 TS_API
86 bool operator==(const TsSpline &other) const;
87
88 TS_API
89 bool operator!=(const TsSpline &other) const;
90
94
95 TS_API
96 static bool IsSupportedValueType(TfType valueType);
97
98 TS_API
99 TfType GetValueType() const;
100
101 template <typename T>
102 bool IsHolding() const;
103
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
128 TS_API
130 const TsExtrapolation &extrap);
131
132 TS_API
133 TsExtrapolation GetPreExtrapolation() const;
134
140 TS_API
142 const TsExtrapolation &extrap);
143
144 TS_API
145 TsExtrapolation GetPostExtrapolation() const;
146
147 // Returns whether pre extrapolation is valid.
148 //
149 // Pre extrapolation is invalid if it is looping and loopBoundaryTime
150 // is set to a value for which the spline does not have an associated
151 // knot time.
152 //
153 // Invalid extrapolation regions evaluate to value-block.
154 TS_API
155 bool IsPreExtrapolationValid() const;
156
157 // Returns whether post extrapolation is valid.
158 //
159 // Post extrapolation is invalid if it is looping and loopBoundaryTime
160 // is set to a value for which the spline does not have an associated
161 // knot time.
162 //
163 // Invalid extrapolation regions evaluate to value-block.
164 TS_API
165 bool IsPostExtrapolationValid() const;
166
187
188 [[deprecated("TsSpline inner looping is deprecated")]]
189 TS_API
190 void SetInnerLoopParams(
191 const Ts_LoopParams &params);
192
193 [[deprecated("TsSpline inner looping is deprecated")]]
194 TS_API
195 Ts_LoopParams GetInnerLoopParams() const;
196
200
202 TS_API
204 const TsKnotMap &knots);
205
206 TS_API
207 bool CanSetKnot(
208 const TsKnot &knot,
209 std::string *reasonOut = nullptr) const;
210
213 TS_API
215 const TsKnot &knot,
216 GfInterval *affectedIntervalOut = nullptr);
217
221 TS_API
223
234 TS_API
235 TsKnotMap GetKnots(const GfInterval& timeInterval) const;
236
240 TS_API
242 TsTime time,
243 TsKnot *knotOut) const;
244
248
249 TS_API
250 void ClearKnots();
251
254 TS_API
256 TsTime time,
257 GfInterval *affectedIntervalOut = nullptr);
258
260 TS_API
262 VtValue defaultValue = VtValue(),
263 const GfInterval &interval = GfInterval::GetFullInterval());
264
268
275 [[deprecated("TsSpline inner looping is deprecated")]]
276 TS_API
278
289 [[deprecated("TsSpline inner looping is deprecated")]]
290 TS_API
292
312
313 TS_API
315 const GfInterval &interval) const;
316
325
342 TS_API
344 TsTime time,
345 GfInterval *affectedIntervalOut = nullptr);
346
354 TS_API
356 TsTime time,
357 std::string* reason = nullptr);
358
368
373 TS_API
374 static TsAntiRegressionMode GetAntiRegressionAuthoringMode();
375
379 TS_API
381
385 TS_API
387
394
395 template <typename T>
396 bool Eval(
397 TsTime time,
398 T *valueOut) const;
399
400 template <typename T>
401 bool EvalPreValue(
402 TsTime time,
403 T *valueOut) const;
404
405 template <typename T>
406 bool EvalDerivative(
407 TsTime time,
408 T *valueOut) const;
409
410 template <typename T>
411 bool EvalPreDerivative(
412 TsTime time,
413 T *valueOut) const;
414
415 template <typename T>
416 bool EvalHeld(
417 TsTime time,
418 T *valueOut) const;
419
420 template <typename T>
421 bool EvalPreValueHeld(
422 TsTime time,
423 T *valueOut) const;
424
425 TS_API
426 bool DoSidesDiffer(
427 TsTime time) const;
428
448 template <typename Vertex>
449 bool
451 const GfInterval& timeInterval,
452 double timeScale,
453 double valueScale,
454 double tolerance,
455 TsSplineSamples<Vertex>* splineSamples) const
456 {
457 return _Sample(timeInterval, timeScale, valueScale, tolerance,
458 splineSamples);
459 }
460
467 template <typename Vertex>
468 bool
470 const GfInterval& timeInterval,
471 double timeScale,
472 double valueScale,
473 double tolerance,
474 TsSplineSamplesWithSources<Vertex>* splineSamples) const
475 {
476 return _Sample(timeInterval, timeScale, valueScale, tolerance,
477 splineSamples);
478 }
479
481
487
519 TS_API
521 const GfInterval& interval,
522 TsExtrapolation preFallback = TsExtrapolation(TsExtrapValueBlock),
523 TsExtrapolation postFallback = TsExtrapolation(TsExtrapValueBlock)
524 ) const;
525
539 TS_API
540 TsSpline GetTimeScaled(double timeScale, double timeOffset) const;
541
571 TS_API
572 static
573 TsSpline Concatenate(const std::vector<TsSpline>& splines);
574
576
577
580
613 TS_API
614 GfInterval Diff(const TsSpline& other) const;
615
623 TS_API
625 const GfInterval& compareInterval) const;
626
630
631 TS_API
632 bool IsEmpty() const;
633
634 TS_API
635 bool HasValueBlocks() const;
636
638 TS_API
639 bool IsVarying() const;
640
642 TS_API
643 bool HasLoops() const;
644
647 [[deprecated("TsSpline inner looping is deprecated")]]
648 TS_API
649 bool HasInnerLoops() const;
650
651 TS_API
652 bool HasExtrapolatingLoops() const;
653
655 TS_API
656 bool IsLinear() const;
657
659 TS_API
660 bool IsC0Continuous() const;
661
663 TS_API
664 bool IsG1Continuous() const;
665
667 TS_API
668 bool IsC1Continuous() const;
669
671 TS_API
673 const GfInterval &timeSpan,
674 std::pair<VtValue, VtValue> *rangeOut) const;
675
677 template <typename T>
679 const GfInterval &timeSpan,
680 std::pair<T, T> *rangeOut) const;
681
685
686 TS_API
687 bool HasValueBlockAtTime(
688 TsTime time) const;
689
691 TS_API
693 TsTime startTime) const;
694
696 TS_API
698 TsTime startTime) const;
699
701 TS_API
703 TsTime time,
704 VtValue defaultValue = VtValue()) const;
705
707
708public:
709 // Hash function. For now this is cheap, and only hashes by data pointer.
710 // If there are two identical but independent splines, they will hash
711 // unequal.
712 template <typename HashState>
713 friend void TfHashAppend(
714 HashState &h,
715 const TsSpline &spline)
716 {
717 h.Append(spline._data.get());
718 }
719
720public:
734 TS_API
735 void _SetInnerLoopParams(
736 const Ts_LoopParams &params);
737
738 TS_API
739 Ts_LoopParams _GetInnerLoopParams() const;
740
741 TS_API
742 bool _BakeInnerLoops();
743
744 TS_API
745 TsKnotMap _GetKnotsWithInnerLoopsBaked() const;
746
747 TS_API
748 bool _HasInnerLoops() const;
751
752private:
753 friend class TsRegressionPreventer;
754
755 // Direct access method used by TsRegressionPreventer.
756 void _SetKnotUnchecked(const TsKnot & knot);
757
758 template <typename SampleHolder>
759 bool _Sample(
760 const GfInterval& timeInterval,
761 double timeScale,
762 double valueScale,
763 double tolerance,
764 SampleHolder* splineSamples) const;
765
766 // External helpers provide direct data access for Ts implementation.
767 friend Ts_SplineData* Ts_GetSplineData(TsSpline &spline);
768 friend const Ts_SplineData* Ts_GetSplineData(const TsSpline &spline);
769
770 friend struct Ts_BinaryDataAccess;
771 friend struct Ts_SplineOffsetAccess;
772
773private:
774 // TsSpline takes ownership of `data`. The caller should not retain or
775 // delete `data` after this constructor is called.
776 TS_API
777 TsSpline(Ts_SplineData* data);
778
779 // Get data to read from. Will be either actual data or default data.
780 TS_API
781 const Ts_SplineData* _GetData() const;
782
783 // Ensure we have our own independent data, in preparation for writing. If
784 // a value type is passed, and we don't yet have typed data, ensure we have
785 // data of the specified type.
786 void _PrepareForWrite(TfType valueType = TfType());
787
788 template <typename T>
789 bool _Eval(
790 TsTime time,
791 T *valueOut,
792 Ts_EvalAspect aspect,
793 Ts_EvalLocation location) const;
794
795 // Update all the tangents based on the tangent algorithms in the knots and
796 // follow that with a call to AdjustRegressiveTangents() to remove any
797 // remaining regressive spline segments. Return true if any changes were
798 // made.
799 TS_API
800 bool _UpdateAllTangents();
801
802 // Update the tangents of a single knot based on its tangent algorithms and
803 // the regression prevention settings.
804 TS_API
805 bool _UpdateKnotTangents(const size_t knotIndex);
806
807private:
808 // Our parameter data. Copy-on-write. Null only if we are in the default
809 // state, with no knots, and all overall parameters set to defaults. To
810 // deal with the possibility of null data, call _GetData for reading, and
811 // _PrepareForWrite before writing.
812 std::shared_ptr<Ts_SplineData> _data;
813};
814
815// TsSpline supports value transforms.
817
819TS_API
820std::ostream& operator<<(std::ostream& out, const TsSpline &spline);
821
822// XXX: This should not be necessary. All it does is call std::swap. This is
823// here as a workaround for a downstream library that tries to call swap on
824// splines, with a "using namespace std" that doesn't appear to work when pxr
825// namespaces are in use.
826TS_API
827void swap(TsSpline &lhs, TsSpline &rhs);
828
829// For applying layer offsets.
830struct Ts_SplineOffsetAccess
831{
832 TS_API
833 static void ApplyOffsetAndScale(
834 TsSpline *spline,
835 const TsTime offset,
836 const double scale);
837};
838
839
841// TEMPLATE IMPLEMENTATIONS
842
843template <typename T>
844bool TsSpline::IsHolding() const
845{
846 if constexpr (!Ts_IsSupportedValueType<T>::value)
847 {
848 return false;
849 }
850
851 return GetValueType() == Ts_GetType<T>();
852}
853
854template <typename T>
855bool TsSpline::_Eval(
856 const TsTime time,
857 T* const valueOut,
858 const Ts_EvalAspect aspect,
859 const Ts_EvalLocation location) const
860{
861 const std::optional<double> result =
862 Ts_Eval(_GetData(), time, aspect, location);
863
864 if (!result)
865 {
866 return false;
867 }
868
869 *valueOut = T(*result);
870 return true;
871}
872
873// Implement a special case that will ensure the contents of the VtValue output
874// variable contain a value of the same type (double, float, GfHalf,
875// GfTimeCode, or GfDuration) as the spline.
876template <>
877TS_API
878bool TsSpline::_Eval(
879 const TsTime time,
880 VtValue* const valueOut,
881 const Ts_EvalAspect aspect,
882 const Ts_EvalLocation location) const;
883
884template <typename T>
885bool TsSpline::Eval(const TsTime time, T* const valueOut) const
886{
887 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalAtTime);
888}
889
890template <typename T>
891bool TsSpline::EvalPreValue(const TsTime time, T* const valueOut) const
892{
893 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalPre);
894}
895
896template <typename T>
897bool TsSpline::EvalDerivative(const TsTime time, T* const valueOut) const
898{
899 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalAtTime);
900}
901
902template <typename T>
903bool TsSpline::EvalPreDerivative(const TsTime time, T* const valueOut) const
904{
905 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalPre);
906}
907
908template <typename T>
909bool TsSpline::EvalHeld(const TsTime time, T* const valueOut) const
910{
911 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalAtTime);
912}
913
914template <typename T>
915bool TsSpline::EvalPreValueHeld(const TsTime time, T* const valueOut) const
916{
917 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalPre);
918}
919
920
921PXR_NAMESPACE_CLOSE_SCOPE
922
923#endif
#define VT_VALUE_TYPE_CAN_TRANSFORM(T)
A helper for specializing the above trait.
Definition traits.h:150
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:249
A knot belonging to a TsSpline.
Definition knot.h:43
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:60
TS_API bool CanBreakdown(TsTime time, std::string *reason=nullptr)
Test if a knot could be inserted by Breakdown at time.
TS_API TsSpline GetTruncated(const GfInterval &interval, TsExtrapolation preFallback=TsExtrapolation(TsExtrapValueBlock), TsExtrapolation postFallback=TsExtrapolation(TsExtrapValueBlock)) const
Returns a new spline resulting from truncation of the given spline to the given interval.
TS_API bool IsG1Continuous() const
Not yet implemented.
TS_API TsKnotMap GetKnots() const
Returns the spline's knots.
TS_API GfInterval Diff(const TsSpline &other, const GfInterval &compareInterval) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
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.
TS_API TsKnotMap GetKnotsWithInnerLoopsBaked() const
Return all the knots on the spline, including knots generated by inner looping.
bool GetValueRange(const GfInterval &timeSpan, std::pair< T, T > *rangeOut) const
Not yet implemented.
static TS_API TsSpline Concatenate(const std::vector< TsSpline > &splines)
Returns a spline resulting from the concatenation of the given splines.
TS_API TsKnotMap GetKnots(const GfInterval &timeInterval) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
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 GfInterval Diff(const TsSpline &other) const
Compare two splines.
TS_API TsSpline GetTimeScaled(double timeScale, double timeOffset) const
Returns a new spline resulting from time scaling the knots of a given spline, applying first the scal...
TS_API void SetPreExtrapolation(const TsExtrapolation &extrap)
Sets pre extrapolation.
TS_API bool ClearRedundantKnots(VtValue defaultValue=VtValue(), const GfInterval &interval=GfInterval::GetFullInterval())
Not yet implemented.
bool Sample(const GfInterval &timeInterval, double timeScale, double valueScale, double tolerance, TsSplineSamples< Vertex > *splineSamples) const
Evaluates the value of the TsSpline over the given time interval, typically for drawing.
Definition spline.h:450
TS_API bool IsSegmentMonotonic(TsTime startTime) const
Not yet implemented.
TS_API bool HasInnerLoops() const
TS_API TsKnotMap GetKnotsWithLoopsBaked(const GfInterval &interval) const
Return baked knots that will replicate this spline over the given time interval without any looping.
TS_API void RemoveKnot(TsTime time, GfInterval *affectedIntervalOut=nullptr)
Incompletely implemented; affectedIntervalOut is not yet populated.
TS_API bool IsTimeValued() const
Convenience function that returns true if the value type of the spline is GfTimeCode or GfDuration.
bool Sample(const GfInterval &timeInterval, double timeScale, double valueScale, double tolerance, TsSplineSamplesWithSources< Vertex > *splineSamples) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition spline.h:469
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 Breakdown(TsTime time, GfInterval *affectedIntervalOut=nullptr)
Add a knot at the specified time.
TS_API bool HasLoops() const
Convenience for HasInnerLoops() || HasExtrapolatingLoops().
TS_API void SetKnots(const TsKnotMap &knots)
Clears existing knots and sets the given knots.
TS_API bool HasRegressiveTangents() const
Returns whether this spline has any tangents long enough to cause regression; or, if the current auth...
TS_API void SetPostExtrapolation(const TsExtrapolation &extrap)
Sets post extrapolation.
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.
static TS_API TsAntiRegressionMode GetAntiRegressionAuthoringMode()
Returns the current effective anti-regression authoring mode.
TS_API bool BakeInnerLoops()
Bake inner loops in the spline.
TS_API bool IsC0Continuous() const
Not yet implemented.
TsSplineSamples<Vertex> holds a collection of piecewise linear polylines that approximate a TsSpline.
Definition types.h:313
TsSplineSamplesWithSources<Vertex> is a TsSplineSamples<Vertex> that also includes source information...
Definition types.h:336
A map with string keys and VtValue values.
Definition dictionary.h:52
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition value.h:90