La interfaz está localizada; las descripciones y documentos de las Skills se traducen automáticamente con IA a su idioma. El código, los comandos, rutas y términos técnicos se mantienen en el original, y prevalece el documento del autor.
Explorar Skills
Despliegue y operaciones · SKILL.md

clipper1

clipper1

Use when maintaining legacy code that depends on Clipper 1.x API for polygon clipping and offsetting. Clipper1: the original widely-deployed polygon boolean library. Prefer Clipper2 for new projects.

Independent GitHub snapshot · Automated classification · Original documentation governs

Documentación de la Skill

GitHub

name: clipper1 description: "Use when maintaining legacy code that depends on Clipper 1.x API for polygon clipping and offsetting. Clipper1: the original widely-deployed polygon boolean library. Prefer Clipper2 for new projects." tags:

  • 2d
  • geometry
  • boolean
  • offset
  • polygon
  • csharp
  • python
  • cpp

项目地址(V6 官方主页): https://sourceforge.net/p/polyclipping/

说明: 原 GitHub 仓库 github.com/AngusJohnson/Clipper 现重定向到 Clipper2,V6 末版为 6.4.2,已不再新增功能

NuGet: Clipper(多个第三方移植版)

许可证: Boost Software License 1.0

概述

Clipper1 主要特征:

  • 整数算法(IntPoint),通过 scale 系数模拟浮点
  • 核心 API:Clipper、ClipperOffset、ClipperBase
  • 支持:布尔运算 + 偏移 + 多边形简化
  • 多语言移植:C++(含 Header-only)、C#、Delphi/Pascal、JS、Python

新项目优先使用 Clipper2,其性能与 API 均优于 Clipper1。本 SKILL 主要用于维护遗留代码。


安装

# C#
dotnet add package Clipper

# JavaScript
npm install js-clipper          # 或 clipper-lib

# Python
pip install pyclipper

C++ 通常直接拷贝 clipper.hpp/.cpp 到工程。


核心数据结构

using ClipperLib;
using IntPoint = ClipperLib.IntPoint;

const long Scale = 1000000;     // 浮点 → 整数缩放因子

List<IntPoint> path = new() {
    new IntPoint(0, 0),
    new IntPoint(100 * Scale, 0),
    new IntPoint(100 * Scale, 100 * Scale),
    new IntPoint(0, 100 * Scale),
};
List<List<IntPoint>> paths = new() { path };

布尔运算

var clipper = new Clipper();
clipper.AddPath(subject, PolyType.ptSubject, true);   // true = 闭合
clipper.AddPath(clip,    PolyType.ptClip,    true);

var solution = new List<List<IntPoint>>();
clipper.Execute(ClipType.ctUnion, solution,
    PolyFillType.pftNonZero, PolyFillType.pftNonZero);

ClipType:ctIntersection、ctUnion、ctDifference、ctXor PolyFillType:pftEvenOdd、pftNonZero、pftPositive、pftNegative


多边形偏移(ClipperOffset)

var co = new ClipperOffset();
co.AddPaths(paths, JoinType.jtRound, EndType.etClosedPolygon);

var solution = new List<List<IntPoint>>();
co.Execute(ref solution, 10 * Scale);     // 正:外扩;负:内缩

JoinType:jtSquare、jtMiter、jtRound EndType:etClosedPolygon、etClosedLine、etOpenButt、etOpenSquare、etOpenRound


PolyTree(保留环层级)

var tree = new PolyTree();
clipper.Execute(ClipType.ctUnion, tree,
    PolyFillType.pftNonZero, PolyFillType.pftNonZero);

foreach (var node in tree.Childs)        // 顶层是外环
    foreach (var hole in node.Childs)    // 子节点是孔
        Console.WriteLine(hole.Contour.Count);

实用方法

double area    = Clipper.Area(path);
bool   ccw     = Clipper.Orientation(path);
var    cleaned = Clipper.CleanPolygon(path, 1.415);    // 去重/共线
var    simp    = Clipper.SimplifyPolygon(path, PolyFillType.pftNonZero);
var    reverse = Clipper.ReversePath(path);

Python(pyclipper)

import pyclipper

