【问题标题】:How to detect intersection of a UIBezierPath and erase it如何检测 UIBezierPath 的交集并将其擦除
【发布时间】:2019-05-29 07:17:46
【问题描述】:

我正在制作一个 iOS 绘图应用程序,并希望添加功能,其中擦除 UIBezierPath 将擦除整个路径,而不仅仅是用白色覆盖该段。

我存储了一个 UIBezierPaths 数组,但我不确定循环遍历每个触摸点的整个数组、检测它是否与当前触摸点相交并将其从数组中删除的效率如何。

有什么建议吗?

【问题讨论】:

    标签: ios swift uikit uibezierpath


    【解决方案1】:

    如果我理解正确,您至少需要遍历路径。毕竟他们是独立的。

    UIBezierPathscontains 方法,它会告诉你一个点是否在路径内。如果这是可用的,那么你需要做的只是

    paths = paths.filter { !$0.contains(touchPoint) }
    

    但由于这是绘图应用程序,因此可以安全地假设您使用的是描边而不是填充,这很可能无法以您想要的方式使用 contains

    你可以手动做交叉点,它应该有相对较好的性能,直到你有太多的点。但是当你的分数太多时,我打赌绘图性能会更受你关注。仍然包含一些笔划线宽度的交叉点可能有点问题;用户需要越过您的线的中心才能检测到命中。

    有一种方法可以将描边路径转换为填充路径。这样做将使您能够使用contains 方法。该方法称为replacePathWithStrokedPath,但问题是它仅存在于CGContext 上(至少我从未设法在UIBezierPath 上找到等效方法)。所以这样做的过程包括创建一个上下文。例如,这样的事情会起作用:

    static func convertStrokePathToFillPath(_ path: UIBezierPath) throws -> UIBezierPath {
        UIGraphicsBeginImageContextWithOptions(CGSize(width: 1.0, height: 1.0), true, 1.0)
        guard let context = UIGraphicsGetCurrentContext() else { throw NSError(domain: "convertStrokePathToFillPath", code: 500, userInfo: ["dev_message":"Could not generate image context"]) }
    
        context.addPath(path.cgPath)
        context.setLineWidth(path.lineWidth)
        // TODO: apply all possible settings from path to context
        context.replacePathWithStrokedPath()
    
        guard let returnedPath = context.path else { throw NSError(domain: "convertStrokePathToFillPath", code: 500, userInfo: ["dev_message":"Could not get path from context"]) }
        UIGraphicsEndImageContext()
    
        return UIBezierPath(cgPath: returnedPath)
    }
    

    所以结果应该是这样的:

    static func filterPaths(_ paths: [UIBezierPath], containingPoint point: CGPoint) -> [UIBezierPath] {
        return paths.filter { !(try! convertStrokePathToFillPath($0).contains(point)) }
    }
    

    【讨论】:

    • 要在不经过上下文的情况下将描边路径转换为填充路径,请参阅CGPath.copy(strokingWithWidth:...)。 (它是底层 CGPath 上的方法,而不是更高级别的 UIBezierPath。)
    • @RobNapier 谢谢你。我多年来一直在寻找这个东西,但从未找到它。我根本不认为它会出现在CGPath 上。从objectiveC开始,函数是CGPathCreateCopyByStrokingPath...想象一下我试图找到它的挫败感。最后我只是认为它必须是私有 API 的一部分。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多