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..4754d07 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,89 @@ 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();
+			final double stubSegmentLength = 25; // metres
+			for(int i = 0; i < points.size(); ++i) {
+				Coord p = points.get(i);
+				// check if this POI denies access and if so, 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((i + 1) < points.size()) {
+							Coord p1 = points.get(i + 1);
+							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);
+							}
+
+							// split the way at the next point to
+							// limit the region that has restricted
+							// access (taking care not to produce a
+							// short arc)
+							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);
+							}
+						}
+
+						// 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);
+						}
+					}
+				}
+
+				// see if the next point restricts access and if so,
+				// split the way either here, or at a new point that's
+				// closer to the POI
+				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) {
+							boolean newPointAdded = false;
+							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);
+								// we have added a new point so
+								// the split now needs to happen
+								// on the next iteration
+								newPointAdded = true;
+							}
+
+							if(!newPointAdded && i > 0 && !p.equals(p1)) {
+								// split the way here to limit the
+								// region that has restricted access
+								// (taking care not to produce a short
+								// arc)
+								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
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to