Index: src/uk/me/parabola/mkgmap/reader/osm/Element.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Element.java	(Revision 1136)
+++ src/uk/me/parabola/mkgmap/reader/osm/Element.java	(Arbeitskopie)
@@ -86,6 +86,7 @@
 	 * element.
 	 */
 	public void copyTags(Element other) {
+		if (other.tags != null)
 		tags = other.tags.copy();
 	}
 
@@ -97,4 +98,9 @@
 		if (this.name == null)
 			this.name = name;
 	}
+	
+	public Tags getTags() {
+		return tags;
+	}
+
 }
Index: src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java	(Revision 1136)
+++ src/uk/me/parabola/mkgmap/reader/osm/MultiPolygonRelation.java	(Arbeitskopie)
@@ -1,11 +1,10 @@
 package uk.me.parabola.mkgmap.reader.osm;
 
 import java.util.ArrayList;
-import java.util.Collection;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-import uk.me.parabola.imgfmt.Utils;
 import uk.me.parabola.imgfmt.app.Coord;
 
 /**
@@ -16,15 +15,19 @@
  */
 public class MultiPolygonRelation extends Relation {
 	private Way outer;
-	private final Collection<Way> inners = new ArrayList<Way>();
+	private List<Way> outers = new ArrayList<Way>();
+	private List<Way> inners = new ArrayList<Way>();
+	private Map<Long, Way> myWayMap;
 
 	/**
 	 * Create an instance based on an exsiting relation.  We need to do
 	 * this because the type of the relation is not known until after all
 	 * its tags are read in.
 	 * @param other The relation to base this one on.
+	 * @param wayMap Map of all ways.
 	 */
-	public MultiPolygonRelation(Relation other) {
+	public MultiPolygonRelation(Relation other, Map<Long, Way> wayMap) {
+		myWayMap = wayMap;
 		setId(other.getId());
 		for (Map.Entry<Element, String> pairs: other.getRoles().entrySet()){
 			addElement(pairs.getValue(), pairs.getKey());
@@ -33,10 +36,12 @@
 
 			if (value != null && pairs.getKey() instanceof Way) {
 				Way way = (Way) pairs.getKey();
-				if (value.equals("outer"))
-					outer = way;
-				else if (value.equals("inner"))
+				if (value.equals("outer")){
+					outers.add(way);
+				}
+				else if (value.equals("inner")){
 					inners.add(way);
+				}
 			}
 		}
 
@@ -45,18 +50,63 @@
 	}
 
 	/** Process the ways in this relation.
+	 * Joins way with the role "outer"
 	 * Adds ways with the role "inner" to the way with the role "outer"
 	 */
 	public void processElements() {
-		if (outer != null)
-		{   
+
+		if (outers != null)
+		{
+			// copy first outer way
+			Iterator<Way> it = outers.iterator();
+			if (it.hasNext()){
+				// duplicate outer way and remove tags for cascaded multipolygons
+				Way tempWay = it.next();
+				outer = new Way(-tempWay.getId());
+				outer.copyTags(tempWay);
+				for(Coord point: tempWay.getPoints()){
+					outer.addPoint(point);
+				}
+				myWayMap.put(outer.getId(), outer);
+				if (tempWay.getTags() != null){
+					tempWay.getTags().removeAll();
+				}
+				it.remove();
+			}
+			
+			// if we have more than one outer way, we join them if they are parts of a long way
+			it = outers.iterator();
+			while (it.hasNext()){
+				Way tempWay = it.next();
+				if (tempWay.getPoints().get(0) == outer.getPoints().get(outer.getPoints().size()-1)){
+					for(Coord point: tempWay.getPoints()){
+						outer.addPoint(point);
+					}
+					if (tempWay.getTags() != null){
+						tempWay.getTags().removeAll();
+					}
+					it.remove();
+					it = outers.iterator();
+				}
+			}
+		
 			for (Way w: inners) {	
-				if (w != null) {
-					List<Coord> pts = w.getPoints();
-					int[] insert = findCpa(outer.getPoints(), pts);
-					if (insert[0] > 0)
-						insertPoints(pts, insert[0], insert[1]);				
-					pts.clear();
+				if (w != null && outer!= null) {
+					int[] insert = findCpa(outer.getPoints(), w.getPoints());
+					insertPoints(w, insert[0], insert[1]);
+
+					// remove tags from inner way that are available in the outer way
+					if (outer.getTags() != null){
+						for (Map.Entry<String, String> mapTags: outer.getTags().getKeyValues().entrySet()){
+							String key = mapTags.getKey();
+							String value = mapTags.getValue();
+							if (w.getTag(key) != null){
+								if (w.getTag(key).equals(value)){
+									w.deleteTag(key);
+								}
+							}
+						}
+					}
 				}
 			}
 		}
@@ -64,22 +114,43 @@
 	
 	/**
 	 * Insert Coordinates into the outer way.
-	 * @param inList List of Coordinates to be inserted
+	 * @param way Way to be inserted
 	 * @param out Coordinates will be inserted after this point in the outer way.
 	 * @param in Points will be inserted starting at this index, 
 	 *    then from element 0 to (including) this element;
 	 */
-	private void insertPoints(List<Coord> inList, int out, int in){
+	private void insertPoints(Way way, int out, int in){
 		List<Coord> outList = outer.getPoints();
+		List<Coord> inList = way.getPoints();
 		int index = out+1;
-		for (int i = in; i < inList.size(); i++)
+		for (int i = in; i < inList.size(); i++){
 			outList.add(index++, inList.get(i));
-		for (int i = 0; i <= in; i++)
+		}
+		for (int i = 0; i < in; i++){
 			outList.add(index++, inList.get(i));
-
-		//with this line commented we get triangles, when uncommented some areas disappear
-		// at least in mapsource, on device itself looks OK.
-		outList.add(index,outList.get(out));  
+		}
+		
+		if (outer.getPoints().size() < 32){
+			outList.add(index++, inList.get(in));
+			outList.add(index, outList.get(out));
+		}
+		else{
+			// we shift the nodes to avoid duplicate nodes (large areas only)
+			int oLat = outList.get(out).getLatitude();
+			int oLon = outList.get(out).getLongitude();
+			int iLat = inList.get(in).getLatitude();
+			int iLon = inList.get(in).getLongitude();
+			if (Math.abs(oLat - iLat) > Math.abs(oLon - iLon)){
+				int delta = (oLon > iLon)? -1 : 1;
+				outList.add(index++, new Coord(iLat + delta, iLon));
+				outList.add(index, new Coord(oLat + delta, oLon));
+				}
+			else{
+				int delta = (oLat > iLat)? 1 : -1;
+				outList.add(index++, new Coord(iLat, iLon + delta));
+				outList.add(index, new Coord(oLat, oLon + delta));
+			}
+		}
 	}
 	
 	/**
Index: src/uk/me/parabola/mkgmap/reader/osm/Tags.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/Tags.java	(Revision 1136)
+++ src/uk/me/parabola/mkgmap/reader/osm/Tags.java	(Arbeitskopie)
@@ -16,7 +16,9 @@
  */
 package uk.me.parabola.mkgmap.reader.osm;
 
+import java.util.HashMap;
 import java.util.Iterator;
+import java.util.Map;
 
 /**
  * Store the tags that belong to an Element.
@@ -271,4 +273,22 @@
 					put(e.key, e.value);
 		}
 	}
+	
+	public void removeAll() {
+		for (int i = 0; i < capacity; i++){
+			keys[i] = null;
+			values[i] = null;
+		}
+		size = 0;
+	}
+
+	public Map<String, String> getKeyValues() {
+		Map<String, String> tagMap = new HashMap<String, String>();
+		for (int i = 0; i < capacity; i++)
+			if (keys[i] != null && values[i] != null)
+				tagMap.put(keys[i], values[i]);
+		return tagMap;
+	}
+
+
 }
Index: src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java	(Revision 1136)
+++ src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java	(Arbeitskopie)
@@ -399,7 +399,7 @@
 		String type = currentRelation.getTag("type");
 		if (type != null) {
 			if ("multipolygon".equals(type))
-				currentRelation = new MultiPolygonRelation(currentRelation);
+				currentRelation = new MultiPolygonRelation(currentRelation, wayMap);
 			else if("restriction".equals(type)) {
 
 				if(ignoreTurnRestrictions)
