From 0c023f99896e3abe64f5586d9a70cca6c51666b0 Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Fri, 4 Jan 2013 22:41:32 +0100
Subject: [PATCH] handle explicitly closed properly: - make buildings work with
 vector-tile-server and old pbmap backend

---
 .../oscim/renderer/layer/ExtrusionLayer.java  | 59 ++++++++++---------
 1 file changed, 32 insertions(+), 27 deletions(-)

diff --git a/src/org/oscim/renderer/layer/ExtrusionLayer.java b/src/org/oscim/renderer/layer/ExtrusionLayer.java
index e6d9d2eb..8ad5b724 100644
--- a/src/org/oscim/renderer/layer/ExtrusionLayer.java
+++ b/src/org/oscim/renderer/layer/ExtrusionLayer.java
@@ -78,8 +78,9 @@ public class ExtrusionLayer extends Layer {
 		else
 			height *= 40;
 
-		for (int ipos = 0, ppos = 0, n = index.length; ipos < n; ipos++) {
-			int length = index[ipos];
+		int length = 0;
+		for (int ipos = 0, ppos = 0, n = index.length; ipos < n; ipos++, ppos += length) {
+			length = index[ipos];
 
 			// end marker
 			if (length < 0)
@@ -93,26 +94,24 @@ public class ExtrusionLayer extends Layer {
 				continue;
 			}
 
-			// we dont need to add duplicate end/start point
+			// check: do not to add duplicate end/start point
+			// triangulator can only handle implicity closed polygons
 			int len = length;
-
-			boolean circle = false;
-			// safety check
-			if (points[ppos] == points[ppos + len - 2]
-					&& points[ppos + 1] == points[ppos + len - 1]) {
-				circle = true;
-				len = -2;
-			}
-
+			boolean closed = false;
 			if (!MapView.enableClosePolygons) {
-				circle = true;
+				closed = true;
+				len -= 2;
+			} else if (points[ppos] == points[ppos + len - 2]
+					&& points[ppos + 1] == points[ppos + len - 1]) {
+				// vector-tile-map does not produce implicty closed
+				// polygons (yet)
+				closed = true;
 				len -= 2;
 			}
+
 			// need at least three points
-			if (len < 6) {
-				ppos += length;
+			if (len < 6)
 				continue;
-			}
 
 			// check if polygon contains inner rings
 			if (simple && (ipos < n - 1) && (index[ipos + 1] > 0))
@@ -121,11 +120,9 @@ public class ExtrusionLayer extends Layer {
 			boolean convex = addOutline(points, ppos, len, height, simple);
 			if (simple && (convex || len <= 8))
 				addRoofSimple(startVertex, len);
-			else if (!circle && ipos == outer) // only add roof once
-				//addRoof(startVertex, pos, len, points);
-				addRoof(startVertex, index, ipos, points, ppos);
-
-			ppos += length;
+			else if (ipos == outer && (!closed || simple)) {// only add roof once
+				addRoof(startVertex, index, ipos, points, ppos, closed);
+			}
 		}
 	}
 
@@ -151,7 +148,8 @@ public class ExtrusionLayer extends Layer {
 		mCurIndices[IND_ROOF].used = i;
 	}
 
-	private void addRoof(int startVertex, short[] index, int ipos, float[] points, int ppos) {
+	private void addRoof(int startVertex, short[] index, int ipos, float[] points, int ppos,
+			boolean closed) {
 		int len = 0;
 		int rings = 0;
 
@@ -160,6 +158,10 @@ public class ExtrusionLayer extends Layer {
 			len += index[i];
 			rings++;
 		}
+		if (closed) {
+			rings = 1;
+			len = index[ipos] - 2;
+		}
 
 		// triangulate up to 200 points (limited only by prepared buffers)
 		if (len > 400) {
@@ -168,7 +170,7 @@ public class ExtrusionLayer extends Layer {
 		}
 
 		int used = triangulate(points, ppos, len, index, ipos, rings,
-				startVertex + 1, mCurIndices[IND_ROOF]);
+				startVertex + 1, mCurIndices[IND_ROOF], closed);
 
 		if (used > 0) {
 			// get back to the last item added..
@@ -414,8 +416,7 @@ public class ExtrusionLayer extends Layer {
 	private static FloatBuffer fBuf;
 
 	public static synchronized int triangulate(float[] points, int ppos, int plen, short[] index,
-			int ipos, int rings,
-			int vertexOffset, VertexPoolItem item) {
+			int ipos, int rings, int vertexOffset, VertexPoolItem item, boolean closed) {
 
 		if (!initialized) {
 			// FIXME also cleanup on shutdown!
@@ -432,9 +433,13 @@ public class ExtrusionLayer extends Layer {
 		fBuf.put(points, ppos, plen);
 
 		sBuf.clear();
-		sBuf.put((short) plen); // all points
-		sBuf.put(index, ipos, rings);
 
+		sBuf.put((short) plen); // all points
+		if (closed) {
+			sBuf.put((short) plen);
+		} else {
+			sBuf.put(index, ipos, rings);
+		}
 		int numTris = TriangleJNI.triangulate(fBuf, rings, sBuf, vertexOffset);
 
 		int numIndices = numTris * 3;