X-Git-Url: http://gitweb.fperrin.net/?p=GpsPrune.git;a=blobdiff_plain;f=src%2Ftim%2Fprune%2Fthreedee%2FTerrainHelper.java;fp=src%2Ftim%2Fprune%2Fthreedee%2FTerrainHelper.java;h=ffe9db888d1ea443ebf1f488d9d4e0e0cc9d9106;hp=0000000000000000000000000000000000000000;hb=ce6f2161b8596f7018d6a76bff79bc9e571f35fd;hpb=2d8cb72e84d5cc1089ce77baf1e34ea3ea2f8465 diff --git a/src/tim/prune/threedee/TerrainHelper.java b/src/tim/prune/threedee/TerrainHelper.java new file mode 100644 index 0000000..ffe9db8 --- /dev/null +++ b/src/tim/prune/threedee/TerrainHelper.java @@ -0,0 +1,477 @@ +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 int cellIndex1 = inCornerIndex + prevIndexWithAlt * inInc; + final double alt1 = inTerrainTrack.getPoint(cellIndex1).getAltitude().getMetricValue(); + final int cellIndex2 = inCornerIndex + i * inInc; + final double alt2 = inTerrainTrack.getPoint(cellIndex2).getAltitude().getMetricValue(); + //System.out.println("Altitude along edge goes from " + alt1 + " (at " + prevIndexWithAlt + ") to " + + // alt2 + " (at " + i + ")"); + for (int j = 1; j < gapLen; j++) + { + final double alt = alt1 + (alt2-alt1) * j / gapLen; + //System.out.println("Fill in " + (prevIndexWithAlt + j) + "(" + (inCornerIndex + (prevIndexWithAlt + j) * inInc) + ") with alt " + (int) alt); + final DataPoint p = inTerrainTrack.getPoint(inCornerIndex + (prevIndexWithAlt + j) * inInc); + p.setFieldValue(Field.ALTITUDE, "" + (int) alt, false); + // TODO: Check forcing metres? + } + } + prevIndexWithAlt = i; + } + } + } + + /** + * Try to fix bigger holes by interpolating between neighbours + * @param inTerrainTrack terrain track + */ + private void fixBiggerHoles(Track inTerrainTrack) + { + TerrainPatch patch = new TerrainPatch(_gridSize); + 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); + patch.addAltitude(i * _gridSize + k, val, k-prevHoriz, j-prevHoriz); + } + } + 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); + patch.addAltitude(k * _gridSize + i, val, k-prevVert, j-prevVert); + } + } + prevVert = j; + } + } + } + // Smooth the patch to reduce the blocky effect from the voids + patch.smooth(); + + // Now the doubles have been set and averaged, we can set the values in the points + for (int i=0; i