logo separator

[mkgmap-dev] How to solve/debug weird problem

From Johannes Formann johannes at formann.de on Thu Jan 13 21:32:07 GMT 2011

WanMil <wmgcnfg at web.de> wrote:

Hello WanMil,


> what do you mean with "branch"?

I mean a branch of the original "Radkarte". The original author has more or
less abandoned to update the map, so I had startet buildig a map every week
an tweeked a bit the style.

> Which mkgmap release do you use before you apply your patches?

Always trunk/the latest. A svn checkout/update is included in the
build process.

> Can you post the patches here?

At the End of the Message or there:
http://bazaar.launchpad.net/%7Eluckyguess/radkarte/main/annotate/head%3A/generate_ways_from_relations.patch

> Can you explain why you need the generate_ways_from_relations.patch and 
> what that starts_with.patch does?

The "generate_ways_from_relations.patch" is used to give cycleroutes good 
attributes (road_class, speed), so they were preferred over normal roads, 
independed on which roads they actually run. (But dependent on the network 
different, rcn other than ncn and so on).

The starts_with.patch prefixes the POI names, but I could disable it too.
A new map ist currently generatet only with the generate_ways_from_relations.patch
an the debug patch from Steve.

> I propose to have a deep look on your patches because we didn't receive 
> any similar complaint on this mailing list before.

I guess the patch must have something to do witch it too, but I don't have
enough knowledge of the mkgmap-internals to dig it out alone.

regards

Johannes



Index: uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java     (revision 1580)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java     (working copy)
@@ -19,8 +19,10 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
@@ -49,6 +51,7 @@
 import uk.me.parabola.mkgmap.general.RoadNetwork;
 import uk.me.parabola.mkgmap.reader.osm.CoordPOI;
 import uk.me.parabola.mkgmap.reader.osm.Element;
+import uk.me.parabola.mkgmap.reader.osm.FakeIdGenerator;
 import uk.me.parabola.mkgmap.reader.osm.GType;
 import uk.me.parabola.mkgmap.reader.osm.Node;
 import uk.me.parabola.mkgmap.reader.osm.OsmConverter;
@@ -173,6 +176,14 @@
 
        private static final Pattern commaPattern = Pattern.compile(",");
 
