Index: /applications/editors/josm/plugins/smed2/src/s57/S57map.java
===================================================================
--- /applications/editors/josm/plugins/smed2/src/s57/S57map.java	(revision 30230)
+++ /applications/editors/josm/plugins/smed2/src/s57/S57map.java	(revision 30231)
@@ -141,5 +141,5 @@
 
 	public class Prim {				// Spatial element
-		public long id;					// ID
+		public long id;					// Snode ID for POINTs, Edge ID for LINEs & AREAs)
 		public boolean forward;	// Direction of vector used (LINEs & AREAs)
 		public boolean outer;		// Exterior/Interior boundary (AREAs)
@@ -158,4 +158,13 @@
 	}
 	
+	public class Comp {
+		public long ref;
+		public int size;
+		public Comp(long r, int s) {
+			ref = r;
+			size = s;
+		}
+	}
+	
 	public enum Pflag {
 		NOSP, POINT, LINE, AREA
@@ -165,7 +174,12 @@
 		public Pflag prim;						// Geometry type
 		public ArrayList<Prim> elems;	// Ordered list of elements
+		public int outers;						// Number of outers
+		public int inners;						// Number of inners
+		public ArrayList<Comp> refs;	// Ordered list of compounds
 		public Geom(Pflag p) {
 			prim = p;
 			elems = new ArrayList<Prim>();
+			outers = inners = 0;
+			refs = new ArrayList<Comp>();
 		}
 	}
@@ -203,4 +217,5 @@
 	private Feature feature;
 	private Edge edge;
+	private long ref;
 
 	public S57map() {
@@ -210,4 +225,5 @@
 		features = new FtrMap();	// All features in map, grouped by type
 		index = new FtrTab();			// Feature look-up table
+		ref = 0x0000ffffffff0000L;// Compound reference generator
 	}
 
@@ -458,4 +474,5 @@
 			long first = 0;
 			long last = 0;
+			Comp comp = null;
 			boolean next = true;
 			if ((geom.prim == Pflag.LINE) || (geom.prim == Pflag.AREA)) {
@@ -474,4 +491,11 @@
 						}
 						sort.elems.add(prim);
