From b7aaaef48581da21740a451a81232cc89b1bdd3e Mon Sep 17 00:00:00 2001
From: Hannes Janetzek <hannes.janetzek@gmail.com>
Date: Sat, 3 Nov 2012 14:45:34 +0100
Subject: [PATCH] - improve way-labeling - let nomination search places instead
 of tags

---
 .../oscim/database/oscimap/MapDatabase.java   |   2 +-
 src/org/oscim/database/pbmap/MapDatabase.java |   8 +-
 src/org/oscim/renderer/LineRenderer.java      |   2 +-
 src/org/oscim/renderer/ScanBox.java           |   6 +-
 src/org/oscim/renderer/TextureRenderer.java   |   7 +-
 src/org/oscim/renderer/WayDecorator.java      |  24 +--
 src/org/oscim/renderer/layer/SymbolLayer.java |  11 +-
 src/org/oscim/renderer/layer/TextItem.java    |   9 +
 src/org/oscim/renderer/layer/TextLayer.java   |  35 +++-
 .../oscim/renderer/overlays/OverlayText.java  | 172 +++++++++++++++---
 .../renderer/overlays/RenderOverlay.java      |   7 +-
 src/org/oscim/theme/osmarender/osmarender.xml |  27 ++-
 src/org/oscim/utils/GeometryUtils.java        |  16 +-
 src/org/oscim/view/MapView.java               |   7 +-
 14 files changed, 260 insertions(+), 73 deletions(-)

