-
-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Description
What problem does this solve or what need does it fill?
Currently, there are few ways to make a Curve trait implementor continue beyond its domain. This is especially apparent for SampleCurve/UnevenSampleCurve. For example, when using a simple lerp(a, b, t)
to interpolate, theres no reason i couldn't extrapolate by providing a t > 1.0
or t < 0.0
, and this can be very useful in some cases.
For example, this curve would translate something along a V shape:
UnevenSampleCurve::new(
vec![
(0.0, Vec2::new(1.0, 0.0)),
(0.5, Vec2::new(0.0, 1.0)),
(1.0, Vec2::new(1.0, 2.0))
],
|a, b, t| a.lerp(*b, t)
)
Its perfectly valid to extrapolate this in both directions infiniteley (making a larger/infinite V shape, in this case) but i can't find a builtin way to encode this in the Curve itself. The domain is 0.0..=1.0
and i can't find a way to change that which leads to the behaviour i'm looking for.
What solution would you like?
I would like some way which allows me to get a infinite domain curve for all curves where extrapolation can make sense. Lerp is the most obvious extrapolate-able example, but bezier curves, for example, are also fine to extrapolate.
I think ideally this should be a wrapper struct, like the various ones returned by ChainExt methods. This would allow passing it to external code which calls .sample(t)
more easily.
What alternative(s) have you considered?
Curve::sample_unchecked
explicitly documents i can't use it for this (quote: "extrapolation beyond a curves domain should not be relied upon"). If that documentation is changed, external code may need to be updated to use sample_unchecked to allow for infinite domain curves. Also, would make it harder to prevent extrapolation for curves which can't/shouldn't be extrapolated.
Additional context
A related feature to consider along with this is some way to cutoff and chain curves with infinite domains. Similar to CurveExt::chain
, i would propose CurveExt::chain_atwith an extra
targument which defines the cutoff point. This could be implemented by having a wrapper struct, similar to the one i've proposed above, which overrides their domain to end at a specific value (which would make the implementation of
chain_atsomething like this:
RightCutoff::new(my_curve, t).chain(LeftCutoff(t, my_other_curve))`).