#线性插值 #曲线 #数据点 #插值 #贝塞尔 #样条

无需 std enterpolation

一个用于创建和计算通用数据点插值、外推和平滑的库

3 个不稳定版本

0.2.1 2023年6月4日
0.2.0 2022年11月20日
0.1.1 2021年9月1日
0.1.0 2021年9月1日

#58 in 数学

Download history 475/week @ 2024-03-13 506/week @ 2024-03-20 500/week @ 2024-03-27 593/week @ 2024-04-03 525/week @ 2024-04-10 644/week @ 2024-04-17 445/week @ 2024-04-24 534/week @ 2024-05-01 426/week @ 2024-05-08 450/week @ 2024-05-15 694/week @ 2024-05-22 524/week @ 2024-05-29 536/week @ 2024-06-05 577/week @ 2024-06-12 603/week @ 2024-06-19 445/week @ 2024-06-26

2,277 每月下载量
用于 10 crates (8 直接使用)

MIT/Apache

265KB
5K SLoC

Enterpolation

Maintenance crates-io api-docs

一个用于创建和计算通用数据点插值、外推和平滑的库。

Enterpolation 是一个生成和使用不同插值和外推方法的库。这包括线性插值、贝塞尔曲线、B-样条及其加权和非均匀对应物,如 NURBS。此库旨在尽可能通用,以允许对任何向量空间的元素进行插值。此外,构建和使用不同的插值应尽可能减少摩擦,以便可以尝试不同的方法以找到最适合其需求的方法。为了实现这一点,Enterpolation 严重使用一致的构建选项来允许定制并在实验时最小化代码更改的需要。

目录

用法

将此添加到您的 Cargo.toml

[dependencies]
enterpolation = "0.2"

以下是一个创建线性插值并从开始到结束提取 21 个值的简单示例。此库支持所有可以相加并且可以与标量相乘的元素(在我们的情况下也是 f64)。代替插值浮点数,可以插值坐标、旋转、变换、速度、几何形状、声音、颜色等。

use enterpolation::{linear::{Linear, LinearError}, Curve};

fn main() -> Result<(), LinearError> {
  let lin = Linear::builder()
    .elements([0.0,5.0,-5.0,0.0])
    .knots([0.0,0.2,0.8,1.0])
    .build()?;
  // generate and print 21 values with equal distances
  // that is: 0.0, 0.05, 0.10, ..., 0.95, 1.00
  for value in lin.take(21){
    println!("{:?}",value);
  }
  Ok(())
}

另一个示例显示了如何以几种不同的方式创建维 B 样条示例,该示例显示在 维基百科的 B 样条页面 上。

use enterpolation::{bspline::{BSpline, BSplineError}, Curve};
use assert_float_eq::{afe_is_f64_near, afe_near_error_msg, assert_f64_near};

fn main() -> Result<(), BSplineError> {
  let bspline = BSpline::builder()
        .clamped()             // the curve should be clamped (variation)
        .elements([0.0,0.0,0.0,6.0,0.0,0.0,0.0])
        .equidistant::<f64>() // knots should be evenly distributed
        .degree(3)            // cubic curve
        .domain(-2.0,2.0)     // input domain
        .constant::<4>()      // we need degree+1 space to interpolate
        .build()?;
  let same_but_different = BSpline::builder()
        .elements([0.0,0.0,0.0,6.0,0.0,0.0,0.0])
        // we repeat the end and start knot 3 times, as
        // we have a degree of 3 and we want a clamped curve
        .knots([-2.0,-2.0,-2.0,-1.0,0.0,1.0,2.0,2.0,2.0])
        .constant::<4>()     // we need knots.len() - elements.len() + 2
        .build()?;
  let run_time_spline = BSpline::builder()
        .elements(vec![0.0,0.0,0.0,6.0,0.0,0.0,0.0])
        .knots(vec![-2.0,-2.0,-2.0,-1.0,0.0,1.0,2.0,2.0,2.0])
        .dynamic()
        .build()?;
  // all three construction define the same curve
  for (a,b,c) in bspline.take(10)
  .zip(same_but_different.take(10))
  .zip(run_time_spline.take(10))
  .map(|((a,b),c)| (a,b,c)) {
    assert_f64_near!(a,b);
    assert_f64_near!(b,c);
  }
  Ok(())
}

有关如何使用任何曲线的更多信息,可以查看此 crate 的主要特质: GeneratorCurve

更多示例

展示用例(例如定义平滑的颜色渐变或使用NURBS)的示例可以在示例目录中找到。

Crates 功能

该包为每种不同的插值方法提供了一个功能,这允许只包含必要的模块。所有功能默认启用。

如果只想启用特定的包功能,他们必须使用以下Cargo.toml依赖配置

