package tim.prune.threedee; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; import javax.vecmath.Point3d; import javax.vecmath.TexCoord2f; import tim.prune.data.Altitude; import tim.prune.data.Coordinate; import tim.prune.data.DataPoint; import tim.prune.data.DoubleRange; import tim.prune.data.Field; import tim.prune.data.FieldList; import tim.prune.data.Latitude; import tim.prune.data.Longitude; import tim.prune.data.Track; import tim.prune.data.TrackExtents; import tim.prune.data.UnitSetLibrary; import tim.prune.gui.map.MapUtils; /** * Helper for generating the arrays needed for the 3d terrain */ public class TerrainHelper { /** Number of nodes on each side of the square grid */ private int _gridSize = 0; /** * Constructor * @param inGridSize grid size */ public TerrainHelper(int inGridSize) { _gridSize = inGridSize; } /** * @return grid size */ public int getGridSize() { return _gridSize; } /** * Convert the terrain coordinates from raw form to TriangleStripArray form * (with repeated nodes) * @param inRawPoints array of raw points as formed from the track * @return point coordinates as array */ public Point3d[] getTerrainCoordinates(Point3d[] inRawPoints) { final int numNodes = _gridSize * _gridSize; if (_gridSize <= 1 || inRawPoints == null || inRawPoints.length != numNodes) {return null;} // Put these nodes into a new result array (repeating nodes as necessary) final int resultSize = _gridSize * (_gridSize * 2 - 2); Point3d[] result = new Point3d[resultSize]; final int numStrips = _gridSize - 1; int resultIndex = 0; for (int strip=0; strip= 0 && prevIndexWithAlt < (i-1)) { final int gapLen = i - prevIndexWithAlt; final double alt1 = inTerrainTrack.getPoint(prevIndexWithAlt).getAltitude().getMetricValue(); final double alt2 = inTerrainTrack.getPoint(i).getAltitude().getMetricValue(); for (int j = 1; j < gapLen; j++) { // System.out.println("Fill in " + (prevIndexWithAlt + j) + " using " + prevIndexWithAlt + " and " + i); final double alt = alt1 + (alt2-alt1) * j / gapLen; final DataPoint p = inTerrainTrack.getPoint(inCornerIndex + (prevIndexWithAlt + j) * inInc); p.setFieldValue(Field.ALTITUDE, "" + (int) alt, false); } } prevIndexWithAlt = i; } } } /** * Try to fix bigger holes by interpolating between neighbours * @param inTerrainTrack terrain track */ private void fixBiggerHoles(Track inTerrainTrack) { double[] altitudes = new double[inTerrainTrack.getNumPoints()]; for (int i=0; i<_gridSize; i++) { int prevHoriz = -1, prevVert = -1; for (int j=0; j<_gridSize; j++) { if (inTerrainTrack.getPoint(i * _gridSize + j).hasAltitude()) { if (prevHoriz > -1 && prevHoriz != (j-1)) { // System.out.println("Found a gap for y=" + i +" between x=" + prevHoriz + " and " + j + " (" + (j-prevHoriz-1) + ")"); double startVal = inTerrainTrack.getPoint(i * _gridSize + prevHoriz).getAltitude().getMetricValue(); double endVal = inTerrainTrack.getPoint(i * _gridSize + j).getAltitude().getMetricValue(); for (int k=prevHoriz + 1; k< j; k++) { double val = startVal + (k-prevHoriz) * (endVal-startVal) / (j-prevHoriz); if (altitudes[i * _gridSize + k] > 0.0) { altitudes[i * _gridSize + k] = (altitudes[i * _gridSize + k] + val) / 2.0; } else { altitudes[i * _gridSize + k] = val; } } } prevHoriz = j; } if (inTerrainTrack.getPoint(j * _gridSize + i).hasAltitude()) { if (prevVert > -1 && prevVert != (j-1)) { // System.out.println("Found a gap for x=" + i +" between y=" + prevVert + " and " + j + " (" + (j-prevVert-1) + ")"); double startVal = inTerrainTrack.getPoint(prevVert * _gridSize + i).getAltitude().getMetricValue(); double endVal = inTerrainTrack.getPoint(j * _gridSize + i).getAltitude().getMetricValue(); for (int k=prevVert + 1; k< j; k++) { double val = startVal + (k-prevVert) * (endVal-startVal) / (j-prevVert); if (altitudes[k * _gridSize + i] > 0.0) { altitudes[k * _gridSize + i] = (altitudes[k * _gridSize + i] + val) / 2.0; } else { altitudes[k * _gridSize + i] = val; } } } prevVert = j; } } } // Now the doubles have been set and/or averaged, we can set the values in the points for (int i=0; i 0.0) { p.setFieldValue(Field.ALTITUDE, "" + altitudes[i], false); p.getAltitude().reset(new Altitude((int) altitudes[i], UnitSetLibrary.UNITS_METRES)); } } } }