惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

B
Blog
V
Vulnerabilities – Threatpost
Apple Machine Learning Research
Apple Machine Learning Research
V
V2EX
博客园 - 叶小钗
阮一峰的网络日志
阮一峰的网络日志
人人都是产品经理
人人都是产品经理
Latest news
Latest news
博客园 - 三生石上(FineUI控件)
美团技术团队
aimingoo的专栏
aimingoo的专栏
Google Online Security Blog
Google Online Security Blog
Security Archives - TechRepublic
Security Archives - TechRepublic
T
Threatpost
Y
Y Combinator Blog
T
Tailwind CSS Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
A
Arctic Wolf
C
Cyber Attacks, Cyber Crime and Cyber Security
小众软件
小众软件
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
Tenable Blog
W
WeLiveSecurity
L
LINUX DO - 热门话题
D
Docker
Cyberwarzone
Cyberwarzone
量子位
A
About on SuperTechFans
The Last Watchdog
The Last Watchdog
雷峰网
雷峰网
C
CERT Recently Published Vulnerability Notes
P
Palo Alto Networks Blog
The Hacker News
The Hacker News
Blog — PlanetScale
Blog — PlanetScale
P
Proofpoint News Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
F
Full Disclosure
The Cloudflare Blog
T
The Blog of Author Tim Ferriss
T
The Exploit Database - CXSecurity.com
Engineering at Meta
Engineering at Meta
O
OpenAI News
Hacker News - Newest:
Hacker News - Newest: "LLM"
Scott Helme
Scott Helme
IT之家
IT之家
S
Secure Thoughts
MongoDB | Blog
MongoDB | Blog
L
Lohrmann on Cybersecurity
博客园 - 司徒正美
Google DeepMind News
Google DeepMind News

博客园 - 我才是银古

第16章:常见问题、排错与最佳实践 第15章:扩展生态、MCAD 与外部集成 第12章:实战案例:机械结构与 3D 打印零件 第14章:构建、测试、调试与贡献流程 第13章:OpenSCAD 源码架构与核心执行流程 第11章:预览、渲染、网格精度与性能优化 第09章:列表推导、递归与算法建模 第08章:参数化零件库与复用设计 第10章:导入导出、命令行与自动化 第06章:CSG 布尔建模方法 第07章:二维图形、拉伸、旋转与投影 第05章:基础几何、坐标系与变换 第04章:参数、变量、函数、模块与作用域 OpenSCAD 教程目录 第03章:OpenSCAD 语言基础 第02章:安装、环境配置与开发工作流 第01章:OpenSCAD 项目全景与学习路线 第02章:源码获取、编译与开发环境配置 第01章:OCCT项目全景与学习路线 第18章:二次开发实战与综合案例 第17章:与 Qt VTK Python pythonOCC 生态集成 第18章:综合实战案例 第17章:数据交换与协同 第16章:源码架构与二次开发 第15章:插件与自定义工作台开发 第14章:Python脚本宏与自动化 第13章:FEM仿真分析 第12章:CAM数控加工 第11章:SurfaceMesh与逆向工程 第10章:Draft二维绘图与BIM建筑 第09章:工程图TechDraw 第07章:参数化表达式与Spreadsheet 第08章:装配设计Assembly 第06章:Part工作台与几何内核 第05章:PartDesign实体特征建模 第04章:草图Sketcher约束建模 第02章:安装版本与工作环境配置 第03章:界面工作台与基础操作 第01章:项目全景与学习路线 第十二章:插件开发、研究功能与最佳实践 第十章:定时任务与自动化(Cron) 第七章:技能、记忆与自学习闭环 第八章:MCP 集成与上下文文件 第六章:工具系统与终端后端 第五章:模型供应商与配置体系 Hermes Agent 教程目录 第十一章:语音、视觉、浏览器与子代理协作 第四章:CLI/TUI 与会话管理 第十二章:学习路线、实战方案与最佳实践 第十一章:源码结构、开发调试与插件开发 第十章:自动化、远程访问、日志与排障 第九章:Control UI、节点、Canvas 与语音能力 第七章:工具、技能、插件与能力扩展 第八章:安全模型、访问控制与沙箱实践 第六章:Agent 工作区、会话与多智能体路由 第五章:多通道消息接入与聊天平台配置 第四章:配置体系、模型接入与认证管理 第三章:Gateway 架构、协议与运行机制 第二章:安装、环境准备与快速上手 第一章:OpenClaw 项目概览与核心定位 oh-my-openagent 教程目录 09-命令模型回退与配置参考 10-实战案例最佳实践与故障排除 05-工作模式-Ultrawork-Prometheus-Atlas 08-Hooks与MCP系统 06-Category与Skill系统 07-核心工具链 04-智能体全景详解 03-安装与环境配置 02-整体架构与多模型编排机制 01-项目简介与核心理念 01-项目概览与学习路线 02-安装部署与工具适配 03-Skill机制与using-superpowers 05-TDD系统化调试与完成前验证 04-需求澄清方案设计与计划编写 07-并行智能体子智能体与Git-Worktree 第六章:代码审查、反馈处理与分支收尾 08-中国特色Skills与本土团队落地 09-MCP构建工作流执行与自定义Skill 第23章:FreeCAD-Python-API Clipper2 C# 源码解读教程 第19章:PolyTree 多边形树结构 第20章:实际应用与最佳实践 第18章:Minkowski 和与差 第17章:RectClip 矩形裁剪优化 第16章:ClipperOffset 偏移类详解 第15章:填充规则详解 第14章:布尔运算执行流程 第13章:ClipperD 浮点裁剪类 第11章:OutRec 与 OutPt 输出结构 第9章:Active 活动边结构 第10章:Vertex 顶点与 LocalMinima 局部极小值 第12章:Clipper64 裁剪类详解 第7章:高精度运算与128位整数 第8章:ClipperBase 基类详解 第6章:InternalClipper 内部工具类 第2章:核心数据结构 - Point64、PointD 第3章:路径与多边形表示 - Path64、PathD、Paths64、PathsD 第4章:矩形边界 - Rect64、RectD
第5章:枚举类型与常量定义
我才是银古 · 2026-04-11 · via 博客园 - 我才是银古