+       private String makeKeyFromGType(GType type) {
+               String key = String.valueOf(type.getFeatureKind()) + "," + String.valueOf(type.getType()) + "," + String.valueOf(type.getMinResolution())
+                       + "," + String.valueOf(type.getMaxResolution());
+               if (type.isRoad())
+                       key += "," + String.valueOf(type.getRoadClass()) + "," + String.valueOf(type.getRoadSpeed());
+               return key;
+       }
+
        private GType makeGTypeFromTags(Element element) {
                String[] vals = commaPattern.split(element.getTag("mkgmap:gtype"));
 
@@ -442,10 +453,38 @@
         *
         * @param relation The relation to convert.
         */
-       public void convertRelation(Relation relation) {
-               // Relations never resolve to a GType and so we ignore the return
-               // value.
-               relationRules.resolveType(relation, TypeResult.NULL_RESULT);
+       public void convertRelation(Relation relation, final Map<Long, Way> wayMap) {
+               // If the relation resolves to a GType of a way then add that way to the map
+               preConvertRules(relation);
+               relationRules.resolveType(relation, new TypeResult() {
+                       public void add(Element el, GType type) {
+                               Relation relation = (Relation) el;
+                               postConvertRules(relation, type);
+
+                               // Create a hash set from the relation elements. This makes sure that each element
+                               // occurs at most once.
+                               HashSet<Element> elements = new HashSet(relation.getElements().size());
+                               for (Map.Entry<String,Element> mapEntry : relation.getElements()) {
+                                       elements.add(mapEntry.getValue());
+                               }
+
+                               // Extract all the ways that belong to the relation
+                               List<Way> ways = new ArrayList<Way>(elements.size());
+                               for (Element ele : elements) {
+                                       if (ele instanceof Way)
+                                               addWayToListAndChainIfPossible(ways, (Way) ele, type.isRoad()); // care about oneways if it is a road
+                               }
+
+                               for (Way w : ways) {
+                                       w.setName(relation.getName());
+                                       // Using mkgmap:gtype way to promote the attributes, so that the generated ways can go through the same
+                                       // process as the ways that come directly from the osm data
+                                       type.setFeatureKind(GType.POLYLINE);
+                                       w.addTag("mkgmap:gtype",makeKeyFromGType(type));
+                                       wayMap.put(FakeIdGenerator.makeFakeId(),w);
+                               }
+                       }
+               });
 
                if(relation instanceof RestrictionRelation) {
                        RestrictionRelation rr = (RestrictionRelation)relation;
@@ -463,6 +502,133 @@
                }
        }
 
+       private void addWayToListAndChainIfPossible(List<Way> ways, Way newWay, boolean careAboutOneways) {
+               outer_loop: for (;;) {
+                       List<Coord> newWayCoords = newWay.getPoints();
+                       int newWayNumPoints = newWayCoords.size();
+                       if (newWayNumPoints == 0) return;
+       
+                       Coord newWayFirstCoord = newWayCoords.get(0);
+                       Coord newWayLastCoord = newWayCoords.get(newWayNumPoints-1);
+       
+                       ListIterator<Way> listIterator = ways.listIterator();
+                       while (listIterator.hasNext()) {
+                               Way existantWay = listIterator.next();
+                               List<Coord> existantWayCoords = existantWay.getPoints();
+                               int existantWayNumPoints = existantWayCoords.size();
+                               if (existantWayNumPoints == 0) continue;
+       
+                               Coord existantWayFirstCoord = existantWayCoords.get(0);
+                               Coord existantWayLastCoord = existantWayCoords.get(existantWayNumPoints-1);
+       
+                               // Test coordinates to see whether two way can be chained together
+                               // If they are chained together the only tag we will copy is the oneway tag (if we care about them).
+                               // Access tags will have to be set by the relation!
+                               // TODO: Handle the oneway=-1 tag in a useful way, now it prevents chaining of the ways.
+       
+                               // Both ways share the same first point. So the new way is connected in reverse, but if we care about oneways
+                               // then only if none of them is one.
+                               if (existantWayFirstCoord.equals(newWayFirstCoord) 
+                                       && (!careAboutOneways || (!existantWay.isBoolTag("oneway") && !newWay.isBoolTag("oneway")))) {
+       
+                                       Way replacementWay = new Way(existantWay.getId());
+
+                                       // Add points of new way in reverse
+                                       ListIterator<Coord> newWayCoordIterator = newWayCoords.listIterator(newWayNumPoints);
+                                       while (newWayCoordIterator.hasPrevious()) {
+                                               replacementWay.addPoint(newWayCoordIterator.previous());
+                                       }
+                                       // And of the existant way in order (starting from the second point)
+                                       ListIterator<Coord> existantWayCoordIterator = existantWayCoords.listIterator(1);
+                                       while (existantWayCoordIterator.hasNext()) {
+                                               replacementWay.addPoint(existantWayCoordIterator.next());
+                                       }
+                                       // Remove the existant way that was chained to the new way and start the search again.
+                                       listIterator.remove();
+                                       newWay = replacementWay;
+                                       continue outer_loop;
+                               // The last point of the existant way is the same as the first point of the new way, so they are
+                               // connected in order, but if we care about oneways then only if they either both have the oneway tag or both have not.
+                               } else if (existantWayLastCoord.equals(newWayFirstCoord)
+                                       && (!careAboutOneways || !(existantWay.isBoolTag("oneway") ^ newWay.isBoolTag("oneway")))) {
+       
+                                       Way replacementWay = new Way(existantWay.getId());
+                                       if (careAboutOneways) {
+                                               String onewayValue = existantWay.getTag("oneway");
+                                               if (onewayValue != null)
+                                                       replacementWay.addTag("oneway",onewayValue);
+                                       }
+
+                                       // Add points of existant way in order
+                                       ListIterator<Coord> existantWayCoordIterator = existantWayCoords.listIterator();
+                                       while (existantWayCoordIterator.hasNext()) {
+                                               replacementWay.addPoint(existantWayCoordIterator.next());
+                                       }
+                                       // And of the new way also in order (starting from the second point)
+                                       ListIterator<Coord> newWayCoordIterator = newWayCoords.listIterator(1);
+                                       while (newWayCoordIterator.hasNext()) {
+                                               replacementWay.addPoint(newWayCoordIterator.next());
+                                       }
+                                       // Remove the existant way that was chained to the new way and start the search again.
+                                       listIterator.remove();
+                                       newWay = replacementWay;
+                                       continue outer_loop;
+                               // The first point of the existant way is the same as the last point of the new way, so connect them,
+                               // but starting with the new way and if we care about oneways then only if they either both have the
+                               // oneway tag or both have not.
+                               } else if (existantWayFirstCoord.equals(newWayLastCoord)
+                                       && (!careAboutOneways || (!(existantWay.isBoolTag("oneway") ^ newWay.isBoolTag("oneway"))))) {
+       
+                                       Way replacementWay = new Way(existantWay.getId());
+                                       if (careAboutOneways) {
+                                               String onewayValue = existantWay.getTag("oneway");
+                                               if (onewayValue != null)
+                                                       replacementWay.addTag("oneway",onewayValue);
+                                       }
+
+                                       // Add points of the new way in order
+                                       ListIterator<Coord> newWayCoordIterator = newWayCoords.listIterator();
+                                       while (newWayCoordIterator.hasNext()) {
+                                               replacementWay.addPoint(newWayCoordIterator.next());
+                                       }
+                                       // And of the existant way also in order (starting from the second point)
+                                       ListIterator<Coord> existantWayCoordIterator = existantWayCoords.listIterator(1);
+                                       while (existantWayCoordIterator.hasNext()) {
+                                               replacementWay.addPoint(existantWayCoordIterator.next());
+                                       }
+                                       // Remove the existant way that was chained to the new way and start the search again.
+                                       listIterator.remove();
+                                       newWay = replacementWay;
+                                       continue outer_loop;
+                               // The last points of the existant and the new way are the same. So the new way is connected in reverse,
+                               // but if we care about oneways than only if neither of them has the oneway tag set.
+                               } else if (existantWayLastCoord.equals(newWayLastCoord)
+                                       && (!careAboutOneways || (!existantWay.isBoolTag("oneway") && !newWay.isBoolTag("oneway")))) {
+       
+                                       Way replacementWay = new Way(existantWay.getId());
+
+                                       // Add points of existant way in order
+                                       ListIterator<Coord> existantWayCoordIterator = existantWayCoords.listIterator();
+                                       while (existantWayCoordIterator.hasNext()) {
+                                               replacementWay.addPoint(existantWayCoordIterator.next());
+                                       }
+                                       // And of the new way in reverse (starting from the second last point)
+                                       ListIterator<Coord> newWayCoordIterator = newWayCoords.listIterator(newWayNumPoints-1);
+                                       while (newWayCoordIterator.hasPrevious()) {
+                                               replacementWay.addPoint(newWayCoordIterator.previous());
+                                       }
+                                       // Remove the existant way that was chained to the new way and start the search again.
+                                       listIterator.remove();
+                                       newWay = replacementWay;
+                                       continue outer_loop;
+                               }
+                       }
+                       // If we get here no way was found anymore that we could chain to. Add the way and return.
+                       ways.add(newWay);
+                       return;
+               }
+       }
+
        private void addLine(Way way, GType gt) {
                List<Coord> wayPoints = way.getPoints();
                List<Coord> points = new ArrayList<Coord>(wayPoints.size());
Index: src/uk/me/parabola/mkgmap/reader/osm/OsmConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/OsmConverter.java      (revision 1580)
+++ src/uk/me/parabola/mkgmap/reader/osm/OsmConverter.java      (working copy)
@@ -16,6 +16,8 @@
  */
 package uk.me.parabola.mkgmap.reader.osm;
 
+import java.util.Map;
+
 import uk.me.parabola.imgfmt.app.Area;
 
 /**
@@ -52,7 +54,7 @@
         *
         * @param relation The relation to convert.
         */
-       public void convertRelation(Relation relation);
+       public void convertRelation(Relation relation, Map<Long, Way> wayMap);
 
        /**
         * Set the bounding box for this map.  This should be set before any other
Index: src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java        (revision 1580)
+++ src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java        (working copy)
@@ -623,7 +623,7 @@
 
                long start = System.currentTimeMillis();
                for (Relation r : relationMap.values())
-                       converter.convertRelation(r);
+                       converter.convertRelation(r, wayMap);
 
                for (Node n : nodeMap.values())
                        converter.convertNode(n);
Index: src/uk/me/parabola/mkgmap/reader/osm/GType.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/GType.java     (revision 1580)
+++ src/uk/me/parabola/mkgmap/reader/osm/GType.java     (working copy)
@@ -34,7 +34,7 @@
        public static final int POLYLINE = 2;
        public static final int POLYGON = 3;
 
-       private final int featureKind;
+       private int featureKind;
        private final int type;
 
        private int minResolution = 24;
@@ -79,6 +79,10 @@
                }
        }
 
+       public void setFeatureKind(int featureKind) {
+               this.featureKind = featureKind;
+       }
+
        public int getFeatureKind() {
                return featureKind;
        }
Index: src/uk/me/parabola/mkgmap/main/StyleTester.java
===================================================================
--- src/uk/me/parabola/mkgmap/main/StyleTester.java     (revision 1580)
+++ src/uk/me/parabola/mkgmap/main/StyleTester.java     (working copy)
@@ -29,6 +29,7 @@
 import java.util.Formatter;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Properties;
 import java.util.regex.Pattern;
 
@@ -273,8 +274,8 @@
                converter.convertNode(node);
        }
 
-       public void convertRelation(Relation relation) {
-               converter.convertRelation(relation);
+       public void convertRelation(Relation relation, Map<Long, Way> wayMap) {
+               converter.convertRelation(relation, wayMap);
        }
 
        public void setBoundingBox(Area bbox) {




More information about the mkgmap-dev mailing list