Rust 2D几何图形处理库clipper-sys的使用,clipper-sys提供高效的布尔运算、偏移和裁剪功能

clipper-sys

C++版Clipper的Rust不安全包装。

这个库不推荐直接使用,应该使用geo-clipper替代。

编译时使用cargo特性generate-bindings可以在构建时生成绑定。

安装

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

cargo add clipper-sys

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

clipper-sys = "0.8.0"

使用示例

以下是一个使用clipper-sys进行2D几何图形布尔运算的完整示例:

use clipper_sys::{Clipper, Path, Paths};

fn main() {
    unsafe {
        // 创建两个矩形路径
        let mut path1 = Path::new();
        path1.push(0.0, 0.0);
        path1.push(100.0, 0.0);
        path1.push(100.0, 100.0);
        path1.push(0.0, 100.0);

        let mut path2 = Path::new();
        path2.push(50.0, 50.0);
        path2.push(150.0, 50.0);
        path2.push(150.0, 150.0);
        path2.push(50.0, 150.0);

        // 创建路径集合
        let mut subject = Paths::new();
        subject.push(path1);
        
        let mut clip = Paths::new();
        clip.push(path2);

        // 创建Clipper对象
        let clipper = Clipper::new();
        
        // 添加路径
        clipper.add_paths(&subject, clipper_sys::PolyType::Subject);
        clipper.add_paths(&clip, clipper_sys::PolyType::Clip);

        // 执行布尔运算(交集)
        let solution = clipper.execute(
            clipper_sys::ClipType::Intersection,
            clipper_sys::PolyFillType::EvenOdd,
            clipper_sys::PolyFillType::EvenOdd
        );

        // 输出结果
        if let Some(sol) = solution {
            for path in sol {
                println!("Path:");
                for point in path {
                    println!("  ({}, {})", point.x, point.y);
                }
            }
        }
    }
}

完整示例代码

use clipper_sys::{Clipper, Path, Paths, ClipType, PolyFillType, PolyType};

fn main() {
    unsafe {
        // 创建两个多边形路径
        // 第一个多边形:三角形
        let mut triangle = Path::new();
        triangle.push(50.0, 0.0);
        triangle.push(100.0, 100.0);
        triangle.push(0.0, 100.0);
        
        // 第二个多边形:正方形
        let mut square = Path::new();
        square.push(25.0, 25.0);
        square.push(125.0, 25.0);
        square.push(125.0, 125.0);
        square.push(25.0, 125.0);

        // 创建路径集合
        let mut subject = Paths::new();
        subject.push(triangle);
        
        let mut clip = Paths::new();
        clip.push(square);

        // 初始化Clipper对象
        let clipper = Clipper::new();
        
        // 添加路径到Clipper
        clipper.add_paths(&subject, PolyType::Subject);
        clipper.add_paths(&clip, PolyType::Clip);

        // 执行布尔运算(并集)
        let union_result = clipper.execute(
            ClipType::Union,
            PolyFillType::EvenOdd,
            PolyFillType::EvenOdd
        );

        println!("Union result:");
        if let Some(solution) = union_result {
            for (i, path) in solution.iter().enumerate() {
                println!("Path {}:", i);
                for point in path {
                    println!("  ({}, {})", point.x, point.y);
                }
            }
        }

        // 执行布尔运算(差集)
        let difference_result = clipper.execute(
            ClipType::Difference,
            PolyFillType::EvenOdd,
            PolyFillType::EvenOdd
        );

        println!("\nDifference result:");
        if let Some(solution) = difference_result {
            for (i, path) in solution.iter().enumerate() {
                println!("Path {}:", i);
                for point in path {
                    println!("  ({}, {})", point.x, point.y);
                }
            }
        }
    }
}

功能

clipper-sys提供以下主要功能:

  • 高效的布尔运算(并集、交集、差集、异或)
  • 多边形偏移(膨胀/收缩)
  • 多边形裁剪

文档

更多详细使用方法请参考官方文档。


1 回复

Rust 2D几何图形处理库clipper-sys使用指南

完整示例代码

以下是一个整合了多边形布尔运算、偏移和裁剪操作的完整示例:

use clipper_sys::{
    Clipper, ClipperOffset, Path, Paths, 
    ClipType, PolyType, PolyFillType, 
    JoinType, EndType
};

fn main() {
    // 示例1: 布尔运算 - 计算两个多边形的并集
    boolean_operations();
    
    // 示例2: 偏移操作 - 对多边形进行外扩和内缩
    offset_operations();
    
    // 示例3: 裁剪操作 - 使用一个多边形裁剪另一个多边形
    clipping_operations();
    
    // 示例4: 处理带孔的多边形
    polygons_with_holes();
}

fn boolean_operations() {
    println!("\n=== 布尔运算示例 ===");
    
    // 创建两个正方形多边形
    let mut subject = Path::new();
    subject.add_point(100.0, 100.0);
    subject.add_point(100.0, 200.0);
    subject.add_point(200.0, 200.0);
    subject.add_point(200.0, 100.0);
    
    let mut clip = Path::new();
    clip.add_point(150.0, 150.0);
    clip.add_point(150.0, 250.0);
    clip.add_point(250.0, 250.0);
    clip.add_point(250.0, 150.0);
    
    // 执行四种布尔运算
    let union = Clipper::new()
        .add_path(&subject, PolyType::Subject, true)
        .add_path(&clip, PolyType::Clip, true)
        .execute(ClipType::Union, PolyFillType::EvenOdd, PolyFillType::EvenOdd)
        .expect("并集运算失败");
    
    let intersection = Clipper::new()
        .add_path(&subject, PolyType::Subject, true)
        .add_path(&clip, PolyType::Clip, true)
        .execute(ClipType::Intersection, PolyFillType::EvenOdd, PolyFillType::EvenOdd)
        .expect("交集运算失败");
    
    let difference = Clipper::new()
        .add_path(&subject, PolyType::Subject, true)
        .add_path(&clip, PolyType::Clip, true)
        .execute(ClipType::Difference, PolyFillType::EvenOdd, PolyFillType::EvenOdd)
        .expect("差集运算失败");
    
    let xor = Clipper::new()
        .add_path(&subject, PolyType::Subject, true)
        .add_path(&clip, PolyType::Clip, true)
        .execute(ClipType::Xor, PolyFillType::EvenOdd, PolyFillType::EvenOdd)
        .expect("异或运算失败");
    
    println!("并集结果多边形数量: {}", union.len());
    println!("交集结果多边形数量: {}", intersection.len());
    println!("差集结果多边形数量: {}", difference.len());
    println!("异或结果多边形数量: {}", xor.len());
}

