I have a section in my app where users can draw something. Because of the slow refresh rate of touchesMoved, if a user draws fast, the line doesn't go smooth. That's why I'm using Hermite. It sets a point for every refresh rate and then draws a UIBezierpath (with extension to make it smooth) between those points. It's working perfectly ! I have a smooth design right now !
The only problem is that I'm sometimes not getting a round begin cap and if I switch on the same path back it also happens.
I think it has something to do with the code that draws a bezierpath between those points. So I'm looking for someone that also uses Hermite and knows how to fix this.
The hermite spline is just a series of cubic beziers. But you can get these weird discrepancies with UIBezierPath
. For example, there is a UIBezierPath
rendering problem when you add multiple cubic beziers where the start, control point 1, control point 2, and end are all collinear. So, I've added a check to my hermite spline path to check to see if these four points are collinear, and, if so, just add a line in those cases.
So, instead of just:
addCurve(to: endPoint, controlPoint1: control1, controlPoint2: control2)
I do:
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)
}
Where
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)
}
Another, more generalized solution (though a bit inelegant, IMHO), approach, is to avoid joining these cubic curves entirely, so, before adding each cubic curve, do a move(to:)
the previous point first. That should prevent all problems stemming from bugs related to joining cubic beziers.