scale = 1_000_000
subj  = [[(0,0),(100,0),(100,100),(0,100)]]
clip  = [[(50,50),(150,50),(150,150),(50,150)]]

pc = pyclipper.Pyclipper()
pc.AddPaths(pyclipper.scale_to_clipper(subj, scale),
            pyclipper.PT_SUBJECT, True)
pc.AddPaths(pyclipper.scale_to_clipper(clip, scale),
            pyclipper.PT_CLIP, True)
sol = pc.Execute(pyclipper.CT_UNION,
                 pyclipper.PFT_NONZERO,
                 pyclipper.PFT_NONZERO)
sol = pyclipper.scale_from_clipper(sol, scale)

# 偏移
pco = pyclipper.PyclipperOffset()
pco.AddPaths(pyclipper.scale_to_clipper(subj, scale),
             pyclipper.JT_ROUND, pyclipper.ET_CLOSEDPOLYGON)
sol = pco.Execute(10 * scale)

C++ 用法

#include "clipper.hpp"
using namespace ClipperLib;

Paths subj{{ {0,0},{1000,0},{1000,1000},{0,1000} }};
Paths clip{{ {500,500},{1500,500},{1500,1500},{500,1500} }};
Clipper c;
c.AddPaths(subj, ptSubject, true);
c.AddPaths(clip, ptClip, true);
Paths solution;
c.Execute(ctUnion, solution, pftNonZero, pftNonZero);

典型工作流

工作流一:CAD/GIS 中多边形布尔运算

  1. 确定浮点精度需求,选定 scale 系数(如 1,000,000 表示微米精度)
  2. 将输入几何(Polygon/MultiLine 等)转换为 List<IntPoint> 格式,乘以 scale 取整
  3. 创建 Clipper 实例,AddPath 添加 Subject 和 Clip
  4. 调用 Execute 执行布尔运算(Union/Intersect/Difference/Xor)
  5. 将结果坐标除以 scale 还原为浮点坐标
  6. 如需保留孔洞关系,使用 PolyTree 替代 List<List<IntPoint>>

工作流二:多边形轮廓偏移(生成安全区/缓冲区)

  1. 构建多边形路径(闭合路径用 etClosedPolygon,开放用 etOpenButt 等)
  2. 创建 ClipperOffset,通过 AddPaths 添加输入
  3. 调用 Execute,正值为外扩(膨胀),负值为内缩(侵蚀)
  4. 检查结果是否自交——偏移前可先用 SimplifyPolygon 清理输入
  5. 输出偏移后的多边形用于刀路生成、安全距离计算等

与 Clipper2 主要差异

维度Clipper1Clipper2
数值类型整数 + scale整数 / 浮点双模式
性能较慢显著更快
APIClipper 类顶层 Union/Intersect/...
简化SimplifyPolygonSimplifyPaths 更准确
维护已停止新功能活跃维护

迁移要点:

  • IntPoint → Point64
  • 移除 scale,使用 PathsD 或保留 Paths64
  • API 改为静态函数

常见问题

问题解决
浮点 → 整数舍入失真增大 scale
偏移产生自相交偏移前 SimplifyPolygon
闭合 path 多余首尾点Clipper 不需要重复首点
Mac/Linux 编译失败启用 use_int32/use_xyz 对应宏

AI 使用建议

  • 推荐工作流模式:AI 助手应将几何数据统一转换为 Clipper 的整数坐标格式(选择恰当的 scale),然后按「创建 Clipper → 添加路径 → 执行运算 → 还原坐标」的流程处理。对于带孔多边形,优先使用 PolyTree 保留层级关系。
  • 关键注意事项:① scale 选择需权衡精度与整数溢出——常用 1e6(微米级);② Clipper1 的闭合路径不需要重复首点;③ PolyFillType 需 Subject 和 Clip 各指定一次,非零环绕(NonZero)是最常用的填充规则;④ Clipper1 为非线程安全,多线程需各自持有实例。
  • 常用代码模式:new Clipper() → AddPath(subject, ptSubject, true) → AddPath(clip, ptClip, true) → Execute(ctUnion, solution, pftNonZero, pftNonZero)。

相关技能


参考资源

Skills guardadas