v4
forgot to make the POI a routing node - it is now - this stops routing
across the POI when the start and end points are within the restricted
area.
-------------
v3
now adds extra points either side of the POI to reduce length of
way that has restricted access. Currently points are 25m away from the
POI. It would be nice if they were really close (like 5m) but if you
try that, the map looks crap due to the limited coordinate resolution.
So, 25m is a compromise between visual appearance and minimising the
extent of the restricted zone.
------------
v2 - quick update based on instantaneous feedback from ML!
Now works for any POI that sets "access=no" (could use the more general
test of any of the access tags being set but let's see how this works
for now).
Default access rights now set in style file.
Any suggestions for a better code for cycle_barrier?
------------
Fed up of being routed in your car down city streets only to find the
way is blocked by a bollard? Well, if so, this is the patch for you.
If a way has a bollard on a point, the segments of the way that
connect to the bollard have access restrictions placed on them. By
default, a bollard implies: access=no, foot=yes, bicycle=yes.
Testing using mapsource shows that it generally works as expected
although if the destination cannot be reached by any other route, it
routes straight through the bollard rather than failing! If the
destination can be reached by some other route, even if the route is
really long, it will avoid the bollard.
I have chosen Garmin code 0x660f (pillar) for the bollard. On my etrex
it appears as a small dot in the way.
As usual, all feedback is welcome.
Cheers,
Mark
diff --git a/resources/styles/default/points b/resources/styles/default/points
index 1c3ae8f..a97fc13 100644
--- a/resources/styles/default/points
+++ b/resources/styles/default/points
@@ -166,3 +166,7 @@ tourism=theme_park [0x2c01 resolution 20]
tourism=viewpoint [0x2c04 resolution 20]
tourism=wine_cellar [0x2c0a resolution 20]
tourism=zoo [0x2c07 resolution 20]
+
+barrier=bollard {add access = no; add bicycle = yes; add foot = yes} [0x660f resolution 20]
+barrier=cycle_barier {add access = no; add bicycle = yes; add foot = yes} [0x660f resolution 20]
+
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index aa5bab1..668f1fd 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -42,6 +42,7 @@ import uk.me.parabola.mkgmap.general.MapPoint;
import uk.me.parabola.mkgmap.general.MapRoad;
import uk.me.parabola.mkgmap.general.MapShape;
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.GType;
import uk.me.parabola.mkgmap.reader.osm.Node;
@@ -426,6 +427,115 @@ public class StyledConverter implements OsmConverter {
}
}
+ // process any Coords that have a POI associated with them
+ if("true".equals(way.getTag("mkgmap:way-has-pois"))) {
+ List<Coord> points = way.getPoints();
+
+ // at this time, we are only looking for POIs that have
+ // the "access" tag defined - if they do, copy the access
+ // permissions to the way - what we want to achieve is
+ // modifying the way's access permissions where it passes
+ // through the POI without affecting the rest of the way
+ // too much - to that end we split the way before and
+ // after the POI - if necessary, extra points are inserted
+ // before and after the POI to limit the size of the
+ // affected region
+
+ final double stubSegmentLength = 25; // metres
+ for(int i = 0; i < points.size(); ++i) {
+ Coord p = points.get(i);
+ // check if this POI modifies access and if so, split
+ // the way at the following point (if any) and then
+ // copy its access restrictions to the way
+ if(p instanceof CoordPOI) {
+ CoordPOI cp = (CoordPOI)p;
+ Node node = cp.getNode();
+ if(node.getTag("access") != null) {
+ // if this or the next point are not the last
+ // points in the way, split at the next point
+ // taking care not to produce a short arc
+ if((i + 1) < points.size()) {
+ Coord p1 = points.get(i + 1);
+ // check if the next point is further away
+ // than we would like
+ double dist = p.distance(p1);
+ if(dist >= (2 * stubSegmentLength)) {
+ // insert a new point after the POI to
+ // make a short stub segment
+ p1 = p.makeBetweenPoint(p1, stubSegmentLength / dist);
+ points.add(i + 1, p1);
+ }
+
+ // now split the way at the next point to
+ // limit the region that has restricted
+ // access
+ if(!p.equals(p1) &&
+ ((i + 2) == points.size() ||
+ !p1.equals(points.get(i + 2)))) {
+ Way tail = splitWayAt(way, i + 1);
+ // recursively process tail of way
+ addRoad(tail, gt);
+ }
+ }
+
+ // make the POI a node so that the region with
+ // restricted access is split into two as far
+ // as routing is concerned - this should stop
+ // routing across the POI when the starting point
+ // is within the restricted region
+ p.incHighwayCount();
+
+ // copy all of the POI's access restrictions
+ // to the way segment
+ for (AccessMapping anAccessMap : accessMap) {
+ String accessType = anAccessMap.type;
+ String accessModifier = node.getTag(accessType);
+ if(accessModifier != null)
+ way.addTag(accessType, accessModifier);
+ }
+ }
+ }
+
+ // check if the next point modifies access and if so,
+ // split the way either here or at a new point that's
+ // closer to the POI taking care not to introduce a
+ // short arc
+ if((i + 1) < points.size()) {
+ Coord p1 = points.get(i + 1);
+ if(p1 instanceof CoordPOI) {
+ CoordPOI cp = (CoordPOI)p1;
+ Node node = cp.getNode();
+ if(node.getTag("access") != null) {
+ // check if this point is further away
+ // from the POI than we would like
+ double dist = p.distance(p1);
+ if(dist >= (2 * stubSegmentLength)) {
+ // insert a new point to make a short
+ // stub segment
+ p1 = p1.makeBetweenPoint(p, stubSegmentLength / dist);
+ points.add(i + 1, p1);
+ // as p1 is now no longer a CoordPOI,
+ // the split below will be deferred
+ // until the next iteration of the
+ // loop (which is what we want!)
+ }
+
+ // now split the way here if it is not the
+ // first point in the way
+ if(p1 instanceof CoordPOI &&
+ i > 0 &&
+ !p.equals(points.get(i - 1)) &&
+ !p.equals(p1)) {
+ Way tail = splitWayAt(way, i);
+ // recursively process tail of road
+ addRoad(tail, gt);
+ }
+ }
+ }
+ }
+ }
+ }
+
// if there is a bounding box, clip the way with it
List<Way> clippedWays = null;
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/CoordPOI.java b/src/uk/me/parabola/mkgmap/reader/osm/CoordPOI.java
new file mode 100644
index 0000000..409965b
--- /dev/null
+++ b/src/uk/me/parabola/mkgmap/reader/osm/CoordPOI.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2008 Steve Ratcliffe
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ *
+ * Author: Steve Ratcliffe
+ * Create date: 13-Jul-2008
+ */
+package uk.me.parabola.mkgmap.reader.osm;
+
+import uk.me.parabola.imgfmt.app.Coord;
+
+/**
+ * A coordinate that has a POI
+ *
+ * @author Steve Ratcliffe
+ */
+public class CoordPOI extends Coord {
+ private final Node node;
+
+ /**
+ * Construct from co-ordinates that are already in map-units.
+ *
+ * @param latitude The latitude in map units.
+ * @param longitude The longitude in map units.
+ * @param node The Node that represents the POI.
+ */
+ public CoordPOI(int latitude, int longitude, Node node) {
+ super(latitude, longitude);
+ this.node = node;
+ }
+
+ public Node getNode() {
+ return node;
+ }
+}
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java b/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
index 2e8ccbb..cd2dfba 100644
--- a/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
+++ b/src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
@@ -29,6 +29,7 @@ import uk.me.parabola.imgfmt.app.Exit;
import uk.me.parabola.log.Logger;
import uk.me.parabola.mkgmap.general.MapDetails;
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.GeneralRelation;
import uk.me.parabola.mkgmap.reader.osm.MultiPolygonRelation;
@@ -636,6 +637,19 @@ class Osm5XmlHandler extends DefaultHandler {
Coord co = coordMap.get(id);
//co.incCount();
if (co != null) {
+ // if this Coord is also a POI, replace it with an equivalent
+ // CoordPOI that contains a reference to the POI's Node so we
+ // can access the POI's tags
+ Node node = nodeMap.get(id);
+ if(node != null) {
+ if(!(co instanceof CoordPOI)) {
+ co = new CoordPOI(co.getLatitude(), co.getLongitude(), node);
+ coordMap.put(id, co);
+ }
+ // flag this Way as having a CoordPOI so it will be
+ // processed later
+ currentWay.addTag("mkgmap:way-has-pois", "true");
+ }
currentWay.addPoint(co);
if(minimumArcLength != null)
nodeIdMap.put(co, id);
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev