Hi,

the patch removes tags from ways not until all multipolygons are processed. This fixes some problems if one way is a member of multiple multipolygons and the multipolygons take their tags from their ways.

This is a result of the thread http://www.mkgmap.org.uk/pipermail/mkgmap-dev/2010q3/008730.html.

Have fun!
WanMil
Index: src/uk/me/parabola/mkgmap/reader/osm/Element.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Element.java	(revision 1667)
+++ src/uk/me/parabola/mkgmap/reader/osm/Element.java	(working copy)
@@ -68,7 +68,7 @@
 
 	String toTagString() {
 		if (tags == null)
-			return "";
+			return "[]";
 
 		StringBuilder sb = new StringBuilder();
 		sb.append('[');
@@ -76,7 +76,9 @@
 			sb.append(nameval);
 			sb.append(',');
 		}
-		sb.setLength(sb.length()-1);
+		if (sb.length() > 1) {
+			sb.setLength(sb.length()-1);
+		}
 		sb.append(']');
 		return sb.toString();
 	}
Index: src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java	(revision 1667)
+++ src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java	(working copy)
@@ -20,6 +20,7 @@
 import java.util.Queue;
 import java.util.Set;
 import java.util.TreeSet;
+import java.util.Map.Entry;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.logging.Level;
 
@@ -46,7 +47,9 @@
 
 	private final uk.me.parabola.imgfmt.app.Area bbox;
 	private Area bboxArea;
-	
+
+	private final Map<Long, Set<String>> wayRemoveTags;
+
 	/** 
 	 * A point that has a lower or equal squared distance from 
 	 * a line is treated as if it lies one the line.<br/>
@@ -72,30 +75,35 @@
 	 *            The relation to base this one on.
 	 * @param wayMap
 	 *            Map of all ways.
+	 * @param wayRemoveTags
+	 * 			  Marks which tags should be removed from a way after the 
+	 *            complete multipolygon processing has finished
 	 */
