This patch adds support for maps crossing borders of SRTM (hgt) files.
So its possible to create contour lines for larger areas.
Additional:
- description of contour relevant options
- "dem-increment" option has been modified so it is possible to create
different contour levels (major, medium, minor)
Open issues:
- I am still struggling with using multiple GeoTiff files (CGIAR + ASTER).
- data files have to be loaded manually.
Ronny
Index: resources/help/en/options
===================================================================
--- resources/help/en/options (revision 1580)
+++ resources/help/en/options (working copy)
@@ -370,11 +370,49 @@
--tdbfile
Write a .tdb file.
---show-profiles=1
+--show-profiles=0|1
Sets a flag in tdb file which marks set mapset as having contour
lines and allows showing profile in MapSource. Default is 0
which means disabled.
-
+ DON'T use this option when combining separate tiles with contour
+ lines and real data tiles for the same area. MapSource will crash
+ on them.
+
+--contour
+ Create contour lines. Behaviour is specified by the dem-* options.
+
+--dem-type=[SRTM|ASTER|CGIAR]
+ Defines kind of processed data. Default is SRTM.
+ SRTM data covers earth surface from 60° north to 56° south in 1°x1°
+ plain data files (1201x1201 short int values).
+ See http://www2.jpl.nasa.gov/srtm/
+ CGIAR contains optimized SRTM to fill missing data areas.
+ Data is provided as 5°x5° GeoTiff files.
+ See http://srtm.csi.cgiar.org/
+ ASTER data covers earth surface from 83° north to 83° south and is
+ provided as 1°x1° GeoTiff files.
+ See http://www.gdem.aster.ersdac.or.jp/
+
+--dem-path
+ Location of DEM source data. Currently mkgmap does not load required
+ files from the web.
+
+--dem-increment=10[,0[,0]]
+ Create contour lines for steps with specified increment in meter.
+ The really used increment depends on option --dem-maxlevels.
+ The optional parameters define a factor which contour lines are
+ marked as major (first parameter) and as medium (second). If both
+ are omitted all lines are just marked as "contour=elevation".
+ Example: 20,10,5 results in minor contour every 20 meter, medium
+ contour every 100 meter and major contour every 200 meter.
+
+--dem-maxlevels=100
+ Defines maximum number of different elevation levels. Increment
+ will be doubled while maxlevel is exceeded. Using the default
+ values of 10 for dem-increment and 100 for dem-maxlevels, the
+ active increment will be set to 20 if lowest point of tile is 0
+ and highest point is 1200: 10*100 < 1200 < 20*100
+
--draw-priority=25
When two maps cover the same area, this option controls what
order they are drawn in and therefore which map is on top of
Index: src/uk/me/parabola/mkgmap/reader/dem/DEM.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/dem/DEM.java (revision 1580)
+++ src/uk/me/parabola/mkgmap/reader/dem/DEM.java (working copy)
@@ -28,6 +28,7 @@
import uk.me.parabola.imgfmt.app.Area;
import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.imgfmt.app.map.Map;
+import uk.me.parabola.log.Logger;
import uk.me.parabola.mkgmap.build.MapBuilder;
import uk.me.parabola.mkgmap.general.LevelInfo;
import uk.me.parabola.mkgmap.general.LoadableMapDataSource;
@@ -38,6 +39,7 @@
import uk.me.parabola.mkgmap.reader.osm.OsmConverter;
import uk.me.parabola.mkgmap.reader.osm.Style;
import uk.me.parabola.mkgmap.reader.osm.Way;
+import uk.me.parabola.mkgmap.reader.osm.xml.Osm5XmlHandler;
import uk.me.parabola.util.EnhancedProperties;
@@ -47,6 +49,8 @@
* Adaptive Grid Contouring Algorithm</a> by Downing and Zoraster.
*/
public abstract class DEM {
+ private static final Logger log = Logger.getLogger(DEM.class);
+
final static double epsilon = 1e-9;
final protected static double delta = 1.5;
final static int maxPoints = 200000;
@@ -104,11 +108,43 @@
}
Isolines lines = data.new Isolines(data, minLat, minLon,
maxLat, maxLon);
- int increment = config.getProperty("dem-increment", 10);
+ // get base increment between isolines (meter)
+ int increment = 10;
+ // which levels are marked as major elevation lines (default is
all)
+ int maj_increment = 0;
+ // which levels are marked as medium elevation lines (default
is all)
+ int med_increment = 0;
+ String strInc = config.getProperty("dem-increment", null);
+ if (strInc != null) {
+ String steps[] = strInc.split(",");
+ try {
+ increment = Integer.parseInt(steps[0]);
+ } catch (NumberFormatException ex) {
+ log.error("dem-increment expects list of
numerical data");
+ }
+ if (steps.length > 1) {
+ try {
+ maj_increment =
Integer.parseInt(steps[1]);
+ } catch (NumberFormatException ex) {
+ log.error("dem-increment expects list
of numerical data");
+ }
+ }
+ if (steps.length > 2) {
+ try {
+ med_increment =
Integer.parseInt(steps[1]);
+ } catch (NumberFormatException ex) {
+ log.error("dem-increment expects list
of numerical data");
+ }
+ }
+ }
double minHeight = lines.getMinHeight();
double maxHeight = lines.getMaxHeight();
+ // get maximum number of isolines
int maxLevels = config.getProperty("dem-maxlevels", 100);
+ // adjust increment to ensure no more than maxLevels isolines
are created
+ // e.g. if we have a difference between lowest and highest
point of 1980 increment is increased to 20.
+ // So the only way to ensure fixed increments is to define
dem-maxlevels to a value which will be reached never.
while ((maxHeight - minHeight) / increment > maxLevels)
increment *= 2;
@@ -149,6 +185,14 @@
for (Isolines.Isoline line : lines.isolines) {
Way way = new Way(id--, line.points);
way.addTag("contour", "elevation");
+ if (maj_increment != 0) {
+ if ((level / increment) % maj_increment
== 0)
+ way.addTag("contour_ext",
"elevation_major");
+ else if (med_increment != 0 && ((level
/ increment) % med_increment == 0))
+ way.addTag("contour_ext",
"elevation_medium");
+ else
+ way.addTag("contour_ext",
"elevation_minor");
+ }
way.addTag("ele", String.format("%d", (int)
line.level));
converter.convertWay(way);
}
@@ -687,10 +731,16 @@
// we need some overlap for bicubic interpolation
max = -1000;
min = 10000;
+ double e;
for (int i = minX; i < maxX; i++)
for (int j = minY; j < maxY; j++) {
- if (data.elevation(i, j) < min) min =
data.elevation(i, j);
- if (data.elevation(i, j) > max) max =
data.elevation(i, j);
+ e = data.elevation(i, j);
+ if (e < - 1000) // SRTM marks invalid
values with Short.MIN_VALUE, so don't get confused by this
+ continue;
+ if (e < min)
+ min = e;
+ if (e > max)
+ max = e;
}
debug("min: %f, max: %f\n", min, max);
Index: src/uk/me/parabola/mkgmap/reader/dem/HGTDEM.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/dem/HGTDEM.java (revision 1580)
+++ src/uk/me/parabola/mkgmap/reader/dem/HGTDEM.java (working copy)
@@ -22,44 +22,69 @@
import static java.nio.channels.FileChannel.MapMode.READ_ONLY;
+import java.util.HashMap;
+import java.util.Map;
+
public class HGTDEM extends DEM
{
- MappedByteBuffer buffer = null;
-
+ Map<Integer, MappedByteBuffer> buffers = new HashMap<Integer,
MappedByteBuffer>();
+
+ int nLon; // number of touched files in longitude direction
+ int nLat; // number of touched files in latitude direction
+
public HGTDEM(String dataPath, double minLat, double minLon, double
maxLat, double maxLon)
{
- this.lat = (int) minLat;
- this.lon = (int) minLon;
- if (maxLat > lat+1 || maxLon > lon+1)
- throw new RuntimeException("Area too large (must not span more than
one SRTM file)");
-
- String northSouth = lat < 0 ? "S" : "N";
- String eastWest = lon > 0 ? "E" : "W";
- String fileName = String.format("%s/%s%02d%s%03d.hgt", dataPath,
- northSouth, lat < 0 ? -lat : lat,
- eastWest, lon < 0 ? -lon : lon);
- try {
- FileInputStream is = new FileInputStream(fileName);
- buffer = is.getChannel().map(READ_ONLY, 0, 2*(M+1)*(M+1));
- }
- catch (Exception e) {
- throw new RuntimeException(e);
- }
+ res = 1.0 / M;
+ this.lat = (int) minLat;
+ this.lon = (int) minLon;
+ nLat = (int)maxLat - this.lat + 1;
+ nLon = (int)maxLon - this.lon + 1;
+ if (nLat > nLon)
+ N = M * nLat;
+ else
+ N = M * nLon;
+ for (int x = 0; x < nLon; ++x) {
+ String eastWest = "E";
+ int actLon = lon + x;
+ if ((lon + x) < 0) {
+ actLon = -(lon + x);
+ eastWest = "W";
+ }
+ for (int y = 0; y < nLat; ++y) {
+ String northSouth = (lat + y) < 0 ? "S" : "N";
+ String fileName = String.format("%s/%s%02d%s%03d.hgt",
dataPath,
+ northSouth, (lat + y) <
0 ? -(lat + y) : (lat + y),
+ eastWest, actLon);
+ try {
+ FileInputStream is = new
FileInputStream(fileName);
+ buffers.put(x * nLat + y,
is.getChannel().map(READ_ONLY, 0, 2*(M+1)*(M+1)));
+ }
+ catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
}
- public void read(int minLon, int minLat, int maxLon, int maxLat)
+ @Override
+ protected void read(int minLon, int minLat, int maxLon, int maxLat)
{
}
- public double ele(int x, int y)
- {
- return buffer.getShort(2*((M-y)*(M+1)+x))+delta;
- }
+ @Override
+ protected double ele(int x, int y) {
+ int actLon = x / M;
+ int actLat = y / M;
+ if (actLon > nLon || actLat > nLat)
+ throw new IndexOutOfBoundsException("point not inside
area");
+ MappedByteBuffer buffer = buffers.get(actLon*nLat+actLat);
+ return buffer.getShort(2*((M-y%M)*(M+1)+x%M))+delta;
+ }
public void serializeCopyRight(Writer out) throws IOException
{
- out.write(" <copyright>\n");
- out.write(" Contour lines generated from DEM data by NASA\n");
- out.write(" </copyright>\n");
+ out.write(" <copyright>\n");
+ out.write(" Contour lines generated from DEM data by NASA\n");
+ out.write(" </copyright>\n");
}
}
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev