为何Path.contains(point)返回结果看似不一致?我忽略了什么?
边界点被Path.contains()判定不一致的原因与解决方法
问题概述
我需要检查点是否落在指定区域内,通过Envelope结构体定义区域边界,构建Path后调用path.contains(point)方法进行判断,但出现部分边界点被判定为外部、部分为内部的不一致情况。
核心原因
- 浮点数精度误差:当点恰好落在路径边界上时,浮点数的精度限制可能导致判定结果不稳定。
- 路径构建不规范:手动重复添加起点闭合路径,可能导致路径边界出现冗余节点,干扰判定逻辑。
- 默认填充规则的特性:
Path.contains(_:)默认使用非零环绕规则,部分边界点的归属判定会受路径绘制方向的影响。
解决方案
方案1:规范路径构建+处理精度问题
修改路径构建逻辑,使用closeSubpath()自动闭合路径,同时给待判断点添加微小偏移规避精度问题:
private func checkIntersection(_ point: CGPoint) -> String { var pathObject = Path() guard let first = envelope.first else { return "Outside" } pathObject.move(to: CGPoint(x: first.x, y: first.y)) for item in envelope.dropFirst() { pathObject.addLine(to: CGPoint(x: item.x, y: item.y)) } // 用closeSubpath替代手动添加起点,规范路径闭合 pathObject.closeSubpath() // 添加极小偏移,避免边界点的浮点数精度问题 let adjustedPoint = CGPoint(x: point.x + 1e-6, y: point.y + 1e-6) return pathObject.contains(adjustedPoint) ? "Inside" : "Outside" }
方案2:针对矩形区域的高效判断
由于你的Envelope是规则矩形,直接使用CGRect的判断逻辑会更准确高效:
private func checkIntersection(_ point: CGPoint) -> String { // 根据Envelope的坐标构建矩形 let rect = CGRect(x: 1.0, y: 1.0, width: 1.0, height: 1.0) // 包含边界点的判断,同时处理精度误差 return rect.contains(point) || rect.insetBy(dx: -1e-6, dy: -1e-6).contains(point) ? "Inside" : "Outside" }
方案3:指定填充规则
使用CGPath的重载方法,明确指定奇偶填充规则,部分场景下能让边界点判定更符合预期:
private func checkIntersection(_ point: CGPoint) -> String { var pathObject = Path() guard let first = envelope.first else { return "Outside" } pathObject.move(to: CGPoint(x: first.x, y: first.y)) for item in envelope.dropFirst() { pathObject.addLine(to: CGPoint(x: item.x, y: item.y)) } pathObject.closeSubpath() let cgPath = pathObject.cgPath return cgPath.contains(point, using: .evenOdd) ? "Inside" : "Outside" }
内容的提问来源于stack exchange,提问作者matyasl
相关产品推荐
相关产品推荐

