Rust曲线插值与样条库splines的使用,splines提供高效灵活的贝塞尔曲线、B样条和NURBS曲线操作

Rust曲线插值与样条库splines的使用

splines是一个提供数学曲线操作的Rust库,它通过控制点(也称为节点)分段定义各种样条曲线。

安装

在您的项目目录中运行以下Cargo命令:

cargo add splines

或者在您的Cargo.toml中添加以下行:

splines = "5.0.0"

基本使用示例

下面是一个使用splines库创建和操作线性样条的完整示例:

use splines::{Interpolation, Key, Spline};

fn main() {
    // 创建一些关键点(控制点)
    let keys = vec![
        Key::new(0.0, 0.0, Interpolation::Linear),
        Key::new(1.0, 1.0, Interpolation::Linear),
        Key::new(2.0, 0.0, Interpolation::Linear),
    ];

    // 创建一个线性样条
    let spline = Spline::from_vec(keys);

    // 在样条上采样点
    for i in 0..10 {
        let t = i as f32 * 0.2;
        if let Some(value) = spline.sample(t) {
            println!("At t={}, value={}", t, value);
        }
    }
}

贝塞尔曲线示例

use splines::{Interpolation, Key, Spline};

fn main() {
    // 创建贝塞尔曲线的控制点
    let keys = vec![
        Key::new(0.0, 0.0, Interpolation::Bezier(0.0, 0.5)),  // 起点
        Key::new(1.0, 1.0, Interpolation::Bezier(0.5, 0.0)),  // 终点
    ];

    let bezier_spline = Spline::from_vec(keys);

    // 在曲线上采样点
    for i in 0..10 {
        let t = i as f32 * 0.1;
        if let Some(value) = bezier_spline.sample(t) {
            println!("Bezier at t={}: {}", t, value);
        }
    }
}

B样条示例

use splines::{Interpolation, Key, Spline};

fn main() {
    // 创建B样条的控制点
    let keys = vec![
        Key::new(0.0, 0.0, Interpolation::BSpline(3)),  // 3阶B样条
        Key::new(1.0, 2.0, Interpolation::BSpline(3)),
        Key::new(2.0, 1.0, Interpolation::BSpline(3)),
        Key::new(3.0, 3.0, Interpolation::BSpline(3)),
    ];

    let bspline = Spline::from_vec(keys);

    // 在B样条上采样点
    for i in 0..20 {
        let t = i as f32 * 0.15;
        if let Some(value) = bspline.sample(t) {
            println!("B-Spline at t={}: {}", t, value);
        }
    }
}

NURBS曲线示例

use splines::{Interpolation, Key, Spline};

fn main() {
    // 创建NURBS曲线的控制点(带权重)
    let keys = vec![
        Key::new(0.0, 0.0, Interpolation::NURBS(1.0)),  // 权重为1.0
        Key::new(1.0, 3.0, Interpolation::NURBS(0.5)),  // 权重为0.5
        Key::new(2.0, 1.0, Interpolation::NURBS(2.0)),  // 权重为2.0
        Key::new(3.0, 2.0, Interpolation::NURBS(1.0)),
    ];

    let nurbs_spline = Spline::from_vec(keys);

    // 在NURBS曲线上采样点
    for i in 0..20 {
        let t = i as f32 * 0.15;
        if let Some(value) = nurbs_spline.sample(t) {
            println!("NURBS at t={}: {}", t, value);
        }
    }
}

更多信息

该库提供了多种插值方法,包括线性、贝塞尔、B样条和NURBS等。您可以通过调整控制点和插值参数来创建各种复杂的曲线。


1 回复

Rust曲线插值与样条库splines使用指南

splines是一个功能强大的Rust库,用于处理各种类型的曲线插值和样条操作,包括贝塞尔曲线、B样条和NURBS曲线。它提供了高效且灵活的API,适合图形编程、动画路径、CAD系统等应用场景。

