Rust地理空间数据处理库geo-clipper的使用,高效实现多边形裁剪与几何运算

Rust地理空间数据处理库geo-clipper的使用,高效实现多边形裁剪与几何运算

geo-clipper简介

geo-clipper是一个用于执行多边形布尔运算和偏移操作的Rust库。它使用了clipper-sys绑定,后者是C++版Clipper库的Rust绑定。

crate.io docs.rs

示例

以下示例展示了如何计算两个多边形的交集。intersection方法(以及differenceunionxor)由Clipper trait提供,该trait为某些geo-types实现了这些方法。

use geo_types::{Coord, LineString, Polygon};
use geo_clipper::Clipper;

let subject = Polygon::new(
    LineString(vec![
        Coord { x: 180.0, y: 200.0 },
        Coord { x: 260.0, y: 200.0 },
        Coord { x: 260.0, y: 150.0 },
        Coord { x: 180.0, y: 150.0 },
    ]),
    vec![LineString(vec![
        Coord { x: 215.0, y: 160.0 },
        Coord { x: 230.0, y: 190.0 },
        Coord { x: 200.0, y: 190.0 },
    ])],
);

let clip = Polygon::new(
    LineString(vec![
        Coord { x: 极客时间 190.0, y: 210.0 },
        Coord { x: 240.0, y: 210.0 },
        Coord { x: 240.0, y: 130.0 },
        Coord { x: 190.0, y: 130.0 },
    ]),
    vec![],
);

let result = subject.intersection(&clip, 1.0);

完整示例代码

下面是一个更完整的示例,展示如何使用geo-clipper进行各种几何运算:

use geo_types::{Coord, LineString, Polygon};
use geo_clipper::Clipper;

fn main() {
    // 创建主体多边形(带有一个孔洞)
    let subject = Polygon::new(
        LineString(vec![
            Coord { x: 180.0, y: 200.0 },
            Coord { x: 260.0, y: 200.0 },
            Coord { x: 260.0, y: 150.0 },
            Coord { x: 180.0, y: 150.0 },
        ]),
        vec![LineString(vec![
            Coord { x: 215.0, y: 160.0 },
            Coord { x: 230.极客时间 0, y: 190.0 },
            Coord { x: 200.0, y: 190.0 },
        ])],
    );

    // 创建裁剪多边形
    let clip = Polygon::new(
        LineString(vec![
            Coord { x: 190.0, y: 210.0 },
            Coord { x: 240.0, y: 210.0 },
            Coord { x: 240.0, y: 130.0 },
            Coord { x: 190.0, y: 130.0 },
        ]),
        vec![],
    );

    // 计算交集
    let intersection = subject.intersection(&clip, 1.0);
    println!("交集结果: {:?}", intersection);

    // 计算差集
    let difference = subject.difference(&clip, 1.0);
    println!("差集结果: {:?}", difference);

    // 计算并集
    let union = subject.union(&clip, 1.0);
    println!("并集结果: {:?}", union);

    // 计算异或
    let xor = subject.xor(&clip, 1.0);
    println!("异或结果: {:?}", xor);
}

安装

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

cargo add geo-clipper

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

geo-clipper = "0.9.0"

特性

  • 支持多边形布尔运算(交集、并集、差集、异或)
  • 支持多边形偏移操作
  • 基于成熟的Clipper库实现
  • 与geo-types库良好集成

使用场景

geo-clipper适用于地理信息系统(GIS)、计算机辅助设计(CAD)、游戏开发等领域中需要进行复杂多边形处理的场景。


1 回复

Rust地理空间数据处理库geo-clipper的使用指南

介绍

geo-clipper是一个高效的Rust库,专门用于地理空间数据的多边形裁剪和几何运算。它基于Clipper库的Rust绑定实现,提供了强大的几何操作能力,包括:

  • 多边形裁剪(交、并、差、异或)
  • 多边形偏移(膨胀/收缩)
  • 多边形简化
  • 其他几何运算

该库特别适合需要处理复杂地理空间数据、GIS应用或CAD软件开发的场景。

安装

在Cargo.toml中添加依赖:

