## 动力学知识库

Note: In the below question, I use the term 'lagging' when I probably mean 'latency' when drawing using the `addCurveToPoint` function.

Problem:

Both bezier curve functions, `addQuadCurveToPoint` and `addCurveToPoint` have one strength and one weakness each. The aim is to get the perfect combination of both, a perfect continuous smooth curved line that is lag-free when drawn. The images below show where the touch on the screen typically is in comparison to the updated drawing.

The below image uses the function `addQuadCurveToPoint`. It draws fast

with no lagging while drawing during touch events, but the end result is a

less perfect smooth curved line that appears more segmented.

The below image uses the function

`addCurveToPoint`. It draws near perfect continuous smooth curved

lines but is slower with some lag noticeable while drawing during

touch events.

Question:

Can anyone help explain or give a solution please:

1. how to get perfect `addQuadCurveToPoint` curved lines or lag-free `addCurveToPoint` curved lines?

Note: The focus of this question is immediate lagging from the initial touch event for `addCurveToPoint`, not lagging over time, and also the less perfect curve line for `addQuadCurveToPoint`.

This code example is just one type of many implementations of `addCurveToPoint`:

``// Swift 2 code below tested using Xcode 7.0.1.class drawView: UIView {var path:UIBezierPath?var incrementalImage:UIImage?var points = [CGPoint?](count: 5, repeatedValue: nil)var counter:Int?var infoView:UIView = UIView()var strokeColor:UIColor?required init?(coder aDecoder: NSCoder) {super.init(coder: aDecoder)self.multipleTouchEnabled = falseself.backgroundColor = UIColor.whiteColor()path = UIBezierPath()path?.lineWidth = 20.0strokeColor = UIColor.darkGrayColor()path?.lineCapStyle = CGLineCap.Round}override init(frame: CGRect) {super.init(frame: frame)self.multipleTouchEnabled = falsepath = UIBezierPath()path?.lineWidth = 20.0}override func drawRect(rect: CGRect) {incrementalImage?.drawInRect(rect)strokeColor?.setStroke()path?.stroke()}override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {counter = 0let touch: AnyObject? = touches.firstpoints[0] = touch!.locationInView(self)infoView.removeFromSuperview()}override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {let touch: AnyObject? = touches.firstlet point = touch!.locationInView(self)counter = counter! + 1points[counter!] = pointif counter == 4{points[3]! = CGPointMake((points[2]!.x + points[4]!.x)/2.0, (points[2]!.y + points[4]!.y)/2.0)path?.moveToPoint(points[0]!)path?.addCurveToPoint(points[3]!, controlPoint1: points[1]!, controlPoint2: points[2]!)self.setNeedsDisplay()points[0]! = points[3]!points[1]! = points[4]!counter = 1}}override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {self.drawBitmap()self.setNeedsDisplay()path?.removeAllPoints()counter = 0}override func touchesCancelled(touches: Set<UITouch>?, withEvent event: UIEvent?) {self.touchesEnded(touches!, withEvent: event)}func drawBitmap(){UIGraphicsBeginImageContextWithOptions(self.bounds.size, true, 0.0)strokeColor?.setStroke()if((incrementalImage) == nil){let rectPath:UIBezierPath = UIBezierPath(rect: self.bounds)UIColor.whiteColor().setFill()rectPath.fill()}incrementalImage?.drawAtPoint(CGPointZero)path?.stroke()incrementalImage = UIGraphicsGetImageFromCurrentImageContext()UIGraphicsEndImageContext()}}``

This code example is just one type of many implementations of `addQuadCurveToPoint`:

``// Swift 2 code below tested using Xcode 7.0.1.class DrawableView: UIView {let path=UIBezierPath()var previousPoint:CGPointvar lineWidth:CGFloat=20.0// Only override drawRect: if you perform custom drawing.// An empty implementation adversely affects performance during animation.override init(frame: CGRect) {previousPoint=CGPoint.zerosuper.init(frame: frame)}required init?(coder aDecoder: NSCoder) {previousPoint=CGPoint.zerosuper.init(coder: aDecoder)let panGestureRecognizer=UIPanGestureRecognizer(target: self, action: "pan:")panGestureRecognizer.maximumNumberOfTouches=1self.addGestureRecognizer(panGestureRecognizer)}override func drawRect(rect: CGRect) {// Drawing codeUIColor.darkGrayColor().setStroke()path.stroke()path.lineWidth=lineWidthpath.lineCapStyle = .Round}func pan(panGestureRecognizer:UIPanGestureRecognizer)->Void{let currentPoint=panGestureRecognizer.locationInView(self)let midPoint=self.midPoint(previousPoint, p1: currentPoint)if panGestureRecognizer.state == .Began{path.moveToPoint(currentPoint)}else if panGestureRecognizer.state == .Changed{path.addQuadCurveToPoint(midPoint,controlPoint: previousPoint)}previousPoint=currentPointself.setNeedsDisplay()}func midPoint(p0:CGPoint,p1:CGPoint)->CGPoint{let x=(p0.x+p1.x)/2let y=(p0.y+p1.y)/2return CGPoint(x: x, y: y)}}``