Hello,

Please find attached a new version of the patch. It will now give an error message instead of asserting when a via way has been split. It still has the following limitations:

* If the via ways gets split for routing (like in http://www.openstreetmap.org/browse/relation/275622 where via way http://www.openstreetmap.org/browse/way/41694496 gets split at http://www.openstreetmap.org/browse/node/62547613 because of an incoming ramp), the relation creation will be skipped * I did not try with more than one via way but it probably just fails as well
* Restrictions with via ways are (unecessarly?) duplicated

  Thanks,

N.
Index: uk/me/parabola/imgfmt/app/net/RouteRestriction.java
===================================================================
--- uk/me/parabola/imgfmt/app/net/RouteRestriction.java (revision 1647)
+++ uk/me/parabola/imgfmt/app/net/RouteRestriction.java (working copy)
@@ -14,6 +14,7 @@
  */
 package uk.me.parabola.imgfmt.app.net;
 
+import java.util.List;
 import uk.me.parabola.imgfmt.app.ImgFileWriter;
 
 /**
@@ -35,19 +36,29 @@
        //private static final Logger log = 
Logger.getLogger(RouteRestriction.class);
 
        // size in bytes
-       private static final int SIZE = 11;
+       private static final int SIZE = 3;
 
-       // first three bytes of the header -- might specify the type of 
restriction
+       // first byte of the header -- might specify the type of restriction
        // and when it is active
-       private static final int HEADER = 0x004005;
+       private static final int HEADER = 0x05;
+       
+       // flags for the second byte
+       private byte flagByte;
 
+       public final static byte FLAG_PEDESTRIAN   = 0x02;
+       public final static byte FLAG_EMERGENCY    = 0x04;
+       public final static byte FLAG_EXCEPT_OTHER = 0x08;
+
+       // third byte (always 0?)
+       public final static byte THIRD_BYTE = 0x00;
+
+
        // To specifiy that a node is given by a relative offset instead
        // of an entry to Table B.
        private static final int F_INTERNAL = 0x8000;
 
        // the arcs
-       private final RouteArc from;
-       private final RouteArc to;
+       private final List<RouteArc> arcs;
 
        // offset in Table C
        private byte offsetSize;
@@ -57,14 +68,18 @@
        private boolean last;
 
        // mask that specifies which vehicle types the restriction doesn't 
apply to
-       private final byte exceptMask;
+       private final int exceptMask;
 
-       public final static byte EXCEPT_CAR      = 0x01;
-       public final static byte EXCEPT_BUS      = 0x02;
-       public final static byte EXCEPT_TAXI     = 0x04;
-       public final static byte EXCEPT_DELIVERY = 0x10;
-       public final static byte EXCEPT_BICYCLE  = 0x20;
-       public final static byte EXCEPT_TRUCK    = 0x40;
+       public final static int EXCEPT_CAR        = 0x0001;
+       public final static int EXCEPT_BUS        = 0x0002;
+       public final static int EXCEPT_TAXI       = 0x0004;
+       public final static int EXCEPT_DELIVERY   = 0x0010;
+       public final static int EXCEPT_BICYCLE    = 0x0020;
+       public final static int EXCEPT_TRUCK      = 0x0040;
+       public final static int EXCEPT_PEDESTRIAN = 0x0100;
+       public final static int EXCEPT_EMERGENCY  = 0x0200;
+       
+       
 
        /**
         * Create a route restriction.
@@ -72,11 +87,12 @@
         * @param from The inverse arc of "from" arc.
         * @param to The "to" arc.
         */
-       public RouteRestriction(RouteArc from, RouteArc to, byte exceptMask) {
-               assert from.getSource().equals(to.getSource()) : "arcs in 
restriction don't meet";
-               this.from = from;
-               this.to = to;
+       public RouteRestriction(List<RouteArc> arcs, int exceptMask) {
+               //assert from.getSource().equals(to.getSource()) : "arcs in 
restriction don't meet";
+         // NAKOR_FIXME: not sure how to handle this with multiple arcs
+               this.arcs = arcs;
                this.exceptMask = exceptMask;
+         this.flagByte = 0;
        }
 
        private int calcOffset(RouteNode node, int tableOffset) {
@@ -93,33 +109,51 @@
         * @param tableOffset The offset in NOD 1 of the tables area.
         */
        public void write(ImgFileWriter writer, int tableOffset) {
-               int header = HEADER;
+               byte header = HEADER;
 
-               if(exceptMask != 0)
-                       header |= 0x0800;
+               writer.put(header);
+               if( (exceptMask & 0xFF) != 0)
+                       flagByte |= FLAG_EXCEPT_OTHER;
+               if( (exceptMask & EXCEPT_PEDESTRIAN) != 0)
+                       flagByte |= FLAG_PEDESTRIAN;
+               if( (exceptMask & EXCEPT_EMERGENCY) != 0)
+                       flagByte |= FLAG_EMERGENCY;
+         assert arcs.size()<=7 : "No more than 7 arcs supported on a turn 
restriction";
+         int arcsCount = arcs.size() << 5;
+         flagByte |= arcsCount;
 
-               writer.put3(header);
+               writer.put(flagByte);
 
-               if(exceptMask != 0)
-                       writer.put(exceptMask);
+               writer.put(THIRD_BYTE);
 
-               int[] offsets = new int[3];
+               if((exceptMask & 0xFF) != 0)
+                       writer.put((byte)exceptMask);
 
-               if (from.isInternal())
-                       offsets[0] = calcOffset(from.getDest(), tableOffset);
-               else
-                       offsets[0] = from.getIndexB();
-               offsets[1] = calcOffset(to.getSource(), tableOffset);
-               if (to.isInternal())
-                       offsets[2] = calcOffset(to.getDest(), tableOffset);
-               else
-                       offsets[2] = to.getIndexB();
+               int[] offsets = new int[arcs.size()+1];
 
+         int index =0;
+         
+         RouteArc fistArc=arcs.get(0);
+         if (fistArc.isInternal())
+           offsets[index] = calcOffset(fistArc.getSource(), tableOffset);
+         else
+           offsets[index] = fistArc.getIndexB();
+         index = index+1;
+         
+         for (RouteArc arc: arcs)
+         {
+           if (arc.isInternal())
+             offsets[index] = calcOffset(arc.getDest(), tableOffset);
+           else
+             offsets[index] = arc.getIndexB();
+           index = index+1;
+         }
+
                for (int offset : offsets)
                        writer.putChar((char) offset);
 
-               writer.put(from.getIndexA());
-               writer.put(to.getIndexA());
+         for (RouteArc arc: arcs)
+           writer.put(arc.getIndexA());
        }
 
        /**
@@ -146,6 +180,7 @@
         */
        public int getSize() {
                int size = SIZE;
+         size += 3*arcs.size() +2; //(2 bytes for nodes, 1 byte for ways with 
1 more node than ways) 
                if(exceptMask != 0)
                        ++size;
                return size;
Index: uk/me/parabola/mkgmap/general/MapCollector.java
===================================================================
--- uk/me/parabola/mkgmap/general/MapCollector.java     (revision 1647)
+++ uk/me/parabola/mkgmap/general/MapCollector.java     (working copy)
@@ -16,6 +16,8 @@
  */
 package uk.me.parabola.mkgmap.general;
 
+import java.util.List;
+
 import uk.me.parabola.imgfmt.app.Coord;
 import uk.me.parabola.imgfmt.app.CoordNode;
 
@@ -72,7 +74,7 @@
         * no left turn.
         * @param exceptMask For exceptions eg. no-left-turn except for buses.
         */
-       public void addRestriction(CoordNode fromNode, CoordNode toNode, 
CoordNode viaNode, byte exceptMask);
+       public void addRestriction(List<CoordNode> restrNodes, int exceptMask);
 
        /**
         * Add a through route to the map. 
Index: uk/me/parabola/mkgmap/general/MapDetails.java
===================================================================
--- uk/me/parabola/mkgmap/general/MapDetails.java       (revision 1647)
+++ uk/me/parabola/mkgmap/general/MapDetails.java       (working copy)
@@ -115,8 +115,8 @@
                addLine(road);
        }
 
-       public void addRestriction(CoordNode fromNode, CoordNode toNode, 
CoordNode viaNode, byte exceptMask) {
-               roadNetwork.addRestriction(fromNode, toNode, viaNode, 
exceptMask);
+       public void addRestriction(List<CoordNode> restrNodes, int exceptMask) {
+               roadNetwork.addRestriction(restrNodes, exceptMask);
        }
 
        public void addThroughRoute(long junctionNodeId, long roadIdA, long 
roadIdB) {
Index: uk/me/parabola/mkgmap/general/RoadNetwork.java
===================================================================
--- uk/me/parabola/mkgmap/general/RoadNetwork.java      (revision 1647)
+++ uk/me/parabola/mkgmap/general/RoadNetwork.java      (working copy)
@@ -264,23 +264,42 @@
                return boundary;
        }
 
-       public void addRestriction(CoordNode fromNode, CoordNode toNode, 
CoordNode viaNode, byte exceptMask) {
-               RouteNode fn = nodes.get(fromNode.getId());
-               RouteNode tn = nodes.get(toNode.getId());
-               RouteNode vn = nodes.get(viaNode.getId());
+       public void addRestriction(List<CoordNode> restrNodes, int exceptMask) {
+               ArrayList<RouteArc> arcs = new ArrayList<RouteArc>();
+       
+         // Initialize by getting the first node
+         RouteNode oldNode = nodes.get(restrNodes.get(0).getId());
+         assert oldNode != null : "can't locate RouteNode with id " + 
restrNodes.get(0).getId();
 
-               assert fn != null : "can't locate 'from' RouteNode with id " + 
fromNode.getId();
-               assert tn != null : "can't locate 'to' RouteNode with id " + 
toNode.getId();
-               assert vn != null : "can't locate 'via' RouteNode with id " + 
viaNode.getId();
+         // Creating arcs and restrictions on intermediate nodes
+               for (CoordNode restrNode: restrNodes.subList(1, 
restrNodes.size()-1) )
+               {
+                       RouteNode node = nodes.get(restrNode.getId());
+               
+                       assert node != null : "can't locate RouteNode with id " 
+ restrNode.getId();
 
-               RouteArc fa = vn.getArcTo(fn); // inverse arc gets used
-               RouteArc ta = vn.getArcTo(tn);
+                       RouteArc arc = oldNode.getArcTo(node); // inverse arc 
gets used
+                       //assert arc != null : "unable to find arc from " + 
restrNode.getId();
+                       if (arc == null)
+                               log.warn("sorry, 'via' way has been splitted 
this is not supported yet - ignoring restriction");
+                       else
+                       {
+                               arcs.add(arc);
+                               node.addRestriction(new RouteRestriction(arcs, 
exceptMask));
+                       }
+           
+           oldNode=node;
+               }
 
-               assert fa != null : "can't locate arc from 'via' node to 'from' 
node";
-               assert ta != null : "can't locate arc from 'via' node to 'to' 
node";
+         // Create arc to final node
+         CoordNode lastNode=restrNodes.get(restrNodes.size()-1);
+         RouteNode finalNode = nodes.get(lastNode.getId());
+       
+         assert finalNode != null : "can't locate RouteNode with id " + 
lastNode.getId();
 
-               vn.addRestriction(new RouteRestriction(fa, ta, exceptMask));
-    }
+         RouteArc finalArc = oldNode.getArcTo(finalNode); // inverse arc gets 
used
+         arcs.add(finalArc);
+       }
 
        public void addThroughRoute(long junctionNodeId, long roadIdA, long 
roadIdB) {
                RouteNode node = nodes.get(junctionNodeId);
Index: uk/me/parabola/mkgmap/main/StyleTester.java
===================================================================
--- uk/me/parabola/mkgmap/main/StyleTester.java (revision 1647)
+++ uk/me/parabola/mkgmap/main/StyleTester.java (working copy)
@@ -716,7 +716,7 @@
                        lines.add(road);
                }
 
-               public void addRestriction(CoordNode fromNode, CoordNode 
toNode, CoordNode viaNode, byte exceptMask) {
+               public void addRestriction(List<CoordNode> restrNodes, int 
exceptMask) {
                }
 
                public void addThroughRoute(long junctionNodeId, long roadIdA, 
long roadIdB) {
@@ -758,7 +758,7 @@
                        }
                }
 
-               public void addRestriction(CoordNode fromNode, CoordNode 
toNode, CoordNode viaNode, byte exceptMask) {
+               public void addRestriction(List<CoordNode> restrNodes, int 
exceptMask) {
                }
 
                public void addThroughRoute(long junctionNodeId, long roadIdA, 
long roadIdB) {
Index: uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- uk/me/parabola/mkgmap/osmstyle/StyledConverter.java (revision 1647)
+++ uk/me/parabola/mkgmap/osmstyle/StyledConverter.java (working copy)
@@ -468,16 +468,22 @@
                // Relations never resolve to a GType and so we ignore the 
return
                // value.
                relationRules.resolveType(relation, TypeResult.NULL_RESULT);
-
+    
+    log.info("Processing relation");
                if(relation instanceof RestrictionRelation) {
                        RestrictionRelation rr = (RestrictionRelation)relation;
                        if(rr.isValid()) {
-                               List<RestrictionRelation> lrr = 
restrictions.get(rr.getViaCoord());
-                               if(lrr == null) {
-                                       lrr = new 
ArrayList<RestrictionRelation>();
-                                       restrictions.put(rr.getViaCoord(), lrr);
-                               }
-                               lrr.add(rr);
+        List<Coord> Coords=rr.getViaCoords();
+        for (Coord coord: Coords)
+        {
+          List<RestrictionRelation> lrr = restrictions.get(coord);
+          if(lrr == null) {
+            lrr = new ArrayList<RestrictionRelation>();
+            restrictions.put(coord, lrr);
+            log.info("Adding relation to map");
+          }
+          lrr.add(rr);
+        }
                        }
                }
                else if("through_route".equals(relation.getTag("type"))) {
Index: uk/me/parabola/mkgmap/reader/osm/RestrictionRelation.java
===================================================================
--- uk/me/parabola/mkgmap/reader/osm/RestrictionRelation.java   (revision 1647)
+++ uk/me/parabola/mkgmap/reader/osm/RestrictionRelation.java   (working copy)
@@ -24,14 +24,14 @@
     private Way fromWay;
     private Way toWay;
     private Way viaWay;
-    private Coord viaCoord;
+    private ArrayList<Coord> viaCoords = new ArrayList<Coord>();
     private final String restriction;
 
     private CoordNode fromNode;
     private CoordNode toNode;
     private CoordNode viaNode;
     private final List<CoordNode> otherNodes = new ArrayList<CoordNode>();
-       private byte exceptMask;
+    private int exceptMask;
     private String messagePrefix;
 
        /**
@@ -55,8 +55,8 @@
 
                        Coord location = null;
 
-                       if(viaCoord != null)
-                               location = viaCoord;
+                       if(viaCoords.size()>0)
+                               location = viaCoords.get(0);
                        else if(fromWay != null && fromWay.getPoints().size() > 
0)
                                location = fromWay.getPoints().get(0);
                        else if(toWay != null && toWay.getPoints().size() > 0)
@@ -92,14 +92,17 @@
                                        fromWay = (Way)el;
                        }
                        else if("via".equals(role)) {
-                               if(viaCoord != null || viaWay != null) {
+                               if(viaCoords.size()>0 || viaWay != null) {
                                        log.warn(messagePrefix + "has extra 
'via' member " + el.toBrowseURL());
                                }
                                else if(el instanceof Node) {
-                                       viaCoord = ((Node)el).getLocation();
+                                       viaCoords.add(((Node)el).getLocation());
                                }
                                else if(el instanceof Way) {
                                        viaWay = (Way)el;
+          List<Coord> points=((Way)el).getPoints();
+                                       viaCoords.add(points.get(0));
+                                       
viaCoords.add(points.get(points.size()-1));
                                }
                                else {
                                        log.warn(messagePrefix + "'via' member 
" + el.toBrowseURL() + " is not a node or way");
@@ -148,6 +151,10 @@
                                        exceptMask |= 
RouteRestriction.EXCEPT_BICYCLE;
                                else if(e.equals("hgv") || e.equals("truck"))
                                        exceptMask |= 
RouteRestriction.EXCEPT_TRUCK;
+                               else if(e.equals("emergency"))
+                                       exceptMask |= 
RouteRestriction.EXCEPT_EMERGENCY;
+                               else if(e.equals("pedestrian"))
+                                       exceptMask |= 
RouteRestriction.EXCEPT_PEDESTRIAN;
                                else
                                        log.warn(messagePrefix + "ignoring 
unsupported vehicle class '" + e + "' in turn restriction exception");
                        }
@@ -166,8 +173,8 @@
                return viaWay;
        }
 
-       public Coord getViaCoord() {
-               return viaCoord;
+       public List<Coord> getViaCoords() {
+               return viaCoords;
        }
 
        public void setFromNode(CoordNode fromNode) {
@@ -187,10 +194,12 @@
                        log.warn(messagePrefix + restriction + " 'via' node 
redefined from " +
                                         this.viaNode.toOSMURL() + " to " + 
viaNode.toOSMURL());
                this.viaNode = viaNode;
+    if (otherNodes.indexOf(viaNode)==-1)
+      otherNodes.add(viaNode);
        }
 
        public void addOtherNode(CoordNode otherNode) {
-               otherNodes.add(otherNode);
+               //otherNodes.add(otherNode);
                log.debug(messagePrefix + restriction + " adding 'other' node " 
+ otherNode.toOSMURL());
        }
 
@@ -213,14 +222,14 @@
                if(fromWay == null || toWay == null)
                        return false;
 
-               if(viaCoord == null && viaWay == null) {
+               if(viaCoords.size() == 0 && viaWay == null) {
                        List<Coord>fromPoints = fromWay.getPoints();
                        List<Coord>toPoints = toWay.getPoints();
                        for(Coord fp : fromPoints) {
                                for(Coord tp : toPoints) {
                                        if(fp.equals(tp)) {
-                                               if(viaCoord == null) {
-                                                       viaCoord = fp;
+                                               if(viaCoords.size() == 0) {
+                                                       viaCoords.add(fp);
                                                }
                                                else {
                                                        log.warn(messagePrefix 
+ "lacks 'via' node and the 'from' (" + fromWay.toBrowseURL() + ") and 'to' (" 
+ toWay.toBrowseURL() + ") ways connect in more than one place");
@@ -230,15 +239,15 @@
                                }
                        }
 
-                       if(viaCoord == null) {
+                       if(viaCoords.size()==0) {
                                log.warn(messagePrefix + "lacks 'via' node and 
the 'from' (" + fromWay.toBrowseURL() + ") and 'to' (" + toWay.toBrowseURL() + 
") ways don't connect");
                                return false;
                        }
 
-                       log.warn(messagePrefix + "lacks 'via' node (guessing it 
should be at " + viaCoord.toOSMURL() + ", why don't you add it to the OSM 
data?)");
+                       log.warn(messagePrefix + "lacks 'via' node (guessing it 
should be at " + viaCoords.get(0).toOSMURL() + ", why don't you add it to the 
OSM data?)");
                }
 
-               Coord v1 = viaCoord;
+               Coord v1 = viaCoords.get(0);
                Coord v2 = null;
 
                if(viaWay != null) {
@@ -262,17 +271,12 @@
                        result = false;
                }
 
-               if (result && viaWay != null) {
-                       log.warn(messagePrefix + "sorry, 'via' ways are not 
supported - ignoring restriction");
-                       result = false;
-               }
-
                return result;
        }
 
        public void addRestriction(MapCollector collector) {
 
-               if(restriction == null || viaNode == null || fromNode == null 
|| toNode == null) {
+               if(restriction == null || (viaNode == null && viaWay == null) 
|| fromNode == null || toNode == null) {
                        // restriction must have some error (reported earlier)
                        return;
                }
@@ -282,7 +286,22 @@
                   restriction.equals("no_straight_on") ||
                   restriction.equals("no_u_turn") ||
                   restriction.startsWith("no_turn")) {
-                       collector.addRestriction(fromNode, toNode, viaNode, 
exceptMask);
+      ArrayList<CoordNode> nodes = new ArrayList<CoordNode>();
+      nodes.add(fromNode);
+      if (viaWay!=null)
+      {
+        nodes.addAll(otherNodes);  
+      }
+      else if (viaNode!=null)  {
+        nodes.add(viaNode);
+      }
+      nodes.add(toNode);
+      log.info ("Creating relation with " +nodes.size()+" nodes");
+      for (Coord node :nodes)
+      {
+        log.info ("  " +node.toOSMURL());
+      }
+                       collector.addRestriction(nodes, exceptMask);
                        if(restriction.startsWith("no_turn"))
                                log.warn(messagePrefix + "has bad type '" + 
restriction + "' it should be of the form no_X_turn rather than no_turn_X - I 
added the restriction anyway - blocks routing to way " + toWay.toBrowseURL());
                        else
@@ -297,7 +316,11 @@
                        log.info(messagePrefix + restriction + " added - allows 
routing to way " + toWay.toBrowseURL());
                        for(CoordNode otherNode : otherNodes) {
                                log.info(messagePrefix + restriction + "  
blocks routing to node " + otherNode.toOSMURL());
-                               collector.addRestriction(fromNode, otherNode, 
viaNode, exceptMask);
+        ArrayList<CoordNode> nodes = new ArrayList<CoordNode>();
+        nodes.add(fromNode);
+        nodes.add(viaNode);
+        nodes.add(otherNode);
+                               collector.addRestriction(nodes, exceptMask);
                        }
                }
                else {
@@ -312,6 +335,6 @@
        }
 
        public String toString() {
-               return "[restriction = " + restriction + ", from = " + 
fromWay.toBrowseURL() + ", to = " + toWay.toBrowseURL() + ", via = " + 
viaCoord.toOSMURL() + "]";
+               return "[restriction = " + restriction + ", from = " + 
fromWay.toBrowseURL() + ", to = " + toWay.toBrowseURL() + ", via = " + 
viaCoords.get(0).toOSMURL() + "]";
        }
 }
Index: uk/me/parabola/mkgmap/reader/overview/OverviewMapDataSource.java
===================================================================
--- uk/me/parabola/mkgmap/reader/overview/OverviewMapDataSource.java    
(revision 1647)
+++ uk/me/parabola/mkgmap/reader/overview/OverviewMapDataSource.java    
(working copy)
@@ -18,6 +18,7 @@
 
 import java.io.FileNotFoundException;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 import uk.me.parabola.imgfmt.FormatException;
@@ -140,8 +141,8 @@
                addLine(road);
        }
 
-       public void addRestriction(CoordNode fromNode, CoordNode toNode, 
CoordNode viaNode, byte exceptMask) {
-               getRoadNetwork().addRestriction(fromNode, toNode, viaNode, 
exceptMask);
+       public void addRestriction(List<CoordNode> restrNodes, int exceptMask) {
+               getRoadNetwork().addRestriction(restrNodes, exceptMask);
        }
 
        public void addThroughRoute(long junctionNodeId, long roadIdA, long 
roadIdB) {
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to