swift: Hermite 圆帽 UIBezierpath

swift: Hermite round cap UIBezierpath

我的应用程序中有一个部分,用户可以在其中绘制内容。 由于 touchesMoved 的刷新率很慢,如果用户快速绘制,线条就不会流畅。 这就是我使用 Hermite 的原因。它为每个刷新率设置一个点,然后在这些点之间绘制一个 UIBezierpath(带有扩展以使其平滑)。 它工作完美!我现在有一个流畅的设计!

唯一的问题是我有时得不到圆开始上限,如果我在相同的路径上切换回来,也会发生这种情况。

我认为这与在这些点之间绘制贝塞尔曲线的代码有关。所以我正在寻找也使用 Hermite 并且知道如何解决这个问题的人。

Hermite 样条只是一系列三次贝塞尔曲线。但是你可以用 UIBezierPath 得到这些奇怪的差异。例如,当您添加起点、控制点 1、控制点 2 和终点都共线的多个立方贝塞尔曲线时,会出现 UIBezierPath 渲染问题。所以,我在我的 hermite 样条路径中添加了一个检查,以检查这四个点是否共线,如果是,则在这些情况下添加一条线。

所以,不只是:

addCurve(to: endPoint, controlPoint1: control1, controlPoint2: control2)

我愿意:

let angleFull = angle(between: previousPoint, and: endPoint)
let angle1 = angle(between: previousPoint, and: control1)
let angle2 = angle(between: control2, and: endPoint)

if (angleFull == angle1 || angle1 == nil) && (angleFull == angle2 || angle2 == nil) {
    addLine(to: endPoint)
} else {
    addCurve(to: endPoint, controlPoint1: control1, controlPoint2: control2)
}

在哪里

private func angle(between point1: CGPoint, and point2: CGPoint) -> CGFloat? {
    if point1 == point2 { return nil }
    return atan2(point2.y - point1.y, point2.x - point1.x)
}

另一个更通用的解决方案(虽然有点不雅,恕我直言),方法是避免完全连接这些三次曲线,因此,在添加每条三次曲线之前,先 move(to:) 前一点。这应该可以防止所有与连接三次方贝塞尔曲线相关的错误引起的问题。