Statistics
| Revision:

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
}