使用android.graphics.Path构造样条曲线
我有一个2d点数组,我需要创建一个通过所有点的路径。我想我应该使用使用android.graphics.Path构造样条曲线,android,path,spline,Android,Path,Spline,我有一个2d点数组,我需要创建一个通过所有点的路径。我想我应该使用Path.cubicTo()方法,使用指定的控制点在两点之间创建贝塞尔曲线。问题是我不知道曲线的控制点。我如何计算它们 也许有更好的方法?也许有某种图书馆可以帮助我?在我读了文章之后,它变得非常简单 这就是你在安卓上的做法。运行此代码后,路径p将通过knotsArr数组中的所有点 Point[] knotsArr = {new Point(0, 0), new Point(5, 5),
Path.cubicTo()
方法,使用指定的控制点在两点之间创建贝塞尔曲线。问题是我不知道曲线的控制点。我如何计算它们
也许有更好的方法?也许有某种图书馆可以帮助我?在我读了文章之后,它变得非常简单
这就是你在安卓上的做法。运行此代码后,路径p
将通过knotsArr
数组中的所有点
Point[] knotsArr = {new Point(0, 0),
new Point(5, 5),
new Point(10, 0),
new Point(15, 5)};
Point[][] controlPoints = BezierSplineUtil.getCurveControlPoints(knotsArr);
Point[] firstCP = controlPoints[0];
Point[] secondCP = controlPoints[1];
Path p = new Path();
p.moveTo(knots.get(0).x, knots.get(0).y);
for (int i = 0; i < firstCP.length; i++) {
p.cubicTo(firstCP[i].x, firstCP[i].y,
secondCP[i].x, secondCP[i].y,
knots.get(i + 1).x, knots.get(i + 1).y);
}
Point[]knotsArr={新点(0,0),
新的点(5,5),
新点(10,0),
新的第(15,5)点};
点[][]控制点=BezierSplineUtil.GetCurveControl点(knotsArr);
点[]第一个CP=控制点[0];
点[]秒Cp=控制点[1];
路径p=新路径();
p、 移动到(节数。获取(0.x),节数。获取(0.y);
for(int i=0;i
BezierSplineUtil.java
public class BezierSplineUtil {
public static class Point {
public final float x;
public final float y;
public Point(float x, float y) {
this.x = x;
this.y = y;
}
}
/**
* Get open-ended bezier spline control points.
*
* @param knots bezier spline points.
* @return [2 x knots.length - 1] matrix. First row of the matrix = first
* control points. Second row of the matrix = second control points.
* @throws IllegalArgumentException if less than two knots are passed.
*/
public static Point[][] getCurveControlPoints(Point[] knots) {
if (knots == null || knots.length < 2) {
throw new IllegalArgumentException("At least two knot points are required");
}
final int n = knots.length - 1;
final Point[] firstControlPoints = new Point[n];
final Point[] secondControlPoints = new Point[n];
// Special case: bezier curve should be a straight line
if (n == 1) {
// 3P1 = 2P0 + P3
float x = (2 * knots[0].x + knots[1].x) / 3;
float y = (2 * knots[0].y + knots[1].y) / 3;
firstControlPoints[0] = new Point(x, y);
// P2 = 2P1 - P0
x = 2 * firstControlPoints[0].x - knots[0].x;
y = 2 * firstControlPoints[0].y - knots[0].y;
secondControlPoints[0] = new Point(x, y);
return new Point[][] { firstControlPoints, secondControlPoints };
}
// Calculate first bezier control points
// Right hand side vector
float[] rhs = new float[n];
// Set right hand side X values
for (int i = 1; i < n - 1; i++) {
rhs[i] = 4 * knots[i].x + 2 * knots[i + 1].x;
}
rhs[0] = knots[0].x + 2 * knots[1].x;
rhs[n - 1] = (8 * knots[n - 1].x + knots[n].x) / 2f;
// Get first control points X-values
float[] x = getFirstControlPoints(rhs);
// Set right hand side Y values
for (int i = 1; i < n - 1; i++) {
rhs[i] = 4 * knots[i].y + 2 * knots[i + 1].y;
}
rhs[0] = knots[0].y + 2 * knots[1].y;
rhs[n - 1] = (8 * knots[n - 1].y + knots[n].y) / 2f;
// Get first control points Y-values
float[] y = getFirstControlPoints(rhs);
for (int i = 0; i < n; i++) {
// First control point
firstControlPoints[i] = new Point(x[i], y[i]);
// Second control point
if (i < n - 1) {
float xx = 2 * knots[i + 1].x - x[i + 1];
float yy = 2 * knots[i + 1].y - y[i + 1];
secondControlPoints[i] = new Point(xx, yy);
} else {
float xx = (knots[n].x + x[n - 1]) / 2;
float yy = (knots[n].y + y[n - 1]) / 2;
secondControlPoints[i] = new Point(xx, yy);
}
}
return new Point[][] { firstControlPoints, secondControlPoints };
}
/**
* Solves a tridiagonal system for one of coordinates (x or y) of first
* bezier control points.
*
* @param rhs right hand side vector.
* @return Solution vector.
*/
private static float[] getFirstControlPoints(float[] rhs) {
int n = rhs.length;
float[] x = new float[n]; // Solution vector
float[] tmp = new float[n]; // Temp workspace
float b = 2.0f;
x[0] = rhs[0] / b;
// Decomposition and forward substitution
for (int i = 1; i < n; i++) {
tmp[i] = 1 / b;
b = (i < n - 1 ? 4.0f : 3.5f) - tmp[i];
x[i] = (rhs[i] - x[i - 1]) / b;
}
// Backsubstitution
for (int i = 1; i < n; i++) {
x[n - i - 1] -= tmp[n - i] * x[n - i];
}
return x;
}
}
公共类BezierSplineUtil{
公共静态类点{
公开最终浮动x;
公开最终浮动;
公共点(浮动x、浮动y){
这个.x=x;
这个。y=y;
}
}
/**
*获取开放式bezier样条曲线控制点。
*
*@param结是贝塞尔样条曲线点。
*@return[2 x knots.length-1]矩阵。矩阵的第一行=第一行
*控制点。矩阵的第二行=第二个控制点。
*@如果通过的速度小于两节,则抛出IllegalArgumentException。
*/
公共静态点[][]GetCurveControl点(点[]节){
如果(节点==null | |节点长度<2){
抛出新的IllegalArgumentException(“至少需要两个节点”);
}
最终整数n=节。长度-1;
终点[]第一个控制点=新点[n];
最终点[]第二控制点=新点[n];
//特殊情况:贝塞尔曲线应该是一条直线
如果(n==1){
//3P1=2P0+P3
浮动x=(2*节[0]。x+节[1]。x)/3;
浮动y=(2*节[0]。y+节[1]。y)/3;
firstControlPoints[0]=新点(x,y);
//P2=2P1-P0
x=2*firstControlPoints[0].x-knots[0].x;
y=2*firstControlPoints[0]。y-节点[0]。y;
第二控制点[0]=新点(x,y);
返回新点[][{firstControlPoints,secondControlPoints};
}
//计算第一个贝塞尔控制点
//右侧向量
浮动[]rhs=新浮动[n];
//设置右侧的X值
对于(int i=1;i