-	public MultiPolygonRelation(Relation other, Map<Long, Way> wayMap, 
+	public MultiPolygonRelation(Relation other, Map<Long, Way> wayMap,
+			Map<Long, Set<String>> wayRemoveTags,
 			uk.me.parabola.imgfmt.app.Area bbox) {
 		this.tileWayMap = wayMap;
 		this.bbox = bbox;
+		this.wayRemoveTags = wayRemoveTags;
 
 		setId(other.getId());
+		setName(other.getName());
+		copyTags(other);
 
 		if (log.isDebugEnabled()) {
-			log.debug("Construct multipolygon", toBrowseURL());
+			log.debug("Construct multipolygon", toBrowseURL(), toTagString());
 		}
 
 		for (Map.Entry<String, Element> pair : other.getElements()) {
 			String role = pair.getKey();
 			Element el = pair.getValue();
 			if (log.isDebugEnabled()) {
-				log.debug(" ", role, el.toBrowseURL());
+				log.debug(" ", role, el.toBrowseURL(), el.toTagString());
 			}
 			addElement(role, el);
 			roleMap.put(el.getId(), role);
 		}
 
-		setName(other.getName());
-		copyTags(other);
 	}
 
 	public boolean isBoundaryRelation() {
@@ -722,12 +730,8 @@
 					// has been replaced by the new cut polygon
 					// the original way should not appear
 					// so we remove all tags
-					currentPolygon.polygon.removeAllTagsDeep();
-				} else {
-					// remove all polygons tags from the original ways
-					// sometimes the ways seem to be auto-closed later on
-					// in mkgmap
-					currentPolygon.polygon.removePolygonTagsInOrgWays();
+					removeTagInOrgWays(currentPolygon.polygon, null, null);
+					currentPolygon.polygon.removeAllTags();
 				}
 
 				boolean useRelationTags = currentPolygon.outer
@@ -735,6 +739,8 @@
 				if (useRelationTags) {
 					// the multipolygon contains tags that overwhelm the
 					// tags of the outer polygon
+					removeTagsInOrgWays(this, currentPolygon.polygon);
+
 					for (Way p : singularOuterPolygons) {
 						p.copyTags(this);
 						p.deleteTag("type");
@@ -1256,6 +1262,10 @@
 
 	private boolean hasPolygonTags(Element element) {
 		for (Map.Entry<String, String> tagEntry : element.getEntryIteratable()) {
+			if ("natural".equals(tagEntry.getKey()) && "coastline".equals(tagEntry.getValue())) {
+				// ignore natural=coastline
+				continue;
+			}
 			if (polygonTags.contains(tagEntry.getKey())) {
 				return true;
 			}
@@ -1272,7 +1282,7 @@
 	 */
 	private void createContainsMatrix(List<JoinedWay> polygonList) {
 		containsMatrix = new ArrayList<BitSet>();
-		for (JoinedWay aPolygonList : polygonList) {
+		for (int i = 0; i < polygonList.size(); i++) {
 			containsMatrix.add(new BitSet());
 		}
 
@@ -1680,6 +1690,69 @@
 		}
 	}
 
+	/**
+	 * Marks all tags of the original ways of the given JoinedWay that are also 
+	 * contained in the given tagElement for removal.
+	 * 
+	 * @param tagElement an element contains the tags to be removed
+	 * @param way a joined way
+	 */
+	private void removeTagsInOrgWays(Element tagElement, JoinedWay way) {
+		for (Entry<String, String> tag : tagElement.getEntryIteratable()) {
+			removeTagInOrgWays(way, tag.getKey(), tag.getValue());
+		}
+	}
+
+	/**
+	 * Mark the given tag of all original ways of the given JoinedWay.
+	 * 
+	 * @param way a joined way
+	 * @param tagname the tag to be removed (<code>null</code> means remove all tags)
+	 * @param tagvalue the value of the tag to be removed (<code>null</code> means don't check the value)
+	 */
+	private void removeTagInOrgWays(JoinedWay way, String tagname,
+			String tagvalue) {
+		for (Way w : way.getOriginalWays()) {
+			if (w instanceof JoinedWay) {
+				// remove the tags recursively 
+				removeTagInOrgWays((JoinedWay) w, tagname, tagvalue);
+				continue;
+			}
+
+			boolean remove = false;
+			if (tagname == null) {
+				// remove all tags
+				remove = true;
+			} else if (tagvalue == null) {
+				// remove the tag without comparing the value
+				remove = way.getTag(tagname) != null;
+			} else if (tagvalue.equals(w.getTag(tagname))) {
+				remove = true;
+			}
+
+			if (remove) {
+				Set<String> tagListToRemove = this.wayRemoveTags.get(way
+						.getId());
+				if (tagListToRemove == null) {
+					tagListToRemove = new TreeSet<String>();
+					wayRemoveTags.put(way.getId(), tagListToRemove);
+				}
+				if (tagname == null) {
+					// remove all tags
+					for (Entry<String,String> tag : w.getEntryIteratable()) {
+						tagListToRemove.add(tag.getKey());
+					}
+					if (log.isDebugEnabled())
+						log.debug("Will remove all tags from",w.getId(),way.toTagString());
+				} else {
+					tagListToRemove.add(tagname);
+					if (log.isDebugEnabled())
+						log.debug("Will remove",tagname+"="+w.getTag(tagname),"from way",w.getId(),w.toTagString());
+				}
+			}
+		}
+	}
+
 	private static final boolean joinWayTagMerge = false;
 	
 	/**
@@ -1816,34 +1889,6 @@
 			return originalWays;
 		}
 
-		public void removePolygonTagsInOrgWays() {
-			for (Way w : getOriginalWays()) {
-				for (String polygonTag : polygonTags) {
-					w.deleteTag(polygonTag);
-				}
-			}
-		}
-		
-		public void removeAllTagsDeep() {
-			removeOriginalTags();
-			removeAllTags();
-		}
-
-		public void removeOriginalTags() {
-			for (Way w : getOriginalWays()) {
-				if (w instanceof JoinedWay) {
-					((JoinedWay) w).removeAllTagsDeep();
-				} else {
-					log.info("Before remove",w.toTagString());
-					for (Map.Entry<String, String> wayTag : w
-							.getEntryIteratable()) {
-						w.deleteTag(wayTag.getKey());
-					}
-					log.info("After remove",w.toTagString());
-				}
-			}
-		}
-
 		public String toString() {
 			StringBuilder sb = new StringBuilder(200);
 			sb.append(getId());
Index: src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java	(revision 1667)
+++ src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java	(working copy)
@@ -35,6 +35,14 @@
 import java.util.Set;
 import java.util.SortedMap;
 import java.util.TreeMap;
+import java.util.TreeSet;
+import java.util.Map.Entry;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+import org.xml.sax.helpers.DefaultHandler;
 
 import uk.me.parabola.imgfmt.MapFailedException;
 import uk.me.parabola.imgfmt.app.Area;
@@ -56,12 +64,6 @@
 import uk.me.parabola.mkgmap.reader.osm.Way;
 import uk.me.parabola.util.EnhancedProperties;
 
-import org.xml.sax.Attributes;
-import org.xml.sax.ContentHandler;
-import org.xml.sax.SAXException;
-import org.xml.sax.SAXParseException;
-import org.xml.sax.helpers.DefaultHandler;
-
 /**
  * Reads and parses the OSM XML format.
  *
@@ -124,6 +126,8 @@
 
 	private HashMap<String,Set<String>> deletedTags;
 	private Map<String, String> usedTags;
+	
+	private final Map<Long,Set<String>> mpWayRemoveTags = new HashMap<Long,Set<String>>();
 
 	public Osm5XmlHandler(EnhancedProperties props) {
 		if(props.getProperty("make-all-cycleways", false)) {
@@ -603,7 +607,7 @@
 		if (type != null) {
 			if ("multipolygon".equals(type)) {
 				Area mpBbox = (bbox != null ? bbox : ((MapDetails) collector).getBounds());
-				currentRelation = new MultiPolygonRelation(currentRelation, wayMap, mpBbox);
+				currentRelation = new MultiPolygonRelation(currentRelation, wayMap, mpWayRemoveTags, mpBbox);
 			} else if("restriction".equals(type)) {
 
 				if(ignoreTurnRestrictions)
@@ -671,6 +675,18 @@
 				}
 			}
 		}
+		
+		for (Entry<Long,Set<String>> wayTagsRemove : mpWayRemoveTags.entrySet()) {
+			Way w = wayMap.get(wayTagsRemove.getKey());
+			if (w==null) {
+				log.warn("Cannot find way",wayTagsRemove.getKey(),"to remove tags by multipolygon processing.");
+				continue;
+			}
+			for (String tagname : wayTagsRemove.getValue()) {
+				w.deleteTag(tagname);
+			}
+		}
+		mpWayRemoveTags.clear();
 
 		coordMap = null;
 
@@ -1576,7 +1592,7 @@
 
 		if(generateSeaUsingMP) {
 			Area mpBbox = (bbox != null ? bbox : ((MapDetails) collector).getBounds());
-			seaRelation = new MultiPolygonRelation(seaRelation, wayMap, mpBbox);
+			seaRelation = new MultiPolygonRelation(seaRelation, wayMap, mpWayRemoveTags, mpBbox);
 			relationMap.put(multiId, seaRelation);
 			seaRelation.processElements();
 		}
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to