Index: src/uk/me/parabola/mkgmap/reader/osm/boundary/Boundary.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/boundary/Boundary.java	(revision 2184)
+++ src/uk/me/parabola/mkgmap/reader/osm/boundary/Boundary.java	(working copy)
@@ -92,7 +92,7 @@
 	
 	public List<BoundaryElement> getBoundaryElements() {
 		if (bList == null) {
-			bList = BoundaryUtil.splitToElements(area);
+			bList = BoundaryUtil.splitToElements(area, tags.get("mkgmap:boundaryid"));
 		}
 		return bList;
 	}
Index: src/uk/me/parabola/mkgmap/reader/osm/boundary/BoundaryElement.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/boundary/BoundaryElement.java	(revision 2184)
+++ src/uk/me/parabola/mkgmap/reader/osm/boundary/BoundaryElement.java	(working copy)
@@ -45,7 +45,7 @@
 	}
 	
 	public String toString() {
-		return isOuter() ? "outer" : "inner";
+		return (isOuter() ? "outer" : "inner") + " " + points ;
 	}
 
 }
Index: src/uk/me/parabola/mkgmap/reader/osm/boundary/BoundarySaver.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/boundary/BoundarySaver.java	(revision 2184)
+++ src/uk/me/parabola/mkgmap/reader/osm/boundary/BoundarySaver.java	(working copy)
@@ -22,7 +22,6 @@
 import java.io.IOException;
 import java.io.OutputStream;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
