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/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
199 TS_API
200 TsKnotMap GetKnots(const GfInterval& timeInterval) const;
201
205 TS_API
207 TsTime time,
208 TsKnot *knotOut) const;
209
213
214 TS_API
215 void ClearKnots();
216
219 TS_API
221 TsTime time,
222 GfInterval *affectedIntervalOut = nullptr);
223
225 TS_API
227 VtValue defaultValue = VtValue(),
228 const GfInterval &interval = GfInterval::GetFullInterval());
229
233
238 TS_API
240
249 TS_API
251
269
270 TS_API
272 const GfInterval &interval) const;
273
282
294 TS_API
296 TsTime time,
297 GfInterval *affectedIntervalOut = nullptr);
298
306 TS_API
308 TsTime time,
309 std::string* reason = nullptr);
310
320
325 TS_API
326 static TsAntiRegressionMode GetAntiRegressionAuthoringMode();
327
331 TS_API
333
337 TS_API
339
346
347 template <typename T>
348 bool Eval(
349 TsTime time,
350 T *valueOut) const;
351
352 template <typename T>
353 bool EvalPreValue(
354 TsTime time,
355 T *valueOut) const;
356
357 template <typename T>
358 bool EvalDerivative(
359 TsTime time,
360 T *valueOut) const;
361
362 template <typename T>
363 bool EvalPreDerivative(
364 TsTime time,
365 T *valueOut) const;
366
367 template <typename T>
368 bool EvalHeld(
369 TsTime time,
370 T *valueOut) const;
371
372 template <typename T>
373 bool EvalPreValueHeld(
374 TsTime time,
375 T *valueOut) const;
376
377 TS_API
378 bool DoSidesDiffer(
379 TsTime time) const;
380
397 template <typename Vertex>
398 bool
400 const GfInterval& timeInterval,
401 double timeScale,
402 double valueScale,
403 double tolerance,
404 TsSplineSamples<Vertex>* splineSamples) const
405 {
406 return _Sample(timeInterval, timeScale, valueScale, tolerance,
407 splineSamples);
408 }
409
416 template <typename Vertex>
417 bool
419 const GfInterval& timeInterval,
420 double timeScale,
421 double valueScale,
422 double tolerance,
423 TsSplineSamplesWithSources<Vertex>* splineSamples) const
424 {
425 return _Sample(timeInterval, timeScale, valueScale, tolerance,
426 splineSamples);
427 }
428
432
433 TS_API
434 bool IsEmpty() const;
435
436 TS_API
437 bool HasValueBlocks() const;
438
440 TS_API
441 bool IsVarying() const;
442
444 TS_API
445 bool HasLoops() const;
446
447 TS_API
448 bool HasInnerLoops() const;
449
450 TS_API
451 bool HasExtrapolatingLoops() const;
452
454 TS_API
455 bool IsLinear() const;
456
458 TS_API
459 bool IsC0Continuous() const;
460
462 TS_API
463 bool IsG1Continuous() const;
464
466 TS_API
467 bool IsC1Continuous() const;
468
470 TS_API
472 const GfInterval &timeSpan,
473 std::pair<VtValue, VtValue> *rangeOut) const;
474
476 template <typename T>
478 const GfInterval &timeSpan,
479 std::pair<T, T> *rangeOut) const;
480
484
485 TS_API
486 bool HasValueBlockAtTime(
487 TsTime time) const;
488
490 TS_API
492 TsTime startTime) const;
493
495 TS_API
497 TsTime startTime) const;
498
500 TS_API
502 TsTime time,
503 VtValue defaultValue = VtValue()) const;
504
506
507public:
508 // Hash function. For now this is cheap, and only hashes by data pointer.
509 // If there are two identical but independent splines, they will hash
510 // unequal.
511 template <typename HashState>
512 friend void TfHashAppend(
513 HashState &h,
514 const TsSpline &spline)
515 {
516 h.Append(spline._data.get());
517 }
518
519private:
520 friend class TsRegressionPreventer;
521
522 // Direct access method used by TsRegressionPreventer.
523 void _SetKnotUnchecked(const TsKnot & knot);
524
525 template <typename SampleHolder>
526 bool _Sample(
527 const GfInterval& timeInterval,
528 double timeScale,
529 double valueScale,
530 double tolerance,
531 SampleHolder* splineSamples) const;
532
533 // External helpers provide direct data access for Ts implementation.
534 friend Ts_SplineData* Ts_GetSplineData(TsSpline &spline);
535 friend const Ts_SplineData* Ts_GetSplineData(const TsSpline &spline);
536
537 friend struct Ts_BinaryDataAccess;
538 friend struct Ts_SplineOffsetAccess;
539
540private:
541 // Get data to read from. Will be either actual data or default data.
542 TS_API
543 const Ts_SplineData* _GetData() const;
544
545 // Ensure we have our own independent data, in preparation for writing. If
546 // a value type is passed, and we don't yet have typed data, ensure we have
547 // data of the specified type.
548 void _PrepareForWrite(TfType valueType = TfType());
549
550 template <typename T>
551 bool _Eval(
552 TsTime time,
553 T *valueOut,
554 Ts_EvalAspect aspect,
555 Ts_EvalLocation location) const;
556
557 // Update all the tangents based on the tangent algorithms in the knots and
558 // follow that with a call to AdjustRegressiveTangents() to remove any
559 // remaining regressive spline segments. Return true if any changes were
560 // made.
561 TS_API
562 bool _UpdateAllTangents();
563
564 // Update the tangents of a single knot based on its tangent algorithms and
565 // the regression prevention settings.
566 TS_API
567 bool _UpdateKnotTangents(const size_t knotIndex);
568
569private:
570 // Our parameter data. Copy-on-write. Null only if we are in the default
571 // state, with no knots, and all overall parameters set to defaults. To
572 // deal with the possibility of null data, call _GetData for reading, and
573 // _PrepareForWrite before writing.
574 std::shared_ptr<Ts_SplineData> _data;
575};
576
578TS_API
579std::ostream& operator<<(std::ostream& out, const TsSpline &spline);
580
581// XXX: This should not be necessary. All it does is call std::swap. This is
582// here as a workaround for a downstream library that tries to call swap on
583// splines, with a "using namespace std" that doesn't appear to work when pxr
584// namespaces are in use.
585TS_API
586void swap(TsSpline &lhs, TsSpline &rhs);
587
588// For applying layer offsets.
589struct Ts_SplineOffsetAccess
590{
591 TS_API
592 static void ApplyOffsetAndScale(
593 TsSpline *spline,
594 const TsTime offset,
595 const double scale);
596};
597
598
600// TEMPLATE IMPLEMENTATIONS
601
602template <typename T>
603bool TsSpline::IsHolding() const
604{
605 if constexpr (!Ts_IsSupportedValueType<T>::value)
606 {
607 return false;
608 }
609
610 return GetValueType() == Ts_GetType<T>();
611}
612
613template <typename T>
614bool TsSpline::_Eval(
615 const TsTime time,
616 T* const valueOut,
617 const Ts_EvalAspect aspect,
618 const Ts_EvalLocation location) const
619{
620 const std::optional<double> result =
621 Ts_Eval(_GetData(), time, aspect, location);
622
623 if (!result)
624 {
625 return false;
626 }
627
628 *valueOut = T(*result);
629 return true;
630}
631
632// Implement a special case that will ensure the contents of the VtValue output
633// variable contain a value of the same type (double, float, or GfHalf) as the
634// spline.
635template <>
636TS_API
637bool TsSpline::_Eval(
638 const TsTime time,
639 VtValue* const valueOut,
640 const Ts_EvalAspect aspect,
641 const Ts_EvalLocation location) const;
642
643template <typename T>
644bool TsSpline::Eval(const TsTime time, T* const valueOut) const
645{
646 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalAtTime);
647}
648
649template <typename T>
650bool TsSpline::EvalPreValue(const TsTime time, T* const valueOut) const
651{
652 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalPre);
653}
654
655template <typename T>
656bool TsSpline::EvalDerivative(const TsTime time, T* const valueOut) const
657{
658 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalAtTime);
659}
660
661template <typename T>
662bool TsSpline::EvalPreDerivative(const TsTime time, T* const valueOut) const
663{
664 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalPre);
665}
666
667template <typename T>
668bool TsSpline::EvalHeld(const TsTime time, T* const valueOut) const
669{
670 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalAtTime);
671}
672
673template <typename T>
674bool TsSpline::EvalPreValueHeld(const TsTime time, T* const valueOut) const
675{
676 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalPre);
677}
678
679
680PXR_NAMESPACE_CLOSE_SCOPE
681
682#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: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:59
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 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 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:399
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:418
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].