[dependencies]
geo-clipper = "0.6"
geo-types = "0.7"  # 可选,用于与geo-types生态系统集成

基本使用方法

1. 多边形裁剪操作

use geo_clipper::Clipper;
use geo_types::{Coordinate, LineString, Polygon};

fn main() {
    // 创建两个多边形
    let subject = Polygon::new(
        LineString::from(vec![
            (0., 0.).into(),
            (0., 10.).into(),
            (10., 10.).into(),
            (10., 0.).into(),
            (0., 0.).into(),
        ]),
        vec![],
    );

    let clip = Polygon::new(
        LineString::from(vec![
            (5., -5.).into(),
            (5., 15.).into(),
            (15., 15.).into(),
            (15., -5.).into(),
            (5., -5.).into(),
        ]),
        vec![],
    );

    // 执行并集操作
    let union = subject.union(&clip);
    println!("Union result: {:?}", union);

    // 执行交集操作
    let intersection = subject.intersection(&clip);
    println!("Intersection result: {:?}", intersection);

    // 执行差集操作
    let difference = subject.difference(&clip);
    println!("Difference result: {:?}", difference);

    // 执行异或操作
    let xor = subject.xor(&clip);
    println!("XOR result: {:?}", xor);
}

2. 多边形偏移(膨胀/收缩)

use geo_clipper::Offset;
use geo_types::{Coordinate, LineString, Polygon};

fn main() {
    let polygon = Polygon::new(
        LineString::from(vec![
            (0., 0.).into(),
            (0., 10.).into(),
            (10., 10.).into(),
            (10., 0.).into(),
            (0., 0.).into(),
        ]),
        vec![],
    );

    // 膨胀多边形(正偏移)
    let expanded = polygon.offset(2.0);
    println!("Expanded polygon: {:?}", expanded);

    // 收缩多边形(负偏移)
    let contracted = polygon.offset(-1.0);
    println!("Contracted polygon: {:?}", contracted);
}

3. 处理复杂多边形(带孔洞)

use geo_clipper::Clipper;
use geo_types::{Coordinate, LineString, Polygon};

fn main() {
    // 带孔洞的多边形
    let subject = Polygon::new(
        LineString::from(vec![
            (0., 0.).into(),
            (0., 10.).into(),
            (10., 10.).into(),
            (10., 0.).into(),
            (0., 0.).into(),
        ]),
        vec![LineString::from(vec![
            (2., 2.).into(),
            (2., 8.).into(),
            (8., 8.).into(),
            (8., 2.).into(),
            (2., 2.).into(),
        ])],
    );

    let clip = Polygon::new(
        LineString::from(vec![
            (5., -5.).into(),
            (5., 15.).into(),
            (15., 15.).into(),
            (15., -5.).into(),
            (5., -5.).into(),
        ]),
        vec![],
    );

    // 执行带孔洞的裁剪操作
    let result = subject.intersection(&clip);
    println!("Result with holes: {:?}", result);
}

高级功能

1. 使用填充规则

use geo_clipper::{Clipper, FillRule};
use geo_types::{Coordinate, LineString, Polygon};

fn main() {
    let subject = // ... 创建多边形 ...
    let clip = // ... 创建多边形 ...

    // 使用非零填充规则
    let result_non_zero = subject.intersection_with_fill_rule(&clip, FillRule::NonZero);
    
    // 使用偶奇填充规则
    let result_even_odd = subject.intersection_with_fill_rule(&clip, FillRule::EvenOdd);
}

2. 处理多个多边形

use geo_clipper::Clipper;
use geo_types::{Coordinate, LineString, Polygon};

fn main() {
    let subjects = vec![
        // 多个主体多边形
    ];
    
    let clips = vec![
        // 多个裁剪多边形
    ];
    
    let results = subjects.union_all(&clips);
}

性能提示

  1. 对于大规模数据集,考虑使用try_前缀的方法(如try_union)来处理可能的错误而不panic
  2. 重复操作时,考虑重用Clipper实例以减少内存分配
  3. 对于复杂操作,可以先简化多边形以提高性能