安装

在Cargo.toml中添加依赖:

[dependencies]
splines = "0.5"

基本概念

splines库支持多种曲线类型:

  • 线性插值
  • 贝塞尔曲线
  • 均匀B样条
  • 非均匀B样条(NURBS)

基本使用方法

1. 创建简单样条

use splines::{Interpolation, Key, Spline};

let spline = Spline::from_vec(vec![
    Key::new(0., 0., Interpolation::Linear),
    Key::new(1., 1., Interpolation::Linear),
    Key::new(2., 0., Interpolation::Linear),
]);

// 在t=0.5处采样
let value = spline.sample(0.5);
println!("Value at t=0.5: {:?}", value);

2. 使用不同的插值方法

use splines::{Interpolation, Key, Spline};

let spline = Spline::from_vec(vec![
    Key::new(0., 0., Interpolation::Linear),
    Key::new(1., 2., Interpolation::Cosine),
    Key::new(2., 0., Interpolation::CatmullRom),
]);

for t in 0..=20 {
    let t = t as f32 * 0.1;
    println!("t={:.1}, value={:.3}", t, spline.sample(t).unwrap());
}

贝塞尔曲线

use splines::{Interpolation, Key, Spline};

// 创建二次贝塞尔曲线
let bezier = Spline::from_vec(vec![
    Key::new(0.0, (0.0, 极坐标系中的点(0.0, 0.0)), Interpolation::Bezier(1.0)),
    Key::new(1.0, (1.0, 1.0), Interpolation::Bezier(1.0)),
    Key::new(2.0, (2.0, 0.0), Interpolation::Bezier(1.0)),
]);

// 采样贝塞尔曲线
for i in 0..=10 {
    let t = i as f32 * 0.2;
    if let Some((x, y)) = bezier.sample(t) {
        println!("Point at t={:.1}: ({:.2}, {:.2})", t, x, y);
    }
}

B样条曲线

use splines::{Interpolation, Key, Spline};

// 创建B样条曲线
let bspline = Spline::from_vec(vec![
    Key::new(0.0, (0.0, 0.0), Interpolation::BSpline(3)),
    Key::new极坐标系中的点(1.0, (1.0, 1.0), Interpolation::BSpline(3)),
    Key::new(2.0, (2.0, 0.0), Interpolation::BSpline(3)),
    Key::new(3.0, (3.0, 1.0), Interpolation::BSpline(3)),
]);

// 采样B样条曲线
for i in 0..=30 {
    let t = i as f32 * 0.1;
    if let Some((x, y)) = bspline.sample(t) {
        println!("Point at t={:.1}: ({:.2}, {:.2})", t, x, y);
    }
}

NURBS曲线

use splines::{Interpolation, Key, Spline};

// 创建NURBS曲线
let nurbs = Spline::from_vec(vec![
    Key::new(0.0, (0.0, 0.0), Interpolation::NURBS(3, 0.5)),
    Key::new(1.0, (1.0, 1.0), Interpolation::NURBS(3, 1.0)),
    Key::new(2.0, (2.0, 0.0), Interpolation::NURBS(3, 0.8)),
    Key::new(3.0, (3.0, 1.0), Interpolation::NURBS极坐标系中的点(3, 1.2)),
]);

// 采样NURBS曲线
for i in 0..=30 {
    let t = i as f32 * 0.1;
    if let Some((x, y)) = nurbs.sample(t) {
        println!("Point at t={:.1}: ({:.2}, {:.2})", t, x, y);
    }
}

高级功能

1. 自定义插值器

use splines::{Interpolation, Key, Spline};

fn custom_interpolator(t: f32) -> f32 {
    t * t * (3.0 - 2.0 * t)  // 平滑阶梯函数
}

let spline = Spline::from_vec(vec![
    Key::new(0., 0., Interpolation::Function(custom_interpolator)),
    Key::new(1., 10., Interpolation::Function(custom_interpolator)),
]);

