As suggested, moved from rhd to dol.
Two options are now available --drive-on-left and --drive-on-right.
By default, you should not have to specify either because mkgmap now
determines the side of the road to drive on from the direction
of the first roundabout it processes. But if you don't like
its choice, you can specify one of these options to override it.
Also, it now issues a warning for each roundabout it finds that appears to go
in the wrong direction. I just got 720 warnings when I processed the GB
map so either there is a problem with the code or there is a lot of duff
roundabouts. I checked a handful of them and they were all wrong.
Please give it a go and if you find any of the warnings to be wrong,
please post the OSM URL of the roundabout in question.
Mark
diff --git a/resources/help/en/options b/resources/help/en/options
index a608abc..44d204f 100644
--- a/resources/help/en/options
+++ b/resources/help/en/options
@@ -178,6 +178,12 @@ Miscellaneous options:
Experimental: Create maps that support routing. This implies --net
(so that --net need not be given if --route is given).
+--drive-on-left
+--drive-on-right
+ Explicitly specify which side of the road vehicles are expected
+ to drive on. By default, mkgmap, determines this from the
+ direction of the roundabouts.
+
--ignore-maxspeeds
When reading OSM files, ignore any "maxspeed" tags.
diff --git a/src/uk/me/parabola/imgfmt/app/Coord.java b/src/uk/me/parabola/imgfmt/app/Coord.java
index 5462602..335284d 100644
--- a/src/uk/me/parabola/imgfmt/app/Coord.java
+++ b/src/uk/me/parabola/imgfmt/app/Coord.java
@@ -174,6 +174,22 @@ public class Coord implements Comparable<Coord> {
(int)(longitude + (other.longitude - longitude) * fraction));
}
+
+ // returns bearing (in degrees) from current point to another point
+ public double bearingTo(Coord point) {
+ double lat1 = Utils.toRadians(latitude);
+ double lat2 = Utils.toRadians(point.latitude);
+ double lon1 = Utils.toRadians(longitude);
+ double lon2 = Utils.toRadians(point.longitude);
+
+ double dlon = lon2 - lon1;
+
+ double y = Math.sin(dlon) * Math.cos(lat2);
+ double x = Math.cos(lat1)*Math.sin(lat2) -
+ Math.sin(lat1)*Math.cos(lat2)*Math.cos(dlon);
+ return Math.atan2(y, x) * 180 / Math.PI;
+ }
+
/**
* Sort lexicographically by longitude, then latitude.
*
diff --git a/src/uk/me/parabola/imgfmt/app/net/NODHeader.java b/src/uk/me/parabola/imgfmt/app/net/NODHeader.java
index 1623fa7..2a8a709 100644
--- a/src/uk/me/parabola/imgfmt/app/net/NODHeader.java
+++ b/src/uk/me/parabola/imgfmt/app/net/NODHeader.java
@@ -37,6 +37,8 @@ public class NODHeader extends CommonHeader {
private final char align = DEF_ALIGN;
+ private static boolean driveOnLeft;
+
public NODHeader() {
super(HEADER_LEN, "GARMIN NOD");
}
@@ -62,7 +64,10 @@ public class NODHeader extends CommonHeader {
nodes.writeSectionInfo(writer);
// now sets 0x02 (enable turn restrictions?)
- writer.putInt(0x27);
+ int val = 0x27;
+ if(driveOnLeft)
+ val |= 0x0300;
+ writer.putInt(val);
writer.putChar(align);
writer.putChar((char) (align - 1));
@@ -100,4 +105,8 @@ public class NODHeader extends CommonHeader {
public Section getBoundarySection() {
return boundary;
}
+
+ public static void setDriveOnLeft(boolean dol) {
+ driveOnLeft = dol;
+ }
}
diff --git a/src/uk/me/parabola/imgfmt/app/net/RouteArc.java b/src/uk/me/parabola/imgfmt/app/net/RouteArc.java
index 3930beb..0b1d1b6 100644
--- a/src/uk/me/parabola/imgfmt/app/net/RouteArc.java
+++ b/src/uk/me/parabola/imgfmt/app/net/RouteArc.java
@@ -173,25 +173,12 @@ public class RouteArc {
if(log.isDebugEnabled())
log.debug("start", start.toDegreeString(), ", end", end.toDegreeString());
- // Quite possibly too slow... TODO
- double lat1 = Utils.toRadians(start.getLatitude());
- double lat2 = Utils.toRadians(end.getLatitude());
- double lon1 = Utils.toRadians(start.getLongitude());
- double lon2 = Utils.toRadians(end.getLongitude());
+ double angle = source.getCoord().bearingTo(end);
- //double dlat = lat2 - lat1;
- double dlon = lon2 - lon1;
-
- double y = Math.sin(dlon) * Math.cos(lat2);
- double x = Math.cos(lat1)*Math.sin(lat2) -
- Math.sin(lat1)*Math.cos(lat2)*Math.cos(dlon);
- double angle = Math.atan2(y, x);
-
- // angle is in radians
if(log.isDebugEnabled())
- log.debug("angle is ", angle, ", deg", angle*57.29);
+ log.debug("angle is ", angle);
- byte b = (byte) (256 * (angle / (2 * Math.PI)));
+ byte b = (byte) (256 * angle / 360);
if(log.isDebugEnabled())
log.debug("deg from ret val", (360 * b) / 256);
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index a7f16b6..35c9c1d 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -28,6 +28,7 @@ import uk.me.parabola.imgfmt.app.Area;
import uk.me.parabola.imgfmt.app.Coord;
import uk.me.parabola.imgfmt.app.CoordNode;
import uk.me.parabola.imgfmt.app.Exit;
+import uk.me.parabola.imgfmt.app.net.NODHeader;
import uk.me.parabola.imgfmt.app.trergn.ExtTypeAttributes;
import uk.me.parabola.log.Logger;
import uk.me.parabola.mkgmap.general.AreaClipper;
@@ -98,6 +99,8 @@ public class StyledConverter implements OsmConverter {
private final Rule relationRules;
private boolean ignoreMaxspeeds;
+ private boolean driveOnLeft;
+ private boolean driveOnRight;
class AccessMapping {
private final String type;
@@ -139,6 +142,9 @@ public class StyledConverter implements OsmConverter {
nodeRules = style.getNodeRules();
relationRules = style.getRelationRules();
ignoreMaxspeeds = props.getProperty("ignore-maxspeeds") != null;
+ driveOnLeft = props.getProperty("drive-on-left") != null;
+ NODHeader.setDriveOnLeft(driveOnLeft);
+ driveOnRight = props.getProperty("drive-on-right") != null;
LineAdder overlayAdder = style.getOverlays(lineAdder);
if (overlayAdder != null)
@@ -523,6 +529,31 @@ public class StyledConverter implements OsmConverter {
}
if("roundabout".equals(way.getTag("junction"))) {
+
+ if(way.getPoints().size() > 3) {
+ // check roundabout direction
+ Coord centre = way.getCofG();
+ double a1 = way.getPoints().get(0).bearingTo(way.getPoints().get(1));
+ double a2 = way.getPoints().get(0).bearingTo(centre) - a1;
+ while(a2 > 180)
+ a2 -= 360;
+ while(a2 < -180)
+ a2 += 360;
+ boolean clockwise = a2 >= 0;
+ if(!driveOnLeft && !driveOnRight) {
+ if(clockwise) {
+ driveOnLeft = true;
+ NODHeader.setDriveOnLeft(true);
+ }
+ else {
+ driveOnRight = true;
+ }
+ }
+ if(driveOnLeft && !clockwise ||
+ driveOnRight && clockwise)
+ log.warn("Roundabout " + way.getId() + " direction is wrong");
+ }
+
String frigFactorTag = way.getTag("mkgmap:frig_roundabout");
if(frigFactorTag != null) {
// do special roundabout frigging to make gps
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/Way.java b/src/uk/me/parabola/mkgmap/reader/osm/Way.java
index 1f2242b..2155669 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/Way.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/Way.java
@@ -101,4 +101,16 @@ public class Way extends Element {
sb.append(toTagString());
return sb.toString();
}
+
+ public Coord getCofG() {
+ int lat = 0;
+ int lon = 0;
+ if(points.size() < 1)
+ return null;
+ for(Coord p : points) {
+ lat += p.getLatitude();
+ lon += p.getLongitude();
+ }
+ return new Coord(lat / points.size(), lon / points.size());
+ }
}
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev