如何计算两个不规则闭合UIBezierPath的交集?
计算两个闭合UIBezierPath的交集方案
核心思路:基于路径的几何运算
UIBezierPath本身没有直接提供交集计算API,得靠Core Graphics底层能力或自定义实现,以下是可行的落地方案:
方法1:利用Core Graphics裁剪上下文间接获取
通过上下文裁剪+像素提取的方式,快速得到交集区域:
- 创建位图上下文,将第一个路径设为裁剪区域
- 填充第二个路径,再从上下文中提取有效像素区域并转换回UIBezierPath
- 代码示例:
func getIntersectionPath(path1: UIBezierPath, path2: UIBezierPath) -> UIBezierPath? { let bounds = path1.bounds.union(path2.bounds) UIGraphicsBeginImageContextWithOptions(bounds.size, false, UIScreen.main.scale) guard let context = UIGraphicsGetCurrentContext() else { UIGraphicsEndImageContext() return nil } context.translateBy(x: -bounds.origin.x, y: -bounds.origin.y) // 设置第一个路径为裁剪范围 context.addPath(path1.cgPath) context.clip() // 填充第二个路径,仅保留交集部分 context.addPath(path2.cgPath) context.setFillColor(UIColor.black.cgColor) context.fillPath() // 从上下文提取图像并转换为路径 guard let image = UIGraphicsGetImageFromCurrentImageContext() else { UIGraphicsEndImageContext() return nil } UIGraphicsEndImageContext() let ciImage = CIImage(image: image) guard let detector = CIDetector(ofType: CIDetectorTypeRectangle, context: nil, options: [CIDetectorAccuracy: CIDetectorAccuracyHigh]) else { return nil } // 注:此方法对规则图形效果好,复杂图形需用CIContour提取精细轮廓 if let rectFeature = detector.features(in: ciImage).first as? CIRectangleFeature { let rect = CGRect(x: rectFeature.topLeft.x + bounds.origin.x, y: rectFeature.topLeft.y + bounds.origin.y, width: rectFeature.bottomRight.x - rectFeature.topLeft.x, height: rectFeature.bottomRight.y - rectFeature.topLeft.y) return UIBezierPath(rect: rect) } return nil }
提示:该方案适合精度要求不高的场景,复杂曲线图形需要额外处理轮廓提取逻辑。
方法2:自定义实现多边形布尔运算
如果路径由直线段构成(多边形),可以手动实现Sutherland-Hodgman算法:
- 解析UIBezierPath的所有顶点:遍历
CGPath的moveTo、addLineTo等指令,提取顶点集合 - 实现裁剪逻辑:以其中一个多边形为裁剪窗口,对另一个多边形的每条边进行交点计算,保留窗口内的顶点
- 将裁剪后的顶点重新构建为UIBezierPath
方法3:修复找到的第三方库
若你找到的Git仓库仅缺失少量文件,可尝试:
- 查看仓库的Issue或提交记录,寻找缺失文件的替代实现
- 手动补全基础工具类(比如CGPath扩展、几何计算函数)
- 检查是否有未引入的子模块或依赖项
注意事项
- 包含曲线的UIBezierPath需先将曲线分段近似为直线段,再进行布尔运算
- 高精度场景优先选择维护活跃的第三方库,避免使用CoreGraphics私有API(无法上线)
内容的提问来源于stack exchange,提问作者April G
相关产品推荐
相关产品推荐

