Skip to content

Commit 1b1c22c

Browse files
authored
Merge pull request graphhopper#1228 from boldtrn/gmted20102
Importing GMTED2010 elevation data and MultiSourceElevationProvider
2 parents b9d4b83 + a4060c0 commit 1b1c22c

File tree

11 files changed

+786
-178
lines changed

11 files changed

+786
-178
lines changed

config-example.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ graph.flag_encoders=car
1414
##### Elevation #####
1515

1616

17-
# To populate your graph with elevation data use SRTM, default is noop (no elevation)
17+
# Per default GraphHopper doesn't use elevation data, you can enable elevation by setting graph.elevation.provider
18+
# to srtm, cgiar, gmted, or multi. See the corresponding classes at com.graphhopper.reader.dem for more information.
1819
# graph.elevation.provider=srtm
1920

2021

core/src/main/java/com/graphhopper/GraphHopper.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -576,10 +576,15 @@ public GraphHopper init(CmdArgs args) {
576576
CGIARProvider cgiarProvider = new CGIARProvider();
577577
cgiarProvider.setAutoRemoveTemporaryFiles(args.getBool("graph.elevation.cgiar.clear", true));
578578
tmpProvider = cgiarProvider;
579+
} else if (eleProviderStr.equalsIgnoreCase("gmted")) {
580+
tmpProvider = new GMTEDProvider();
581+
} else if (eleProviderStr.equalsIgnoreCase("multi")) {
582+
tmpProvider = new MultiSourceElevationProvider();
579583
}
580584

