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
104 TS_API
105 void SetTimeValued(bool timeValued);
106
107 TS_API
108 bool IsTimeValued() const;
109
113
114 TS_API
115 void SetCurveType(TsCurveType curveType);
116
117 TS_API
118 TsCurveType GetCurveType() const;
119
123
129 TS_API
131 const TsExtrapolation &extrap);
132
133 TS_API
134 TsExtrapolation GetPreExtrapolation() const;
135
141 TS_API
143 const TsExtrapolation &extrap);
144
145 TS_API
146 TsExtrapolation GetPostExtrapolation() const;
147
148 // Returns whether pre extrapolation is valid.
149 //
150 // Pre extrapolation is invalid if it is looping and loopBoundaryTime
151 // is set to a value for which the spline does not have an associated
152 // knot time.
153 //
154 // Invalid extrapolation regions evaluate to value-block.
155 TS_API
156 bool IsPreExtrapolationValid() const;
157
158 // Returns whether post extrapolation is valid.
159 //
160 // Post extrapolation is invalid if it is looping and loopBoundaryTime
161 // is set to a value for which the spline does not have an associated
162 // knot time.
163 //
164 // Invalid extrapolation regions evaluate to value-block.
165 TS_API
166 bool IsPostExtrapolationValid() const;
167
186
187 TS_API
188 void SetInnerLoopParams(
189 const TsLoopParams &params);
190
191 TS_API
192 TsLoopParams GetInnerLoopParams() const;
193
197
198 TS_API
199 void SetKnots(
200 const TsKnotMap &knots);
201
202 TS_API
203 bool CanSetKnot(
204 const TsKnot &knot,
205 std::string *reasonOut = nullptr) const;
206
209 TS_API
211 const TsKnot &knot,
212 GfInterval *affectedIntervalOut = nullptr);
213
217 TS_API
219
230 TS_API
231 TsKnotMap GetKnots(const GfInterval& timeInterval) const;
232
236 TS_API
238 TsTime time,
239 TsKnot *knotOut) const;
240
244
245 TS_API
246 void ClearKnots();
247
250 TS_API
252 TsTime time,
253 GfInterval *affectedIntervalOut = nullptr);
254
256 TS_API
258 VtValue defaultValue = VtValue(),
259 const GfInterval &interval = GfInterval::GetFullInterval());
260
264
269 TS_API
271
280 TS_API
282
302
303 TS_API
305 const GfInterval &interval) const;
306
315
332 TS_API
334 TsTime time,
335 GfInterval *affectedIntervalOut = nullptr);
336
344 TS_API
346 TsTime time,
347 std::string* reason = nullptr);
348
358
363 TS_API
364 static TsAntiRegressionMode GetAntiRegressionAuthoringMode();
365
369 TS_API
371
375 TS_API
377
384
385 template <typename T>
386 bool Eval(
387 TsTime time,
388 T *valueOut) const;
389
390 template <typename T>
391 bool EvalPreValue(
392 TsTime time,
393 T *valueOut) const;
394
395 template <typename T>
396 bool EvalDerivative(
397 TsTime time,
398 T *valueOut) const;
399
400 template <typename T>
401 bool EvalPreDerivative(
402 TsTime time,
403 T *valueOut) const;
404
405 template <typename T>
406 bool EvalHeld(
407 TsTime time,
408 T *valueOut) const;
409
410 template <typename T>
411 bool EvalPreValueHeld(
412 TsTime time,
413 T *valueOut) const;
414
415 TS_API
416 bool DoSidesDiffer(
417 TsTime time) const;
418
438 template <typename Vertex>
439 bool
441 const GfInterval& timeInterval,
442 double timeScale,
443 double valueScale,
444 double tolerance,
445 TsSplineSamples<Vertex>* splineSamples) const
446 {
447 return _Sample(timeInterval, timeScale, valueScale, tolerance,
448 splineSamples);
449 }
450
457 template <typename Vertex>
458 bool
460 const GfInterval& timeInterval,
461 double timeScale,
462 double valueScale,
463 double tolerance,
464 TsSplineSamplesWithSources<Vertex>* splineSamples) const
465 {
466 return _Sample(timeInterval, timeScale, valueScale, tolerance,
467 splineSamples);
468 }
469
471
477
509 TS_API
511 const GfInterval& interval,
512 TsExtrapolation preFallback = TsExtrapolation(TsExtrapValueBlock),
513 TsExtrapolation postFallback = TsExtrapolation(TsExtrapValueBlock)
514 ) const;
515
517
518
521
554 TS_API
555 GfInterval Diff(const TsSpline& other) const;
556
564 TS_API
566 const GfInterval& compareInterval) const;
567
571
572 TS_API
573 bool IsEmpty() const;
574
575 TS_API
576 bool HasValueBlocks() const;
577
579 TS_API
580 bool IsVarying() const;
581
583 TS_API
584 bool HasLoops() const;
585
586 TS_API
587 bool HasInnerLoops() const;
588
589 TS_API
590 bool HasExtrapolatingLoops() const;
591
593 TS_API
594 bool IsLinear() const;
595
597 TS_API
598 bool IsC0Continuous() const;
599
601 TS_API
602 bool IsG1Continuous() const;
603
605 TS_API
606 bool IsC1Continuous() const;
607
609 TS_API
611 const GfInterval &timeSpan,
612 std::pair<VtValue, VtValue> *rangeOut) const;
613
615 template <typename T>
617 const GfInterval &timeSpan,
618 std::pair<T, T> *rangeOut) const;
619
623
624 TS_API
625 bool HasValueBlockAtTime(
626 TsTime time) const;
627
629 TS_API
631 TsTime startTime) const;
632
634 TS_API
636 TsTime startTime) const;
637
639 TS_API
641 TsTime time,
642 VtValue defaultValue = VtValue()) const;
643
645
646public:
647 // Hash function. For now this is cheap, and only hashes by data pointer.
648 // If there are two identical but independent splines, they will hash
649 // unequal.
650 template <typename HashState>
651 friend void TfHashAppend(
652 HashState &h,
653 const TsSpline &spline)
654 {
655 h.Append(spline._data.get());
656 }
657
658private:
659 friend class TsRegressionPreventer;
660
661 // Direct access method used by TsRegressionPreventer.
662 void _SetKnotUnchecked(const TsKnot & knot);
663
664 template <typename SampleHolder>
665 bool _Sample(
666 const GfInterval& timeInterval,
667 double timeScale,
668 double valueScale,
669 double tolerance,
670 SampleHolder* splineSamples) const;
671
672 // External helpers provide direct data access for Ts implementation.
673 friend Ts_SplineData* Ts_GetSplineData(TsSpline &spline);
674 friend const Ts_SplineData* Ts_GetSplineData(const TsSpline &spline);
675
676 friend struct Ts_BinaryDataAccess;
677 friend struct Ts_SplineOffsetAccess;
678
679private:
680 // TsSpline takes ownership of `data`. The caller should not retain or
681 // delete `data` after this constructor is called.
682 TS_API
683 TsSpline(Ts_SplineData* data);
684
685 // Get data to read from. Will be either actual data or default data.
686 TS_API
687 const Ts_SplineData* _GetData() const;
688
689 // Ensure we have our own independent data, in preparation for writing. If
690 // a value type is passed, and we don't yet have typed data, ensure we have
691 // data of the specified type.
692 void _PrepareForWrite(TfType valueType = TfType());
693
694 template <typename T>
695 bool _Eval(
696 TsTime time,
697 T *valueOut,
698 Ts_EvalAspect aspect,
699 Ts_EvalLocation location) const;
700
701 // Update all the tangents based on the tangent algorithms in the knots and
702 // follow that with a call to AdjustRegressiveTangents() to remove any
703 // remaining regressive spline segments. Return true if any changes were
704 // made.
705 TS_API
706 bool _UpdateAllTangents();
707
708 // Update the tangents of a single knot based on its tangent algorithms and
709 // the regression prevention settings.
710 TS_API
711 bool _UpdateKnotTangents(const size_t knotIndex);
712
713private:
714 // Our parameter data. Copy-on-write. Null only if we are in the default
715 // state, with no knots, and all overall parameters set to defaults. To
716 // deal with the possibility of null data, call _GetData for reading, and
717 // _PrepareForWrite before writing.
718 std::shared_ptr<Ts_SplineData> _data;
719};
720
721// TsSpline supports value transforms.
723
725TS_API
726std::ostream& operator<<(std::ostream& out, const TsSpline &spline);
727
728// XXX: This should not be necessary. All it does is call std::swap. This is
729// here as a workaround for a downstream library that tries to call swap on
730// splines, with a "using namespace std" that doesn't appear to work when pxr
731// namespaces are in use.
732TS_API
733void swap(TsSpline &lhs, TsSpline &rhs);
734
735// For applying layer offsets.
736struct Ts_SplineOffsetAccess
737{
738 TS_API
739 static void ApplyOffsetAndScale(
740 TsSpline *spline,
741 const TsTime offset,
742 const double scale);
743};
744
745
747// TEMPLATE IMPLEMENTATIONS
748
749template <typename T>
750bool TsSpline::IsHolding() const
751{
752 if constexpr (!Ts_IsSupportedValueType<T>::value)
753 {
754 return false;
755 }
756
757 return GetValueType() == Ts_GetType<T>();
758}
759
760template <typename T>
761bool TsSpline::_Eval(
762 const TsTime time,
763 T* const valueOut,
764 const Ts_EvalAspect aspect,
765 const Ts_EvalLocation location) const
766{
767 const std::optional<double> result =
768 Ts_Eval(_GetData(), time, aspect, location);
769
770 if (!result)
771 {
772 return false;
773 }
774
775 *valueOut = T(*result);
776 return true;
777}
778
779// Implement a special case that will ensure the contents of the VtValue output
780// variable contain a value of the same type (double, float, or GfHalf) as the
781// spline.
782template <>
783TS_API
784bool TsSpline::_Eval(
785 const TsTime time,
786 VtValue* const valueOut,
787 const Ts_EvalAspect aspect,
788 const Ts_EvalLocation location) const;
789
790template <typename T>
791bool TsSpline::Eval(const TsTime time, T* const valueOut) const
792{
793 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalAtTime);
794}
795
796template <typename T>
797bool TsSpline::EvalPreValue(const TsTime time, T* const valueOut) const
798{
799 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalPre);
800}
801
802template <typename T>
803bool TsSpline::EvalDerivative(const TsTime time, T* const valueOut) const
804{
805 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalAtTime);
806}
807
808template <typename T>
809bool TsSpline::EvalPreDerivative(const TsTime time, T* const valueOut) const
810{
811 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalPre);
812}
813
814template <typename T>
815bool TsSpline::EvalHeld(const TsTime time, T* const valueOut) const
816{
817 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalAtTime);
818}
819
820template <typename T>
821bool TsSpline::EvalPreValueHeld(const TsTime time, T* const valueOut) const
822{
823 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalPre);
824}
825
826
827PXR_NAMESPACE_CLOSE_SCOPE
828
829#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:223
A knot belonging to a TsSpline.
Definition knot.h:41
The knots in a spline.
Definition knotMap.h:37
Inner-loop parameters.
Definition types.h:196
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.
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 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:440
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.
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:459
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 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:287
TsSplineSamplesWithSources<Vertex> is a TsSplineSamples<Vertex> that also includes source information...
Definition types.h:310
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