第5章:枚举类型与常量定义

5.1 概述

Clipper2 定义了多种枚举类型来控制裁剪、偏移等操作的行为。这些枚举类型直接影响算法的执行逻辑和最终结果。本章将详细解析每种枚举类型的含义和应用场景。

5.2 ClipType 裁剪类型

5.2.1 枚举定义

public enum ClipType
{
    NoClip,
    Intersection,
    Union,
    Difference,
    Xor
}

5.2.2 各类型详解

NoClip(无裁剪)

ClipType.NoClip

不执行任何裁剪操作。通常用于测试或占位符。

Intersection(交集)

ClipType.Intersection

返回主体和裁剪多边形的公共区域。

Subject:          Clip:             Result:
┌────────┐       ┌────────┐        ┌────┐
│        │       │        │        │    │
│   ┌────┼───┐   │   ┌────┼───┐    │    │
│   │    │   │   │   │    │   │    └────┘
│   │    │   │ ∩ │   │    │   │ =  
│   └────┼───┘   │   └────┼───┘    
│        │       │        │        
└────────┘       └────────┘        

Union(并集)

ClipType.Union

返回主体和裁剪多边形的合并区域。

Subject:          Clip:             Result:
┌────────┐       ┌────────┐        ┌────────────────┐
│        │       │        │        │                │
│   ┌────┼───┐   │   ┌────┼───┐    │                │
│   │    │   │   │   │    │   │    │                │
│   │    │   │ ∪ │   │    │   │ =  │                │
│   └────┼───┘   │   └────┼───┘    │                │
│        │       │        │        │                │
└────────┘       └────────┘        └────────────────┘

Difference(差集)

ClipType.Difference

返回主体多边形减去裁剪多边形的区域。

注意:差集运算是非交换的,Subject - Clip ≠ Clip - Subject

Subject:          Clip:             Result:
┌────────┐       ┌────────┐        ┌────┐
│        │       │        │        │    │
│   ┌────┼───┐   │   ┌────┼───┐    │    │
│   │    │   │   │   │    │   │    │    └────┐
│   │    │   │ - │   │    │   │ =  │         │
│   └────┼───┘   │   └────┼───┘    │    ┌────┘
│        │       │        │        │    │
└────────┘       └────────┘        └────┘

Xor(异或)

ClipType.Xor

返回主体和裁剪多边形的非公共区域(属于其中一个但不同时属于两个)。

Subject:          Clip:             Result:
┌────────┐       ┌────────┐        ┌────┐    ┌────┐
│        │       │        │        │    │    │    │
│   ┌────┼───┐   │   ┌────┼───┐    │    └────┘    │
│   │    │   │   │   │    │   │    │              │
│   │    │   │ ⊕ │   │    │   │ =  │              │
│   └────┼───┘   │   └────┼───┘    │    ┌────┐    │
│        │       │        │        │    │    │    │
└────────┘       └────────┘        └────┘    └────┘

