如何定义枚举类型和常量,实现代码的可读性与可维护性?

摘要:layout: default title: 第5章:枚举类型与常量定义 第5章:枚举类型与常量定义 5.1 概述 Clipper2 定义了多种枚举类型来控制裁剪、偏移等操作的行为。这些枚举类型直接影响算法的执行逻辑和最终结果。本章将详细解
第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 的枚举类型和常量: ClipType:四种布尔运算类型 PathType:区分主体和裁剪路径 FillRule:四种填充规则 JoinType:四种拐角连接方式 EndType:五种端点处理方式 PointInPolygonResult:点位置判断结果 VertexFlags:内部顶点标志 内部常量:坐标范围和容差定义 理解这些枚举类型是正确使用 Clipper2 的基础。 上一章:矩形边界 | 返回目录 | 下一章:InternalClipper内部工具类