gpt4 book ai didi

android - 使用 android.graphics.Path 构造样条

转载 作者:太空狗 更新时间:2023-10-29 13:24:41 25 4
gpt4 key购买 nike

我有二维点数组,我需要创建一个通过所有点的 Path。我想我应该使用 Path.cubicTo() 方法,该方法使用指定的控制点在两点之间创建贝塞尔曲线。问题是我不知道曲线的控制点。我如何计算它们?

也许有更好的方法?也许有某种图书馆可以帮助我?

最佳答案

读完this文章变得非常简单。

这就是您在 Android 上的操作方式。运行此代码后,您的路径 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);
}

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

}

关于android - 使用 android.graphics.Path 构造样条,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22763632/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com