+						if (prim.outer) {
+							sort.outers++;
+						} else {
+							sort.inners++;
+						}
+						comp = new Comp(ref++, 1);
+						sort.refs.add(comp);
 					} else {
 						if (prim.forward) {
@@ -479,7 +503,9 @@
 								sort.elems.add(prim);
 								last = edge.last;
+								comp.size++;
 							} else if (edge.last == first) {
 								sort.elems.add(0, prim);
 								first = edge.first;
+								comp.size++;
 							} else {
 								geom.elems.add(prim);
@@ -489,7 +515,9 @@
 								sort.elems.add(prim);
 								last = edge.first;
+								comp.size++;
 							} else if (edge.first == first) {
 								sort.elems.add(0, prim);
 								first = edge.last;
+								comp.size++;
 							} else {
 								geom.elems.add(prim);
@@ -517,4 +545,7 @@
 				ArrayList<Prim> closed = null;
 				sort = new Geom(geom.prim);
+				sort.outers = feature.geom.outers;
+				sort.inners = feature.geom.inners;
+				sort.refs = feature.geom.refs;
 				next = true;
 				while (!sorting.isEmpty()) {
@@ -620,12 +651,12 @@
 		EdgeIterator eit;
 		ListIterator<S57map.Prim> it;
-		long first;
-		long last;
+		int cc, ec;
+		Comp comp;
 		
 		public GeomIterator(Geom g) {
 			geom = g;
 			eit = null;
-			first = 0;
-			last = -1;
+			cc = ec = 0;
+			comp = null;
 			if ((geom.prim != Pflag.NOSP) && (geom.prim != Pflag.POINT)) {
 				it = geom.elems.listIterator();
@@ -636,37 +667,29 @@
 		
 		public boolean hasMore() {
-			return (it != null) && it.hasNext();
+			return (cc < geom.refs.size());
 		}
 		
-		public boolean more() {
-			if ((it != null) && it.hasNext()) {
-				prim = it.next();
-				eit = new EdgeIterator(edges.get(prim.id), prim.forward);
-				return prim.outer;
-			}
-			return false;
+		public long getMore() {
+			comp = geom.refs.get(cc++);
+			ec = 0;
+			return comp.ref;
 		}
 		
 		public boolean hasNext() {
-			return (first != last) && (it.hasNext() || eit.hasNext());
+			if (eit == null) {
+				return (ec < comp.size);
+			} else {
+				return (eit.hasNext());
+			}
 		}
 		
 		public long nextRef() {
-			if ((eit == null) || !eit.hasNext()) {
-				if (it.hasNext()) {
-					prim = it.next();
-					eit = new EdgeIterator(edges.get(prim.id), prim.forward);
-				} else {
-					return 0;
-				}
+			if ((eit == null) && (ec < comp.size)) {
+				prim = geom.elems.get(ec++);
+				eit = new EdgeIterator(edges.get(prim.id), prim.forward);
 			}
 			long ref = eit.nextRef();
-			if (ref == last)
-				ref = eit.nextRef();
-			if (first == 0) {
-				first = ref;
-				last = 0;
-			} else {
-				last = ref;
+			if (!eit.hasNext()) {
+				eit = null;
 			}
 			return ref;
@@ -683,5 +706,6 @@
 		lat = lon = llon = llat = 0;
 		double sigma = 0;
-/*		BoundIterator it = new BoundIterator(bound);
+		GeomIterator it = new GeomIterator(geom);
+		it.getMore();
 		while (it.hasNext()) {
 			llon = lon;
@@ -692,5 +716,5 @@
 			sigma += (lon * Math.sin(llat)) - (llon * Math.sin(lat));
 		}
-*/		return sigma / 2.0;
+		return sigma / 2.0;
 	}
 
@@ -704,9 +728,10 @@
 
 	public double calcLength(Geom geom) {
-/*		Snode node;
+		Snode node;
 		double lat, lon, llon, llat;
 		lat = lon = llon = llat = 0;
 		double sigma = 0;
-		BoundIterator it = new BoundIterator(bound);
+		GeomIterator it = new GeomIterator(geom);
+		it.getMore();
 		if (it.hasNext()) {
 			node = it.next();
@@ -723,9 +748,8 @@
 		}
 		return sigma * 3444;
-*/		return 0;
 	}
 
 	public Snode findCentroid(Feature feature) {
-/*		double lat, lon, slat, slon, llat, llon;
+		double lat, lon, slat, slon, llat, llon;
 		llat = llon = lat = lon = slat = slon = 0;
 		double sarc = 0;
@@ -733,10 +757,10 @@
 		switch (feature.geom.prim) {
 		case POINT:
-			return nodes.get(feature.geom);
+			return nodes.get(feature.geom.elems.get(0).id);
 		case LINE:
-			Edge edge = edges.get(feature.geom);
-			EdgeIterator eit = new EdgeIterator(edge, true);
-			while (eit.hasNext()) {
-				Snode node = eit.next();
+			GeomIterator it = new GeomIterator(feature.geom);
+			it.getMore();
+			while (it.hasNext()) {
+				Snode node = it.next();
 				lat = node.lat;
 				lon = node.lon;
@@ -752,7 +776,8 @@
 			sarc = 0;
 			first = true;
-			eit = new EdgeIterator(edge, true);
-			while (eit.hasNext()) {
-				Snode node = eit.next();
+			it = new GeomIterator(feature.geom);
+			while (it.hasNext()) {
+				it.getMore();
+				Snode node = it.next();
 				lat = node.lat;
 				lon = node.lon;
@@ -770,6 +795,6 @@
 			return new Snode(llat + ((lat - llat) * harc / sarc), llon + ((lon - llon) * harc / sarc));
 		case AREA:
-			Bound bound = areas.get(feature.geom).get(0);
-			BoundIterator bit = new BoundIterator(bound);
+			GeomIterator bit = new GeomIterator(feature.geom);
+			bit.getMore();
 			while (bit.hasNext()) {
 				Snode node = bit.next();
@@ -790,5 +815,5 @@
 		default:
 		}
-*/		return null;
+		return null;
 	}
 
Index: /applications/editors/josm/plugins/smed2/src/s57/S57val.java
===================================================================
--- /applications/editors/josm/plugins/smed2/src/s57/S57val.java	(revision 30230)
+++ /applications/editors/josm/plugins/smed2/src/s57/S57val.java	(revision 30231)
@@ -1180,23 +1180,26 @@
 	
 	public static String stringValue(AttVal<?> attval) {                  // Convert OSeaM value object to OSeaM attribute value string
-		switch (attval.conv) {
-		case A:
-		case S:
-			return (String)attval.val;
-		case E:
-			EnumMap<?,?> map = keys.get(attval.att).map;
-			return ((S57enum)map.get(attval.val)).val;
-		case L:
-			String str = "";
-			map = keys.get(attval.att).map;
-			for (Object item : (ArrayList<?>)attval.val) {
-				if (!str.isEmpty()) str += ";";
-				str += ((S57enum)map.get(item)).val;
+		if (attval != null) {
+			switch (attval.conv) {
+			case A:
+			case S:
+				return (String) attval.val;
+			case E:
+				EnumMap<?, ?> map = keys.get(attval.att).map;
+				return ((S57enum) map.get(attval.val)).val;
+			case L:
+				String str = "";
+				map = keys.get(attval.att).map;
+				for (Object item : (ArrayList<?>) attval.val) {
+					if (!str.isEmpty())
+						str += ";";
+					str += ((S57enum) map.get(item)).val;
+				}
+				return str;
+			case I:
+				return ((Long) attval.val).toString();
+			case F:
+				return ((Double) attval.val).toString();
 			}
-			return str;
-		case I:
-			return ((Long)attval.val).toString();
-		case F:
-			return ((Double)attval.val).toString();
 		}
 		return "";
