绘制平滑曲线

2024-05-29

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

这是我的代码:

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;
    }
}

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

绘制平滑曲线 的相关文章

随机推荐