我有一个代码使用二次贝塞尔线来平滑点。结果工作得非常好。它也非常高效。使用以下类构建平滑路径。每次你有一个新点时,使用addPoint(x, y)
添加它。完成后,您可以致电constructPath()
得到平滑的路径。与评论中的解决方案(例如“corner.squareup.com/2012/07/smoother-signatures.html”)相比,我的解决方案避免了原始路径的非常尖角处的伪影。
public class BezierCurveConstructor {
Path path;
PointF previousPoint;
int pointCounter = 0;
public BezierCurveConstructor() {
reset();
}
/**
* reset the path
*/
public void reset() {
path = new Path();
pointCounter = 0;
}
public void addPoint(float x, float y) {
pointCounter ++;
if (pointCounter == 1) {
path.moveTo(x, y);
previousPoint = new PointF(x, y);
return;
}
PointF mid = new PointF((x + previousPoint.x) / 2.0f, (y + previousPoint.y) / 2.0f);
if (pointCounter < 3) {
path.lineTo(mid.x, mid.y);
} else {
path.quadTo(previousPoint.x, previousPoint.y, mid.x, mid.y);
}
previousPoint = new PointF(x, y);
}
/**
* construct path by points
*
* @return
*/
public Path constructPath() {
return path;
}
}
该路径包含二次贝塞尔曲线列表,穿过触摸的上一个点和下一个点的所有中间点。请注意,该路径具有恒定的二阶导数,但一阶导数在粘合点处匹配。我们可以通过以下推导来说明为什么会这样:
Denote the list of points as p_0, p_1, ... p_n, (these can be points in R^n)
let c_i = (pi+p_{i_1})/2 as the middle point of pi and p_{i-1}.
We can model the quadratic Bezier line as following, here t is a number between 0 and 1:
G_i(t)=(1-t)^2c_i +2(1-t)tp_i + t^2 c_{i+1}
Consider the derivative against t:
G_i'(t) = -2(1-t)c_i + 2(1-t-t)p_i + 2t c_{i+1}, and
G_i''(t) = 2c_i -4p_i + 2c_{i+1} = 2p_{i-1} + 2 p_{i+1}
Thus the second derivatives are constants. To show that the
first derivatives match at each c_i, we can plug in t=0, and t=1.
G_i'(0) = 2p_i-2c_i = p_i - p_{i-1}
G_{i-1}'(1) = -2p_{i-1}+2c_i = p_i - p_{i-1} = G_i'(0)
顺便说一句,您可以查看 wiki,了解贝塞尔曲线的明确定义https://en.wikipedia.org/wiki/B%C3%A9zier_curve https://en.wikipedia.org/wiki/B%C3%A9zier_curve
查看此链接以获取原始代码:https://github.com/lyang36/codeNotes/blob/master/BezierCurveConstructor.java https://github.com/lyang36/codeNotes/blob/master/BezierCurveConstructor.java