v2 - sans syntax error
---------
Bloody typical, you wait around for ages hoping for a new routing
capability to be added to mkgmap and then two come along on
the same day.
I've been trying to discover how unpavedness is encoded for at least 6
months. Every now and again, I return to think about it some more.
Check and re-check the same old data structures. Very
frustrating, no progress. Damn those cunning bastards at Garmin....
However, a month or two ago, I discovered that Table C contains more
than just turn restrictions. I still don't know many of it's little
secrets but, today, having exhausted all other possibilities, I finally
twigged that Table C contains the key to understanding "unpavedness".
Gotcha!
The attached patch allows you to add either unpaved=yes/true/1 or
paved=no/false/0 to a way and then it will be ignored for routing
purposes when the GPS has been told to avoid unpaved roads.
Not sure if those are the best tags to use - any thoughts?
BTW - the unpaved road line type 0x0a has nothing to do with
unpavedness, it's just a routable way that gets drawn as a dashed line
(default rendering).
Feedback, etc.
Mark
diff --git a/src/uk/me/parabola/imgfmt/app/net/RoadDef.java b/src/uk/me/parabola/imgfmt/app/net/RoadDef.java
index 7323017..2642211 100644
--- a/src/uk/me/parabola/imgfmt/app/net/RoadDef.java
+++ b/src/uk/me/parabola/imgfmt/app/net/RoadDef.java
@@ -122,6 +122,7 @@ public class RoadDef implements Comparable {
private City city;
private Zip zip;
+ private boolean paved = true;
private boolean roundabout;
private boolean linkRoad;
private boolean synthesised;
@@ -586,6 +587,14 @@ public class RoadDef implements Comparable {
return city;
}
+ public boolean paved() {
+ return paved;
+ }
+
+ public void paved(boolean p) {
+ paved = p;
+ }
+
public void setRoundabout(boolean r) {
roundabout = r;
}
diff --git a/src/uk/me/parabola/imgfmt/app/net/RouteCenter.java b/src/uk/me/parabola/imgfmt/app/net/RouteCenter.java
index a4134c4..931778c 100644
--- a/src/uk/me/parabola/imgfmt/app/net/RouteCenter.java
+++ b/src/uk/me/parabola/imgfmt/app/net/RouteCenter.java
@@ -49,6 +49,9 @@ public class RouteCenter {
this.tabB = tabB;
this.tabC = new TableC();
+ // let Table C know how many unpaved arcs there are
+ tabC.numUnpavedArcs(tabA.numUnpavedArcs());
+
log.info("new RouteCenter at " + centralPoint.toDegreeString() +
", nodes: " + nodes.size() + " tabA: " + tabA.size() +
" tabB: " + tabB.size());
@@ -106,7 +109,7 @@ public class RouteCenter {
writer.position(tablesOffset);
// Write the tables header
- writer.put(tabC.getSizeBytes());
+ writer.put(tabC.getFormat());
writer.put3(centralPoint.getLongitude());
writer.put3(centralPoint.getLatitude());
writer.put(tabA.getNumberOfItems());
diff --git a/src/uk/me/parabola/imgfmt/app/net/TableA.java b/src/uk/me/parabola/imgfmt/app/net/TableA.java
index a0c87ee..bc57844 100644
--- a/src/uk/me/parabola/imgfmt/app/net/TableA.java
+++ b/src/uk/me/parabola/imgfmt/app/net/TableA.java
@@ -16,6 +16,7 @@
*/
package uk.me.parabola.imgfmt.app.net;
+import java.util.HashMap;
import java.util.LinkedHashMap;
import uk.me.parabola.imgfmt.app.ImgFileWriter;
@@ -37,10 +38,15 @@ public class TableA {
// This table's start position relative to the start of NOD 1
private int offset;
- private final LinkedHashMap<Arc,Integer> arcs = new LinkedHashMap<Arc,Integer>();
+ // arcs for paved ways
+ private final HashMap<Arc,Integer> pavedArcs = new LinkedHashMap<Arc,Integer>();
+ // arcs for unpaved ways
+ private final HashMap<Arc,Integer> unpavedArcs = new LinkedHashMap<Arc,Integer>();
private static int count;
+ private boolean frozen = false; // true when no more arcs should be added
+
public TableA() {
log.debug("creating TableA", count);
count++;
@@ -88,24 +94,42 @@ public class TableA {
* the table fulfills the size constraint.
*/
public void addArc(RouteArc arc) {
+ assert !frozen : "trying to add arc to Table A after it has been frozen";
Arc narc = new Arc(arc);
int i;
- if (!arcs.containsKey(narc)) {
- i = arcs.size();
- arcs.put(narc, i);
- log.debug("added arc", count, narc, i);
+ if(arc.getRoadDef().paved()) {
+ if (!pavedArcs.containsKey(narc)) {
+ i = pavedArcs.size();
+ pavedArcs.put(narc, i);
+ log.debug("added paved arc", count, narc, i);
+ }
+ }
+ else {
+ if (!unpavedArcs.containsKey(narc)) {
+ i = unpavedArcs.size();
+ unpavedArcs.put(narc, i);
+ log.debug("added unpaved arc", count, narc, i);
+ }
}
}
/**
- * Retrieve an arc's index.
+ * Retrieve an arc's index (unpaved arcs are all before the paved arcs)
*/
public byte getIndex(RouteArc arc) {
- log.debug("getting index", arc);
+ frozen = true;
Arc narc = new Arc(arc);
- assert arcs.containsKey(narc):
+ int i;
+ if(arc.getRoadDef().paved()) {
+ assert pavedArcs.containsKey(narc):
+ "Trying to read Table A index for non-registered arc: " + count + " " + narc;
+ i = unpavedArcs.size() + pavedArcs.get(narc);
+ }
+ else {
+ assert unpavedArcs.containsKey(narc):
"Trying to read Table A index for non-registered arc: " + count + " " + narc;
- int i = arcs.get(narc);
+ i = unpavedArcs.get(narc);
+ }
assert i < 0x100 : "Table A index too large: " + narc;
return (byte) i;
}
@@ -118,7 +142,11 @@ public class TableA {
* the network.
*/
public int size() {
- return arcs.size();
+ return unpavedArcs.size() + pavedArcs.size();
+ }
+
+ public int numUnpavedArcs() {
+ return unpavedArcs.size();
}
/**
@@ -130,8 +158,8 @@ public class TableA {
* it isn't too large.
*/
public byte getNumberOfItems() {
- assert arcs.size() < 0x100 : "Table A too large";
- return (byte) arcs.size();
+ assert size() < 0x100 : "Table A too large";
+ return (byte)size();
}
/**
@@ -140,7 +168,7 @@ public class TableA {
*/
public void write(ImgFileWriter writer) {
offset = writer.position();
- int size = arcs.size() * ITEM_SIZE;
+ int size = size() * ITEM_SIZE;
log.debug("tab a offset", offset, "tab a size", size);
for (int i = 0; i < size; i++)
@@ -152,19 +180,27 @@ public class TableA {
*/
public void writePost(ImgFileWriter writer) {
writer.position(offset);
- for (Arc arc : arcs.keySet()) {
- // write the table A entries. Consists of a pointer to net
- // followed by 2 bytes of class and speed flags and road restrictions.
- log.debug("writing Table A entry", arcs.get(arc));
- int pos = arc.roadDef.getOffsetNet1();
- int access = arc.roadDef.getTabAAccess();
- // top bits of access go into net1 offset
- final int ACCESS_TOP_BITS = 0xc000;
- pos |= (access & ACCESS_TOP_BITS) << 8;
- access &= ~ACCESS_TOP_BITS;
- writer.put3(pos);
- writer.put((byte) arc.roadDef.getTabAInfo());
- writer.put((byte) access);
+ // unpaved arcs first
+ for (Arc arc : unpavedArcs.keySet()) {
+ writePost(writer, arc);
}
+ // followed by the paved arcs
+ for (Arc arc : pavedArcs.keySet()) {
+ writePost(writer, arc);
+ }
+ }
+
+ public void writePost(ImgFileWriter writer, Arc arc) {
+ // write the table A entries. Consists of a pointer to net
+ // followed by 2 bytes of class and speed flags and road restrictions.
+ int pos = arc.roadDef.getOffsetNet1();
+ int access = arc.roadDef.getTabAAccess();
+ // top bits of access go into net1 offset
+ final int ACCESS_TOP_BITS = 0xc000;
+ pos |= (access & ACCESS_TOP_BITS) << 8;
+ access &= ~ACCESS_TOP_BITS;
+ writer.put3(pos);
+ writer.put((byte) arc.roadDef.getTabAInfo());
+ writer.put((byte) access);
}
}
diff --git a/src/uk/me/parabola/imgfmt/app/net/TableC.java b/src/uk/me/parabola/imgfmt/app/net/TableC.java
index 5cd9992..17be303 100644
--- a/src/uk/me/parabola/imgfmt/app/net/TableC.java
+++ b/src/uk/me/parabola/imgfmt/app/net/TableC.java
@@ -31,23 +31,33 @@ public class TableC {
private final List<RouteRestriction> restrictions = new ArrayList<RouteRestriction>();
+ private int numUnpavedArcs = 0;
+
+ public void numUnpavedArcs(int nua) {
+ numUnpavedArcs = nua;
+ }
+
/**
* Write the table including size field.
*/
public void write(ImgFileWriter writer, int tablesOffset) {
if (restrictions.isEmpty()) {
+ if(numUnpavedArcs > 0)
+ writer.put((byte)numUnpavedArcs);
writer.put((byte) 0);
- return;
- } else {
+ }
+ else {
byte b = getSizeBytes();
assert size < (1 << 8*b);
if (b == 1)
writer.put((byte) size);
else
writer.putChar((char) size);
+ for (RouteRestriction restr : restrictions)
+ restr.write(writer, tablesOffset);
+ if(numUnpavedArcs > 0)
+ writer.put((byte)numUnpavedArcs);
}
- for (RouteRestriction restr : restrictions)
- restr.write(writer, tablesOffset);
}
/**
@@ -85,4 +95,11 @@ public class TableC {
for (RouteRestriction restr : restrictions)
restr.setOffsetSize(b);
}
+
+ public byte getFormat() {
+ byte format = getSizeBytes();
+ if(numUnpavedArcs > 0)
+ format |= 0x08;
+ return format;
+ }
}
diff --git a/src/uk/me/parabola/mkgmap/general/MapRoad.java b/src/uk/me/parabola/mkgmap/general/MapRoad.java
index c540a69..d887099 100644
--- a/src/uk/me/parabola/mkgmap/general/MapRoad.java
+++ b/src/uk/me/parabola/mkgmap/general/MapRoad.java
@@ -72,6 +72,10 @@ public class MapRoad extends MapLine {
this.roadDef.setToll();
}
+ public void paved(boolean p) {
+ this.roadDef.paved(p);
+ }
+
public void showOSMBrowseURL() {
this.roadDef.showOSMBrowseURL();
}
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index fbff7e0..db2178e 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -1426,6 +1426,11 @@ public class StyledConverter implements OsmConverter {
if(way.isBoolTag("toll"))
road.setToll();
+ // assume road is paved unless unpaved tag is true or paved
+ // tag is false, in which case, consider road as unpaved
+ if(way.isBoolTag("unpaved") || way.isNotBoolTag("paved"))
+ road.paved(false);
+
Way origWay = originalWay.get(way);
if(origWay == null)
origWay = way;
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev