1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
package com.pau101.util;
/**
* @author Paul Fulham (pau101)
*/
public final class BezierUtils {
private BezierUtils() {
}
/**
* Compute the value of all nth degree Bernstein polynomials.
*
* @param curveDegree
* : degree of curve
* @param t
* : curve parameter on interval [0,1]
* @param scalars
* : curveDegree + 1 Bernstein values.
*/
public static void allBernstein(int curveDegree, float t,
float scalars[]) {
int j, k;
float nt = 1 - t;
float saved;
scalars[0] = 1;
for (j = 1; j <= curveDegree; j++) {
saved = 0;
for (k = 0; k < j; k++) {
float temp = scalars[k];
scalars[k] = saved + nt * temp;
saved = t * temp;
}
scalars[j] = saved;
}
}
/**
* Compute point of nth degree Bezier curve.
*
* @param controlPoints
* : curveDegree + 1 control points
* @param curveDegree
* : degree of curve
* @param t
* : curve parameter on interval [0,1]
* @param point
* : resulting point
*/
public static void pointOnBezierCurve(float controlPoints[][],
int curveDegree, float t, float point[]) {
float scalars[] = new float[curveDegree + 1];
int k;
allBernstein(curveDegree, t, scalars);
point[0] = point[1] = point[2] = 0;
for (k = 0; k <= curveDegree; k++) {
point[0] += scalars[k] * controlPoints[k][0];
point[1] += scalars[k] * controlPoints[k][1];
point[2] += scalars[k] * controlPoints[k][2];
}
}
/**
* Compute an approximate length of a Bezier curve given the
* control points.
*
* @param controlPoints
* : control points of a Bezier curve
* @return the approximate length
*/
public static float approximateLength(float controlPoints[][]) {
float length = 0;
for (int i = 0; i < controlPoints.length - 1; i++) {
float xDif = controlPoints[i + 1][0]
- controlPoints[i][0];
float yDif = controlPoints[i + 1][1]
- controlPoints[i][1];
float zDif = controlPoints[i + 1][2]
- controlPoints[i][2];
length += Math.sqrt(xDif * xDif + yDif * yDif
+ zDif * zDif);
}
return length;
}
public static int tesselationSegementsForLength(float length,
float scale) {
float noLessThan = 10 * scale;
float segs = length * scale / 30F;
return (int) Math.ceil(Math.sqrt(segs * segs * 0.6
+ noLessThan * noLessThan));
}
public static float[][] curve(float controlPoints[][]) {
return curve(controlPoints, 1);
}
public static float[][] curve(float controlPoints[][],
float scale) {
int count = tesselationSegementsForLength(
approximateLength(controlPoints), scale);
float[][] points = new float[count][3];
for (int i = 0; i < count; i++) {
float t = i / (float) (count - 1);
float[] point = new float[3];
pointOnBezierCurve(controlPoints,
controlPoints.length - 1, t,
point);
points[i] = point;
}
return points;
}
}
|