[mkgmap-dev] [PATCH v1] sea polygons
From Christian Gawron christian.gawron at gmx.de on Sun Aug 2 10:03:54 BST 2009
Thanks for posting this! The output suggests that the code repeatedly concatenates a (closed) way with itself - this surely will exhaust the heap space quickly. I'will post an improved patch later. Best wishes Christian maning sambale schrieb: > 1 GB of heap size could not compile 62 MB osm file > > time java -Xmx1012m -jar > /home/maning/osm/routable_garmin/mkgmap/trunk/dist/mkgmap.jar > --code-page=1252 --tdbfile --latin1 --country-abbr=PHI > --country-name=PHILIPPINES --remove-short-arcs --route > --road-name-pois --add-pois-to-areas --location-autofill=2 > --family-id=639 --family-name="OSM_PHIL" --overview-mapname=40000001 > --series-name="OSM_PHIL" --description="OSM_PHIL" --generate-sea > /home/maning/osm/routable_garmin/magellan/20090713/manila_20090713.osm > generating sea > merging: 33 4263797 33615705 > merging: 32 4591652 4591687 > merging: 31 4591978 33658311 > merging: 30 4592000 4611686018427387909 > merging: 29 4592029 4611686018427387908 > merging: 28 4598416 4598418 > merging: 27 23225661 23225148 > merging: 26 23959594 33050431 > merging: 25 27428886 32978387 > merging: 24 27635420 28340210 > merging: 23 28340457 4611686018427387916 > merging: 22 28538727 28538728 > merging: 21 31263118 4611686018427387918 > merging: 20 31390236 31390245 > merging: 19 33615706 33615707 > merging: 18 33615793 33658198 > merging: 17 33658197 4611686018427387907 > merging: 16 33677950 4611686018427387910 > merging: 15 4611686018427387912 4611686018427387912 > merging: 15 4611686018427387914 4611686018427387913 > merging: 14 4611686018427387915 4611686018427387926 > merging: 13 4611686018427387917 4611686018427387927 > merging: 12 4611686018427387919 4611686018427387928 > merging: 11 4611686018427387920 4611686018427387929 > merging: 10 4611686018427387921 33615708 > merging: 9 4611686018427387922 4611686018427387923 > merging: 8 4611686018427387925 4611686018427387925 > merging: 8 4611686018427387932 4611686018427387931 > merging: 7 4611686018427387933 4611686018427387933 > merging: 7 4611686018427387935 4611686018427387935 > merging: 7 4611686018427387936 4611686018427387936 > merging: 7 4611686018427387937 4611686018427387937 > merging: 7 4611686018427387938 4611686018427387938 > merging: 7 4611686018427387939 4611686018427387939 > merging: 7 4611686018427387940 4611686018427387940 > merging: 7 4611686018427387941 4611686018427387941 > merging: 7 4611686018427387942 4611686018427387942 > merging: 7 4611686018427387943 4611686018427387943 > merging: 7 4611686018427387944 4611686018427387944 > merging: 7 4611686018427387945 4611686018427387945 > merging: 7 4611686018427387946 4611686018427387946 > merging: 7 4611686018427387947 4611686018427387947 > merging: 7 4611686018427387948 4611686018427387948 > merging: 7 4611686018427387949 4611686018427387949 > merging: 7 4611686018427387950 4611686018427387950 > merging: 7 4611686018427387951 4611686018427387951 > merging: 7 4611686018427387952 4611686018427387952 > ^[[BSEVERE (Main): java.util.concurrent.ExecutionException: > java.lang.OutOfMemoryError: Java heap space > java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: > Java heap space > at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:252) > at java.util.concurrent.FutureTask.get(FutureTask.java:111) > at uk.me.parabola.mkgmap.main.Main.endOptions(Main.java:289) > at uk.me.parabola.mkgmap.CommandArgsReader.readArgs(CommandArgsReader.java:124) > at uk.me.parabola.mkgmap.main.Main.main(Main.java:100) > Caused by: java.lang.OutOfMemoryError: Java heap space > at java.util.Arrays.copyOf(Arrays.java:2772) > at java.util.Arrays.copyOf(Arrays.java:2746) > at java.util.ArrayList.ensureCapacity(ArrayList.java:187) > at java.util.ArrayList.addAll(ArrayList.java:499) > at uk.me.parabola.mkgmap.reader.osm.xml.Osm5XmlHandler.concatenateWays(Osm5XmlHandler.java:838) > at uk.me.parabola.mkgmap.reader.osm.xml.Osm5XmlHandler.generateSeaPolygon(Osm5XmlHandler.java:793) > at uk.me.parabola.mkgmap.reader.osm.xml.Osm5XmlHandler.endDocument(Osm5XmlHandler.java:457) > at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endDocument(AbstractSAXParser.java:740) > at com.sun.org.apache.xerces.internal.xinclude.XIncludeHandler.endDocument(XIncludeHandler.java:1122) > at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:491) > at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:810) > at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:740) > at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:110) > at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(AbstractSAXParser.java:1208) > at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(SAXParserImpl.java:525) > at javax.xml.parsers.SAXParser.parse(SAXParser.java:392) > at javax.xml.parsers.SAXParser.parse(SAXParser.java:195) > at uk.me.parabola.mkgmap.reader.osm.xml.Osm5MapDataSource.load(Osm5MapDataSource.java:80) > at uk.me.parabola.mkgmap.main.MapMaker.loadFromFile(MapMaker.java:148) > at uk.me.parabola.mkgmap.main.MapMaker.makeMap(MapMaker.java:56) > at uk.me.parabola.mkgmap.main.Main$1.call(Main.java:168) > at uk.me.parabola.mkgmap.main.Main$1.call(Main.java:166) > at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) > at java.util.concurrent.FutureTask.run(FutureTask.java:166) > at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) > at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) > at java.lang.Thread.run(Thread.java:636) > Exiting - if you want to carry on regardless, use the --keep-going option > > > On Sun, Aug 2, 2009 at 3:56 PM, Dermot McNally<dermotm at gmail.com> wrote: > >> This exhausted the 2G of heap space I had allocated when I tried it on >> a map of Ireland. Are there known practical limits I should try to >> stay within? >> >> Dermot >> >> 2009/8/1 Christian Gawron <christian.gawron at gmx.de>: >> >>> Hi, >>> >>> the attached patch adds a sea polygon (based on the bounding box of the >>> map) and a multipolygon relation with all lines tagged as natural=coastline >>> as inner elements. The code merges coastline components as far as possible. >>> The patch also contains the multipolygon patch by Rudi which wasn't commited >>> so far (without this patch, the rendering fails). >>> >>> The sea polygon is created as "natural=sea", for which I added a mapping to >>> garmin type 0x32. >>> >>> Caveat: I have only tested this for islands (Corsica) so far. >>> >>> Best wishes >>> Christian >>> >>> Index: src/uk/me/parabola/mkgmap/reader/osm/Way.java >>> =================================================================== >>> --- src/uk/me/parabola/mkgmap/reader/osm/Way.java (Revision 1115) >>> +++ src/uk/me/parabola/mkgmap/reader/osm/Way.java (Arbeitskopie) >>> @@ -76,6 +76,10 @@ >>> } >>> } >>> >>> + public boolean isClosed() { >>> + return points.get(0).equals(points.get(points.size()-1)); >>> + } >>> + >>> /** >>> * A simple representation of this way. >>> * @return A string with the name and start point >>> Index: src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java >>> =================================================================== >>> --- src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java >>> (Revision 1115) >>> +++ src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java >>> (Arbeitskopie) >>> @@ -5,7 +5,6 @@ >>> import java.util.List; >>> import java.util.Map; >>> >>> -import uk.me.parabola.imgfmt.Utils; >>> import uk.me.parabola.imgfmt.app.Coord; >>> >>> /** >>> @@ -23,8 +22,9 @@ >>> * this because the type of the relation is not known until after all >>> * its tags are read in. >>> * @param other The relation to base this one on. >>> + * @param wayMap Map of all ways. >>> */ >>> - public MultiPolygonRelation(Relation other) { >>> + public MultiPolygonRelation(Relation other, Map<Long, Way> wayMap) { >>> setId(other.getId()); >>> for (Map.Entry<Element, String> pairs: >>> other.getRoles().entrySet()){ >>> addElement(pairs.getValue(), pairs.getKey()); >>> @@ -33,8 +33,16 @@ >>> >>> if (value != null && pairs.getKey() instanceof Way) { >>> Way way = (Way) pairs.getKey(); >>> - if (value.equals("outer")) >>> - outer = way; >>> + if (value.equals("outer")){ >>> + // duplicate outer way and remove >>> tags for cascaded multipolygons >>> + outer = new Way(-way.getId()); >>> + outer.copyTags(way); >>> + for(Coord point: way.getPoints()) >>> + outer.addPoint(point); >>> + wayMap.put(outer.getId(), outer); >>> + if (way.getTags() != null) >>> + way.getTags().removeAll(); >>> + } >>> else if (value.equals("inner")) >>> inners.add(way); >>> } >>> @@ -52,11 +60,20 @@ >>> { >>> for (Way w: inners) { >>> if (w != null) { >>> - List<Coord> pts = w.getPoints(); >>> - int[] insert = >>> findCpa(outer.getPoints(), pts); >>> - if (insert[0] > 0) >>> - insertPoints(pts, insert[0], >>> insert[1]); >>> - pts.clear(); >>> + int[] insert = >>> findCpa(outer.getPoints(), w.getPoints()); >>> + //if (insert[0] > 0) >>> + insertPoints(w, insert[0], >>> insert[1]); >>> + >>> + // remove tags from inner way that >>> are available in the outer way >>> + if (outer.getTags() != null){ >>> + for (Map.Entry<String, >>> String> mapTags: outer.getTags().getKeyValues().entrySet()){ >>> + String key = >>> mapTags.getKey(); >>> + String value = >>> mapTags.getValue(); >>> + if (w.getTag(key) != >>> null) >>> + if >>> (w.getTag(key).equals(value)) >>> + >>> w.deleteTag(key); >>> + } >>> + } >>> } >>> } >>> } >>> @@ -64,22 +81,39 @@ >>> >>> /** >>> * Insert Coordinates into the outer way. >>> - * @param inList List of Coordinates to be inserted >>> + * @param way Way to be inserted >>> * @param out Coordinates will be inserted after this point in the >>> outer way. >>> * @param in Points will be inserted starting at this index, >>> * then from element 0 to (including) this element; >>> */ >>> - private void insertPoints(List<Coord> inList, int out, int in){ >>> + private void insertPoints(Way way, int out, int in){ >>> List<Coord> outList = outer.getPoints(); >>> + List<Coord> inList = way.getPoints(); >>> int index = out+1; >>> for (int i = in; i < inList.size(); i++) >>> outList.add(index++, inList.get(i)); >>> - for (int i = 0; i <= in; i++) >>> + for (int i = 0; i < in; i++) >>> outList.add(index++, inList.get(i)); >>> - >>> - //with this line commented we get triangles, when >>> uncommented some areas disappear >>> - // at least in mapsource, on device itself looks OK. >>> - outList.add(index,outList.get(out)); >>> + >>> + if (outer.getPoints().size() < 32){ >>> + outList.add(index++, inList.get(in)); >>> + outList.add(index, outList.get(out)); >>> + } >>> + else { >>> + // we shift the nodes to avoid duplicate nodes >>> (large areas only) >>> + int oLat = outList.get(out).getLatitude(); >>> + int oLon = outList.get(out).getLongitude(); >>> + int iLat = inList.get(in).getLatitude(); >>> + int iLon = inList.get(in).getLongitude(); >>> + if ((oLat - iLat) > (oLon - iLon)){ >>> + outList.add(index++, new Coord(iLat-1, >>> iLon)); >>> + outList.add(index, new Coord(oLat-1, oLon)); >>> + } >>> + else{ >>> + outList.add(index++, new Coord(iLat, >>> iLon-1)); >>> + outList.add(index, new Coord(oLat, oLon-1)); >>> + } >>> + } >>> } >>> >>> /** >>> Index: src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java >>> =================================================================== >>> --- src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java >>> (Revision 1115) >>> +++ src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java >>> (Arbeitskopie) >>> @@ -19,6 +19,7 @@ >>> import java.util.ArrayList; >>> import java.util.HashMap; >>> import java.util.IdentityHashMap; >>> +import java.util.Iterator; >>> import java.util.LinkedHashMap; >>> import java.util.List; >>> import java.util.Map; >>> @@ -65,6 +66,7 @@ >>> private final Map<String, Long> fakeIdMap = new HashMap<String, >>> Long>(); >>> private final List<Node> exits = new ArrayList<Node>(); >>> private final List<Way> motorways = new ArrayList<Way>(); >>> + private final List<Way> shoreline = new ArrayList<Way>(); >>> >>> private static final int MODE_NODE = 1; >>> private static final int MODE_WAY = 2; >>> @@ -92,6 +94,7 @@ >>> private final boolean ignoreTurnRestrictions; >>> private final boolean linkPOIsToWays; >>> private final boolean routing; >>> + private final boolean generateSea; >>> private final Double minimumArcLength; >>> private final String frigRoundabouts; >>> >>> @@ -105,6 +108,7 @@ >>> } >>> linkPOIsToWays = props.getProperty("link-pois-to-ways", >>> false); >>> ignoreBounds = props.getProperty("ignore-osm-bounds", false); >>> + generateSea = props.getProperty("generate-sea", false); >>> routing = props.containsKey("route"); >>> String rsa = props.getProperty("remove-short-arcs", null); >>> if(rsa != null) >>> @@ -370,6 +374,8 @@ >>> if("motorway".equals(highway) || >>> "trunk".equals(highway)) >>> motorways.add(currentWay); >>> + if(generateSea && >>> "coastline".equals(currentWay.getTag("natural"))) >>> + shoreline.add(currentWay); >>> currentWay = null; >>> // ways are processed at the end of the >>> document, >>> // may be changed by a Relation class >>> @@ -399,7 +405,7 @@ >>> String type = currentRelation.getTag("type"); >>> if (type != null) { >>> if ("multipolygon".equals(type)) >>> - currentRelation = new >>> MultiPolygonRelation(currentRelation); >>> + currentRelation = new >>> MultiPolygonRelation(currentRelation, wayMap); >>> else if("restriction".equals(type)) { >>> >>> if(ignoreTurnRestrictions) >>> @@ -446,6 +452,10 @@ >>> } >>> >>> coordMap = null; >>> + >>> + if (generateSea) >>> + generateSeaPolygon(shoreline); >>> + >>> for (Relation r : relationMap.values()) >>> converter.convertRelation(r); >>> >>> @@ -746,4 +756,95 @@ >>> return fakeIdVal; >>> } >>> } >>> + >>> + private void generateSeaPolygon(List<Way> shoreline) { >>> + System.out.printf("generating sea\n"); >>> + long seaId; >>> + seaId = (1L << 62) + nextFakeId++; >>> + Way sea = new Way(seaId); >>> + wayMap.put(seaId, sea); >>> + Area bbox = mapper.getBounds(); >>> + Coord nw = new Coord(bbox.getMinLat(), bbox.getMinLong()); >>> + Coord ne = new Coord(bbox.getMinLat(), bbox.getMaxLong()); >>> + Coord sw = new Coord(bbox.getMaxLat(), bbox.getMinLong()); >>> + Coord se = new Coord(bbox.getMaxLat(), bbox.getMaxLong()); >>> + sea.addPoint(nw); >>> + sea.addPoint(ne); >>> + sea.addPoint(se); >>> + sea.addPoint(sw); >>> + sea.addPoint(nw); >>> + sea.addTag("natural", "sea"); >>> + >>> + Relation seaRelation = new GeneralRelation((1L << 62) + >>> nextFakeId++); >>> + seaRelation.addTag("type", "multipolygon"); >>> + seaRelation.addElement("outer", sea); >>> + >>> + List<Way> islands = new ArrayList(); >>> + >>> + // handle islands (closes shoreline components) first (they're >>> easy) >>> + Iterator<Way> it = shoreline.iterator(); >>> + while (it.hasNext()) { >>> + Way w = it.next(); >>> + if (w.isClosed()) { >>> + islands.add(w); >>> + it.remove(); >>> + } >>> + } >>> + concatenateWays(shoreline); >>> + // there may be more islands now >>> + it = shoreline.iterator(); >>> + while (it.hasNext()) { >>> + Way w = it.next(); >>> + if (w.isClosed()) { >>> + System.out.println("island after concatenating\n"); >>> + islands.add(w); >>> + it.remove(); >>> + } >>> + } >>> + >>> + for (Way w : islands) { >>> + seaRelation.addElement("inner", w); >>> + } >>> + for (Way w : shoreline) { >>> + seaRelation.addElement("inner", w); >>> + } >>> + seaRelation = new MultiPolygonRelation(seaRelation, wayMap); >>> + relationMap.put(seaId, seaRelation); >>> + seaRelation.processElements(); >>> + } >>> + >>> + public void concatenateWays(List<Way> ways) { >>> + Map<Coord, Way> beginMap = new HashMap(); >>> + >>> + for (Way w : ways) { >>> + if (!w.isClosed()) { >>> + List<Coord> points = w.getPoints(); >>> + beginMap.put(points.get(0), w); >>> + } >>> + } >>> + >>> + int merged = 1; >>> + while (merged > 0) { >>> + merged = 0; >>> + for (Way w1 : ways) { >>> + List<Coord> points1 = w1.getPoints(); >>> + Way w2 = beginMap.get(points1.get(points1.size()-1)); >>> + >>> + if (w2 != null) { >>> + System.out.printf("merging: %d %d %d\n", >>> ways.size(), w1.getId(), w2.getId()); >>> + List<Coord> points2 = w2.getPoints(); >>> + Way wm = new Way((1L << 62) + nextFakeId++); >>> + wm.getPoints().addAll(points1); >>> + wm.getPoints().addAll(points2); >>> + ways.remove(w1); >>> + ways.remove(w2); >>> + beginMap.remove(points2.get(0)); >>> + ways.add(wm); >>> + beginMap.put(points1.get(0), wm); >>> + merged++; >>> + break; >>> + } >>> + } >>> + } >>> + } >>> } >>> Index: src/uk/me/parabola/mkgmap/reader/osm/Element.java >>> =================================================================== >>> --- src/uk/me/parabola/mkgmap/reader/osm/Element.java (Revision 1115) >>> +++ src/uk/me/parabola/mkgmap/reader/osm/Element.java (Arbeitskopie) >>> @@ -86,6 +86,7 @@ >>> * element. >>> */ >>> public void copyTags(Element other) { >>> + if (other.tags != null) >>> tags = other.tags.copy(); >>> } >>> >>> @@ -97,4 +98,8 @@ >>> if (this.name == null) >>> this.name = name; >>> } >>> + >>> + public Tags getTags() { >>> + return tags; >>> + } >>> } >>> Index: src/uk/me/parabola/mkgmap/reader/osm/Tags.java >>> =================================================================== >>> --- src/uk/me/parabola/mkgmap/reader/osm/Tags.java (Revision 1115) >>> +++ src/uk/me/parabola/mkgmap/reader/osm/Tags.java (Arbeitskopie) >>> @@ -16,7 +16,9 @@ >>> */ >>> package uk.me.parabola.mkgmap.reader.osm; >>> >>> +import java.util.HashMap; >>> import java.util.Iterator; >>> +import java.util.Map; >>> >>> /** >>> * Store the tags that belong to an Element. >>> @@ -111,7 +113,7 @@ >>> } >>> return null; >>> } >>> - >>> + >>> /** >>> * Make a deep copy of this object. >>> * @return A copy of this object. >>> @@ -262,4 +264,22 @@ >>> put(e.key, e.value); >>> } >>> } >>> -} >>> + >>> + public void removeAll() { >>> + for (int i = 0; i < capacity; i++){ >>> + keys[i] = null; >>> + values[i] = null; >>> + } >>> + size = 0; >>> + } >>> + >>> + public Map<String, String> getKeyValues() { >>> + Map<String, String> tagMap = new HashMap<String, String>(); >>> + for (int i = 0; i < capacity; i++) >>> + if (keys[i] != null && values[i] != null) >>> + tagMap.put(keys[i], values[i]); >>> + return tagMap; >>> + } >>> + >>> + >>> +} >>> \ No newline at end of file >>> Index: resources/styles/default/polygons >>> =================================================================== >>> --- resources/styles/default/polygons (Revision 1115) >>> +++ resources/styles/default/polygons (Arbeitskopie) >>> @@ -55,6 +55,7 @@ >>> natural=mud [0x51 resolution 20] >>> natural=scrub [0x4f resolution 20] >>> natural=water [0x3c resolution 20] >>> +natural=sea [0x32 resolution 10] >>> natural=wood [0x50 resolution 18] >>> >>> place=village [0x03 resolution 18] >>> >>> _______________________________________________ >>> mkgmap-dev mailing list >>> mkgmap-dev at lists.mkgmap.org.uk >>> http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev >>> >>> >> >> -- >> -------------------------------------- >> Iren sind menschlich >> _______________________________________________ >> mkgmap-dev mailing list >> mkgmap-dev at lists.mkgmap.org.uk >> http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev >> >> > > > >
- Previous message: [mkgmap-dev] [PATCH v1] sea polygons
- Next message: [mkgmap-dev] [PATCH v1] sea polygons
- Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
More information about the mkgmap-dev mailing list