Hi

Well, if this doesnt take too much calculation time, please go ahead :-)

OK here is a first attempt.

The parsers are modified to save a flag on the way if it is actually closed. It also aggressively refuses to make anything into a polygon that is not closed.

So there should be errors as a result of splitter. But on the other hand there may be more due to OSM data errors. Will have to investigate this and adjust if necessary.

Attached is the before and after results of my test and the patch.

A precompiled jar is at:  http://files.mkgmap.org.uk/download/72/mkgmap.jar

..Steve

<<attachment: existing.png>>

<<attachment: with-patch.png>>

Index: src/uk/me/parabola/mkgmap/reader/osm/bin/OsmBinHandler.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/bin/OsmBinHandler.java	(revision 2338)
+++ src/uk/me/parabola/mkgmap/reader/osm/bin/OsmBinHandler.java	(revision )
@@ -16,7 +16,6 @@
 
 import uk.me.parabola.imgfmt.MapFailedException;
 import uk.me.parabola.imgfmt.app.Coord;
-import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.reader.osm.Element;
 import uk.me.parabola.mkgmap.reader.osm.GeneralRelation;
 import uk.me.parabola.mkgmap.reader.osm.Node;
@@ -34,7 +33,6 @@
  * @author Steve Ratcliffe
  */
 public class OsmBinHandler extends OsmHandler {
-	private static final Logger log = Logger.getLogger(OsmBinHandler.class);
 
 	public OsmBinHandler(EnhancedProperties props) {
 	}
@@ -129,7 +127,7 @@
 
 		protected void parseWays(List<Osmformat.Way> ways) {
 			for (Osmformat.Way binWay : ways) {
-				Way way = new Way(binWay.getId());
+				Way way = startWay(binWay.getId());
 
 				for (int j = 0; j < binWay.getKeysCount(); j++) {
 
@@ -143,21 +141,10 @@
 				long nid = 0;
 				for (long idDelta : binWay.getRefsList()) {
 					nid += idDelta;
-					Coord co = saver.getCoord(nid);
-					if (co != null) {
-						hooks.onCoordAddedToWay(way, nid, co);
-						co = saver.getCoord(nid);
-						way.addPoint(co);
-
-						// nodes (way joins) will have highwayCount > 1
-						co.incHighwayCount();
-					} else {
-						log.info("Way", way.toBrowseURL(), "references undefined node", nid);
+					addCoordToWay(way, nid);
-					}
+				}
-				}
 
-				saver.addWay(way);
-				hooks.onAddWay(way);
+				endWay(way);
 			}
 		}
 
Index: src/uk/me/parabola/mkgmap/reader/osm/OsmHandler.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/OsmHandler.java	(revision 2338)
+++ src/uk/me/parabola/mkgmap/reader/osm/OsmHandler.java	(revision )
@@ -17,6 +17,7 @@
 import java.util.Set;
 
 import uk.me.parabola.imgfmt.app.Area;
+import uk.me.parabola.imgfmt.app.Coord;
 
 /**
  * Base class for OSM file handlers.
@@ -32,6 +33,11 @@
 	private Map<String,Set<String>> deletedTags;
 	private Map<String, String> usedTags;
 
+	// Node references within a way
+	protected long firstNodeRef;
+	protected long lastNodeRef;
+	protected boolean missingNodeRef;
+
 	/**
 	 * Set a set of tags with values that are to be deleted on input.
 	 * For each key there is a set of values.  If the value set is empty then
@@ -129,5 +135,56 @@
 
 	public void setHooks(OsmReadingHooks plugin) {
 		this.hooks = plugin;
+	}
+
+	/**
+	 * Common actions to take when creating a new way.
+	 * Reset some state and create the Way object.
+	 * @param id The osm id of the new way.
+	 * @return The new Way itself.
+	 */
+	protected Way startWay(long id) {
+		firstNodeRef = 0;
+		lastNodeRef = 0;
+		missingNodeRef = false;
+		return new Way(id);
+	}
+
+	/**
+	 * Common actions to take when a way has been completely read by the parser.
+	 * It is saved
+	 * @param way The way that was read.
+	 */
+	protected void endWay(Way way) {
+		way.setClosed(firstNodeRef == lastNodeRef);
+		way.setIncomplete(missingNodeRef);
+
+		//System.out.printf("way %d is %s and %s\n", way.getId(), way.isClosed()?"closed":"not closed",
+		//		way.isIncomplete()?"incomplete": "complete");
+		saver.addWay(way);
+		hooks.onAddWay(way);
+	}
+
+	/**
+	 * Add a coordinate point to the way.
+	 * @param way The Way.
+	 * @param id The coordinate id.
+	 */
+	protected void addCoordToWay(Way way, long id) {
+		lastNodeRef = id;
+		if (firstNodeRef == 0) firstNodeRef = id;
+
+		Coord co = saver.getCoord(id);
+
+		if (co != null) {
+			hooks.onCoordAddedToWay(way, id, co);
+			co = saver.getCoord(id);
+			way.addPoint(co);
+
+			// nodes (way joins) will have highwayCount > 1
+			co.incHighwayCount();
+		} else {
+			missingNodeRef = true;
+		}
 	}
 }