581585
tmpProvider.setCalcMean(eleCalcMean);
582-
tmpProvider.setCacheDir(new File(cacheDirStr));
586+
if (!cacheDirStr.isEmpty())
587+
tmpProvider.setCacheDir(new File(cacheDirStr));
583588
if (!baseURL.isEmpty())
584589
tmpProvider.setBaseURL(baseURL);
585590
tmpProvider.setDAType(elevationDAType);
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Licensed to GraphHopper GmbH under one or more contributor
3+
* license agreements. See the NOTICE file distributed with this work for
4+
* additional information regarding copyright ownership.
5+
*
6+
* GraphHopper GmbH licenses this file to you under the Apache License,
7+
* Version 2.0 (the "License"); you may not use this file except in
8+
* compliance with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package com.graphhopper.reader.dem;
19+
20+
import com.graphhopper.storage.DAType;
21+
import com.graphhopper.storage.DataAccess;
22+
import com.graphhopper.storage.Directory;
23+
import com.graphhopper.storage.GHDirectory;
24+
import com.graphhopper.util.Downloader;
25+
import org.slf4j.Logger;
26+
import org.slf4j.LoggerFactory;
27+
28+
import java.awt.image.Raster;
29+
import java.io.File;
30+
import java.io.IOException;
31+
import java.net.SocketTimeoutException;
32+
import java.util.HashMap;
33+
import java.util.Map;
34+
35+
/**
36+
* Provides basic methods that are usually used in an ElevationProvider that reads tiff files.
37+
*
38+
* @author Robin Boldt
39+
*/
40+
public abstract class AbstractTiffElevationProvider implements ElevationProvider {
41+
final Logger logger = LoggerFactory.getLogger(getClass());
42+
final Map<String, HeightTile> cacheData = new HashMap<String, HeightTile>();
43+
protected Downloader downloader;
44+
File cacheDir;
45+
String baseUrl;
46+
private Directory dir;
47+
private DAType daType = DAType.MMAP;
48+
boolean calcMean = false;
49+
boolean autoRemoveTemporary = true;
50+
long sleep = 2000;
51+
52+
public AbstractTiffElevationProvider(String baseUrl, String cacheDir, String downloaderName) {
53+
this.baseUrl = baseUrl;
54+
this.cacheDir = new File(cacheDir);
55+
downloader = new Downloader(downloaderName).setTimeout(10000);
56+
}
57+
58+
@Override
59+
public void setCalcMean(boolean eleCalcMean) {
60+
calcMean = eleCalcMean;
61+
}
62+
63+
void setSleep(long sleep) {
64+
this.sleep = sleep;
65+
}
66+
67+
/**
68+
* Creating temporary files can take a long time as we need to unpack tiff as well as to fill
69+
* our DataAccess object, so this option can be used to disable the default clear mechanism via
70+
* specifying 'false'.
71+
*/
72+
public void setAutoRemoveTemporaryFiles(boolean autoRemoveTemporary) {
73+
this.autoRemoveTemporary = autoRemoveTemporary;
74+
}
75+
76+
public void setDownloader(Downloader downloader) {
77+
this.downloader = downloader;
78+
}
79+
80+
@Override
81+
public ElevationProvider setCacheDir(File cacheDir) {
82+
if (cacheDir.exists() && !cacheDir.isDirectory())
83+
throw new IllegalArgumentException("Cache path has to be a directory");
84+
try {
85+
this.cacheDir = cacheDir.getCanonicalFile();
86+
} catch (IOException ex) {
87+
throw new RuntimeException(ex);
88+
}
89+
return this;
90+
}
91+
92+
protected File getCacheDir() {
93+
return cacheDir;
94+
}
95+
96+
@Override
97+
public ElevationProvider setBaseURL(String baseUrl) {
98+
if (baseUrl == null || baseUrl.isEmpty())
99+
throw new IllegalArgumentException("baseUrl cannot be empty");
100+
101+
this.baseUrl = baseUrl;
102+
return this;
103+
}
104+
105+
@Override
106+
public ElevationProvider setDAType(DAType daType) {
107+
this.daType = daType;
108+
return this;
109+
}
110+
111+
112+
@Override
113+
public void release() {
114+
cacheData.clear();
115+
116+
// for memory mapped type we create temporary unpacked files which should be removed
117+
if (autoRemoveTemporary && dir != null)
118+
dir.clear();
119+
}
120+
121+
/**
122+
* Download a file at the provided url and save it as the given downloadFile if the downloadFile does not exist.
123+
*/
124+
protected void downloadFile(File downloadFile, String url) throws IOException {
125+
if (!downloadFile.exists()) {
126+
int max = 3;
127+
for (int trial = 0; trial < max; trial++) {
128+
try {
129+
downloader.downloadFile(url, downloadFile.getAbsolutePath());
130+
return;
131+
} catch (SocketTimeoutException ex) {
132+
if (trial >= max - 1)
133+
throw new RuntimeException(ex);
134+
try {
135+
Thread.sleep(sleep);
136+
} catch (InterruptedException ignored) {
137+
}
138+
}
139+
}
140+
}
141+
}
142+
143+
protected void fillDataAccessWithElevationData(Raster raster, DataAccess heights, int dataAccessWidth) {
144+
final int height = raster.getHeight();
145+
final int width = raster.getWidth();
146+
int x = 0;
147+
int y = 0;
148+
try {
149+
for (y = 0; y < height; y++) {
150+
for (x = 0; x < width; x++) {
151+
short val = (short) raster.getPixel(x, y, (int[]) null)[0];
152+
if (val < -1000 || val > 12000)
153+
val = Short.MIN_VALUE;
154+
155+
heights.setShort(2 * (y * dataAccessWidth + x), val);
156+
}
157+
}
158+
heights.flush();
159+
160+
// TODO remove tifName and zip?
161+
} catch (Exception ex) {
162+
throw new RuntimeException("Problem at x:" + x + ", y:" + y, ex);
163+
}
164+
}
165+
166+
protected Directory getDirectory() {
167+
if (dir != null)
168+
return dir;
169+
170+
logger.info(this.toString() + " Elevation Provider, from: " + baseUrl + ", to: " + cacheDir + ", as: " + daType);
171+
return dir = new GHDirectory(cacheDir.getAbsolutePath(), daType);
172+
}
173+
}

0 commit comments

Comments
 (0)