You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Path.contains(point)返回结果看似不一致?我忽略了什么?

边界点被Path.contains()判定不一致的原因与解决方法

问题概述

我需要检查点是否落在指定区域内,通过Envelope结构体定义区域边界,构建Path后调用path.contains(point)方法进行判断,但出现部分边界点被判定为外部、部分为内部的不一致情况。

核心原因

  1. 浮点数精度误差:当点恰好落在路径边界上时,浮点数的精度限制可能导致判定结果不稳定。
  2. 路径构建不规范:手动重复添加起点闭合路径,可能导致路径边界出现冗余节点,干扰判定逻辑。
  3. 默认填充规则的特性: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 12:35:23