4个版本

0.1.4 2024年1月26日
0.1.3 2024年1月24日
0.1.2 2023年12月6日
0.1.0 2023年11月10日

#234 in 算法


用于 street-engine

MPL-2.0 许可证

1MB
911

fastlem

terrain

Crates.io Documentation

fastlem [/ˈfæstlɛm/] 是一个Rust库,提供模拟景观演化过程的方法,以创建具有合理地貌的真实地形数据。

给定一个平面图,每个节点分配了地形参数,fastlem运行模拟并将高程分配给图作为输出。

fastlem网页模拟器 可用于尝试使用fastlem手动创建虚拟地形。fastlemweb2

安装

[!警告] 此项目目前正在开发中。在 0.1.* 期间,接口可能会发生很大变化。

建议详细指定版本。

[dependencies]
fastlem = "0.1.4"

关于模拟

fastlem遵循 Salève 模型[1],这是一个用于模拟二维景观演化的分析模型。创建排水网络的算法遵循Guillaume Cordonnier、Jean Braun、Marie-Paule Cani、Bedrich Benes、Eric Galin等人[2]的方法。

构建图

地形数据表示为平面图。此图结构用于计算地形生成的所有地形模拟。

对于具有二维模型的fastlem,需要 TerrainModel2DBulider 从给定的站点构建图,作为 TerrainModel2D。您可以选择使用 relaxate_sites 通过Lloyd算法将站点移动到大约相等的位置。

let model = TerrainModel2DBulider::from_random_sites(num, bound_min, bound_max) // generate sites randomly
    .relaxate_sites(1) // relaxate sites using Lloyd's algorithm
    .unwrap()
    .build() // build
    .unwrap();

创建地形生成器

在开始地形生成之前,需要 TerrainGenerator 使用平面图并将地形参数分配给每个站点。

let terrain_generator = TerrainGenerator::default()
    .set_model(model)
    .set_parameters(
        (0..num)
            .map(|_| TopographicalParameters::default().set_erodibility(1.0))
            .collect::<_>(),
    );
  • is_outlet 表示该站点是否可以是出口(包括海洋)或不是。如果 is_outlet,则高程始终设置为0.0。
  • erodibility 是站点的侵蚀性。这是确定地形形状的主要参数。

生成地形

let terrain = terrain_generator.generate().unwrap();

通过调用 TerrainGenerator::generate() 生成地形。

获取高程

通常,您可以通过调用 [Terrain]::sites()[Terrain]::elevations() 来获取网站和海拔高度作为向量。

每个向量的索引相互对应。

let sites = terrain.sites();
let elevations = terrain.elevations();
// print
for i in 0..sites.len() {
    println!(
        "Site: ({}, {}), Elevation: {}",
        sites[i].x, sites[i].y, elevations[i]
    );
}

您还可以通过调用 Terrain2D::get_elevation(Site2D) 在2D表面模型中查询特定地点的海拔高度。

let site = Site2D { x, y };
let elevation = terrain.get_elevation(&site);

请注意,此方法使用自然邻域插值(使用 naturalneighbor 包)在站点之间插值特定海拔,大约需要 O(logN) 的时间。

以下是一个使用 get_elevation 创建生成的地形图像的示例

let img_width = 500;
let img_height = 500;

let mut image_buf = image::RgbImage::new(img_width, img_height);
// calculate the max elevation
let max_elevation = terrain
    .elevations()
    .iter()
    .fold(std::f64::MIN, |acc, &n| n.max(acc));

for imgx in 0..img_width {
    for imgy in 0..img_height {
        let x = bound_max.x * (imgx as f64 / img_width as f64);
        let y = bound_max.y * (imgy as f64 / img_height as f64);
        let site = Site2D { x, y };
        let elevation = terrain.get_elevation(&site);
        if let Some(elevation) = elevation {
            let color = ((elevation / max_elevation) * 255.0) as u8;
            // put grayscale pixel
            image_buf.put_pixel(imgx as u32, imgy as u32, image::Rgb([color, color, color]));
        }
    }
}

image_buf.save("image.png").unwrap();

参考

[1] Steer, P.: 简报:二维景观演化的分析模型,Earth Surf. Dynam., 9, 1239–1250, https://doi.org/10.5194/esurf-9-1239-2021, 2021。

[2] Guillaume Cordonnier, Jean Braun, Marie-Paule Cani, Bedrich Benes, Eric Galin, 等等。从构造隆升和河流侵蚀生成大规模地形。计算机图形学论坛,2016,Proc. EUROGRAPHICS 2016,35 (2),pp.165-175. ⟨10.1111/cgf.12820⟩. ⟨hal-01262376⟩

贡献

欢迎贡献。如果您有任何问题或建议,请随意打开一个问题或拉取请求。

文档

此项目的 API参考 可用。

以下是一些示例,阅读 landscape_evolution.rs 是第一步。

许可

MPL-2.0

示例预览

简单景观演化 简单地形生成
Simple Landscape Evolution Simple Terrain Generation
$cargo run --examplelandscape_evolution --release $cargo run --exampleterrain_generation --release
高级地形生成 从给定参数生成地形
Advanced Terrain Generation Terrain Generation from Given Parameters
$cargo run --exampleterrain_generation_advanced --release $cargo run --examplesample_terrain --release

依赖

~4MB
~57K SLoC