All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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
192 TS_API
194 TsTime time,
195 TsKnot *knotOut) const;
196
200
201 TS_API
202 void ClearKnots();
203
206 TS_API
208 TsTime time,
209 GfInterval *affectedIntervalOut = nullptr);
210
212 TS_API
214 VtValue defaultValue = VtValue(),
215 const GfInterval &interval = GfInterval::GetFullInterval());
216
220
222 TS_API
224 const GfInterval &interval);
225
227 //
228 // Result cached
229 TS_API
231
233 //
234 // Bakes inner loops (finite) and extrapolating loops (infinite)
235 // Result cached, but only for last specified interval
236 TS_API
238 const GfInterval &interval) const;
239
243
248 TS_API
249 bool Split(
250 TsTime time,
251 GfInterval *affectedIntervalOut = nullptr);
252
262
267 TS_API
268 static TsAntiRegressionMode GetAntiRegressionAuthoringMode();
269
273 TS_API
275
279 TS_API
281
288
289 template <typename T>
290 bool Eval(
291 TsTime time,
292 T *valueOut) const;
293
294 template <typename T>
295 bool EvalPreValue(
296 TsTime time,
297 T *valueOut) const;
298
299 template <typename T>
300 bool EvalDerivative(
301 TsTime time,
302 T *valueOut) const;
303
304 template <typename T>
305 bool EvalPreDerivative(
306 TsTime time,
307 T *valueOut) const;
308
309 template <typename T>
310 bool EvalHeld(
311 TsTime time,
312 T *valueOut) const;
313
314 template <typename T>
315 bool EvalPreValueHeld(
316 TsTime time,
317 T *valueOut) const;
318
319 TS_API
320 bool DoSidesDiffer(
321 TsTime time) const;
322
339 template <typename Vertex>
340 bool
342 const GfInterval& timeInterval,
343 double timeScale,
344 double valueScale,
345 double tolerance,
346 TsSplineSamples<Vertex>* splineSamples) const
347 {
348 return _Sample(timeInterval, timeScale, valueScale, tolerance,
349 splineSamples);
350 }
351
358 template <typename Vertex>
359 bool
361 const GfInterval& timeInterval,
362 double timeScale,
363 double valueScale,
364 double tolerance,
365 TsSplineSamplesWithSources<Vertex>* splineSamples) const
366 {
367 return _Sample(timeInterval, timeScale, valueScale, tolerance,
368 splineSamples);
369 }
370
374
375 TS_API
376 bool IsEmpty() const;
377
378 TS_API
379 bool HasValueBlocks() const;
380
382 TS_API
383 bool IsVarying() const;
384
386 TS_API
387 bool HasLoops() const;
388
389 TS_API
390 bool HasInnerLoops() const;
391
392 TS_API
393 bool HasExtrapolatingLoops() const;
394
396 TS_API
397 bool IsLinear() const;
398
400 TS_API
401 bool IsC0Continuous() const;
402
404 TS_API
405 bool IsG1Continuous() const;
406
408 TS_API
409 bool IsC1Continuous() const;
410
412 TS_API
414 const GfInterval &timeSpan,
415 std::pair<VtValue, VtValue> *rangeOut) const;
416
418 template <typename T>
420 const GfInterval &timeSpan,
421 std::pair<T, T> *rangeOut) const;
422
426
427 TS_API
428 bool HasValueBlockAtTime(
429 TsTime time) const;
430
432 TS_API
434 TsTime startTime) const;
435
437 TS_API
439 TsTime startTime) const;
440
442 TS_API
444 TsTime time,
445 VtValue defaultValue = VtValue()) const;
446
448
449public:
450 // Hash function. For now this is cheap, and only hashes by data pointer.
451 // If there are two identical but independent splines, they will hash
452 // unequal.
453 template <typename HashState>
454 friend void TfHashAppend(
455 HashState &h,
456 const TsSpline &spline)
457 {
458 h.Append(spline._data.get());
459 }
460
461private:
462 friend class TsRegressionPreventer;
463 void _SetKnotUnchecked(const TsKnot & knot);
464
465 template <typename SampleHolder>
466 bool _Sample(
467 const GfInterval& timeInterval,
468 double timeScale,
469 double valueScale,
470 double tolerance,
471 SampleHolder* splineSamples) const;
472
473 // External helpers provide direct data access for Ts implementation.
474 friend Ts_SplineData* Ts_GetSplineData(TsSpline &spline);
475 friend const Ts_SplineData* Ts_GetSplineData(const TsSpline &spline);
476
477 friend struct Ts_BinaryDataAccess;
478 friend struct Ts_SplineOffsetAccess;
479
480private:
481 // Get data to read from. Will be either actual data or default data.
482 TS_API
483 const Ts_SplineData* _GetData() const;
484
485 // Ensure we have our own independent data, in preparation for writing. If
486 // a value type is passed, and we don't yet have typed data, ensure we have
487 // data of the specified type.
488 void _PrepareForWrite(TfType valueType = TfType());
489
490 template <typename T>
491 bool _Eval(
492 TsTime time,
493 T *valueOut,
494 Ts_EvalAspect aspect,
495 Ts_EvalLocation location) const;
496
497private:
498 // Our parameter data. Copy-on-write. Null only if we are in the default
499 // state, with no knots, and all overall parameters set to defaults. To
500 // deal with the possibility of null data, call _GetData for reading, and
501 // _PrepareForWrite before writing.
502 std::shared_ptr<Ts_SplineData> _data;
503};
504
506TS_API
507std::ostream& operator<<(std::ostream& out, const TsSpline &spline);
508
509// XXX: This should not be necessary. All it does is call std::swap. This is
510// here as a workaround for a downstream library that tries to call swap on
511// splines, with a "using namespace std" that doesn't appear to work when pxr
512// namespaces are in use.
513TS_API
514void swap(TsSpline &lhs, TsSpline &rhs);
515
516// For applying layer offsets.
517struct Ts_SplineOffsetAccess
518{
519 TS_API
520 static void ApplyOffsetAndScale(
521 TsSpline *spline,
522 const TsTime offset,
523 const double scale);
524};
525
526
528// TEMPLATE IMPLEMENTATIONS
529
530template <typename T>
531bool TsSpline::IsHolding() const
532{
533 if constexpr (!Ts_IsSupportedValueType<T>::value)
534 {
535 return false;
536 }
537
538 return GetValueType() == Ts_GetType<T>();
539}
540
541template <typename T>
542bool TsSpline::_Eval(
543 const TsTime time,
544 T* const valueOut,
545 const Ts_EvalAspect aspect,
546 const Ts_EvalLocation location) const
547{
548 const std::optional<double> result =
549 Ts_Eval(_GetData(), time, aspect, location);
550
551 if (!result)
552 {
553 return false;
554 }
555
556 *valueOut = T(*result);
557 return true;
558}
559
560// Implement a special case that will ensure the contents of the VtValue output
561// variable contain a value of the same type (double, float, or GfHalf) as the
562// spline.
563template <>
564TS_API
565bool TsSpline::_Eval(
566 const TsTime time,
567 VtValue* const valueOut,
568 const Ts_EvalAspect aspect,
569 const Ts_EvalLocation location) const;
570
571template <typename T>
572bool TsSpline::Eval(const TsTime time, T* const valueOut) const
573{
574 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalAtTime);
575}
576
577template <typename T>
578bool TsSpline::EvalPreValue(const TsTime time, T* const valueOut) const
579{
580 return _Eval(time, valueOut, Ts_EvalValue, Ts_EvalPre);
581}
582
583template <typename T>
584bool TsSpline::EvalDerivative(const TsTime time, T* const valueOut) const
585{
586 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalAtTime);
587}
588
589template <typename T>
590bool TsSpline::EvalPreDerivative(const TsTime time, T* const valueOut) const
591{
592 return _Eval(time, valueOut, Ts_EvalDerivative, Ts_EvalPre);
593}
594
595template <typename T>
596bool TsSpline::EvalHeld(const TsTime time, T* const valueOut) const
597{
598 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalAtTime);
599}
600
601template <typename T>
602bool TsSpline::EvalPreValueHeld(const TsTime time, T* const valueOut) const
603{
604 return _Eval(time, valueOut, Ts_EvalHeldValue, Ts_EvalPre);
605}
606
607
608PXR_NAMESPACE_CLOSE_SCOPE
609
610#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:190
A knot belonging to a TsSpline.
Definition: knot.h:40
The knots in a spline.
Definition: knotMap.h:37
Inner-loop parameters.
Definition: types.h:163
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 const TsKnotMap & GetKnotsWithInnerLoopsBaked() const
Not yet implemented.
TS_API bool IsG1Continuous() const
Not yet implemented.
TS_API TsKnotMap GetKnots() const
Returns the spline's knots.
TS_API bool Split(TsTime time, GfInterval *affectedIntervalOut=nullptr)
Not yet implemented.
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.
bool GetValueRange(const GfInterval &timeSpan, std::pair< T, T > *rangeOut) const
Not yet implemented.
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:341
TS_API bool IsSegmentMonotonic(TsTime startTime) const
Not yet implemented.
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:360
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 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.
TS_API const TsKnotMap & GetKnotsWithLoopsBaked(const GfInterval &interval) const
Not yet implemented.
static TS_API TsAntiRegressionMode GetAntiRegressionAuthoringMode()
Returns the current effective anti-regression authoring mode.
TS_API bool BakeLoops(const GfInterval &interval)
Not yet implemented.
TS_API bool IsC0Continuous() const
Not yet implemented.
TsSplineSamples<Vertex> holds a collection of piecewise linear polylines that approximate a TsSpline.
Definition: types.h:222
TsSplineSamplesWithSources<Vertex> is a TsSplineSamples<Vertex> that also includes source information...
Definition: types.h:245
A map with string keys and VtValue values.
Definition: dictionary.h:43
Provides a container which may hold any type, and provides introspection and iteration over array typ...
Definition: value.h:147
GF_API std::ostream & operator<<(std::ostream &, const GfBBox3d &)
Output a GfBBox3d using the format [(range) matrix zeroArea].