root / org.gvsig.toolbox / trunk / org.gvsig.toolbox / org.gvsig.toolbox.algorithm / src / main / java / es / unex / sextante / vectorTools / smoothLines / NatCubic.java @ 59
History | View | Annotate | Download (3.34 KB)
1 |
/*********************************************************
|
---|---|
2 |
* Code adapted from Tim Lambert's Java Classes
|
3 |
* http://www.cse.unsw.edu.au/~lambert/
|
4 |
*********************************************************/
|
5 |
package es.unex.sextante.vectorTools.smoothLines; |
6 |
|
7 |
import java.util.ArrayList; |
8 |
|
9 |
import com.vividsolutions.jts.geom.Coordinate; |
10 |
import com.vividsolutions.jts.geom.Geometry; |
11 |
import com.vividsolutions.jts.geom.GeometryFactory; |
12 |
import com.vividsolutions.jts.geom.LineString; |
13 |
|
14 |
public class NatCubic |
15 |
extends
|
16 |
ControlCurve { |
17 |
|
18 |
/* calculates the natural cubic spline that interpolates
|
19 |
y[0], y[1], ... y[n]
|
20 |
The first segment is returned as
|
21 |
C[0].a + C[0].b*u + C[0].c*u^2 + C[0].d*u^3 0<=u <1
|
22 |
the other segments are in C[1], C[2], ... C[n-1] */
|
23 |
|
24 |
public NatCubic(final Geometry geom) { |
25 |
|
26 |
super(geom);
|
27 |
|
28 |
} |
29 |
|
30 |
|
31 |
Cubic[] calcNaturalCubic(final int n, |
32 |
final double[] x) { |
33 |
final double[] gamma = new double[n + 1]; |
34 |
final double[] delta = new double[n + 1]; |
35 |
final double[] D = new double[n + 1]; |
36 |
int i;
|
37 |
/* We solve the equation
|
38 |
[2 1 ] [D[0]] [3(x[1] - x[0]) ]
|
39 |
|1 4 1 | |D[1]| |3(x[2] - x[0]) |
|
40 |
| 1 4 1 | | . | = | . |
|
41 |
| ..... | | . | | . |
|
42 |
| 1 4 1| | . | |3(x[n] - x[n-2])|
|
43 |
[ 1 2] [D[n]] [3(x[n] - x[n-1])]
|
44 |
|
45 |
by using row operations to convert the matrix to upper triangular
|
46 |
and then back sustitution. The D[i] are the derivatives at the knots.
|
47 |
*/
|
48 |
|
49 |
gamma[0] = 1.0f / 2.0f; |
50 |
for (i = 1; i < n; i++) { |
51 |
gamma[i] = 1 / (4 - gamma[i - 1]); |
52 |
} |
53 |
gamma[n] = 1 / (2 - gamma[n - 1]); |
54 |
|
55 |
delta[0] = 3 * (x[1] - x[0]) * gamma[0]; |
56 |
for (i = 1; i < n; i++) { |
57 |
delta[i] = (3 * (x[i + 1] - x[i - 1]) - delta[i - 1]) * gamma[i]; |
58 |
} |
59 |
delta[n] = (3 * (x[n] - x[n - 1]) - delta[n - 1]) * gamma[n]; |
60 |
|
61 |
D[n] = delta[n]; |
62 |
for (i = n - 1; i >= 0; i--) { |
63 |
D[i] = delta[i] - gamma[i] * D[i + 1];
|
64 |
} |
65 |
|
66 |
/* now compute the coefficients of the cubics */
|
67 |
final Cubic[] C = new Cubic[n]; |
68 |
for (i = 0; i < n; i++) { |
69 |
C[i] = new Cubic(x[i], D[i], 3 * (x[i + 1] - x[i]) - 2 * D[i] - D[i + 1], 2 * (x[i] - x[i + 1]) + D[i] + D[i + 1]); |
70 |
} |
71 |
return C;
|
72 |
} |
73 |
|
74 |
|
75 |
@Override
|
76 |
public LineString getSmoothedLine(final int iSteps) { |
77 |
|
78 |
final ArrayList<Coordinate> coords = new ArrayList<Coordinate>(); |
79 |
|
80 |
if (m_X.length >= 2) { |
81 |
final Cubic[] X = calcNaturalCubic(m_X.length - 1, m_X); |
82 |
final Cubic[] Y = calcNaturalCubic(m_Y.length - 1, m_Y); |
83 |
|
84 |
/* very crude technique - just break each segment up into steps lines */
|
85 |
coords.add(new Coordinate((int) Math.round(X[0].eval(0)), (int) Math.round(Y[0].eval(0)))); |
86 |
for (int i = 0; i < X.length; i++) { |
87 |
for (int j = 1; j <= iSteps; j++) { |
88 |
final float u = j / (float) iSteps; |
89 |
coords.add(new Coordinate(X[i].eval(u), Y[i].eval(u)));
|
90 |
} |
91 |
} |
92 |
|
93 |
return new GeometryFactory().createLineString((Coordinate[]) coords.toArray(new Coordinate[0])); |
94 |
|
95 |
} |
96 |
else {
|
97 |
return new GeometryFactory().createLineString(m_Geometry.getCoordinates()); |
98 |
} |
99 |
|
100 |
} |
101 |
|
102 |
|
103 |
} |