fn offset_operations() {
    println!("\n=== 偏移操作示例 ===");
    
    // 创建一个正方形路径
    let mut path = Path::new();
    path.add_point(100.0, 100.0);
    path.add_point(200.0, 100.0);
    path.add_point(200.0, 200.0);
    path.add_point(100.0, 200.0);
    
    // 外扩偏移(正偏移量)
    let mut offset = ClipperOffset::new(2.0, 0.25);
    offset.add_path(&path, JoinType::Round, EndType::ClosedPolygon);
    let expanded: Paths = offset.execute(10.0).expect("外扩偏移失败");
    println!("外扩偏移结果多边形数量: {}", expanded.len());
    
    // 内缩偏移(负偏移量)
    let mut offset = ClipperOffset::new(2.0, 0.25);
    offset.add_path(&path, JoinType::Round, EndType::ClosedPolygon);
    let contracted: Paths = offset.execute(-5.0).expect("内缩偏移失败");
    println!("内缩偏移结果多边形数量: {}", contracted.len());
}

fn clipping_operations() {
    println!("\n=== 裁剪操作示例 ===");
    
    // 创建被裁剪的多边形(一个大正方形)
    let mut subject = Path::new();
    subject.add_point(50.0, 50.0);
    subject.add_point(50.0, 250.0);
    subject.add_point(250.0, 250.0);
    subject.add_point(250.0, 50.0);
    
    // 创建裁剪多边形(一个小正方形)
    let mut clip = Path::new();
    clip.add_point(100.0, 100.0);
    clip.add_point(100.0, 200.0);
    clip.add_point(200.0, 200.0);
    clip.add_point(200.0, 100.0);
    
    // 执行裁剪操作(保留在裁剪多边形外的部分)
    let result = Clipper::new()
        .add_path(&subject, PolyType::Subject, true)
        .add_path(&clip, PolyType::Clip, true)
        .execute(ClipType::Difference, PolyFillType::EvenOdd, PolyFillType::EvenOdd)
        .expect("裁剪操作失败");
    
    println!("裁剪结果多边形数量: {}", result.len());
}

fn polygons_with_holes() {
    println!("\n=== 带孔多边形示例 ===");
    
    // 外轮廓(大正方形)
    let mut outer = Path::new();
    outer.add_point(50.0, 50.0);
    outer.add_point(50.0, 250.0);
    outer.add_point(250.0, 250.0);
    outer.add_point(250.0, 50.0);
    
    // 内轮廓1(孔,小正方形)
    let mut hole1 = Path::new();
    hole1.add_point(100.0, 100.0);
    hole1.add_point(100.0, 200.0);
    hole1.add_point(200.0, 200.0);
    hole1.add_point(200.0, 100.0);
    hole1.reverse(); // 反转方向
    
    // 内轮廓2(孔,三角形)
    let mut hole2 = Path::new();
    hole2.add_point(150.0, 150.0);
    hole2.add_point(175.0, 175.0);
    hole2.add_point(125.0, 175.0);
    hole2.reverse(); // 反转方向
    
    // 创建带孔的多边形组
    let mut subject = Paths::new();
    subject.push(outer);
    subject.push(hole1);
    subject.push(hole2);
    
    // 创建裁剪矩形
    let mut clip = Path::new();
    clip.add_point(0.0, 0.0);
    clip.add_point(0.0, 300.0);
    clip.add_point(300.0, 300.0);
    clip.add_point(300.0, 0.0);
    
    // 执行带孔多边形的裁剪操作
    let result = Clipper::new()
        .add_paths(&subject, PolyType::Subject, true)
        .add_path(&clip, PolyType::Clip, true)
        .execute(ClipType::Intersection, PolyFillType::EvenOdd, PolyFillType::EvenOdd)
        .expect("带孔多边形操作失败");
    
    println!("带孔多边形裁剪结果数量: {}", result.len());
}

代码说明

  1. 布尔运算

    • 演示了四种布尔运算:并集(Union)、交集(Intersection)、差集(Difference)和异或(Xor)
    • 使用相同的两个正方形多边形作为输入
  2. 偏移操作

    • 展示了多边形外扩(正偏移量)和内缩(负偏移量)两种操作
    • 使用圆角连接(JoinType::Round)使偏移结果更平滑
  3. 裁剪操作

    • 使用一个小正方形裁剪一个大正方形
    • 演示了差集(Difference)操作,保留大正方形中不在小正方形内的部分
  4. 带孔多边形

    • 创建了一个带有两个孔(一个方形孔和一个三角形孔)的多边形
    • 演示了如何正确处理孔的方向(与外轮廓相反)
    • 展示了带孔多边形与另一个多边形的交集操作

这个完整示例涵盖了clipper-sys库的主要功能,可以作为实际项目开发的起点。

回到顶部