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
124 TS_API
125 void SetPreExtrapolation(
126 const TsExtrapolation &extrap);
127
128 TS_API
129 TsExtrapolation GetPreExtrapolation() const;
130
131 TS_API
132 void SetPostExtrapolation(
133 const TsExtrapolation &extrap);
134
135 TS_API
136 TsExtrapolation GetPostExtrapolation() const;
137
156
157 TS_API
158 void SetInnerLoopParams(
159 const TsLoopParams &params);
160
161 TS_API
162 TsLoopParams GetInnerLoopParams() const;
163
167
168 TS_API
169 void SetKnots(
170 const TsKnotMap &knots);
171
172 TS_API
173 bool CanSetKnot(
174 const TsKnot &knot,
175 std::string *reasonOut = nullptr) const;
176
179 TS_API
181 const TsKnot &knot,
182 GfInterval *affectedIntervalOut = nullptr);
183
187 TS_API
189
200 TS_API
201 TsKnotMap GetKnots(const GfInterval& timeInterval) const;
202
206 TS_API
208 TsTime time,
209 TsKnot *knotOut) const;
210
214
215 TS_API
216 void ClearKnots();
217
220 TS_API
222 TsTime time,
223 GfInterval *affectedIntervalOut = nullptr);
224
226 TS_API
228 VtValue defaultValue = VtValue(),
229 const GfInterval &interval = GfInterval::GetFullInterval());
230
234
239 TS_API
241
250 TS_API
252
270
271 TS_API
273 const GfInterval &interval) const;
274
283
295 TS_API
297 TsTime time,
298 GfInterval *affectedIntervalOut = nullptr);
299
307 TS_API
309 TsTime time,
310 std::string* reason = nullptr);
311
321
326 TS_API
327 static TsAntiRegressionMode GetAntiRegressionAuthoringMode();
328
332 TS_API
334
338 TS_API
340
347
348 template <typename T>
349 bool Eval(
350 TsTime time,
351 T *valueOut) const;
352
353 template <typename T>
354 bool EvalPreValue(
355 TsTime time,
356 T *valueOut) const;
357
358 template <typename T>
359 bool EvalDerivative(
360 TsTime time,
361 T *valueOut) const;
362
363 template <typename T>
364 bool EvalPreDerivative(
365 TsTime time,
366 T *valueOut) const;
367
368 template <typename T>
369 bool EvalHeld(
370 TsTime time,
371 T *valueOut) const;
372
373 template <typename T>
374 bool EvalPreValueHeld(
375 TsTime time,
376 T *valueOut) const;
377
378 TS_API
379 bool DoSidesDiffer(
380 TsTime time) const;
381
398 template <typename Vertex>
399 bool
401 const GfInterval& timeInterval,
402 double timeScale,
403 double valueScale,
404 double tolerance,
405 TsSplineSamples<Vertex>* splineSamples) const
406 {
407 return _Sample(timeInterval, timeScale, valueScale, tolerance,
408 splineSamples);
409 }
410
417 template <typename Vertex>
418 bool
420 const GfInterval& timeInterval,
421 double timeScale,
422 double valueScale,
423 double tolerance,
424 TsSplineSamplesWithSources<Vertex>* splineSamples) const
425 {
426 return _Sample(timeInterval, timeScale, valueScale, tolerance,
427 splineSamples);
428 }
429
433
466 TS_API
467 GfInterval Diff(const TsSpline& other) const;
468
476 TS_API
478 const GfInterval& compareInterval) const;
479
483
484 TS_API
485 bool IsEmpty() const;
486
487 TS_API
488 bool HasValueBlocks() const;
489
491 TS_API
492 bool IsVarying() const;
493
495 TS_API
496 bool HasLoops() const;
497
498 TS_API
499 bool HasInnerLoops() const;
500
501 TS_API
502 bool HasExtrapolatingLoops() const;
503
505 TS_API
506 bool IsLinear() const;
507
509 TS_API
510 bool IsC0Continuous() const;
511
513 TS_API
514 bool IsG1Continuous() const;
515
517 TS_API
518 bool IsC1Continuous() const;
519
521 TS_API
523 const GfInterval &timeSpan,
524 std::pair<VtValue, VtValue> *rangeOut) const;
525
527 template <typename T>
529 const GfInterval &timeSpan,
530 std::pair<T, T> *rangeOut) const;
531
535
536 TS_API
537 bool HasValueBlockAtTime(
538 TsTime time) const;
539
541 TS_API
543 TsTime startTime) const;
544
546 TS_API
548 TsTime startTime) const;
549
551 TS_API
553 TsTime time,
554 VtValue defaultValue = VtValue()) const;
555
557
558public:
559 // Hash function. For now this is cheap, and only hashes by data pointer.
560 // If there are two identical but independent splines, they will hash
561 // unequal.
562 template <typename HashState>
563 friend void TfHashAppend(
564 HashState &h,
565 const TsSpline &spline)
566 {
567 h.Append(spline._data.get());
568 }
569
570private:
571 friend class TsRegressionPreventer;
572
573 // Direct access method used by TsRegressionPreventer.
574 void _SetKnotUnchecked(const TsKnot & knot);
575
576 template <typename SampleHolder>
577 bool _Sample(
578 const GfInterval& timeInterval,
579 double timeScale,
580 double valueScale,
581 double tolerance,
582 SampleHolder* splineSamples) const;
583
584 // External helpers provide direct data access for Ts implementation.
585 friend Ts_SplineData* Ts_GetSplineData(TsSpline &spline);
586 friend const Ts_SplineData* Ts_GetSplineData(const TsSpline &spline);
587
588 friend struct Ts_BinaryDataAccess;
589 friend struct Ts_SplineOffsetAccess;
590
591private:
592 // Get data to read from. Will be either actual data or default data.
593 TS_API
594 const Ts_SplineData* _GetData() const;
595
596 // Ensure we have our own independent data, in preparation for writing. If
597 // a value type is passed, and we don't yet have typed data, ensure we have
598 // data of the specified type.
599 void _PrepareForWrite(TfType valueType = TfType());
600
601 template <typename T>
602 bool _Eval(
603 TsTime time,
604 T *valueOut,
605 Ts_EvalAspect aspect,
606 Ts_EvalLocation location) const;
607
608 // Update all the tangents based on the tangent algorithms in the knots and
609 // follow that with a call to AdjustRegressiveTangents() to remove any
610 // remaining regressive spline segments. Return true if any changes were
611 // made.
612 TS_API
613 bool _UpdateAllTangents();
614
615 // Update the tangents of a single knot based on its tangent algorithms and
616 // the regression prevention settings.
617 TS_API
618 bool _UpdateKnotTangents(const size_t knotIndex);
619
620private:
621 // Our parameter data. Copy-on-write. Null only if we are in the default
622 // state, with no knots, and all overall parameters set to defaults. To
623 // deal with the possibility of null data, call _GetData for reading, and
624 // _PrepareForWrite before writing.
625 std::shared_ptr<Ts_SplineData> _data;
626};
627
628// TsSpline supports value transforms.
630
632TS_API
633std::ostream& operator<<(std::ostream& out, const TsSpline &spline);
634
635// XXX: This should not be necessary. All it does is call std::swap. This is
636// here as a workaround for a downstream library that tries to call swap on
637// splines, with a "using namespace std" that doesn't appear to work when pxr
638// namespaces are in use.
639TS_API
640void swap(TsSpline &lhs, TsSpline &rhs);
641
642// For applying layer offsets.
643struct Ts_SplineOffsetAccess
644{
645 TS_API
646 static void ApplyOffsetAndScale(
647 TsSpline *spline,
648 const TsTime offset,
649 const double scale);
650};
651
652
654// TEMPLATE IMPLEMENTATIONS
655
656template <typename T>
657bool TsSpline::IsHolding() const
658{
659 if constexpr (!Ts_IsSupportedValueType<T>::value)
660 {
661 return false;
662 }
663
664 return GetValueType() == Ts_GetType<T>();
665}
666
667template <typename T>
668bool TsSpline::_Eval(
669 const TsTime time,
670 T* const valueOut,
671 const Ts_EvalAspect aspect,
672 const Ts_EvalLocation location) const
673{
674 const std::optional<double> result =
675 Ts_Eval(_GetData(), time, aspect, location);
676
677 if (!result)
678 {
679 return false;
680 }
681
682 *valueOut = T(*result);
683 return true;
684}
685
686// Implement a special case that will ensure the contents of the VtValue output
687// variable contain a value of the same type (double, float, or GfHalf) as the
688// spline.
689template <>
690TS_API
691bool TsSpline::_Eval(
692 const TsTime time,
693 VtValue* const valueOut,
694 const Ts_EvalAspect aspect,
695 const Ts_EvalLocation location) const;
696
697template <typename T>
698bool TsSpline::Eval(const TsTime time, T* const valueOut) const
699{
700 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalAtTime);
701}
702
703template <typename T>
704bool TsSpline::EvalPreValue(const TsTime time, T* const valueOut) const
705{
706 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalPre);
707}
708
709template <typename T>
710bool TsSpline::EvalDerivative(const TsTime time, T* const valueOut) const
711{
712 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalAtTime);
713}
714
715template <typename T>
716bool TsSpline::EvalPreDerivative(const TsTime time, T* const valueOut) const
717{
718 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalPre);
719}
720
721template <typename T>
722bool TsSpline::EvalHeld(const TsTime time, T* const valueOut) const
723{
724 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalAtTime);
725}
726
727template <typename T>
728bool TsSpline::EvalPreValueHeld(const TsTime time, T* const valueOut) const
729{
730 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalPre);
731}
732
733
734PXR_NAMESPACE_CLOSE_SCOPE
735
736#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:220
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:193
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 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 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:400
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:419
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 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:255
TsSplineSamplesWithSources<Vertex> is a TsSplineSamples<Vertex> that also includes source information...
Definition: types.h:278
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
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
Output a GfBBox3d using the format [(range) matrix zeroArea].