writing-skills
writing-skills
Use when creating new skills, editing existing skills, or verifying skills work before deployment
clipper1Use 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
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:
项目地址(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 系数模拟浮点Clipper、ClipperOffset、ClipperBase新项目优先使用 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
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
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);
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)
#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);
scale 系数(如 1,000,000 表示微米精度)List<IntPoint> 格式,乘以 scale 取整Clipper 实例,AddPath 添加 Subject 和 ClipExecute 执行布尔运算(Union/Intersect/Difference/Xor)PolyTree 替代 List<List<IntPoint>>etClosedPolygon,开放用 etOpenButt 等)ClipperOffset,通过 AddPaths 添加输入Execute,正值为外扩(膨胀),负值为内缩(侵蚀)SimplifyPolygon 清理输入| 维度 | Clipper1 | Clipper2 |
|---|---|---|
| 数值类型 | 整数 + scale | 整数 / 浮点双模式 |
| 性能 | 较慢 | 显著更快 |
| API | Clipper 类 | 顶层 Union/Intersect/... |
| 简化 | SimplifyPolygon | SimplifyPaths 更准确 |
| 维护 | 已停止新功能 | 活跃维护 |
迁移要点:
IntPoint → Point64PathsD 或保留 Paths64| 问题 | 解决 |
|---|---|
| 浮点 → 整数舍入失真 | 增大 scale |
| 偏移产生自相交 | 偏移前 SimplifyPolygon |
| 闭合 path 多余首尾点 | Clipper 不需要重复首点 |
| Mac/Linux 编译失败 | 启用 use_int32/use_xyz 对应宏 |
PolyTree 保留层级关系。PolyFillType 需 Subject 和 Clip 各指定一次,非零环绕(NonZero)是最常用的填充规则;④ Clipper1 为非线程安全,多线程需各自持有实例。new Clipper() → AddPath(subject, ptSubject, true) → AddPath(clip, ptClip, true) → Execute(ctUnion, solution, pftNonZero, pftNonZero)。