注意事项

  • 输入多边形必须有效(无自相交,正确的环方向等)
  • 经度/纬度坐标可能需要投影到平面坐标系以获得最佳结果
  • 某些操作可能产生多个多边形结果(MultiPolygon)

geo-clipper为Rust中的地理空间数据处理提供了强大而高效的工具,特别适合需要精确几何运算的应用场景。

完整示例demo

以下是一个结合多个功能的完整示例,展示如何使用geo-clipper进行复杂的地理空间数据处理:

use geo_clipper::{Clipper, FillRule, Offset};
use geo_types::{Coordinate, LineString, Polygon};

fn main() {
    // 创建主体多边形(带孔洞)
    let subject = Polygon::new(
        LineString::from(vec![
            (0., 0.).into(),
            (0., 10.).into(),
            (10., 10.).into(),
            (10., 0.).into(),
            (0., 0.).into(),
        ]),
        vec![LineString::from(vec![
            (2., 2.).into(),
            (2., 8.).into(),
            (8., 8.).into(),
            (8., 2.).into(),
            (2., 2.).into(),
        ])],
    );

    // 创建裁剪多边形
    let clip = Polygon::new(
        LineString::from(vec![
            (5., -5.).into(),
            (5., 15.).into(),
            (15., 15.).into(),
            (15., -5.).into(),
            (5., -5.).into(),
        ]),
        vec![],
    );

    // 1. 使用不同填充规则进行裁剪
    println!("=== 使用不同填充规则进行裁剪 ===");
    
    // 非零填充规则
    let result_non_zero = subject.intersection_with_fill_rule(&clip, FillRule::NonZero);
    println!("非零填充规则结果: {:?}", result_non_zero);
    
    // 偶奇填充规则
    let result_even_odd = subject.intersection_with_fill_rule(&clip, FillRule::EvenOdd);
    println!("偶奇填充规则结果: {:?}", result_even_odd);

    // 2. 多边形偏移操作
    println!("\n=== 多边形偏移操作 ===");
    
    // 膨胀多边形
    let expanded = subject.offset(1.5);
    println!("膨胀1.5单位后的多边形: {:?}", expanded);
    
    // 收缩多边形
    let contracted = subject.offset(-0.5);
    println!("收缩0.5单位后的多边形: {:?}", contracted);

    // 3. 处理多个多边形
    println!("\n=== 处理多个多边形 ===");
    
    let subjects = vec![
        Polygon::new(
            LineString::from(vec![
                (0., 0.).into(),
                (0., 5.).into(),
                (5., 5.).into(),
                (5., 0.).into(),
                (0., 0.).into(),
            ]),
            vec![],
        ),
        Polygon::new(
            LineString::from(vec![
                (3., 3.).into(),
                (3., 8.).into(),
                (8., 8.).into(),
                (8., 3.).into(),
                (3., 3.).into(),
            ]),
            vec![],
        ),
    ];
    
    let clips = vec![
        Polygon::new(
            LineString::from(vec![
                (2., 2.).into(),
                (2., 7.).into(),
                (7., 7.).into(),
                (7., 2.).into(),
                (2., 2.).into(),
            ]),
            vec![],
        ),
    ];
    
    let union_results = subjects.union_all(&clips);
    println!("多个多边形并集结果: {:?}", union_results);

    // 4. 使用try_方法处理可能错误
    println!("\n=== 使用try_方法处理错误 ===");
    
    let invalid_polygon = Polygon::new(
        LineString::from(vec![
            (0., 0.).into(),
            (0., 10.).into(),
            (10., 10.).into(),
            (0., 0.).into(),  // 无效多边形,缺少闭合点
        ]),
        vec![],
    );
    
    match invalid_polygon.try_union(&clip) {
        Ok(result) => println!("成功执行并集: {:?}", result),
        Err(e) => println!("执行并集时出错: {}", e),
    }
}

这个完整示例展示了geo-clipper库的主要功能:

  1. 使用不同填充规则进行多边形裁剪
  2. 执行多边形偏移(膨胀和收缩)操作
  3. 处理多个多边形的集合运算
  4. 使用try_前缀方法安全地处理可能出现的错误

输出将显示各种几何操作的结果,帮助理解不同操作对多边形的影响。

回到顶部