// License: GPL. For details, see LICENSE file. package btools.mapcreator; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.InputStream; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.ShortBuffer; import java.nio.channels.FileChannel; import java.util.HashMap; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; /** * adapted from https://github.com/JOSM/josm-plugins/blob/master/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java *
* Class HgtReader reads data from SRTM HGT files. Currently this class is restricted to a resolution of 3 arc seconds. *
* SRTM data files are available at the NASA SRTM site
*
* @author Oliver Wieland <oliver.wieland@online.de>
*/
public class HgtReader {
final static boolean DEBUG = false;
private static final int SECONDS_PER_MINUTE = 60;
public static final String HGT_EXT = ".hgt";
public static final String ZIP_EXT = ".zip";
// alter these values for different SRTM resolutions
public static final int HGT3_RES = 3; // resolution in arc seconds
public static final int HGT3_ROW_LENGTH = 1201; // number of elevation values per line
public static final int HGT_VOID = -32768; // magic number which indicates 'void data' in HGT file
public static final int HGT1_RES = 1; // <<- The new SRTM is 1-ARCSEC
public static final int HGT1_ROW_LENGTH = 3601; //-- New file resolution is 3601x3601
/**
* The 'no elevation' data magic.
*/
public static double NO_ELEVATION = Double.NaN;
private static String srtmFolder = "";
private static final Map
* See also stackexchange.com
*
* @param lat, lon the coordinate to get the elevation data for
* @return the elevation value or Double.NaN
, if no value is present
*/
public static double readElevation(double lat, double lon) {
String tag = getHgtFileName(lat, lon);
ShortBuffer sb = cache.get(tag);
if (sb == null) {
return NO_ELEVATION;
}
if (DEBUG) System.out.println("SRTM buffer size " + sb.capacity() + " limit " + sb.limit());
try {
int rowLength = HGT3_ROW_LENGTH;
int resolution = HGT3_RES;
if (sb.capacity() > (HGT3_ROW_LENGTH * HGT3_ROW_LENGTH)) {
rowLength = HGT1_ROW_LENGTH;
resolution = HGT1_RES;
}
// see http://gis.stackexchange.com/questions/43743/how-to-extract-elevation-from-hgt-file
double fLat = frac(lat) * SECONDS_PER_MINUTE;
double fLon = frac(lon) * SECONDS_PER_MINUTE;
// compute offset within HGT file
int row = (int) Math.round((fLat) * SECONDS_PER_MINUTE / resolution);
int col = (int) Math.round((fLon) * SECONDS_PER_MINUTE / resolution);
if (lon < 0) col = rowLength - col - 1;
if (lat > 0) row = rowLength - row - 1;
//row = rowLength - row;
int cell = (rowLength * (row)) + col;
//int cell = ((rowLength * (latitude)) + longitude);
if (DEBUG)
System.out.println("Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + ", " + sb.limit());
// valid position in buffer?
if (cell < sb.limit()) {
short ele = sb.get(cell);
// check for data voids
if (ele == HGT_VOID) {
return NO_ELEVATION;
} else {
return ele;
}
} else {
return NO_ELEVATION;
}
} catch (Exception e) {
System.err.println("error at " + lon + " " + lat + " ");
e.printStackTrace();
}
return NO_ELEVATION;
}
/**
* Gets the associated HGT file name for the given way point. Usually the
* format is [N|S]nn[W|E]mmm.hgt where nn is the integral latitude
* without decimals and mmm is the longitude.
*
* @param llat,llon the coordinate to get the filename for
* @return the file name of the HGT file
*/
public static String getHgtFileName(double llat, double llon) {
int lat = (int) llat;
int lon = (int) llon;
String latPref = "N";
if (lat < 0) {
latPref = "S";
lat = -lat + 1;
}
String lonPref = "E";
if (lon < 0) {
lonPref = "W";
lon = -lon + 1;
}
return String.format("%s%02d%s%03d", latPref, lat, lonPref, lon);
}
public static double frac(double d) {
long iPart;
double fPart;
// Get user input
iPart = (long) d;
fPart = d - iPart;
return Math.abs(fPart);
}
public static void clear() {
if (cache != null) {
cache.clear();
}
}
}