Skip to content

Commit

Permalink
Use 1/9 Arcsecond Elevation Data (#155)
Browse files Browse the repository at this point in the history
  • Loading branch information
rsarathy authored Jul 23, 2024
1 parent b98eff4 commit 5f19853
Show file tree
Hide file tree
Showing 7 changed files with 116 additions and 47 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,11 @@ public abstract class AbstractTiffElevationProvider extends TileBasedElevationPr
final int HEIGHT;

// Degrees of latitude covered by this tile
final int LAT_DEGREE;
final double LAT_DEGREE;
// Degrees of longitude covered by this tile
final int LON_DEGREE;
final double LON_DEGREE;

public AbstractTiffElevationProvider(String baseUrl, String cacheDir, String downloaderName, int width, int height, int latDegree, int lonDegree) {
public AbstractTiffElevationProvider(String baseUrl, String cacheDir, String downloaderName, int width, int height, double latDegree, double lonDegree) {
super(cacheDir);
this.baseUrl = baseUrl;
this.downloader = new Downloader(downloaderName).setTimeout(10000);
Expand Down Expand Up @@ -74,12 +74,12 @@ public void release() {
/**
* The smallest lat that is still in the HeightTile
*/
abstract int getMinLatForTile(double lat);
abstract double getMinLatForTile(double lat);

/**
* The smallest lon that is still in the HeightTile
*/
abstract int getMinLonForTile(double lon);
abstract double getMinLonForTile(double lon);

/**
* Specify the name of the file after downloading
Expand Down Expand Up @@ -110,8 +110,8 @@ public double getEle(double lat, double lon) {
if (!cacheDir.exists())
cacheDir.mkdirs();

int minLat = getMinLatForTile(lat);
int minLon = getMinLonForTile(lon);
double minLat = getMinLatForTile(lat);
double minLon = getMinLonForTile(lon);
// less restrictive against boundary checking
demProvider = new HeightTile(minLat, minLon, WIDTH, HEIGHT, LON_DEGREE * precision, LON_DEGREE, LAT_DEGREE);
demProvider.setInterpolate(interpolate);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,9 +118,9 @@ Raster generateRasterFromFile(File file, String tifName) {

int down(double val) {
// 'rounding' to closest 5
int intVal = (int) (val / LAT_DEGREE) * LAT_DEGREE;
int intVal = (int) ((int) (val / LAT_DEGREE) * LAT_DEGREE);
if (!(val >= 0 || intVal - val < invPrecision))
intVal = intVal - LAT_DEGREE;
intVal = (int) (intVal - LAT_DEGREE);

return intVal;
}
Expand Down Expand Up @@ -151,12 +151,12 @@ protected String getFileName(double lat, double lon) {
}

@Override
int getMinLatForTile(double lat) {
double getMinLatForTile(double lat) {
return down(lat);
}

@Override
int getMinLonForTile(double lon) {
double getMinLonForTile(double lon) {
return down(lon);
}

Expand Down
20 changes: 10 additions & 10 deletions core/src/main/java/com/graphhopper/reader/dem/GMTEDProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,15 +154,15 @@ Raster generateRasterFromFile(File file, String tifName) {
}
}

int getMinLatForTile(double lat) {
double getMinLatForTile(double lat) {
return (int) (Math.floor((90 + lat) / LAT_DEGREE) * LAT_DEGREE) - 90;
}

int getMinLonForTile(double lon) {
double getMinLonForTile(double lon) {
return (int) (Math.floor((180 + lon) / LON_DEGREE) * LON_DEGREE) - 180;
}

private String getLonString(int lonInt) {
private String getLonString(double lonInt) {
lonInt = Math.abs(lonInt);
String lonString = lonInt < 100 ? "0" : "";
if (lonInt < 10)
Expand All @@ -171,7 +171,7 @@ private String getLonString(int lonInt) {
return lonString;
}

private String getLatString(int latInt) {
private String getLatString(double latInt) {
latInt = Math.abs(latInt);
String latString = latInt < 10 ? "0" : "";
latString += latInt;
Expand All @@ -184,14 +184,14 @@ boolean isOutsideSupportedArea(double lat, double lon) {
}

String getFileName(double lat, double lon) {
int lonInt = getMinLonForTile(lon);
int latInt = getMinLatForTile(lat);
double lonInt = getMinLonForTile(lon);
double latInt = getMinLatForTile(lat);
return toLowerCase(getLatString(latInt) + getNorthString(latInt) + getLonString(lonInt) + getEastString(lonInt) + FILE_NAME_END);
}

String getDownloadURL(double lat, double lon) {
int lonInt = getMinLonForTile(lon);
int latInt = getMinLatForTile(lat);
double lonInt = getMinLonForTile(lon);
double latInt = getMinLatForTile(lat);
String east = getEastString(lonInt);
String lonString = getLonString(lonInt);
return baseUrl + "/" + east + lonString + "/" + getLatString(latInt) + getNorthString(latInt) + lonString + east + FILE_NAME_END + ".tif";
Expand All @@ -202,14 +202,14 @@ String getFileNameOfLocalFile(double lat, double lon) {
return getFileName(lat, lon) + ".tif";
}

private String getNorthString(int lat) {
private String getNorthString(double lat) {
if (lat < 0) {
return "S";
}
return "N";
}

private String getEastString(int lon) {
private String getEastString(double lon) {
if (lon < 0) {
return "W";
}
Expand Down
10 changes: 5 additions & 5 deletions core/src/main/java/com/graphhopper/reader/dem/HeightTile.java
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@
* @author Peter Karich
*/
public class HeightTile {
private final int minLat;
private final int minLon;
private final double minLat;
private final double minLon;
private final int width;
private final int height;
private final int horizontalDegree;
private final int verticalDegree;
private final double horizontalDegree;
private final double verticalDegree;
private final double lowerBound;
private final double lonHigherBound;
private final double latHigherBound;
Expand All @@ -47,7 +47,7 @@ public class HeightTile {
private final double MIN_ELEVATION_METERS = -12_000;
private final double MAX_ELEVATION_METERS = 9_000;

public HeightTile(int minLat, int minLon, int width, int height, double precision, int horizontalDegree, int verticalDegree) {
public HeightTile(double minLat, double minLon, int width, int height, double precision, double horizontalDegree, double verticalDegree) {
this.minLat = minLat;
this.minLon = minLon;
this.width = width;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@ public class MultiSourceElevationProvider extends TileBasedElevationProvider {
// The fallback provider that provides elevation data globally
private final TileBasedElevationProvider fallback;

// While we may have precise elevation data for certain coordinates lying
// on the edges of a defined supported area, a TileElevationProvider's
// implementation could result in a situation where it requests elevation
// data from an adjacent tile instead, in consistency with its naming
// convention.
//
// Removing a small buffer region from the supported area eliminates this
// literal edge case.
private final double DEGREES_BUFFER = 0.001;

public MultiSourceElevationProvider(
TileBasedElevationProvider primary,
TileBasedElevationProvider fallback) {
Expand All @@ -50,7 +60,8 @@ public MultiSourceElevationProvider(String cacheDir) {

@Override
public double getEle(double lat, double lon) {
if (lat > 37 && lat < 38 && lon > -123 && lon < -122)
if (lat > 37.5 + DEGREES_BUFFER && lat < 38.25 - DEGREES_BUFFER &&
lon > -122.75 + DEGREES_BUFFER && lon < -122 - DEGREES_BUFFER)
return primary.getEle(lat, lon);
return fallback.getEle(lat, lon);
}
Expand Down
58 changes: 38 additions & 20 deletions core/src/main/java/com/graphhopper/reader/dem/USGSProvider.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@

public class USGSProvider extends AbstractTiffElevationProvider {

String filename = "n38w123";

public USGSProvider(String cacheDir) {
this("", cacheDir, "", 10812, 10812, 1, 1);
this("", cacheDir, "", 8112, 8112, 0.25, 0.25);
}

public USGSProvider(String baseUrl, String cacheDir,
String downloaderName, int width, int height, int latDegree,
int lonDegree) {
String downloaderName, int width, int height, double latDegree,
double lonDegree) {
super(baseUrl, cacheDir, downloaderName, width, height, latDegree,
lonDegree);
}
Expand All @@ -32,34 +30,54 @@ public static void main(String[] args) {
// Market Street ~-5ft to 260ft in prod.
System.out.println("Elevation: " + elevationProvider.getEle(37.7903317182555, -122.39999824547087) + "m");
System.out.println("Elevation: " + elevationProvider.getEle(37.79112431722635, -122.39901032204128) + "m");

// Mount Davidson, expected: ~283m
System.out.println("Elevation: " + elevationProvider.getEle(37.738259, -122.45463) + "m");
}

@Override
boolean isOutsideSupportedArea(double lat, double lon) {
return lat < 37 || lat > 38 || lon < -123 || lon > -122;
return lat < 37.5 || lat > 38.25 || lon < -122.75 || lon > -122;
}

@Override
int getMinLatForTile(double lat) {
return 37;
double getMinLatForTile(double lat) {
return Math.floor(lat * 4) / 4;
}

@Override
int getMinLonForTile(double lon) {
return -123;
double getMinLonForTile(double lon) {
return Math.floor(lon * 4) / 4;
}

@Override
String getFileNameOfLocalFile(double lat, double lon) {
return filename + ".tif";
return getFileName(lat, lon) + ".tif";
}

/**
* The USGS National Elevation Dataset (NED)'s 1/9th arc-second DEM offering
* categorizes individual 0.25x0.25 degree tiles using the northwestern
* corner of each tile. For example, <i>ned19_n37x75_w122x50</i> means that
* the corners of the tile are (starting from the northwestern corner and
* moving clockwise):
* <ul>
* <li>37.75, -122.50</li>
* <li>37.75, -122.25</li>
* <li>37.50, -122.25</li>
* <li>37.50, -122.50</li>
* </ul>
* @param lat latitude in degrees, ranges from [-90.0, 90.0]
* @param lon longitude in degrees, ranges from [-180.0, 180.0]
* @return Filename in format ned19_{n,s}AAxAA_{e,w}BBBxBB;
* AAxAA being latitude in degrees and BBBxBB being longitude in degrees
*/
@Override
String getFileName(double lat, double lon) {
return filename;
double latAdjusted = Math.abs(Math.ceil(lat * 4) / 4);
int latDecimals = (int)(latAdjusted * 100) % 100;

double lonAdjusted = Math.abs(getMinLonForTile(lon));
int lonDecimals = (int)(lonAdjusted * 100) % 100;

return String.format("ned19_n%dx%02d_w%dx%02d", (int) latAdjusted, latDecimals, (int) lonAdjusted, lonDecimals);
}

@Override
Expand All @@ -79,8 +97,8 @@ public double getEle(double lat, double lon) {
if (demProvider == null) {
if (!cacheDir.exists()) cacheDir.mkdirs();

int minLat = getMinLatForTile(lat);
int minLon = getMinLonForTile(lon);
double minLat = getMinLatForTile(lat);
double minLon = getMinLonForTile(lon);
// less restrictive against boundary checking
demProvider = new HeightTile(minLat, minLon, WIDTH, HEIGHT,
LON_DEGREE * precision, LON_DEGREE, LAT_DEGREE);
Expand All @@ -101,11 +119,9 @@ public double getEle(double lat, double lon) {
new File(getFileNameOfLocalFile(lat, lon)).getName());

// short == 2 bytes
heights.create(2 * WIDTH * HEIGHT);

heights.create(2L * WIDTH * HEIGHT);
Raster raster = generateRasterFromFile(file, name + ".tif");
super.fillDataAccessWithElevationData(raster, heights, WIDTH);

} // loadExisting
}

Expand All @@ -128,4 +144,6 @@ Raster generateRasterFromFile(File file, String tifName) {
close(ss);
}
}

public String toString() { return "usgs"; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.graphhopper.reader.dem;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.jupiter.api.Test;

class USGSProviderTest {

USGSProvider provider = new USGSProvider("");

@Test
public void testMinLat() {
assertEquals(37.75, provider.getMinLatForTile(37.76));
assertEquals(37.75, provider.getMinLatForTile(37.75));
assertEquals(37.5, provider.getMinLatForTile(37.74));

assertEquals(-38, provider.getMinLatForTile(-37.76));
assertEquals(-37.75, provider.getMinLatForTile(-37.75));
assertEquals(-37.75, provider.getMinLatForTile(-37.74));
}

@Test
public void testMinLon() {
assertEquals(122.25, provider.getMinLonForTile(122.26));
assertEquals(122.25, provider.getMinLonForTile(122.25));
assertEquals(122, provider.getMinLonForTile(122.24));

assertEquals(-122.5, provider.getMinLonForTile(-122.26));
assertEquals(-122.25, provider.getMinLonForTile(-122.25));
assertEquals(-122.25, provider.getMinLonForTile(-122.24));
}

@Test
public void testFilename() {
assertEquals("ned19_n38x00_w122x50",
provider.getFileName(38, -122.5));
assertEquals("ned19_n38x00_w122x50",
provider.getFileName(37.76, -122.26));
}
}

0 comments on commit 5f19853

Please sign in to comment.