Index: src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java	(revision 4614)
+++ src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java	(working copy)
@@ -37,6 +37,8 @@
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.logging.Level;
 import java.util.stream.Collectors;
+//%%%RWB
+import uk.me.parabola.util.MultiIdentityHashMap;
 
 import uk.me.parabola.imgfmt.app.Coord;
 import uk.me.parabola.log.Logger;
@@ -61,6 +63,7 @@
 	private static final short TKM_MP_ROLE = TagDict.getInstance().xlate("mkgmap:mp_role");
 	private static final short TKM_CACHE_AREA_SIZEKEY = TagDict.getInstance().xlate("mkgmap:cache_area_size");
 	private final Map<Long, Way> tileWayMap;
+	//%%%RWB get rid of following
 	private final Map<Long, String> roleMap = new HashMap<>();
  
 	private Map<Long, Way> mpPolygons = new LinkedHashMap<>();
@@ -120,6 +123,7 @@
 			log.debug("Construct multipolygon", toBrowseURL(), toTagString());
 		}
 
+		//%%%RWB just copy the whole thing (need to make protected), there are duplicates, but sometimes these are needed
 		for (Map.Entry<String, Element> pair : other.getElements()) {
 			String role = pair.getKey();
 			Element el = pair.getValue();
@@ -764,6 +768,9 @@
 	public void processElements() {
 		log.info("Processing multipolygon", toBrowseURL());
 		
+		//%%%RWB
+		makePolygons();
+
 		List<Way> allWays = getSourceWays();
 		
 		// check if it makes sense to process the mp 
@@ -1952,7 +1959,157 @@
 		return Math.abs(areaSize);
 	}
 
+	/* %%%RWB
+alternate logic for:
+  getSourceWays()
+  joinWays() * 2
+  +
+  getRole()
+  closeWays (partial)
+  removeUnclosedWays()
 
+maybe not needed now:
+  connectUnclosedWays
+  etc
+	 */
+	private void makePolygons() {
+		log.warn("%%%RWB make", toBrowseURL(), toTagString());
+		MultiIdentityHashMap<Coord, JoinedWay> endPoints = new MultiIdentityHashMap<>();
+		ArrayList<JoinedWay> polygons = new ArrayList<>();
+		ArrayList<JoinedWay> unclosedWays = new ArrayList<>(); // these are probably errors
+		int waysInCoordMap = 0;
+
+		// go through relation elements. For "ways" add both ends to coord map. For "nodes" note label
+		for (Map.Entry<String, Element> entry : getElements()) {
+			String role = entry.getKey();
+			Element el = entry.getValue();
+			if (el instanceof Way) {
+				Way wayEl = (Way) el;
+				if (wayEl.getPoints().size() <= 1) {
+					log.warn("%%%RWB Way", wayEl, "has", wayEl.getPoints().size(),
+							 "points and cannot be used for the multipolygon", toBrowseURL());
+				} else {
+					JoinedWay jw = new JoinedWay(wayEl);
+					if ("outer".equals(role))
+						jw.outerCount = 1;
+					else if ("inner".equals(role))
+						jw.innerCount = 1;
+					else if (role != null && !"".equals(role)) // blank/missing is normally assumed to be outer
+						log.warn("%%%RWB Way role not inner/outer", role, el.toBrowseURL(),
+								 "in multipolygon", toBrowseURL(), toTagString());
+					if (wayEl.isClosed()) { // single closed way, bypass endPoints map
+						polygons.add(jw);
+					} else {
+						++waysInCoordMap;
+						endPoints.add(jw.firstCoord, jw);
+						endPoints.add(jw.lastCoord, jw);
+					}
+				}
+			} else if (el instanceof Node) {
+				if ("admin_centre".equals(role) || "label".equals(role))
+					cOfG = ((Node) el).getLocation();
+				else
+					log.warn("%%%RWB Node with unknown role", role, el.toBrowseURL(),
+							 "in multipolygon", toBrowseURL(), toTagString());
+			} else {
+				log.warn("%%%RWB Non Way/Node member with role", role, el.toBrowseURL(),
+						 "in multipolygon", toBrowseURL(), toTagString());
+			}
+		}
+
+		// start joining ways that share end-points
+		int iterCount = 0;
+		while (waysInCoordMap > 0) {
+			++iterCount;
+			int initialCount = waysInCoordMap;
+			log.warn("%%%RWB iter", iterCount, "waysInMap", waysInCoordMap, "mapSize", endPoints.size(), "#Poly", polygons.size(), "#Lines", unclosedWays.size());
+			Iterator<Entry<Coord, List<JoinedWay>>> iter = endPoints.entrySet().iterator();
+			while (iter.hasNext()) {
+				Entry<Coord, List<JoinedWay>> entry = iter.next();
+				Coord theCoord = entry.getKey();
+				List<JoinedWay> waysAtCoord = entry.getValue();
+				int numHere = waysAtCoord.size();
+				if (numHere == 0) { // previous operation emptied list
+					iter.remove();
+				} else if (numHere == 2) { // have to join them regardless
+					JoinedWay jw = waysAtCoord.get(0);
+					JoinedWay jwNext = waysAtCoord.get(1);
+					// going to append jwNext to jw, so ensure both in correct direction
+					if (jw.lastCoord != theCoord)
+						jw.flip();
+					if (jwNext.firstCoord != theCoord)
+						jwNext.flip();
+					jw.addWay(jwNext);
+					--waysInCoordMap;
+					List<JoinedWay> otherEnd = endPoints.get(jwNext.lastCoord);
+					if (jw.firstCoord == jw.lastCoord) { // now it is closed
+						polygons.add(jw);
+						//endPoints.removeMapping(jw.firstCoord, jw);
+						//endPoints.removeMapping(jw.firstCoord, jwNext);
+						// best not to do above because it might do endPoints:remove() in iterator
+						otherEnd.remove(jw);
+						otherEnd.remove(jwNext);
+						--waysInCoordMap;
+					} else { // replace ref to jwNext (now gone) with jw
+						otherEnd.remove(jwNext);
+						otherEnd.add(jw);
+					}
+					iter.remove();
+				} else if (iterCount == 1) { // ignore all but the simplest processing in first iteration
+					continue; // then we get unclosedWays fully joined, etc
+				} else if (numHere == 1) { // an unattached end
+					JoinedWay jw = waysAtCoord.get(0);
+					List<JoinedWay> otherEnd = endPoints.get(jw.firstCoord == theCoord ? jw.lastCoord
+															                           : jw.firstCoord);
+					if (otherEnd.size() % 2 == 1) { // either unconnected or a spur - remove
+						unclosedWays.add(jw);
+						otherEnd.remove(jw); // again, best to avoid removeMapping()
+						--waysInCoordMap;
+						iter.remove();
+					}
+				}
+ 				// >=4 ways at a node is more complicated. Often double-touching polygons.
+				// %%% can add some code to resolve if have just 2 of the same role
+				// but these are invalid and can be ignored here and flagged as errors later
+			}
+			if (iterCount > 1 && initialCount == waysInCoordMap)
+				break; // stop if nothing resolved
+		}
+		log.warn("%%%RWB stop", "waysInMap", waysInCoordMap, "mapSize", endPoints.size(), "#Poly", polygons.size(), "#Lines", unclosedWays.size());
+		/*%%%
+Above logic resolves almost all relations in britain-and-ireland-latest.osm.pbf into polygons or lines.
+
+more processing needed?:
+  distinguish between line that touches polygon and one on own
+  complex points with even # of ways. normally double touching.
+  if above is inner and outer, should be able to resolve in the main logic
+  single lines - should it attempt to join outside the box
+		*/
+		if (waysInCoordMap != 0) { // mostly diagnostics, but moves remaining ways to the unclosed list
+			log.error("%%%RWB err", toBrowseURL(), toTagString(), "waysInMap", waysInCoordMap, "mapSize", endPoints.size(), "#Poly", polygons.size(), "#Lines", unclosedWays.size());
+			for (Entry<Coord, List<JoinedWay>> entry : endPoints.entrySet()) {
+				Coord theCoord = entry.getKey();
+				List<JoinedWay> waysAtCoord = entry.getValue();
+				log.warn("%%%RWB map", theCoord, "#ends", waysAtCoord.size());
+				for (JoinedWay jw : waysAtCoord) {
+					log.warn("%%%RWB way", jw, "first", jw.firstCoord, "last", jw.lastCoord, jw.outerCount, jw.innerCount);
+					unclosedWays.add(jw);
+					List<JoinedWay> otherEnd = endPoints.get(jw.firstCoord == theCoord ? jw.lastCoord
+															                           : jw.firstCoord);
+					otherEnd.remove(jw);
+				}
+			}
+		}
+		/*
+validation:
+  not mixed inner / outer
+  don't have only inner
+  the matrix of contained for polygon by polygon
+  etc
+		*/
+	} // makePolygons
+
+
 	/**
 	 * This is a helper class that gives access to the original
 	 * segments of a joined way.
@@ -1966,6 +2123,9 @@
 		private int minLon;
 		private int maxLon;
 		private Rectangle bounds;
+		//%%%RWB haven't bothered with actual ways (reversing points when ness), just keep list in consistent order. add attributes:
+		Coord firstCoord, lastCoord;
+		int outerCount, innerCount;
 
 		public JoinedWay(Way originalWay) {
 			super(originalWay.getOriginalId(), originalWay.getPoints());
@@ -1979,6 +2139,9 @@
 			minLon = maxLon = c0.getLongitude();
 
 			updateBounds(originalWay.getPoints());
+			//%%%RWB
+			firstCoord = c0;
+			lastCoord = originalWay.getLastPoint();
 		}
 
 		public void addPoint(int index, Coord point) {
@@ -2065,6 +2228,10 @@
 					addWay(w);
 				}
 				updateBounds((JoinedWay) way);
+				//%%%RWB
+				this.lastCoord = ((JoinedWay) way).lastCoord;
+				this.outerCount += ((JoinedWay) way).outerCount;
+				this.innerCount += ((JoinedWay) way).innerCount;
 			} else {
 				if (log.isDebugEnabled()) {
 					log.debug("Joined", this.getId(), "with", way.getId());
@@ -2073,6 +2240,14 @@
 			}
 		}
 
+		//%%%RWB
+		public void flip() {
+			Coord tempCoord = firstCoord;
+			firstCoord = lastCoord;
+			lastCoord = tempCoord;
+			Collections.reverse(originalWays);
+		}
+
 		public void closeWayArtificially() {
 			addPoint(getPoints().get(0));
 			closedArtificially = true;