5.2.3 交换性

操作 交换性
Intersection 是(A ∩ B = B ∩ A)
Union 是(A ∪ B = B ∪ A)
Difference 否(A - B ≠ B - A)
Xor 是(A ⊕ B = B ⊕ A)

5.3 PathType 路径类型

5.3.1 枚举定义

public enum PathType
{
    Subject,
    Clip
}

5.3.2 用途

用于区分添加到裁剪器的路径是主体还是裁剪多边形:

Clipper64 clipper = new Clipper64();
clipper.AddPath(subjectPath, PathType.Subject, true);
clipper.AddPath(clipPath, PathType.Clip, true);

或使用便捷方法:

clipper.AddSubject(subjectPath);  // 等同于 AddPath(..., PathType.Subject, false)
clipper.AddClip(clipPath);        // 等同于 AddPath(..., PathType.Clip, false)

5.4 FillRule 填充规则

5.4.1 枚举定义

public enum FillRule
{
    EvenOdd,
    NonZero,
    Positive,
    Negative
}

填充规则决定了多边形内部的判定方式,特别是对于自相交或嵌套的多边形。

5.4.2 EvenOdd(奇偶规则)

FillRule.EvenOdd

从任一点向外画一条射线,如果与多边形边界相交的次数为奇数,则该点在多边形内部。

特点

  • 最直观的规则
  • 自相交多边形会产生"孔洞"效果
  • 路径方向无关
        ↗ 穿过 1 次 → 内部
┌─────────────────┐
│                 │
│    ┌───────┐    │   ↗ 穿过 2 次 → 外部
│    │       │    │
│    │   ●   │    │   ↗ 穿过 3 次 → 内部
│    │       │    │
│    └───────┘    │
│                 │
└─────────────────┘

5.4.3 NonZero(非零规则)

FillRule.NonZero

从任一点向外画一条射线,计算与边界相交时的"缠绕数":

  • 从右向左穿过边界:+1
  • 从左向右穿过边界:-1

如果缠绕数不为零,则该点在多边形内部。

特点

  • 考虑路径方向
  • 同向嵌套多边形会合并
  • 反向嵌套多边形会产生孔洞

5.4.4 Positive(正向规则)

FillRule.Positive

只有当缠绕数为正数时,点才在多边形内部。

用途:只保留逆时针方向(正面积)的多边形区域。

5.4.5 Negative(负向规则)

FillRule.Negative

只有当缠绕数为负数时,点才在多边形内部。

用途:只保留顺时针方向(负面积)的多边形区域。

5.4.6 填充规则比较

同向嵌套正方形:
┌───────────────┐
│  ┌─────────┐  │
│  │  ┌───┐  │  │
│  │  │   │  │  │
│  │  └───┘  │  │
│  └─────────┘  │
└───────────────┘

EvenOdd:  内外内(三层交替)
NonZero:  全内(合并)
Positive: 全内(同向)
Negative: 全外(反向为空)

5.5 JoinType 连接类型

5.5.1 枚举定义

public enum JoinType
{
    Miter,    // 斜接
    Square,   // 方形
    Bevel,    // 斜角
    Round     // 圆角
}

这些类型用于 ClipperOffset 的路径偏移操作,决定拐角处的处理方式。

5.5.2 Miter(斜接)

JoinType.Miter

拐角处的两条偏移边延伸到相交点。

原始:           Miter 偏移:
  ╱              ╱│
 ╱              ╱ │
╱───────  →   ╱──────
              │
              │

注意:当角度很小时,斜接点会非常远,因此有 MiterLimit 参数限制。

5.5.3 Square(方形)

JoinType.Square

在拐角处添加一个方形端点。

原始:           Square 偏移:
  ╱              ┌─┐
 ╱              ╱  │
╱───────  →   ╱───────
              │
              └──

5.5.4 Bevel(斜角)

JoinType.Bevel

直接连接两条偏移边的端点,形成斜切面。

原始:           Bevel 偏移:
  ╱               ╱
 ╱              ╱╲
╱───────  →   ╱──────
              │
              │

5.5.5 Round(圆角)

JoinType.Round

在拐角处使用圆弧连接。

原始:           Round 偏移:
  ╱              ╭─╮
 ╱              ╱   ╲
╱───────  →   ╱───────
              │
              ╰─

5.6 EndType 端点类型

5.6.1 枚举定义

public enum EndType
{
    Polygon,   // 闭合多边形
    Joined,    // 连接的开放路径
    Butt,      // 平头
    Square,    // 方形端
    Round      // 圆形端
}

