Reduce jitter with smoothing.

pull/1/head
Matthew Chen 6 years ago
parent b8775006bb
commit 825826aa05

@ -201,9 +201,9 @@ public class ImageEditorView: UIView, ImageEditorModelDelegate {
// TODO: Use bezier curves to smooth stroke.
let bezierPath = UIBezierPath()
let points = unitSamples.map { (unitSample) in
let points = applySmoothing(to: unitSamples.map { (unitSample) in
transformSampleToPoint(unitSample)
}
})
var lastForwardVector = CGPoint.zero
for index in 0..<points.count {
let point = points[index]
@ -213,7 +213,7 @@ public class ImageEditorView: UIView, ImageEditorModelDelegate {
// First sample.
let nextPoint = points[index + 1]
forwardVector = CGPointSubtract(nextPoint, point)
} else if index == unitSamples.count - 1 {
} else if index == points.count - 1 {
// Last sample.
let lastPoint = points[index - 1]
forwardVector = CGPointSubtract(point, lastPoint)
@ -231,6 +231,12 @@ public class ImageEditorView: UIView, ImageEditorModelDelegate {
bezierPath.move(to: point)
} else {
let lastPoint = points[index - 1]
// We apply more than one kind of smoothing.
// This smoothing avoids rendering "angled segments"
// by drawing the stroke as a series of curves.
// We use bezier curves and infer the control points
// from the "next" and "prev" points.
//
// This factor controls how much we're smoothing.
//
// * 0.0 = No smoothing.
@ -239,7 +245,7 @@ public class ImageEditorView: UIView, ImageEditorModelDelegate {
let controlPointFactor: CGFloat = 0.25
let controlPoint1 = CGPointAdd(lastPoint, CGPointScale(lastForwardVector, +controlPointFactor))
let controlPoint2 = CGPointAdd(point, CGPointScale(forwardVector, -controlPointFactor))
// We're using Cubic curves.
// We're using Cubic curves.
bezierPath.addCurve(to: point, controlPoint1: controlPoint1, controlPoint2: controlPoint2)
}
lastForwardVector = forwardVector
@ -252,6 +258,38 @@ public class ImageEditorView: UIView, ImageEditorModelDelegate {
return shapeLayer
}
// We apply more than one kind of smoothing.
//
// This (simple) smoothing reduces jitter from the touch sensor.
private class func applySmoothing(to points: [CGPoint]) -> [CGPoint] {
AssertIsOnMainThread()
var result = [CGPoint]()
for index in 0..<points.count {
let point = points[index]
if index == 0 {
// First sample.
result.append(point)
} else if index == points.count - 1 {
// Last sample.
result.append(point)
} else {
// Middle samples.
let lastPoint = points[index - 1]
let nextPoint = points[index + 1]
let alpha: CGFloat = 0.1
let smoothedPoint = CGPointAdd(CGPointScale(point, 1.0 - 2.0 * alpha),
CGPointAdd(CGPointScale(lastPoint, alpha),
CGPointScale(nextPoint, alpha)))
result.append(smoothedPoint)
}
}
return result
}
// MARK: - Actions
// Returns nil on error.

Loading…
Cancel
Save