@@ -293,6 +292,11 @@
 	}
 
 	private void write(OutputStream stream, Boundary boundary) {
+		List<BoundaryElement> boundaryElements = boundary.getBoundaryElements();
+		if (boundaryElements.size() == 0){
+			log.error("boundary area is not usable " + boundary.getTags().get("mkgmap:boundaryid"));
+			return;
+		}
 		ByteArrayOutputStream oneItemStream = new ByteArrayOutputStream();
 		DataOutputStream dos = new DataOutputStream(oneItemStream);
 		try {
@@ -313,8 +317,6 @@
 					+ boundary.getTags().toString();
 
 			// write the number of boundary elements to create the multipolygon
-			List<BoundaryElement> boundaryElements = boundary
-					.getBoundaryElements();
 			dos.writeInt(boundaryElements.size());
 
 			// now write each element
Index: src/uk/me/parabola/mkgmap/reader/osm/boundary/BoundaryUtil.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/boundary/BoundaryUtil.java	(revision 2184)
+++ src/uk/me/parabola/mkgmap/reader/osm/boundary/BoundaryUtil.java	(working copy)
@@ -35,6 +35,7 @@
 import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.reader.osm.Tags;
 import uk.me.parabola.mkgmap.reader.osm.Way;
+import uk.me.parabola.util.GpxCreator;
 import uk.me.parabola.util.Java2DConverter;
 
 public class BoundaryUtil {
@@ -46,20 +47,21 @@
 		}
 	}
 	
-	public static List<BoundaryElement> splitToElements(Area area) {
+	public static List<BoundaryElement> splitToElements(Area area, String id) {
 		if (area.isEmpty()) {
 			return Collections.emptyList();
 		}
 
-		List<List<Coord>> areaElements = Java2DConverter.areaToShapes(area);
-
+		//List<List<Coord>> areaElements = Java2DConverter.areaToShapes(area);
+		List<List<Coord>> areaElements = Java2DConverter.verifiedAreaToShapes(area, id);
+		
 		if (areaElements.isEmpty()) {
 			// this may happen if a boundary overlaps a raster tile in a very small area
 			// so that it is has no dimension
 			log.debug("Area has no dimension. Area:",area.getBounds());
 			return Collections.emptyList();
 		}
-		
+
 		List<BoundaryElement> bElements = new ArrayList<BoundaryElement>();
 		for (List<Coord> singleElement : areaElements) {
 			if (singleElement.size() <= 3) {
@@ -67,7 +69,6 @@
 				continue;
 			}
 			Way w = new Way(0, singleElement);
-
 			boolean outer = w.clockwise();
 			bElements.add(new BoundaryElement(outer, singleElement));
 		}
@@ -84,7 +85,13 @@
 		// we need the other way round
 		Collections.reverse(bElements);
 
-		assert bElements.get(0).isOuter() : log.threadTag()+" first element is not outer. "+ bElements;
+		if (bElements.get(0).isOuter() == false){
+			log.error(" first element is not outer. "+ bElements.get(0));
+			//String fname = ".\\bnd_gpx\\invalid_" + id ;
+			//GpxCreator.createGpx(fname, bElements.get(0).getPoints());
+		}
+		assert bElements.get(0).isOuter() : log.threadTag()+" first element is not outer. "+ bElements.get(0);
+		
 		return bElements;
 	}
 
@@ -138,7 +145,7 @@
 						for (int i = 0; i < noOfTags; i++) {
 							String name = inpStream.readUTF();
 							String value = inpStream.readUTF();
-							tags.put(name, value);
+							tags.put(name, value.intern());
 						}
 
 						int noBElems = inpStream.readInt();
Index: src/uk/me/parabola/util/FloatCoord.java
===================================================================
--- src/uk/me/parabola/util/FloatCoord.java	(revision 0)
+++ src/uk/me/parabola/util/FloatCoord.java	(working copy)
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2006 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: 11-Dec-2006
+ */
+package uk.me.parabola.util;
+
+/**
+ * A point coordinate in unshifted map-units stored in float fields. 
+ * This is a helper class for the Java2DConverter, see also class Coord 
+ *
+ * @author GerdP
+ */
+public class FloatCoord {
+	private final float latitude;
+	private final float longitude;
+
+	/**
+	 * Construct from co-ordinates that are already in map-units.
+	 * @param latitude The latitude in map units.
+	 * @param longitude The longitude in map units.
+	 */
+	public FloatCoord(float latitude, float longitude) {
+		this.latitude = latitude;
+		this.longitude = longitude;
+	}
+
+	public float getLatitude() {
+		return latitude;
+	}
+
+	public float getLongitude() {
+		return longitude;
+	}
+
+	public int hashCode() {
+		// Use a factor for latitude to span over the whole integer range:
+		// max lat: 4194304
+		// max lon: 8388608
+		// max hashCode: 2118123520 < 2147483647 (Integer.MAX_VALUE)
+		return 503 * (int) latitude + (int) longitude;
+	}
+
+	public boolean equals(Object obj) {
+		if (obj == null || !(obj instanceof FloatCoord))
+			return false;
+		FloatCoord other = (FloatCoord) obj;
+		return latitude == other.latitude && longitude == other.longitude;
+	}
+	public String toString() {
+		return (latitude) + "/" + (longitude);
+	}
+
+}
Index: src/uk/me/parabola/util/Java2DConverter.java
===================================================================
--- src/uk/me/parabola/util/Java2DConverter.java	(revision 2184)
+++ src/uk/me/parabola/util/Java2DConverter.java	(working copy)
@@ -213,7 +213,7 @@
 	 * Convert the area back into a list of polygons each represented by a list
 	 * of coords. It is possible that the area contains multiple discontiguous
 	 * polygons, so you may append more than one shape to the output list.<br/>
-	 * <b>Attention:</b> The outline of the polygon is has clockwise order whereas
+	 * <b>Attention:</b> The outline of the polygon has clockwise order whereas
 	 * holes in the polygon have counterclockwise order. 
 	 * 
 	 * @param area The area to be converted.
@@ -281,4 +281,154 @@
 		return outputs;
 	}
 
+	/**
+	 * Convert the area back into a list of polygons each represented by a list
+	 * of coords. It is possible that the area contains multiple discontiguous
+	 * polygons, so you may append more than one shape to the output list.<br/>
+	 * <b>Attention:</b> The outline of the polygon is has clockwise order whereas
+	 * holes in the polygon have counterclockwise order. 
+	 * 
+	 * @param area The area to be converted.
+	 * @return a list of closed polygons
+	 */
+	public static List<List<Coord>> verifiedAreaToShapes(java.awt.geom.Area area, String id) {
+		List<List<Coord>> outputs = new ArrayList<List<Coord>>(4);
+
+		float[] res = new float[6];
+		PathIterator pit = area.getPathIterator(null);
+		List<FloatCoord> testCoords = null;
+		List<Coord> coords = null;
+
+		int iPrevLat = Integer.MIN_VALUE;
+		int iPrevLong = Integer.MIN_VALUE;
+
+		float maxLat = Float.MIN_VALUE,maxLon= Float.MIN_VALUE,minLat=Float.MAX_VALUE,minLon=Float.MAX_VALUE;
+		while (!pit.isDone()) {
+			int type = pit.currentSegment(res);
+
+			float lat = res[1];
+			float lon = res[0];
+			int iLat = Math.round(lat);
+			int iLon = Math.round(lon);
+			
+			if (lat > maxLat ) maxLat = lat; 
+			if (lat < minLat ) minLat = lat;
+			if (lon > maxLon ) maxLon = lon; 
+			if (lon < minLon ) minLon = lon; 
+
+			switch (type) {
+			case PathIterator.SEG_LINETO:
+				if (iPrevLat != iLat || iPrevLong != iLon) {
+					testCoords.add(new FloatCoord(lat,lon));
+					coords.add(new Coord(iLat,iLon));
+				}
+				iPrevLat = iLat;
+				iPrevLong = iLon;
+				break;
+			case PathIterator.SEG_MOVETO: 
+			case PathIterator.SEG_CLOSE:
+				if ((type == PathIterator.SEG_MOVETO && testCoords != null) || type == PathIterator.SEG_CLOSE) {
+					if (testCoords.size() > 2) {
+						if (testCoords.get(0).equals(testCoords.get(testCoords.size() - 1)) == false){
+							testCoords.add(testCoords.get(0));
+							coords.add(coords.get(0));
+						}
+						if (testCoords.size() > 3){
+							String reason = new String();
+							boolean isUsable = true;
+							float width = maxLat-minLat;
+							
+							float height = maxLon-minLon;
+							if (width <= 0 || height <= 0){
+								isUsable = false;
+								reason = "too_small";
+							}
+							long intAreaSize = 0;
+							double realAreaSize = 0;
+							float ratio = 1;
+							if (isUsable){
+								// calculate area size, onece with int, once with float precision.
+								// If the results have different signs we cannot trust the 
+								// algorithm in Way.clockwise()
+								Coord p1 = coords.get(0);
+								for(int i = 1; i < coords.size(); ++i) {
+									Coord p2 = coords.get(i);
+									intAreaSize += ((long)p1.getLongitude() * p2.getLatitude() - 
+											(long)p2.getLongitude() * p1.getLatitude());
+									p1 = p2;
+								}
+								
+								FloatCoord pf1 = testCoords.get(0);
+								for(int i = 1; i < testCoords.size(); ++i) {
+									FloatCoord pf2 = testCoords.get(i);
+									realAreaSize += ((double)pf1.getLongitude() * pf2.getLatitude() - 
+											(double)pf2.getLongitude() * pf1.getLatitude());
+									pf1 = pf2;
+								}
+								if (isUsable && (realAreaSize >= 0 && intAreaSize < 0 || realAreaSize < 0 && intAreaSize >= 0)){
+									isUsable = false;
+									reason = "undecided_inner_outer";
+								}
+								/*
+								if (width > height) 
+									ratio = width/height;
+								else
+									ratio = height/width;
+								if (ratio > 10 && Math.abs(realAreaSize) < 10){
+									isUsable = false;
+									reason = "too_narrow";
+								}
+								 */
+							}
+							/*
+							double bboxAreaSize = (double) width * height;
+							if (isUsable &&   Math.abs(realAreaSize) < 100
+									&& bboxAreaSize > (50/ratio) * Math.abs(realAreaSize)){
+								isUsable = false;
+								reason = "too_spiky";
+							}
+							*/
+
+							
+							if (isUsable)
+								outputs.add(coords);
+							else{
+								//String fname = ".\\bnd_gpx\\del_" + id +  "_" + reason + "_" + Math.abs(intAreaSize);
+								//System.out.println("area shape removed [" + reason + "] " + fname);
+               System.out.println("area shape removed [" + reason + "] " + id);
+								//GpxCreator.createGpx(fname, coords);
+								
+							}
+						}
+					}
+				}
+				if (type == PathIterator.SEG_MOVETO){
+					testCoords = new ArrayList<FloatCoord>();
+					testCoords.add(new FloatCoord(lat,lon));
+					coords = new ArrayList<Coord>();
+					coords.add(new Coord(iLat,iLon));
+					iPrevLat = iLat;
+					iPrevLong = iLon;
+				}
+				else {
+					testCoords = null;
+					coords = null;
+					iPrevLat = Integer.MIN_VALUE;
+					iPrevLong = Integer.MIN_VALUE;
+				}
+				minLat = lat;
+				minLon = lon;
+				maxLat = lat;
+				maxLon = lon;
+				break;
+			default:
+				log.error("Unsupported path iterator type " + type
+						+ ". This is an mkgmap error.");
+			}
+
+			pit.next();
+		}
+
+		return outputs;
+	}
+
 }
