Index: src/uk/me/parabola/imgfmt/app/dem/DEMFile.java =================================================================== --- src/uk/me/parabola/imgfmt/app/dem/DEMFile.java (revision 4070) +++ src/uk/me/parabola/imgfmt/app/dem/DEMFile.java (working copy) @@ -52,20 +52,57 @@ * @param outsidePolygonHeight the height value that should be used for points outside of the bounding polygon */ public void calc(Area area, java.awt.geom.Area demPolygonMapUnits, String pathToHGT, List pointDistances, short outsidePolygonHeight) { - HGTConverter hgtConverter = new HGTConverter(pathToHGT, area, demPolygonMapUnits); + // HGT area is extended by 0.01 degree in each direction + HGTConverter hgtConverter = new HGTConverter(pathToHGT, area, demPolygonMapUnits, 0.01D); hgtConverter.setOutsidePolygonHeight(outsidePolygonHeight); + int top = area.getMaxLat() * 256; + int bottom = area.getMinLat() * 256; + int left = area.getMinLong() * 256; + int right = area.getMaxLong() * 256; + int zoom = 0; int lastDist = pointDistances.get(pointDistances.size()-1); for (int pointDist : pointDistances) { - DEMSection section = new DEMSection(zoom++, area, hgtConverter, pointDist, pointDist == lastDist); + int distance = pointDist; + if (distance == -1) { + int res = (hgtConverter.getHighestRes() > 0) ? hgtConverter.getHighestRes() : 1200; + distance = (int) ((1 << 29) / (res * 45)); + } + // last 4 bits of distance should be 0 + distance = ((distance + 8)/16)*16; + + int xtop = top; + int xleft = left; + + // align DEM to distance raster, if distance not bigger than widening of HGT area + if (distance < (int)Math.floor((0.01D/45.0D * (1 << 29)))) { + if (xtop >= 0) { + xtop -= xtop % distance; + if (xtop < 0x3FFFFFFF - distance) + xtop += distance; + } + else { + xtop -= xtop % distance; + } + + if (xleft >= 0) { + xleft -= xleft % distance; + } + else { + xleft -= xleft % distance; + if (xleft > Integer.MIN_VALUE + distance) + xleft -= distance; + } + } + + // to improve: DEM secition should get area in 32bit units + DEMSection section = new DEMSection(zoom++, xtop, xleft, xtop - bottom, right - xleft, hgtConverter, distance, pointDist == lastDist); demHeader.addSection(section); } return; } - - public void write() { ImgFileWriter w = getWriter(); if (w instanceof BufferedImgFileWriter) { Index: src/uk/me/parabola/imgfmt/app/dem/DEMSection.java =================================================================== --- src/uk/me/parabola/imgfmt/app/dem/DEMSection.java (revision 4070) +++ src/uk/me/parabola/imgfmt/app/dem/DEMSection.java (working copy) @@ -48,16 +48,12 @@ private int maxHeight = Integer.MIN_VALUE; private List tiles = new ArrayList<>(); - public DEMSection(int zoomLevel, Area bbox, HGTConverter hgtConverter, int pointDist, boolean lastLevel) { + public DEMSection(int zoomLevel, int areaTop, int areaLeft, int areaHeight, int areaWidth, HGTConverter hgtConverter, int pointDist, boolean lastLevel) { this.zoomLevel = zoomLevel; this.lastLevel = lastLevel; - if (pointDist == -1) { - int res = (hgtConverter.getHighestRes() > 0) ? hgtConverter.getHighestRes() : 1200; - pointDist = (int) ((1 << 29) / (res * 45)); - } - this.top = bbox.getMaxLat() * 256; - this.left = bbox.getMinLong() * 256; + this.top = areaTop; + this.left = areaLeft; // calculate raster that starts at top left corner // last row and right column have non-standard height / row values @@ -64,8 +60,8 @@ pointsDistanceLat = pointDist; pointsDistanceLon = pointDist; - int []latInfo = getTileInfo(bbox.getHeight() * 256, pointsDistanceLat); - int []lonInfo = getTileInfo(bbox.getWidth() * 256, pointsDistanceLon); + int []latInfo = getTileInfo(areaHeight, pointsDistanceLat); + int []lonInfo = getTileInfo(areaWidth, pointsDistanceLon); // store the values written to the header tilesLat = latInfo[0]; tilesLon = lonInfo[0]; Index: src/uk/me/parabola/mkgmap/reader/hgt/HGTConverter.java =================================================================== --- src/uk/me/parabola/mkgmap/reader/hgt/HGTConverter.java (revision 4070) +++ src/uk/me/parabola/mkgmap/reader/hgt/HGTConverter.java (working copy) @@ -46,14 +46,18 @@ * @param demPolygonMapUnits optional bounding polygon which describes the area for * which elevation should be read from hgt files. */ - public HGTConverter(String path, Area bbox, java.awt.geom.Area demPolygonMapUnits) { - int minLat = (int) Math.floor(Utils.toDegrees(bbox.getMinLat())); - int minLon = (int) Math.floor(Utils.toDegrees(bbox.getMinLong())); - // the bbox is slightly enlarged so that we dont fail when rounding has no effect - // e.g. if getMaxLat() returns 0 - int maxLat = (int) Math.ceil(Utils.toDegrees(bbox.getMaxLat() + 1)); - int maxLon = (int) Math.ceil(Utils.toDegrees(bbox.getMaxLong() + 1)); + public HGTConverter(String path, Area bbox, java.awt.geom.Area demPolygonMapUnits, double extra) { + // make bigger box for interpolation or aligning of areas + int minLat = (int) Math.floor(Utils.toDegrees(bbox.getMinLat()) - extra); + int minLon = (int) Math.floor(Utils.toDegrees(bbox.getMinLong()) - extra); + int maxLat = (int) Math.ceil(Utils.toDegrees(bbox.getMaxLat()) + extra); + int maxLon = (int) Math.ceil(Utils.toDegrees(bbox.getMaxLong()) + extra); + if (minLat < -90) minLat = -90; + if (maxLat > 90) maxLat = 90; + if (minLon < -180) minLon = -180; + if (maxLon > 180) maxLon = 180; + minLat32 = Utils.toMapUnit(minLat) * 256; minLon32 = Utils.toMapUnit(minLon) * 256; // create matrix of readers