diff --git a/src/org/oscim/database/oscimap/MapDatabase.java b/src/org/oscim/database/oscimap/MapDatabase.java
index 981459cc..64a4fa38 100644
--- a/src/org/oscim/database/oscimap/MapDatabase.java
+++ b/src/org/oscim/database/oscimap/MapDatabase.java
@@ -65,7 +65,7 @@ public class MapDatabase implements IMapDatabase {
 	private static final String CACHE_FILE = "%d-%d-%d.tile";
 
 	private static final String SERVER_ADDR = "city.informatik.uni-bremen.de";
-	// private static final String URL = "/osci/map-live/";
+	//private static final String URL = "/osci/map-live/";
 	private static final String URL = "/osci/oscim/";
 
 	private final static float REF_TILE_SIZE = 4096.0f;
diff --git a/src/org/oscim/database/pbmap/MapDatabase.java b/src/org/oscim/database/pbmap/MapDatabase.java
index 4a371a3e..7d92ddf6 100644
--- a/src/org/oscim/database/pbmap/MapDatabase.java
+++ b/src/org/oscim/database/pbmap/MapDatabase.java
@@ -94,6 +94,8 @@ public class MapDatabase implements IMapDatabase {
 	// private static final String URL =
 	// "http://city.informatik.uni-bremen.de:8020/test/%d/%d/%d.osmtile";
 	private static final String URL = "http://city.informatik.uni-bremen.de/osmstache/test/%d/%d/%d.osmtile";
+	//private static final String URL = "http://city.informatik.uni-bremen.de/osmstache/gis-live/%d/%d/%d.osmtile";
+
 	// private static final String URL =
 	// "http://city.informatik.uni-bremen.de/tiles/tiles.py///test/%d/%d/%d.osmtile";
 	// private static final String URL =
@@ -1217,10 +1219,8 @@ public class MapDatabase implements IMapDatabase {
 		mCacheFile = null;
 	}
 
-	/*
-	 * All code below is taken from or based on Google's Protocol Buffers
-	 * implementation:
-	 */
+	/* All code below is taken from or based on Google's Protocol Buffers
+	 * implementation: */
 
 	// Protocol Buffers - Google's data interchange format
 	// Copyright 2008 Google Inc. All rights reserved.
diff --git a/src/org/oscim/renderer/LineRenderer.java b/src/org/oscim/renderer/LineRenderer.java
index fba92c3c..0d670141 100644
--- a/src/org/oscim/renderer/LineRenderer.java
+++ b/src/org/oscim/renderer/LineRenderer.java
@@ -170,7 +170,7 @@ public final class LineRenderer {
 						blur = true;
 					}
 
-					if (line.cap == Cap.ROUND) {
+					if (o.line.cap == Cap.ROUND) {
 						if (lineMode != 1) {
 							lineMode = 1;
 							GLES20.glUniform1i(hLineMode[mode], lineMode);
diff --git a/src/org/oscim/renderer/ScanBox.java b/src/org/oscim/renderer/ScanBox.java
index 103553e8..4b4831ed 100644
--- a/src/org/oscim/renderer/ScanBox.java
+++ b/src/org/oscim/renderer/ScanBox.java
@@ -160,10 +160,8 @@ public abstract class ScanBox {
 		}
 	}
 
-	/*
-	 * ported from Polymaps: Layer.js Copyright (c) 2010, SimpleGeo and Stamen
-	 * Design
-	 */
+	/* ported from Polymaps: Layer.js Copyright (c) 2010, SimpleGeo and Stamen
+	 * Design */
 
 	//	// scan-line conversion
 	//	function edge(a, b) {
diff --git a/src/org/oscim/renderer/TextureRenderer.java b/src/org/oscim/renderer/TextureRenderer.java
index 252a113b..6cc67626 100644
--- a/src/org/oscim/renderer/TextureRenderer.java
+++ b/src/org/oscim/renderer/TextureRenderer.java
@@ -24,6 +24,7 @@ import org.oscim.renderer.layer.TextureLayer;
 import org.oscim.utils.GlUtils;
 
 import android.opengl.GLES20;
+import android.util.FloatMath;
 import android.util.Log;
 
 public final class TextureRenderer {
@@ -42,7 +43,7 @@ public final class TextureRenderer {
 	final static int VERTICES_PER_SPRITE = 4;
 	final static int SHORTS_PER_VERTICE = 6;
 	// per texture
-	public final static int MAX_ITEMS = 50;
+	private final static int MAX_ITEMS = 50;
 
 	static void init() {
 		mTextureProgram = GlUtils.createProgram(Shaders.textVertexShader,
@@ -111,7 +112,8 @@ public final class TextureRenderer {
 		TextureLayer tl = (TextureLayer) layer;
 
 		if (tl.fixed)
-			GLES20.glUniform1f(hTextureScale, scale);
+
+			GLES20.glUniform1f(hTextureScale, FloatMath.sqrt(scale));
 		else
 			GLES20.glUniform1f(hTextureScale, 1);
 
@@ -129,6 +131,7 @@ public final class TextureRenderer {
 			GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, to.id);
 			int maxVertices = MAX_ITEMS * INDICES_PER_SPRITE;
 
+			// can only draw MAX_ITEMS in each iteration
 			for (int i = 0; i < to.vertices; i += maxVertices) {
 				// to.offset * (24(shorts) * 2(short-bytes) / 6(indices) == 8)
 				int off = (to.offset + i) * 8 + offset;
diff --git a/src/org/oscim/renderer/WayDecorator.java b/src/org/oscim/renderer/WayDecorator.java
index 26f801cb..e3a37cac 100644
--- a/src/org/oscim/renderer/WayDecorator.java
+++ b/src/org/oscim/renderer/WayDecorator.java
@@ -179,7 +179,7 @@ public final class WayDecorator {
 					wayNameWidth = text.paint.measureText(string);
 				}
 
-				if (segmentLengthInPixel > wayNameWidth + 25) {
+				if (segmentLengthInPixel > wayNameWidth * 0.80) {
 
 					float s = (wayNameWidth + 25) / segmentLengthInPixel;
 					int width, height;
@@ -244,17 +244,17 @@ public final class WayDecorator {
 					// Log.d("mapsforge", "add " + text + " " + first + " " +
 					// last);
 
-					if (previousX < currentX) {
-						x1 = previousX;
-						y1 = previousY;
-						x2 = currentX;
-						y2 = currentY;
-					} else {
-						x1 = currentX;
-						y1 = currentY;
-						x2 = previousX;
-						y2 = previousY;
-					}
+					//					if (previousX < currentX) {
+					//						x1 = previousX;
+					//						y1 = previousY;
+					//						x2 = currentX;
+					//						y2 = currentY;
+					//					} else {
+					//						x1 = currentX;
+					//						y1 = currentY;
+					//						x2 = previousX;
+					//						y2 = previousY;
+					//					}
 
 					// if (t == null)
 					t = TextItem.get();
diff --git a/src/org/oscim/renderer/layer/SymbolLayer.java b/src/org/oscim/renderer/layer/SymbolLayer.java
index 434f670d..613ea5fb 100644
--- a/src/org/oscim/renderer/layer/SymbolLayer.java
+++ b/src/org/oscim/renderer/layer/SymbolLayer.java
@@ -119,7 +119,7 @@ public final class SymbolLayer extends TextureLayer {
 		textures = to;
 		mCanvas.setBitmap(to.bitmap);
 
-		int maxIndices = TextureRenderer.MAX_ITEMS * TextureRenderer.INDICES_PER_SPRITE;
+		//		int maxIndices = TextureRenderer.MAX_ITEMS * TextureRenderer.INDICES_PER_SPRITE;
 
 		for (SymbolItem it = symbols; it != null;) {
 			float width, height;
@@ -143,7 +143,7 @@ public final class SymbolLayer extends TextureLayer {
 
 			}
 
-			if (y + height > TEXTURE_HEIGHT || curIndices == maxIndices) {
+			if (y + height > TEXTURE_HEIGHT) { // || curIndices == maxIndices) {
 				Log.d(TAG, "reached max symbols: " + numIndices);
 
 				to.offset = offsetIndices;
@@ -249,13 +249,6 @@ public final class SymbolLayer extends TextureLayer {
 					pos = 0;
 				}
 
-				// FIXME this does not work, need to draw bitmap on next
-				// texture...
-				//	if (pos == bufLen) {
-				//	sbuf.put(buf, 0, pos);
-				//	pos = 0;
-				//	}
-
 				x += width;
 			}
 		}
diff --git a/src/org/oscim/renderer/layer/TextItem.java b/src/org/oscim/renderer/layer/TextItem.java
index 501192d1..8facb304 100644
--- a/src/org/oscim/renderer/layer/TextItem.java
+++ b/src/org/oscim/renderer/layer/TextItem.java
@@ -68,6 +68,15 @@ public class TextItem {
 		return this;
 	}
 
+	public TextItem move(TextItem ti, float dx, float dy, float scale) {
+		this.x = dx + (ti.x * scale);
+		this.y = dy + (ti.y * scale);
+		this.string = ti.string;
+		this.text = ti.text;
+		this.width = ti.width;
+		return this;
+	}
+
 	public TextItem next;
 
 	public float x, y;
diff --git a/src/org/oscim/renderer/layer/TextLayer.java b/src/org/oscim/renderer/layer/TextLayer.java
index 6cb08eb2..3118602f 100644
--- a/src/org/oscim/renderer/layer/TextLayer.java
+++ b/src/org/oscim/renderer/layer/TextLayer.java
@@ -35,9 +35,9 @@ public final class TextLayer extends TextureLayer {
 	private static int mFontPadX = 1;
 	private static int mFontPadY = 1;
 
-	TextItem labels;
-
+	public TextItem labels;
 	private Canvas mCanvas;
+	private float mScale;
 
 	public TextItem getLabels() {
 		return labels;
@@ -47,6 +47,31 @@ public final class TextLayer extends TextureLayer {
 		type = Layer.SYMBOL;
 		mCanvas = new Canvas();
 		fixed = true;
+		mScale = 1;
+	}
+
+	public void setScale(float scale) {
+		mScale = scale;
+	}
+
+	public boolean removeText(TextItem item) {
+		TextItem prev = null;
+
+		for (TextItem it = labels; it != null; it = it.next) {
+			if (it == item) {
+				if (prev == null)
+					labels = it.next;
+				else
+					prev.next = it.next;
+
+				verticesCnt -= 4;
+				return true;
+			}
+
+			prev = it;
+		}
+
+		return false;
 	}
 
 	public void addText(TextItem item) {
@@ -170,8 +195,14 @@ public final class TextLayer extends TextureLayer {
 
 				float ux = -vy;
 				float uy = vx;
+
+				hw /= mScale;
 				float hh2 = hh + it.text.fontDescent / 2;
 				hh -= it.text.fontDescent / 2;
+
+				hh /= mScale;
+				hh2 /= mScale;
+
 				x1 = (short) (SCALE * (vx * hw - ux * hh));
 				y1 = (short) (SCALE * (vy * hw - uy * hh));
 				x2 = (short) (SCALE * (-vx * hw - ux * hh));
diff --git a/src/org/oscim/renderer/overlays/OverlayText.java b/src/org/oscim/renderer/overlays/OverlayText.java
index 3937646b..74985c4e 100644
--- a/src/org/oscim/renderer/overlays/OverlayText.java
+++ b/src/org/oscim/renderer/overlays/OverlayText.java
@@ -17,15 +17,18 @@ package org.oscim.renderer.overlays;
 
 import org.oscim.core.MapPosition;
 import org.oscim.core.Tile;
+import org.oscim.renderer.GLRenderer;
 import org.oscim.renderer.MapTile;
 import org.oscim.renderer.TileManager;
 import org.oscim.renderer.Tiles;
 import org.oscim.renderer.layer.TextItem;
 import org.oscim.renderer.layer.TextLayer;
 import org.oscim.utils.FastMath;
+import org.oscim.utils.GeometryUtils;
 import org.oscim.utils.PausableThread;
 import org.oscim.view.MapView;
 
+import android.opengl.Matrix;
 import android.os.SystemClock;
 import android.util.FloatMath;
 
@@ -45,7 +48,7 @@ public class OverlayText extends RenderOverlay {
 
 		@Override
 		protected void doWork() {
-			SystemClock.sleep(300);
+			SystemClock.sleep(500);
 			mRun = false;
 			updateLabels();
 			mMapView.redrawMap();
@@ -96,54 +99,131 @@ public class OverlayText extends RenderOverlay {
 			return;
 		}
 
-		float div = FastMath.pow(diff);
-
-		// fix map position to tile coordinates
-		float size = Tile.TILE_SIZE;
-		int x = (int) (mWorkPos.x / div / size);
-		int y = (int) (mWorkPos.y / div / size);
-		mWorkPos.x = x * size;
-		mWorkPos.y = y * size;
-		mWorkPos.zoomLevel += diff;
-		mWorkPos.scale = div;
-
+		float scale = mWorkPos.scale;
 		float angle = (float) Math.toRadians(mWorkPos.angle);
 		float cos = FloatMath.cos(angle);
 		float sin = FloatMath.sin(angle);
 
+		TextItem ti2 = null;
+
 		// TODO more sophisticated placement :)
 		for (int i = 0, n = tiles.cnt; i < n; i++) {
 			MapTile t = tiles.tiles[i];
 			if (!t.isVisible)
 				continue;
 
-			int dx = (t.tileX - x) * Tile.TILE_SIZE;
-			int dy = (t.tileY - y) * Tile.TILE_SIZE;
+			float dx = (float) ((t.pixelX - mWorkPos.x) * scale);
+			float dy = (float) ((t.pixelY - mWorkPos.y) * scale);
 
 			for (TextItem ti = t.labels; ti != null; ti = ti.next) {
 
-				TextItem ti2 = TextItem.get().move(ti, dx, dy);
+				if (ti2 == null)
+					ti2 = TextItem.get();
+
+				ti2.move(ti, dx, dy, scale);
+
+				boolean overlaps = false;
+
+				if (ti.text.caption) {
+					int tx = (int) (ti2.x);
+					int ty = (int) (ti2.y);
+					int tw = (int) (ti2.width / 2);
+					int th = (int) (ti2.text.fontHeight / 2);
+
+					for (TextItem lp = tl.labels; lp != null; lp = lp.next) {
+						int px = (int) (lp.x);
+						int py = (int) (lp.y);
+						int ph = (int) (lp.text.fontHeight / 2);
+						int pw = (int) (lp.width / 2);
+
+						if ((tx - tw) < (px + pw)
+								&& (px - pw) < (tx + tw)
+								&& (ty - th) < (py + ph)
+								&& (py - ph) < (ty + th)) {
+							overlaps = true;
+							break;
+						}
+					}
+				} else {
 
-				if (!ti.text.caption) {
 					if (cos * (ti.x2 - ti.x1) - sin * (ti.y2 - ti.y1) < 0) {
 						// flip label upside-down
-						ti2.x1 = ti.x2;
-						ti2.y1 = ti.y2;
-						ti2.x2 = ti.x1;
-						ti2.y2 = ti.y1;
+						ti2.x1 = (short) ((ti.x2 * scale + dx));
+						ti2.y1 = (short) ((ti.y2 * scale + dy));
+						ti2.x2 = (short) ((ti.x1 * scale + dx));
+						ti2.y2 = (short) ((ti.y1 * scale + dy));
 					} else {
-						ti2.x1 = ti.x1;
-						ti2.y1 = ti.y1;
-						ti2.x2 = ti.x2;
-						ti2.y2 = ti.y2;
+						ti2.x1 = (short) ((ti.x1 * scale + dx));
+						ti2.y1 = (short) ((ti.y1 * scale + dy));
+						ti2.x2 = (short) ((ti.x2 * scale + dx));
+						ti2.y2 = (short) ((ti.y2 * scale + dy));
+					}
+
+					//float normalLength = (float) Math.hypot(ti2.x2 - ti2.x1, ti2.y2 - ti2.y1);
+
+					for (TextItem lp = tl.labels; lp != null;) {
+						if (lp.text.caption) {
+							lp = lp.next;
+							continue;
+						}
+
+						if (GeometryUtils.lineIntersect(ti2.x1, ti2.y1, ti2.x2, ti2.y2,
+								lp.x1, lp.y1, lp.x2, lp.y2)) {
+							// just to make it more deterministic
+							if (lp.width < ti2.width) {
+								TextItem tmp = lp;
+								lp = lp.next;
+
+								tl.removeText(tmp);
+								tmp.next = null;
+								TextItem.release(tmp);
+								continue;
+							}
+							overlaps = true;
+							break;
+						}
+
+						if ((ti2.x1) < (lp.x2)
+								&& (lp.x1) < (ti2.x2)
+								&& (ti2.y1) < (lp.y2)
+								&& (lp.y1) < (ti2.y2)) {
+
+							// just to make it more deterministic
+							if (lp.width < ti2.width) {
+								TextItem tmp = lp;
+								lp = lp.next;
+
+								tl.removeText(tmp);
+								tmp.next = null;
+								TextItem.release(tmp);
+								continue;
+							}
+							overlaps = true;
+							break;
+						}
+
+						lp = lp.next;
 					}
 				}
 
-				tl.addText(ti2);
+				if (!overlaps) {
+					tl.addText(ti2);
+					ti2 = null;
+				}
 			}
 		}
 
+		if (ti2 != null)
+			TextItem.release(ti2);
+
+		// scale back to fixed zoom-level. could be done in setMatrix..
+		for (TextItem lp = tl.labels; lp != null; lp = lp.next) {
+			lp.x /= scale;
+			lp.y /= scale;
+		}
+
 		// draw text to bitmaps and create vertices
+		tl.setScale(scale);
 		tl.prepare();
 
 		// everything synchronized?
@@ -153,7 +233,8 @@ public class OverlayText extends RenderOverlay {
 	}
 
 	@Override
-	public synchronized void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged) {
+	public synchronized void update(MapPosition curPos, boolean positionChanged,
+			boolean tilesChanged) {
 		// Log.d("...", "update " + tilesChanged + " " + positionChanged);
 
 		if (mNewLayer != null) {
@@ -183,4 +264,43 @@ public class OverlayText extends RenderOverlay {
 			}
 		}
 	}
+
+	@Override
+	protected float setMatrix(MapPosition curPos, float[] matrix) {
+		// TODO if oPos == curPos this could be simplified
+
+		MapPosition oPos = mMapPosition;
+
+		byte z = oPos.zoomLevel;
+
+		float div = FastMath.pow(z - curPos.zoomLevel);
+
+		float x = (float) (oPos.x - curPos.x * div);
+		float y = (float) (oPos.y - curPos.y * div);
+
+		// flip around date-line
+		float max = (Tile.TILE_SIZE << z);
+		if (x < -max / 2)
+			x = max + x;
+		else if (x > max / 2)
+			x = x - max;
+
+		float scale = curPos.scale / div;
+
+		Matrix.setIdentityM(matrix, 0);
+
+		// translate relative to map center
+		matrix[12] = x * scale;
+		matrix[13] = y * scale;
+
+		// scale to current tile world coordinates
+		scale = curPos.scale / div; // oPos.scale / div;
+		scale /= GLRenderer.COORD_MULTIPLIER;
+		matrix[0] = scale;
+		matrix[5] = scale;
+
+		Matrix.multiplyMM(matrix, 0, curPos.viewMatrix, 0, matrix, 0);
+
+		return div;
+	}
 }
diff --git a/src/org/oscim/renderer/overlays/RenderOverlay.java b/src/org/oscim/renderer/overlays/RenderOverlay.java
index 495a3b2b..da0b6c66 100644
--- a/src/org/oscim/renderer/overlays/RenderOverlay.java
+++ b/src/org/oscim/renderer/overlays/RenderOverlay.java
@@ -54,7 +54,6 @@ public abstract class RenderOverlay {
 
 	/**
 	 * Utility: update mMapPosition
-	 * 
 	 * @return true if position has changed
 	 */
 	protected boolean updateMapPosition() {
@@ -71,7 +70,8 @@ public abstract class RenderOverlay {
 	 * @param tilesChanged
 	 *            true when loaded tiles changed
 	 */
-	public synchronized void update(MapPosition curPos, boolean positionChanged, boolean tilesChanged) {
+	public synchronized void update(MapPosition curPos, boolean positionChanged,
+			boolean tilesChanged) {
 		// // keep position constant (or update layer relative to new position)
 		// mMapView.getMapViewPosition().getMapPosition(mMapPosition, null);
 		//
@@ -114,7 +114,8 @@ public abstract class RenderOverlay {
 		}
 	}
 
-	private float setMatrix(MapPosition curPos, float[] matrix) {
+	// set matrix to scale relative to zoomlevel
+	protected float setMatrix(MapPosition curPos, float[] matrix) {
 		// TODO if oPos == curPos this could be simplified
 
 		MapPosition oPos = mMapPosition;
diff --git a/src/org/oscim/theme/osmarender/osmarender.xml b/src/org/oscim/theme/osmarender/osmarender.xml
index f9dbd923..fb50c121 100644
--- a/src/org/oscim/theme/osmarender/osmarender.xml
+++ b/src/org/oscim/theme/osmarender/osmarender.xml
@@ -497,7 +497,26 @@
     
     <!-- highway -->
     <rule e="way" k="highway" v="*">
-      <rule e="way" k="*" v="*" zoom-min="3" zoom-max="10">
+      <rule e="way" k="*" v="*" zoom-min="3" zoom-max="5">
+ 			  <rule e="way" k="area" v="~|no|false">
+        <!--   <rule e="way" k="*" v="secondary|primary_link" zoom-min="9">
+            <line stroke="#f2df6d" width="1.3" cap="butt" fixed="true" fade="9"/>
+          </rule> -->
+
+          <rule e="way" k="*" v="route_primary" zoom-min="3">
+            <line stroke="#f2df6d" width="1.4" cap="butt" fixed="true" fade="3"/>
+          </rule>
+
+          <rule e="way" k="*" v="route_trunk" zoom-min="3">
+            <line stroke="#fed6a3" width="1.4" cap="butt" fixed="true" fade="3"/>
+          </rule>
+
+          <rule e="way" k="*" v="route_motorway">
+            <line stroke="#eec693" width="1.5" cap="butt" fixed="true" fade="3"/>
+          </rule>
+        </rule>
+      </rule>
+      <rule e="way" k="*" v="*" zoom-min="5" zoom-max="10">
  			  <rule e="way" k="area" v="~|no|false">
           <rule e="way" k="*" v="secondary|primary_link" zoom-min="9">
             <line stroke="#f2df6d" width="1.3" cap="butt" fixed="true" fade="9"/>
@@ -916,7 +935,7 @@
     </rule>
 
      <rule e="node" k="debug" v="*" >
-        <caption k="name" font-size="12" fill="#0000ff" />
+        <caption k="name" font-size="16" fill="#0000ff" />
       </rule>
       
 
@@ -941,7 +960,7 @@
     <!-- place -->
     <rule e="node" k="place" v="*">
       <rule e="node" k="*" v="suburb|town|village">
-        <caption k="name" font-size="18" fill="#000000"
+        <caption k="name" font-size="17" fill="#000000"
                  stroke="#ffffff" stroke-width="2.0" />
       </rule>
       <rule e="node" k="*" v="island" zoom-min="10">
@@ -949,7 +968,7 @@
                  stroke="#ffffff" stroke-width="2.0" />
       </rule>
       <rule e="node" k="*" v="city">
-        <caption k="name" font-size="19" fill="#000000"
+        <caption k="name" font-size="20" fill="#000000"
                  stroke="#ffffff" stroke-width="2.0" />
       </rule>
       <rule e="node" k="*" v="country">
diff --git a/src/org/oscim/utils/GeometryUtils.java b/src/org/oscim/utils/GeometryUtils.java
index c3cf8091..fd1b5e15 100644
--- a/src/org/oscim/utils/GeometryUtils.java
+++ b/src/org/oscim/utils/GeometryUtils.java
@@ -14,6 +14,8 @@
  */
 package org.oscim.utils;
 
+import android.graphics.Point;
+
 /**
  * 
  *
@@ -22,7 +24,6 @@ public final class GeometryUtils {
 	/**
 	 * Calculates the center of the minimum bounding rectangle for the given
 	 * coordinates.
-	 * 
 	 * @param coordinates
 	 *            the coordinates for which calculation should be done.
 	 * @return the center coordinates of the minimum bounding rectangle.
@@ -165,12 +166,12 @@ public final class GeometryUtils {
 	 */
 	public static boolean lineIntersect(int x1, int y1, int x2, int y2, int x3, int y3, int x4,
 			int y4) {
-		double denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
+		float denom = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
 		if (denom == 0.0) { // Lines are parallel.
 			return false;
 		}
-		double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
-		double ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;
+		float ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / denom;
+		float ub = ((x2 - x1) * (y1 - y3) - (y2 - y1) * (x1 - x3)) / denom;
 		if (ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f) {
 			// Get the intersection point.
 			return true;
@@ -178,4 +179,11 @@ public final class GeometryUtils {
 
 		return false;
 	}
+
+	// http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
+	public static double pointToLineDistance(Point A, Point B, Point P) {
+		double normalLength = Math.hypot(B.x - A.x, B.y - A.y);
+		return Math.abs((P.x - A.x) * (B.y - A.y) - (P.y - A.y) * (B.x - A.x)) / normalLength;
+	}
+
 }
diff --git a/src/org/oscim/view/MapView.java b/src/org/oscim/view/MapView.java
index a8fcf46f..aa8941e4 100644
--- a/src/org/oscim/view/MapView.java
+++ b/src/org/oscim/view/MapView.java
@@ -215,7 +215,8 @@ public class MapView extends RelativeLayout {
 			worker.start();
 
 		mOverlayManager.add(new LabelingOverlay(this));
-		//		mOverlayManager.add(new GenericOverlay(this, new OverlayGrid(this)));
+		//mOverlayManager.add(new GenericOverlay(this, new OverlayGrid(this)));
+
 		//		mOverlayManager.add(new GenericOverlay(this, new OverlayTest(this)));
 
 		//		ArrayList<OverlayItem> pList = new ArrayList<OverlayItem>();
@@ -710,6 +711,10 @@ public class MapView extends RelativeLayout {
 		return mMapViewPosition.getViewBox();
 	}
 
+	public GeoPoint getCenter() {
+		return new GeoPoint(mMapPosition.lat, mMapPosition.lon);
+	}
+
 	//	@Override
 	//	protected void onLayout(boolean changed, int l, int t, int r, int b) {
 	//		// TODO Auto-generated method stub