]> gitweb.fperrin.net Git - GpsPrune.git/blob - tim/prune/threedee/TerrainPatch.java
10f0b6ee1c4c1fb3492a20e9537950c5c92d13ba
[GpsPrune.git] / tim / prune / threedee / TerrainPatch.java
1 package tim.prune.threedee;
2
3 public class TerrainPatch
4 {
5         private int      _gridSize = 0;
6         private double[] _altitudes = null;
7         private int[]    _tempDists = null;
8
9         /**
10          * Constructor
11          * @param inGridSize size of grid edge
12          */
13         public TerrainPatch(int inGridSize)
14         {
15                 _gridSize = inGridSize;
16                 int numNodes = inGridSize * inGridSize;
17                 _altitudes = new double[numNodes];
18                 _tempDists = new int[numNodes];
19         }
20
21         /**
22          * Add an altitude interpolation to the mix
23          * @param inPointIndex point index to array
24          * @param inValue altitude value in metres
25          * @param inGapIndex index of point within gap, from 1 to gapLength-1
26          * @param inGapLength length of gap, minimum 2
27          */
28         public void addAltitude(int inPointIndex, double inValue, int inGapIndex, int inGapLength)
29         {
30                 final int dist = Math.min(inGapIndex, inGapLength-inGapIndex);
31                 if (_tempDists[inPointIndex] == 0)
32                 {
33                         if (_altitudes[inPointIndex] > 0.0) System.err.println("Altitude shouldn't be 0 if dist is 0!");
34                         // first point
35                         _altitudes[inPointIndex] = inValue;
36                         _tempDists[inPointIndex] = dist;
37                 }
38                 else
39                 {
40                         // second point
41                         final double firstValue = _altitudes[inPointIndex];
42                         final int firstDist     = _tempDists[inPointIndex];
43                         final double firstWeight = dist * 1.0 / (dist + firstDist);
44                         final double secondWeight= firstDist * 1.0 / (dist + firstDist);
45                         _altitudes[inPointIndex] = firstWeight * firstValue + secondWeight * inValue;
46                         _tempDists[inPointIndex] = 0;
47                 }
48         }
49
50         /**
51          * Smooth the patch to reduce blockiness
52          */
53         public void smooth()
54         {
55                 double[] altCopy = new double[_altitudes.length];
56                 for (int i=0; i<_gridSize; i++)
57                 {
58                         for (int j=0; j<_gridSize; j++)
59                         {
60                                 if (hasAltitude(i, j) && hasAltitude(i-1, j) && hasAltitude(i+1, j)
61                                         && hasAltitude(i, j+1) && hasAltitude(i-1, j+1) && hasAltitude(i+1, j+1)
62                                         && hasAltitude(i, j-1) && hasAltitude(i-1, j-1) && hasAltitude(i+1, j-1))
63                                 {
64                                         // got a 3x3 square, can do a blur
65                                         double alt = (getAltitude(i, j) + getAltitude(i-1, j) + getAltitude(i+1, j)
66                                                 + getAltitude(i, j+1) + getAltitude(i-1, j+1) + getAltitude(i+1, j+1)
67                                                 + getAltitude(i, j-1) + getAltitude(i-1, j-1) + getAltitude(i+1, j-1)) / 9.0;
68                                         altCopy[i * _gridSize + j] = alt;
69                                 }
70                         }
71                 }
72                 // Copy results back
73                 for (int k=0; k<altCopy.length; k++)
74                 {
75                         if (altCopy[k] > 0.0)
76                         {
77                                 _altitudes[k] = altCopy[k];
78                         }
79                 }
80         }
81
82         /**
83          * @param inI first index
84          * @param inJ second index
85          * @return true if there is an altitude in the patch in this position
86          */
87         private boolean hasAltitude(int inI, int inJ)
88         {
89                 return inI >= 0 && inI < _gridSize && inJ >= 0 && inJ < _gridSize
90                         && _altitudes[inI * _gridSize + inJ] > 0.0;
91         }
92
93         /**
94          * @param inI first index
95          * @param inJ second index
96          * @return true if there is an altitude in the patch in this position
97          */
98         private double getAltitude(int inI, int inJ)
99         {
100                 if (inI >= 0 && inI < _gridSize && inJ >= 0 && inJ < _gridSize)
101                 {
102                         return _altitudes[inI * _gridSize + inJ];
103                 }
104                 return 0.0;
105         }
106
107         /**
108          * @param inPointIndex point index
109          * @return altitude value
110          */
111         public double getAltitude(int inPointIndex)
112         {
113                 if (_tempDists[inPointIndex] != 0) System.err.println("Dists should be 0 if we're retrieving!");
114                 return _altitudes[inPointIndex];
115         }
116 }