[dependencies.enterpolation]
version = "0.2"
default-features = false
# re-enable all wanted features
features = ["linear"]
  • std - 启用后,运行时分配可以使用std::vec。大多数情况下,可以禁用此功能,实现自定义运行时分配所需的特性,或仅使用数组。
  • libm - 如果禁用了功能,则必须启用此功能才能使包正常工作。
  • serde - Serde的序列化和反序列化实现。
  • linear - 启用所有相关方法和线性插值的构造。
  • bezier - 启用所有相关方法和贝塞尔曲线的构造。
  • bspline - 启用所有相关方法和B-Spline的构造。

详细信息

与其他包的区别

Enterpolation旨在成为一个包,它可以推广曲线到一种程度,在您不需要更改太多代码的情况下,您将能够更改曲线的类型。它提供了一个简单的接口来从曲线中提取样本。它对易用性的关注也使其与其他包区别开来

  • 构建器模式会检查您的输入并返回一个错误,说明什么没有工作。
  • 允许各种不同的输入类型,无需进行转换。它还允许根据您的需求优化曲线。
  • 所有可能进行插值的都可以插值到曲线中。
  • 每个采样输入都会返回一个值;不会发生panic。相反,曲线将尝试外推(可能不数值稳定)。如果想要限制值,可以使用适配器。
  • 许多适配器允许进行其他曲线更改,这些更改在其他情况下是不可行的。

此包不是图形库。在图形环境中使用的良好包已经存在。此包旨在更通用,以允许实验并解决这些包不适合的边缘情况。

性能

衡量性能可能相当棘手,编译器的优化可能相当混乱(从函数本身没有变化但函数性能可能会变化的角度来看),因此这些测量应谨慎对待。它们仅用于指导决策。+/-15%的性能变化并不罕见,因此在这些区域我们认为函数速度大致相同。

我们比较了动态bsplines与crate bspline(v1.0.0)中的等效bsplines。除此之外,我们还比较了具有常数元素和节点的bsplines、具有共享元素和节点的bsplines以及具有均匀节点的bsplines(和常数元素)。测试的bspline具有100个元素和3次度。

BSplines 动态 常数 静态 均匀 crate bspline
采样200个值 23.160 us 6.6834 us 6.6521 us 9.9186 us 20.734 us
创建曲线 389.72 ns 389.23 ns 225.27 ns 131.35 ns 496.66 ns

与具有更多节点的曲线相比,均匀曲线的采样将更快。

元素的要求

如果您想要插值的元素已经实现了与自身的加法和与标量的乘法,那么您应该已经没有问题。如果不是这种情况,您可能需要考虑实现这些操作,因为大多数插值只有在元素存在于向量空间中时才能正常工作(并且这些加法和乘法对这些元素是定义良好的)。

否则,这个crate重新导出一个Merge trait,它表示一个元素可以与其他元素合并的能力。这个trait对所有插值都是必要的。此外,核心的Default trait对于贝塞尔曲线和B样条也是必要的。

可以将数组、向量或通过实现DiscreteGenerator trait的元素提供给曲线。基本上,任何具有索引操作的集合都可以实现这个trait。然而,生成器也可以实现它。这种生成器可以动态生成应插值的元素。如果可以泛型生成元素并且想插值许多元素,这可以减少内存占用。

节点的需求

节点表示输入空间中元素的位置。这样的节点通常与插值本身的输入具有相同的类型。由于所有插值(目前)都是曲线,节点通常是f32f64。元素必须可以与节点相乘,并且节点必须按从小到大的顺序排序,最小节点位于索引零。

节点也可以通过数组、向量或其他实现DiscreteGenerator trait的类型来提供。如果类型总是保证表示排序的节点,还可以实现SortedGenerator trait。

B样条的特殊性

除了B样条的Legacy模式外,这个crate中的构建方式与大多数其他库不同。通常,每个B样条定义的第一个和最后一个节点是无用的,因为它们不会影响B样条允许的域内点的生成。没有这两个节点,B样条的操作及其与其他插值曲线的相似之处将更加清晰。因此,决定省略了通常的定义。我们承认可能需要接受旧的节点格式,BSpline实现了一个可以用于以传统方式定义B样条的旧模式。

示例bspline-reasoning说明了忽略这两个端节点和代码的优点,该代码使用了旧模式。

B样变的变体

由于B样条是相当复杂的曲线,其builder允许不同的模式,以便用户可以定义他们想要的曲线。

  • open - 这可以看作是builder的默认模式。不对曲线的形状做出保证。通过正确的配置,此模式能够实现与其他模式相同的曲线。
  • clamped - 此模式将曲线固定,使其起点和终点保证是给定的第一个和最后一个元素。这是通过重复第一个和最后一个节点来实现的。
  • 遗留模式 - 此模式可以用于以与大多数其他来源相同的方式配置B样条。如果您只获取B样条的配置值而不自己创建它们,则此模式非常有用。

贡献

欢迎所有贡献,无论大小。如果您感兴趣,请查看CONTRIBUTING.md以获取指南。

许可协议

以下任一许可证下授权:

任选其一。

除非您明确表示,否则您根据Apache-2.0许可证定义的任何有意提交给作品并由您包含的贡献,将根据上述方式双重许可,而不附加任何额外条款或条件。

依赖项

~130–420KB