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
107 TS_API
108 void SetTimeValued(bool timeValued);
109
112 TS_API
113 bool IsTimeValued() const;
114
118
119 TS_API
120 void SetCurveType(TsCurveType curveType);
121
122 TS_API
123 TsCurveType GetCurveType() const;
124
128
134 TS_API
136 const TsExtrapolation &extrap);
137
138 TS_API
139 TsExtrapolation GetPreExtrapolation() const;
140
146 TS_API
148 const TsExtrapolation &extrap);
149
150 TS_API
151 TsExtrapolation GetPostExtrapolation() const;
152
153 // Returns whether pre extrapolation is valid.
154 //
155 // Pre extrapolation is invalid if it is looping and loopBoundaryTime
156 // is set to a value for which the spline does not have an associated
157 // knot time.
158 //
159 // Invalid extrapolation regions evaluate to value-block.
160 TS_API
161 bool IsPreExtrapolationValid() const;
162
163 // Returns whether post extrapolation is valid.
164 //
165 // Post extrapolation is invalid if it is looping and loopBoundaryTime
166 // is set to a value for which the spline does not have an associated
167 // knot time.
168 //
169 // Invalid extrapolation regions evaluate to value-block.
170 TS_API
171 bool IsPostExtrapolationValid() const;
172
191
192 TS_API
193 void SetInnerLoopParams(
194 const TsLoopParams &params);
195
196 TS_API
197 TsLoopParams GetInnerLoopParams() const;
198
202
204 TS_API
206 const TsKnotMap &knots);
207
208 TS_API
209 bool CanSetKnot(
210 const TsKnot &knot,
211 std::string *reasonOut = nullptr) const;
212
215 TS_API
217 const TsKnot &knot,
218 GfInterval *affectedIntervalOut = nullptr);
219
223 TS_API
225
236 TS_API
237 TsKnotMap GetKnots(const GfInterval& timeInterval) const;
238
242 TS_API
244 TsTime time,
245 TsKnot *knotOut) const;
246
250
251 TS_API
252 void ClearKnots();
253
256 TS_API
258 TsTime time,
259 GfInterval *affectedIntervalOut = nullptr);
260
262 TS_API
264 VtValue defaultValue = VtValue(),
265 const GfInterval &interval = GfInterval::GetFullInterval());
266
270
275 TS_API
277
286 TS_API
288
308
309 TS_API
311 const GfInterval &interval) const;
312
321
338 TS_API
340 TsTime time,
341 GfInterval *affectedIntervalOut = nullptr);
342
350 TS_API
352 TsTime time,
353 std::string* reason = nullptr);
354
364
369 TS_API
370 static TsAntiRegressionMode GetAntiRegressionAuthoringMode();
371
375 TS_API
377
381 TS_API
383
390
391 template <typename T>
392 bool Eval(
393 TsTime time,
394 T *valueOut) const;
395
396 template <typename T>
397 bool EvalPreValue(
398 TsTime time,
399 T *valueOut) const;
400
401 template <typename T>
402 bool EvalDerivative(
403 TsTime time,
404 T *valueOut) const;
405
406 template <typename T>
407 bool EvalPreDerivative(
408 TsTime time,
409 T *valueOut) const;
410
411 template <typename T>
412 bool EvalHeld(
413 TsTime time,
414 T *valueOut) const;
415
416 template <typename T>
417 bool EvalPreValueHeld(
418 TsTime time,
419 T *valueOut) const;
420
421 TS_API
422 bool DoSidesDiffer(
423 TsTime time) const;
424
444 template <typename Vertex>
445 bool
447 const GfInterval& timeInterval,
448 double timeScale,
449 double valueScale,
450 double tolerance,
451 TsSplineSamples<Vertex>* splineSamples) const
452 {
453 return _Sample(timeInterval, timeScale, valueScale, tolerance,
454 splineSamples);
455 }
456
463 template <typename Vertex>
464 bool
466 const GfInterval& timeInterval,
467 double timeScale,
468 double valueScale,
469 double tolerance,
470 TsSplineSamplesWithSources<Vertex>* splineSamples) const
471 {
472 return _Sample(timeInterval, timeScale, valueScale, tolerance,
473 splineSamples);
474 }
475
477
483
515 TS_API
517 const GfInterval& interval,
518 TsExtrapolation preFallback = TsExtrapolation(TsExtrapValueBlock),
519 TsExtrapolation postFallback = TsExtrapolation(TsExtrapValueBlock)
520 ) const;
521
535 TS_API
536 TsSpline GetTimeScaled(double timeScale, double timeOffset) const;
537
567 TS_API
568 static
569 TsSpline Concatenate(const std::vector<TsSpline>& splines);
570
572
573
576
609 TS_API
610 GfInterval Diff(const TsSpline& other) const;
611
619 TS_API
621 const GfInterval& compareInterval) const;
622
626
627 TS_API
628 bool IsEmpty() const;
629
630 TS_API
631 bool HasValueBlocks() const;
632
634 TS_API
635 bool IsVarying() const;
636
638 TS_API
639 bool HasLoops() const;
640
641 TS_API
642 bool HasInnerLoops() const;
643
644 TS_API
645 bool HasExtrapolatingLoops() const;
646
648 TS_API
649 bool IsLinear() const;
650
652 TS_API
653 bool IsC0Continuous() const;
654
656 TS_API
657 bool IsG1Continuous() const;
658
660 TS_API
661 bool IsC1Continuous() const;
662
664 TS_API
666 const GfInterval &timeSpan,
667 std::pair<VtValue, VtValue> *rangeOut) const;
668
670 template <typename T>
672 const GfInterval &timeSpan,
673 std::pair<T, T> *rangeOut) const;
674
678
679 TS_API
680 bool HasValueBlockAtTime(
681 TsTime time) const;
682
684 TS_API
686 TsTime startTime) const;
687
689 TS_API
691 TsTime startTime) const;
692
694 TS_API
696 TsTime time,
697 VtValue defaultValue = VtValue()) const;
698
700
701public:
702 // Hash function. For now this is cheap, and only hashes by data pointer.
703 // If there are two identical but independent splines, they will hash
704 // unequal.
705 template <typename HashState>
706 friend void TfHashAppend(
707 HashState &h,
708 const TsSpline &spline)
709 {
710 h.Append(spline._data.get());
711 }
712
713private:
714 friend class TsRegressionPreventer;
715
716 // Direct access method used by TsRegressionPreventer.
717 void _SetKnotUnchecked(const TsKnot & knot);
718
719 template <typename SampleHolder>
720 bool _Sample(
721 const GfInterval& timeInterval,
722 double timeScale,
723 double valueScale,
724 double tolerance,
725 SampleHolder* splineSamples) const;
726
727 // External helpers provide direct data access for Ts implementation.
728 friend Ts_SplineData* Ts_GetSplineData(TsSpline &spline);
729 friend const Ts_SplineData* Ts_GetSplineData(const TsSpline &spline);
730
731 friend struct Ts_BinaryDataAccess;
732 friend struct Ts_SplineOffsetAccess;
733
734private:
735 // TsSpline takes ownership of `data`. The caller should not retain or
736 // delete `data` after this constructor is called.
737 TS_API
738 TsSpline(Ts_SplineData* data);
739
740 // Get data to read from. Will be either actual data or default data.
741 TS_API
742 const Ts_SplineData* _GetData() const;
743
744 // Ensure we have our own independent data, in preparation for writing. If
745 // a value type is passed, and we don't yet have typed data, ensure we have
746 // data of the specified type.
747 void _PrepareForWrite(TfType valueType = TfType());
748
749 template <typename T>
750 bool _Eval(
751 TsTime time,
752 T *valueOut,
753 Ts_EvalAspect aspect,
754 Ts_EvalLocation location) const;
755
756 // Update all the tangents based on the tangent algorithms in the knots and
757 // follow that with a call to AdjustRegressiveTangents() to remove any
758 // remaining regressive spline segments. Return true if any changes were
759 // made.
760 TS_API
761 bool _UpdateAllTangents();
762
763 // Update the tangents of a single knot based on its tangent algorithms and
764 // the regression prevention settings.
765 TS_API
766 bool _UpdateKnotTangents(const size_t knotIndex);
767
768private:
769 // Our parameter data. Copy-on-write. Null only if we are in the default
770 // state, with no knots, and all overall parameters set to defaults. To
771 // deal with the possibility of null data, call _GetData for reading, and
772 // _PrepareForWrite before writing.
773 std::shared_ptr<Ts_SplineData> _data;
774};
775
776// TsSpline supports value transforms.
778
780TS_API
781std::ostream& operator<<(std::ostream& out, const TsSpline &spline);
782
783// XXX: This should not be necessary. All it does is call std::swap. This is
784// here as a workaround for a downstream library that tries to call swap on
785// splines, with a "using namespace std" that doesn't appear to work when pxr
786// namespaces are in use.
787TS_API
788void swap(TsSpline &lhs, TsSpline &rhs);
789
790// For applying layer offsets.
791struct Ts_SplineOffsetAccess
792{
793 TS_API
794 static void ApplyOffsetAndScale(
795 TsSpline *spline,
796 const TsTime offset,
797 const double scale);
798};
799
800
802// TEMPLATE IMPLEMENTATIONS
803
804template <typename T>
805bool TsSpline::IsHolding() const
806{
807 if constexpr (!Ts_IsSupportedValueType<T>::value)
808 {
809 return false;
810 }
811
812 return GetValueType() == Ts_GetType<T>();
813}
814
815template <typename T>
816bool TsSpline::_Eval(
817 const TsTime time,
818 T* const valueOut,
819 const Ts_EvalAspect aspect,
820 const Ts_EvalLocation location) const
821{
822 const std::optional<double> result =
823 Ts_Eval(_GetData(), time, aspect, location);
824
825 if (!result)
826 {
827 return false;
828 }
829
830 *valueOut = T(*result);
831 return true;
832}
833
834// Implement a special case that will ensure the contents of the VtValue output
835// variable contain a value of the same type (double, float, GfHalf,
836// GfTimeCode) as the spline.
837template <>
838TS_API
839bool TsSpline::_Eval(
840 const TsTime time,
841 VtValue* const valueOut,
842 const Ts_EvalAspect aspect,
843 const Ts_EvalLocation location) const;
844
845template <typename T>
846bool TsSpline::Eval(const TsTime time, T* const valueOut) const
847{
848 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalAtTime);
849}
850
851template <typename T>
852bool TsSpline::EvalPreValue(const TsTime time, T* const valueOut) const
853{
854 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalPre);
855}
856
857template <typename T>
858bool TsSpline::EvalDerivative(const TsTime time, T* const valueOut) const
859{
860 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalAtTime);
861}
862
863template <typename T>
864bool TsSpline::EvalPreDerivative(const TsTime time, T* const valueOut) const
865{
866 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalPre);
867}
868
869template <typename T>
870bool TsSpline::EvalHeld(const TsTime time, T* const valueOut) const
871{
872 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalAtTime);
873}
874
875template <typename T>
876bool TsSpline::EvalPreValueHeld(const TsTime time, T* const valueOut) const
877{
878 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalPre);
879}
880
881
882PXR_NAMESPACE_CLOSE_SCOPE
883
884#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:231
A knot belonging to a TsSpline.
Definition knot.h:42
The knots in a spline.
Definition knotMap.h:37
Inner-loop parameters.
Definition types.h:204
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:446
TS_API bool IsSegmentMonotonic(TsTime startTime) const
Not yet implemented.
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.
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:465
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 void SetTimeValued(bool timeValued)
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:295
TsSplineSamplesWithSources<Vertex> is a TsSplineSamples<Vertex> that also includes source information...
Definition types.h:318
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