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