gpt4 book ai didi

ios - CAShapeLayer。直线穿过点吗?

转载 作者:搜寻专家 更新时间:2023-11-01 06:02:28 27 4
gpt4 key购买 nike

我使用 CAShapeLayer 来在屏幕上画一条线。在方法 touchesEnded 中,我想检查“线是否通过该点?”。在我的代码中,当我按下屏幕的任何部分时,方法 contains 始终返回 true。也许,我在 line.frame = (view?.bounds)! 有问题。我该如何解决? 抱歉我的英语不好。

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

let touch = touches.first
let firstPosition = touch?.location(in: self)

if atPoint(firstPosition!) == lvl1 {

let firstPositionX = firstPosition?.x
let firstPositionY = frame.size.height - (firstPosition?.y)!
view?.layer.addSublayer(line)
line.lineWidth = 8
let color = #colorLiteral(red: 0.8078431487, green: 0.02745098062, blue: 0.3333333433, alpha: 1).cgColor
line.strokeColor = color
line.fillColor = nil
line.frame = (view?.bounds)!
path.move(to: CGPoint(x: firstPositionX!, y: firstPositionY))

}

}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

let touch = touches.first
let firstPosition = touch?.location(in: self)

if atPoint(firstPosition!) == lvl1 {

let firstPositionX = firstPosition?.x
let firstPositionY = frame.size.height - (firstPosition?.y)!
path.addLine(to: CGPoint(x: firstPositionX!, y: firstPositionY))
line.path = path.cgPath

}
}


override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

if line.contains(screenCenterPoint) {
print("ok")
}

}

最佳答案

问题

方法func contains(_ p: CGPoint) -> BoolCAShapeLayer返回 true如果层的 bounds 包含该点。 ( see documentation )

所以你不能用它来检查线是否包含一个点。

然而,在类 CGPath 中还有另一个同名方法。返回指定点是否在路径的内部。但是由于您只是描边您的路径而您没有填充内部,因此此方法也不会给出所需的结果。

解决方案

诀窍是使用以下方法创建路径的轮廓:

let outline = path.cgPath.copy(strokingWithWidth: line.lineWidth, lineCap: .butt, lineJoin: .round, miterLimit: 0)

然后检查大纲内部是否包含你的screenCenterPoint

if outline.contains(screenCenterPoint) {
print("ok")
}

Stroke vs outline

性能考虑

由于您仅在触及末端时才检查包含,我认为创建路径轮廓不会增加太多开销。

当您想实时检查包含情况时,例如在touchesMoved 内部函数,计算轮廓可能会产生一些开销,因为每秒调用此方法很多次。此外,路径越长,计算轮廓所需的时间就越长。

因此,最好只实时生成最后绘制的线段的轮廓,然后检查该轮廓是否包含您的观点。

如果你真的想减少开销,你可以编写自己的包含函数。直线上的点的包含非常简单,可以简化为以下公式:

Given a line from start to end with width and a point p

Calculate:

  • dx = start.x - end.x
  • dy = start.y - end.y
  • a = dy * p.x - dx * p.y + end.x * start.y - end.y * start.x
  • b = hypot(dy, dx)

The line contains point p if:

abs(a/b) < width/2 and p is in the bounding box of the line.

关于ios - CAShapeLayer。直线穿过点吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45532330/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com