这些类型决定开放路径端点的处理方式。

5.6.2 Polygon(闭合多边形)

EndType.Polygon

将路径视为闭合多边形处理。偏移后仍然是闭合多边形。

5.6.3 Joined(连接)

EndType.Joined

开放路径,但首尾相连。偏移后会产生两条平行路径。

原始:    Joined 偏移:
○────○    ○────○
          │    │
          ○────○

5.6.4 Butt(平头)

EndType.Butt

端点处垂直截断。

原始:    Butt 偏移:
○────○    │────│
          │    │
          │────│

5.6.5 Square(方形端)

EndType.Square

端点处添加方形延伸。

原始:    Square 偏移:
○────○    ┌─────┐
          │     │
          └─────┘

5.6.6 Round(圆形端)

EndType.Round

端点处添加半圆形。

原始:    Round 偏移:
○────○    ╭─────╮
          │     │
          ╰─────╯

5.7 PointInPolygonResult 点在多边形中的结果

5.7.1 枚举定义

[Flags]
public enum PointInPolygonResult
{
    IsOn = 0,      // 在边界上
    IsInside = 1,  // 在内部
    IsOutside = 2  // 在外部
}

5.7.2 使用示例

Point64 testPoint = new Point64(50, 50);
Path64 polygon = Clipper.MakePath(new long[] {
    0, 0, 100, 0, 100, 100, 0, 100
});

PointInPolygonResult result = Clipper.PointInPolygon(testPoint, polygon);

switch (result)
{
    case PointInPolygonResult.IsInside:
        Console.WriteLine("点在多边形内部");
        break;
    case PointInPolygonResult.IsOutside:
        Console.WriteLine("点在多边形外部");
        break;
    case PointInPolygonResult.IsOn:
        Console.WriteLine("点在多边形边界上");
        break;
}

5.8 VertexFlags 顶点标志

5.8.1 枚举定义

[Flags]
internal enum VertexFlags
{
    None = 0,
    OpenStart = 1,   // 开放路径起点
    OpenEnd = 2,     // 开放路径终点
    LocalMax = 4,    // 局部最大值
    LocalMin = 8     // 局部最小值
}

这是内部使用的标志枚举,用于标记顶点的特殊属性。

5.8.2 位标志操作

由于使用了 [Flags] 特性,可以组合多个标志:

// 开放路径起点同时是局部极小值
VertexFlags flags = VertexFlags.OpenStart | VertexFlags.LocalMin;

// 检查是否包含某标志
if ((flags & VertexFlags.OpenStart) != VertexFlags.None)
{
    // 是开放路径起点
}

5.9 内部常量

5.9.1 InternalClipper 常量

internal static class InternalClipper
{
    internal const long MaxInt64 = 9223372036854775807;
    internal const long MaxCoord = MaxInt64 / 4;
    internal const double max_coord = MaxCoord;
    internal const double min_coord = -MaxCoord;
    internal const long Invalid64 = MaxInt64;

    internal const double floatingPointTolerance = 1E-12;
    internal const double defaultMinimumEdgeLength = 0.1;
}

5.9.2 常量说明

常量 说明
MaxInt64 2⁶³-1 64位有符号整数最大值
MaxCoord MaxInt64/4 最大坐标值,预留溢出空间
Invalid64 MaxInt64 用于标记无效值
floatingPointTolerance 10⁻¹² 浮点数近似相等容差
defaultMinimumEdgeLength 0.1 默认最小边长

5.9.3 为什么 MaxCoord = MaxInt64 / 4?

在几何计算中,经常需要计算两点坐标差的乘积:

// 叉积计算
double cross = (x2 - x1) * (y3 - y2) - (y2 - y1) * (x3 - x2);

如果坐标接近 MaxInt64,差值可能接近 2 * MaxInt64,乘积可能接近 4 * MaxInt64²,超出 long 范围。

MaxCoord 限制为 MaxInt64 / 4,确保中间计算不会溢出。

5.10 本章小结

本章详细介绍了 Clipper2 的枚举类型和常量:

  1. ClipType:四种布尔运算类型
  2. PathType:区分主体和裁剪路径
  3. FillRule:四种填充规则
  4. JoinType:四种拐角连接方式
  5. EndType:五种端点处理方式
  6. PointInPolygonResult:点位置判断结果
  7. VertexFlags:内部顶点标志
  8. 内部常量:坐标范围和容差定义

理解这些枚举类型是正确使用 Clipper2 的基础。


上一章:矩形边界 | 返回目录 | 下一章:InternalClipper内部工具类