画出平滑的曲线

时间:2013-03-11 11:54:37

标签: java android

我想创建更平滑的曲线,而不仅仅是线角度。这就是我现在画的画面:

enter image description here

这是我的代码:

case FREEHAND:
    float[] pts;
    float[] ptk;
    ptk = new float[2];
    imageMatrix.invert(inv);            
    if (mCurrentShape == null) {                
        mCurrentShape = new Line();
        pts = new float[2];
        ((Line) mCurrentShape).setBegin(mDownPoint);
        pts[0] = (float)((Line) mCurrentShape).getBegin().getX();
        pts[1] = (float)((Line) mCurrentShape).getBegin().getY();
        inv.mapPoints(pts);
        ((Line) mCurrentShape).getPath().moveTo(pts[0], pts[1]);
    }
    ptk[0] = (float)currentPoint.getX();
    ptk[1] = (float)currentPoint.getY();
    inv.mapPoints(ptk);
    ((Line) mCurrentShape).getPath().lineTo(ptk[0], ptk[1]);
    break;

手绘代码:

package aa.bb.cc;
import java.util.ArrayList;
import android.graphics.Path;

public class FreeHand extends Shape{
    private ArrayList<Path>_graphics;

    public FreeHand(){
        super();
        _graphics = new ArrayList<Path>();
    }

    public ArrayList<Path> getGraphicsPath(){
        return _graphics;
    }
}

1 个答案:

答案 0 :(得分:-1)

我有一个代码使用二次贝塞尔线来平滑点。事实证明工作非常好。它也非常有效。使用以下类构建平滑路径。每次有新点时,使用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)

顺便说一句,您可以查看维基,了解贝塞尔曲线的明确定义https://en.wikipedia.org/wiki/B%C3%A9zier_curve

检查此链接以获取原始代码: https://github.com/lyang36/codeNotes/blob/master/BezierCurveConstructor.java