Index: src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(revision 2338)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(revision )
@@ -528,11 +528,15 @@
 	}
 
 	private void addShape(Way way, GType gt) {
+		if (!way.isClosed()) {
+			return;
+		}
+		// TODO: the code above or the code below, not both
 		if (way.isClosed()==false) {
 			// check if start or end point lie within the bbox
 			if (bbox.insideBoundary(way.getPoints().get(0)) || 
 				bbox.insideBoundary(way.getPoints().get(way.getPoints().size()-1))) {
-				log.warn("Unclosed way",way.toBrowseURL(),way.toTagString(),
+				log.error("Unclosed way"+way.toBrowseURL()+way.toTagString()+
 						"should be converted as shape but the start or end point lies inside the bbox. Skip it.");
 				return;
 			}
Index: src/uk/me/parabola/mkgmap/reader/osm/Way.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Way.java	(revision 2338)
+++ src/uk/me/parabola/mkgmap/reader/osm/Way.java	(revision )
@@ -33,6 +33,8 @@
 public class Way extends Element {
 
 	private final List<Coord> points;
+	private boolean isClosed;
+	private boolean isIncomplete; // TODO: useful for testing, but maybe not afterwards
 
 	public Way(long id) {
 		points = new ArrayList<Coord>(5);
@@ -96,8 +98,25 @@
 		Collections.reverse(points);
 	}
 
-	public boolean isClosed() {
+	// TODO for testing. remove when done
+	public boolean isClosedOld() {
 		return !points.isEmpty() && points.get(0).equals(points.get(points.size()-1));
+	}
+
+	public boolean isClosed() {
+		return isClosed;
+	}
+
+	public void setClosed(boolean closed) {
+		isClosed = closed;
+	}
+
+	public boolean isIncomplete() {
+		return isIncomplete;
+	}
+
+	public void setIncomplete(boolean incomplete) {
+		isIncomplete = incomplete;
 	}
 
 	/**
Index: src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java	(revision 2338)
+++ src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java	(revision )
@@ -55,15 +55,14 @@
 	private static final int MODE_RELATION = 4;
 	private static final int MODE_BOUNDS = 5;
 
-	// Current state.
-	private Node currentNode;
-	private Way currentWay;
-	private Relation currentRelation;
-	private long currentElementId;
-
 	// Options
 	private final boolean reportUndefinedNodes;
 	private final boolean ignoreBounds;
+	// Current state.
+	protected Node currentNode;
+	protected Way currentWay;
+	protected Relation currentRelation;
+	protected long currentElementId;
 
 	public Osm5XmlHandler(EnhancedProperties props) {
 		ignoreBounds = props.getProperty("ignore-osm-bounds", false);
@@ -163,8 +162,8 @@
 			} else if (mode == MODE_WAY) {
 				if (qName.equals("way")) {
 					mode = 0;
-					saver.addWay(currentWay);
-					hooks.onAddWay(currentWay);
+
+					endWay(currentWay);
 					currentWay = null;
 				}
 
@@ -238,7 +237,7 @@
 	private void startInWay(String qName, Attributes attributes) {
 		if (qName.equals("nd")) {
 			long id = idVal(attributes.getValue("ref"));
-			addCoordToWay(id);
+			addCoordToWay(currentWay, id);
 		} else if (qName.equals("tag")) {
 			String key = attributes.getValue("k");
 			String val = attributes.getValue("v");
@@ -353,28 +352,9 @@
 	private void startWay(String sid) {
 		try {
 			long id = idVal(sid);
-			currentWay = new Way(id);
+			currentWay = startWay(id);
 		} catch (NumberFormatException e) {
 			// ignore bad numeric data. The way will be discarded
-		}
-	}
-
-	/**
-	 * Add a coordinate point to the way.
-	 * @param id The coordinate id.
-	 */
-	private void addCoordToWay(long id) {
-		Coord co = saver.getCoord(id);
-
-		if (co != null) {
-			hooks.onCoordAddedToWay(currentWay, id, co);
-			co = saver.getCoord(id);
-			currentWay.addPoint(co);
-
-			// nodes (way joins) will have highwayCount > 1
-			co.incHighwayCount();
-		} else if(reportUndefinedNodes && currentWay != null) {
-			log.warn("Way", currentWay.toBrowseURL(), "references undefined node", id);
 		}
 	}
 }
_______________________________________________
mkgmap-dev mailing list
[email protected]
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to