如何检测和删除UIBezierPath的交集

时间:2019-05-29 07:17:46

标签: ios swift uikit uibezierpath

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

我存储了一个UIBezierPaths数组,但是我不确定在每个触摸点遍历整个数组,检测它是否与当前触摸点相交并将其从中移除是多么有效。数组。

有什么建议吗?

1 个答案:

答案 0 :(得分:2)

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

UIBezierPaths具有方法contains,该方法将告诉您路径中是否有点。如果可以使用,那么您只需要做

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)) }
}