21个版本

0.8.0 2024年7月16日
0.7.1 2023年12月14日
0.7.0 2023年8月16日
0.6.2 2023年1月4日
0.4.5 2019年7月30日

#225算法 分类中

Download history 28/week @ 2024-07-01 147/week @ 2024-07-15 22/week @ 2024-07-22 101/week @ 2024-07-29

270 每月下载量

MIT 许可证

105KB
2K SLoC

startin

crates.io docs.rs PyPI

输入为2.5D点的Delaunay三角剖分器,DT在2D中计算,但保留了顶点的高程。这主要用于地形的建模。构建2D Delaunay三角剖分也是可能的。

使用的构造算法是基于翻转的增量插入,数据结构是Blandford等人(2003年)定义的基于星状结构的廉价实现,廉价是因为每个顶点的链接存储在简单的数组(Vec)中,而不是像他们那样存储在优化的blob中。这使得库非常快速(比较将在某个时候进行),但比优化的版本使用更多的空间。

也可以删除顶点。实现的算法是Mostafavi、Gold和Dakowicz(2003年)算法的一种修改。通过翻转填充耳朵,因此在理论上更稳健。我还扩展了该算法,允许删除凸包边界的顶点。该算法次优,但在实践中,DT中给定顶点的邻居数量仅为6,所以这并不重要。

使用稳健的几何谓词算术(Shewchuk的谓词,也就是Rust代码的Rust端口(robust crate)),因此startin是稳健的,不应该崩溃(摸摸木头)。

实现了几个插值函数:(1)最近邻,(2)在TIN中的线性,(3)拉普拉斯,(4)自然邻域(又称Sibson插值),(5)具有搜索半径的IDW。

Python绑定

我还创建了名为"startinpy"的Python绑定: https://github.com/hugoledoux/startinpy/

还有一些其他功能(例如,读取GeoTIFF,LAZ可以轻松读取),文档更好,所有输入/输出都是NumPy数组。

使用WebAssembly的Web演示

Rust 可以编译成 WebAssembly,您可以查看一些启始(所有计算都在本地进行,速度快!)的演示。

--> web-demo

C 接口

基本 C 接口位于 src/c_interface.rs 中,要编译它

cargo build --features c_api

文档

您可以在 这里 阅读完整的文档

使用方法

extern crate startin;
fn main() {
    let mut pts: Vec<[f64; 3]> = Vec::new();
    pts.push([20.0, 30.0, 2.0]);
    pts.push([120.0, 33.0, 12.5]);
    pts.push([124.0, 222.0, 7.65]);
    pts.push([20.0, 133.0, 21.0]);
    pts.push([60.0, 60.0, 33.0]);
    let mut dt = startin::Triangulation::new();
    dt.insert(&pts, startin::InsertionStrategy::AsIs);
    println!("{}", dt);
    //-- print all the vertices
    for (i, each) in dt.all_vertices().iter().enumerate() {
        // skip the first one, the infinite vertex
        if i > 0 {
            println!("#{}: ({:.3}, {:.3}, {:.3})", i, each[0], each[1], each[2]);
        }
   }
   //-- insert a new vertex
   let re = dt.insert_one_pt(22.2, 33.3, 4.4);
   match re {
        Ok(_v) => println!(
            "Inserted new point, now the DT has {} vertices",
            dt.number_of_vertices()
        ),
        Err(v) => println!("Duplicate of vertex #{}, not inserted", v),
   }
   //-- remove it
   match dt.remove(6) {
        Ok(num) => println!("Vertex deleted, now the DT has {} vertices", num),
        Err(why) => println!("!!! Deletion error: {:?}", why),
   }
   //-- get the convex hull
   let ch = dt.convex_hull();
   println!("Convex hull: {:?}", ch);
   //-- fetch triangle containing (x, y)
   match dt.locate(50.0, 50.0) {
        Ok(tr) => println!("The triangle is {}", tr),
        Err(why) => println!("Error: {:?}", why),
   }
   //-- interpolate with Laplace interpolation at 2 locations
   let locs = vec![[51.0, 22.0], [50.3, 19.9]];
   let interpolant = startin::interpolation::Laplace {};
   let zs = startin::interpolation::interpolate(&interpolant, &mut dt, &locs);
   for z in &zs {
        match z {
            Ok(value) => println!("z = {}", value),
            Err(why) => println!("Interplation impossible: {:?}", why),
        }
   }
   //-- save the triangulation in OBJ for debug purposes
    let _re = dt.write_obj("/home/elvis/tr.obj".to_string());
}

依赖项

~1.8–3MB
~48K SLoC