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

Reply via email to