Curve extrapolation for curves which can be extrapolated
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
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:
```rs
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_at` with an extra `t` argument 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_at` something like this: `RightCutoff::new(my_curve, t).chain(LeftCutoff(t, my_other_curve))`).
Contributor guide
Assessment
This issue has not been assessed yet.