println!("Custom interpolation at t=0.7: {:?}", spline.sample(0.7));

2. 多维数据插值

use splines::{Interpolation, Key, Spline};

// 3D位置插值
let spline = Spline::from_vec(vec![
    Key::new(0.0, (0.0, 0.0, 0.0), Interpolation::CatmullRom),
    Key::new(1.0, (1.0, 2.0, 0.5), Interpolation::CatmullRom),
    Key::new(2.0, (2.0, 0.0, 1.0), Interpolation::CatmullRom),
]);

if let Some((x, y, z)) = spline.sample(1.5) {
    println!("3D position at t=1.5: ({:.2}, {:.2}, {:.2})", x, y, z);
}

性能提示

  1. 对于大量采样,考虑使用sample_iter方法创建迭代器
  2. 对于静态样条,可以使用Spline::from_vec的常量版本
  3. 复杂的NURBS曲线可能需要预处理以提高采样性能

splines库提供了丰富的功能来处理各种曲线插值和样条操作,是Rust生态中处理这类问题的优秀选择。

完整示例代码

// 完整示例:创建并可视化多种曲线类型
use splines::{Interpolation, Key, Spline};

fn main() {
    // 1. 创建线性插值样条
    let linear_spline = Spline::from_vec(vec![
        Key::new(0.0, 0.0, Interpolation::Linear),
        Key::new(1.0, 2.0, Interpolation::Linear),
        Key::new(2.0, 1.0, Interpolation::Linear),
    ]);

    // 2. 创建贝塞尔曲线
    let bezier_spline = Spline::from_vec(vec![
        Key::new(0.0, (0.0, 0.0), Interpolation::Bezier(1.0)),
        Key::new(1.0, (1.0, 2.0), Interpolation::Bezier(1.0)),
        Key::new(2.0, (2.0, 0.0), Interpolation::Bezier(1.0)),
    ]);

    // 3. 创建B样条曲线
    let bspline = Spline::from_vec(vec![
        Key::new(0.0, (0.0, 0.0), Interpolation::BSpline(3)),
        Key::new(1.0, (1.0, 1.5), Interpolation::BSpline(3)),
        Key::new(2.0, (2.0, 0.5), Interpolation::BSpline(3)),
        Key::new(3.0, (3.0, 1.0), Interpolation::BSpline(3)),
    ]);

    // 4. 创建NURBS曲线
    let nurbs = Spline::from_vec(vec![
        Key::new(0.0, (0.0, 0.0), Interpolation::NURBS(3, 0.5)),
        Key::new(1.0, (1.0, 1.0), Interpolation::NURBS(3, 1.0)),
        Key::new(2.0, (2.0, 0.5), Interpolation::NURBS(3, 0.8)),
        Key::new(3.0, (3.0, 1.5), Interpolation::NURBS(3, 1.2)),
    ]);

    // 采样并打印所有曲线
    println!("Linear Spline:");
    for i in 0..=20 {
        let t = i as f32 * 0.1;
        println!("  t={:.1}: {}", t, linear_spline.sample(t).unwrap());
    }

    println!("\nBezier Curve:");
    for i in 0..=10 {
        let t = i as f32 * 0.2;
        if let Some((x, y)) = bezier_spline.sample(t) {
            println!("  t={:.1}: ({:.2}, {:.2})", t, x, y);
        }
    }

    println!("\nB-Spline:");
    for i in 0..=30 {
        let t = i as f32 * 0.1;
        if let Some((x, y)) = bspline.sample(t) {
            println!("  t={:.1}: ({:.2}, {:.2})", t, x, y);
        }
    }

    println!("\nNURBS:");
    for i in 0..=30 {
        let t = i as f32 * 0.1;
        if let Some((x, y)) = nurbs.sample(t) {
            println!("  t={:.1}: ({:.2}, {:.2})", t, x, y);
        }
    }
}
回到顶部