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());
}
代码说明
-
布尔运算:
- 演示了四种布尔运算:并集(Union)、交集(Intersection)、差集(Difference)和异或(Xor)
- 使用相同的两个正方形多边形作为输入
-
偏移操作:
- 展示了多边形外扩(正偏移量)和内缩(负偏移量)两种操作
- 使用圆角连接(JoinType::Round)使偏移结果更平滑
-
裁剪操作:
- 使用一个小正方形裁剪一个大正方形
- 演示了差集(Difference)操作,保留大正方形中不在小正方形内的部分
-
带孔多边形:
- 创建了一个带有两个孔(一个方形孔和一个三角形孔)的多边形
- 演示了如何正确处理孔的方向(与外轮廓相反)
- 展示了带孔多边形与另一个多边形的交集操作
这个完整示例涵盖了clipper-sys库的主要功能,可以作为实际项目开发的起点。