Index: src/uk/me/parabola/mkgmap/osmstyle/housenumber/ExtNumbers.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/housenumber/ExtNumbers.java	(revision 3659)
+++ src/uk/me/parabola/mkgmap/osmstyle/housenumber/ExtNumbers.java	(working copy)
@@ -22,8 +22,6 @@
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Set;
 import java.util.TreeMap;
 
@@ -72,7 +70,8 @@
 	private static final Logger log = Logger.getLogger(ExtNumbers.class);
 
 	private final HousenumberRoad housenumberRoad;
-	private static final int MAX_LOCATE_ERROR = 40; 
+	private static final int MAX_LOCATE_ERROR = 40;
+	private static final double NEARLY_INVISIBLE_DIST_TO_LINE = 0.4;
 	
 	private static final List<HousenumberMatch> NO_HOUSES = Collections.emptyList();
 	
@@ -586,7 +585,7 @@
 			if (toAdd == null) {
 				Coord wanted = c1.makeBetweenPoint(c2, wantedFraction);
 				
-				toAdd = rasterLineNearPoint(c1, c2, wanted, true);
+				toAdd = rasterLineNearPoint(c1, c2, wanted);
 				if (toAdd != null){
 					if (toAdd.equals(c1)){
 						toAdd = new Coord(c1);
@@ -657,7 +656,7 @@
 	
 	private boolean checkLineDistortion(Coord c1, Coord c2, Coord toAdd){
 		double distToLine = toAdd.getDisplayedCoord().distToLineSegment(c1.getDisplayedCoord(), c2.getDisplayedCoord());
-		if (distToLine > 0.2){
+		if (distToLine > NEARLY_INVISIBLE_DIST_TO_LINE){
 			double angle = Utils.getDisplayedAngle(c1, toAdd, c2);
 			if (Math.abs(angle) > 3){
 				return false;
@@ -718,13 +717,10 @@
 			// try to find a good split point depending on the split reason
 			double wantedFraction, midFraction;
 			wantedFraction = midFraction = (minFraction0To1 + maxFraction0To1) / 2;
-			Coord toAdd = null;  
 			double len1 = segmentLength * minFraction0To1; // dist to first 
 			double len2 = segmentLength * maxFraction0To1; 
 			double len3 = (1-maxFraction0To1) * segmentLength;
-			double expectedError = c1.getDisplayedCoord().distance(new Coord(c1.getLatitude()+1,c1.getLongitude()));
-			double maxDistBefore = expectedError;
-			double maxDistAfter = expectedError;
+			//double expectedError = c1.getDisplayedCoord().distance(new Coord(c1.getLatitude()+1,c1.getLongitude()));
 			if (reason == SR_FIX_ERROR && worstHouse != null){
 				wantedFraction = worstHouse.getSegmentFrac();
 				if (wantedFraction < minFraction0To1 || wantedFraction > maxFraction0To1){
@@ -768,86 +764,44 @@
 			}
 			double usedFraction = 0;
 			double bestDist = Double.MAX_VALUE;
-			if (wantedFraction < minFraction0To1){
-				maxDistAfter = 0;
-			}
-			if (wantedFraction > maxFraction0To1){
-				maxDistBefore = 0;
-			}
-			for (;;){
-				Coord wanted = c1.makeBetweenPoint(c2, wantedFraction);
-				Map<Double, List<Coord>> candidates = rasterLineNearPoint2(c1, c2, wanted, maxDistBefore, maxDistAfter);
-				boolean foundGood = false;
-				for (Entry<Double, List<Coord>> entry : candidates.entrySet()){
-					if (foundGood)
-						break;
-					bestDist = entry.getKey();
-					for (Coord candidate: entry.getValue()){
-						toAdd = candidate;
-						usedFraction = HousenumberGenerator.getFrac(c1, c2, toAdd);
-						if (usedFraction <= 0 || usedFraction >= 1)
-							toAdd = null;
-						else if (usedFraction > minFraction0To1 && wantedFraction < minFraction0To1 || usedFraction < maxFraction0To1 && wantedFraction > maxFraction0To1){
-							toAdd = null;
-						} else if (allowSplitBetween == false && usedFraction > minFraction0To1 && usedFraction < maxFraction0To1){
-							toAdd = null;
-						} else {
-							if (bestDist > 0.2){
-								double angle = Utils.getDisplayedAngle(c1, toAdd, c2);
-								if (Math.abs(angle) > 3){
-									toAdd = null;
-									continue;
-								}
-							}
-							foundGood = true;
-							break;
+			SplitPoint bestSplitPoint = null;
+			Coord wanted = c1.makeBetweenPoint(c2, wantedFraction);
+			List<SplitPoint> candidates = HousenumberGenerator.rasterLine(c1, c2, wanted);
+
+			for (SplitPoint sp : candidates){
+				usedFraction = HousenumberGenerator.getFrac(c1, c2, sp.getLocation());
+				if (usedFraction <= 0 || usedFraction >= 1)
+					continue;
+				else if (usedFraction > minFraction0To1 && wantedFraction < minFraction0To1 || usedFraction < maxFraction0To1 && wantedFraction > maxFraction0To1){
+					continue;
+				} else if (allowSplitBetween == false && usedFraction > minFraction0To1 && usedFraction < maxFraction0To1){
+					continue;
+				} else {
+					// we found a point that might be good enough for splitting
+					// check if it is the best possible
+					if (sp.getDistToLine() <= NEARLY_INVISIBLE_DIST_TO_LINE){
+						if (bestSplitPoint == null){
+							bestSplitPoint = sp;
+						} else if (bestSplitPoint.getDistToLine() > NEARLY_INVISIBLE_DIST_TO_LINE || bestSplitPoint.getDistToTarget() > sp.getDistToTarget())
+							bestSplitPoint = sp;
+					} else {
+						double angle = Utils.getDisplayedAngle(c1, sp.getLocation(), c2);
+						if (Math.abs(angle) > 3)
+							continue;
+						if (bestSplitPoint == null)
+							bestSplitPoint = sp;
+						else {
+							if (bestSplitPoint.getDistToLine() < sp.getDistToLine())
+								continue;
+							if (bestSplitPoint.getDistToLine() > sp.getDistToLine())
+								bestSplitPoint = sp;
+							else if (bestSplitPoint.getDistToTarget() > sp.getDistToTarget())
+								bestSplitPoint = sp;
 						}
 					}
 				}
-				if (foundGood){
-					break;
-				}
-				toAdd = null;
-				boolean tryAgain = false;
-				if (maxDistBefore > 0 && maxDistBefore < segmentLength * wantedFraction) {
-					maxDistBefore *= 2;
-					tryAgain = true;
-				}
-				if (maxDistAfter > 0 && maxDistAfter < segmentLength * (1 - wantedFraction)) {
-					maxDistAfter *= 2;
-					tryAgain = true;
-				}
-				if (!tryAgain)
-					break;
-			} 			
-			
-			boolean addOK = true;
-			if (toAdd == null)
-				addOK = false;
-			else {
-				toAdd.incHighwayCount();
-				if (log.isDebugEnabled()){
-					log.debug("spliting road segment",startInRoad,"at",formatLen(usedFraction * segmentLength));
-				}
 			}
-			if (!addOK){
-				if (reason == SR_FIX_ERROR && minFraction0To1 == maxFraction0To1)
-					return dupNode(midFraction, SR_FIX_ERROR);
-				if (Math.min(len1, len3) < MAX_LOCATE_ERROR ){
-					double splitFrac = -1;
-					if (reason == SR_OPT_LEN){
-						if (wantedFraction <= minFraction0To1)
-							splitFrac = minFraction0To1;
-						else if (wantedFraction >= maxFraction0To1)
-							splitFrac = maxFraction0To1;
-						if (splitFrac <= 0.5 && len1 >= MAX_LOCATE_ERROR || splitFrac > 0.5 && len3 >= MAX_LOCATE_ERROR){
-							splitFrac = -1;
-						}
-					}
-					if (splitFrac < 0)
-						splitFrac = (minFraction0To1 != maxFraction0To1) ? midFraction : minFraction0To1;
-					return dupNode(splitFrac, SR_OPT_LEN);
-				}
+			if (bestSplitPoint == null){
 				if(reason == SR_FIX_ERROR)
 					log.warn("can't fix error in interval",this);
 				else if (log.isDebugEnabled())
@@ -854,8 +808,17 @@
 					log.debug("can't improve search result",this);
 				return this;
 			}
+			
+			Coord toAdd = bestSplitPoint.getLocation();
+			bestDist = bestSplitPoint.getDistToLine();
+			usedFraction = HousenumberGenerator.getFrac(c1, c2, toAdd);
+			toAdd.incHighwayCount();
+			if (log.isDebugEnabled()){
+				log.debug("spliting road segment",startInRoad,"at",formatLen(usedFraction * segmentLength));
+			}
 			if (log.isInfoEnabled())
 				log.info("adding number node at",toAdd.toDegreeString(),"to split, dist to line is",formatLen(bestDist));
+
 			action = "add";
 			this.endInRoad = addAsNumberNode(startInRoad + 1, toAdd);
 			int forcedSegment = - 1;
@@ -910,7 +873,6 @@
 		return en1;
 	}
 
-
 	/**
 	 * Duplicate a node in the road. This creates a zero-length segment.
 	 * We can add house numbers to this segment and the position in the 
@@ -1742,7 +1704,7 @@
 	 * @param p
 	 * @return point with smallest perpendicular distance to line
 	 */
-	public static Coord rasterLineNearPoint(Coord c1, Coord c2, Coord p, boolean includeEndPoints){
+	public static Coord rasterLineNearPoint(Coord c1, Coord c2, Coord p){
 		int x0 = c1.getLongitude();
 		int y0 = c1.getLatitude();
 		int x1 = c2.getLongitude();
@@ -1758,23 +1720,17 @@
 		int bestX = Integer.MAX_VALUE, bestY = Integer.MAX_VALUE;
 		
 		for(;;){  /* loop */
-			if (!includeEndPoints && x==x1 && y==y1)
-				break;
-			if (Math.abs(y - p.getLatitude()) <= 1  || Math.abs(x - p.getLongitude()) <= 1){
-				Coord t = new Coord(y, x);
-				double distToTarget = t.distance(p);
+			Coord t = new Coord(y, x);
+			double distToTarget = t.distance(p);
 
-				if (includeEndPoints || x != x0 || y != y0){
-					if (distToTarget < 10){ 
-						double distLine = t.distToLineSegment(c1Dspl, c2Dspl);
-						if (distLine < minDistLine || distLine == minDistLine && distToTarget < minDistTarget || distLine < 0.2 && distToTarget < minDistTarget){
-							bestX = x;
-							bestY = y;
-							minDistLine = distLine;
-							minDistTarget = distToTarget;
-						} 
-					}
-				}
+			if (distToTarget < 10){ 
+				double distLine = t.distToLineSegment(c1Dspl, c2Dspl);
+				if (distLine < minDistLine || distLine == minDistLine && distToTarget < minDistTarget || distLine < NEARLY_INVISIBLE_DIST_TO_LINE && distToTarget < minDistTarget){
+					bestX = x;
+					bestY = y;
+					minDistLine = distLine;
+					minDistTarget = distToTarget;
+				} 
 			}
 			if (x==x1 && y==y1) break;
 			e2 = 2*err;
@@ -1788,95 +1744,6 @@
 	}
 
 
-	/**
-	 * Use Bresenham algorithm to get the Garmin points which are close to the line
-	 * described by c1 and c2 and the point p.
-	 * @param c1
-	 * @param c2
-	 * @param p
-	 * @param maxBefore tolerated distance before p
-	 * @param maxAfter tolerated distance after p
-	 * @return sorted map with closest points 
-	 */
-	public static TreeMap<Double,List<Coord>> rasterLineNearPoint2(Coord c1, Coord c2, Coord p, double maxBefore, double maxAfter){
-		int x0 = c1.getLongitude();
-		int y0 = c1.getLatitude();
-		int x1 = c2.getLongitude();
-		int y1 = c2.getLatitude();
-		Coord c1Dspl = c1.getDisplayedCoord();
-		Coord c2Dspl = c2.getDisplayedCoord();
-		int x = x0, y = y0;
-		int dx =  Math.abs(x1-x), sx = x<x1 ? 1 : -1;
-		int dy = -Math.abs(y1-y), sy = y<y1 ? 1 : -1;
-		int err = dx+dy, e2; /* error value e_xy */
-		
-		TreeMap<Double,List<Coord>> sortedByDistToLine = new TreeMap<>();
-		boolean beforeTarget = true;
-		double lastDist = Double.NaN;
-		for(;;){  /* loop */
-			if (Math.abs(y - p.getLatitude()) <= 1  || Math.abs(x - p.getLongitude()) <= 1){
-				Coord t = new Coord(y, x);
-				double distToTarget = t.distance(p);
-
-				if (beforeTarget){
-					if (Double.isNaN(lastDist) == false && lastDist < distToTarget)
-						beforeTarget = false;
-				}
-				if (beforeTarget && distToTarget < maxBefore || !beforeTarget && distToTarget < maxAfter){ 
-					Double distLine = t.distToLineSegment(c1Dspl, c2Dspl);
-					List<Coord> list = sortedByDistToLine.get(distLine);
-					if (list == null){
-						list = new ArrayList<>();
-						sortedByDistToLine.put(distLine, list);
-					}
-					list.add(t);
-				}
-				lastDist = distToTarget;
-			}
-			if (x==x1 && y==y1) 
-				break;
-			e2 = 2*err;
-			if (e2 > dy) { err += dy; x += sx; } /* e_xy+e_x > 0 */
-			if (e2 < dx) { err += dx; y += sy; } /* e_xy+e_y < 0 */
-		}
-		return sortedByDistToLine;
-	}
-
-	/**
-	 * Use Bresemham algorithm to get the Garmin points which are close to the line
-	 * described by c1 and c2 and the point p.
-	 * @param c1
-	 * @param c2
-	 * @param p
-	 * @return the list of points
-	 */
-	public static List<Coord> rasterLineNearPoint3(Coord c1, Coord c2, double maxDistToLine){
-		int x0 = c1.getLongitude();
-		int y0 = c1.getLatitude();
-		int x1 = c2.getLongitude();
-		int y1 = c2.getLatitude();
-		Coord c1Dspl = c1.getDisplayedCoord();
-		Coord c2Dspl = c2.getDisplayedCoord();
-		int x = x0, y = y0;
-		int dx =  Math.abs(x1-x), sx = x<x1 ? 1 : -1;
-		int dy = -Math.abs(y1-y), sy = y<y1 ? 1 : -1;
-		int err = dx+dy, e2; /* error value e_xy */
-		
-		List<Coord> rendered = new ArrayList<>();
-		for(;;){  /* loop */
-			Coord t = new Coord(y, x);
-			double distLine = t.distToLineSegment(c1Dspl, c2Dspl);
-			if (distLine <= maxDistToLine)
-				rendered.add(t);
-			if (x==x1 && y==y1) 
-				break;
-			e2 = 2*err;
-			if (e2 > dy) { err += dy; x += sx; } /* e_xy+e_x > 0 */
-			if (e2 < dx) { err += dx; y += sy; } /* e_xy+e_y < 0 */
-		}
-		return rendered;
-	}
-
 	private static int countOccurence(List<HousenumberMatch> houses, int num){
 		int count = 0;
 		for (HousenumberMatch house : houses){
@@ -1957,5 +1824,6 @@
 		return getRoad().toString() + getHouses(Numbers.LEFT).toString() + getHouses(Numbers.RIGHT).toString();
 	}
 
+	 
 }
 
Index: src/uk/me/parabola/mkgmap/osmstyle/housenumber/HousenumberGenerator.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/housenumber/HousenumberGenerator.java	(revision 3659)
+++ src/uk/me/parabola/mkgmap/osmstyle/housenumber/HousenumberGenerator.java	(working copy)
@@ -1929,6 +1929,43 @@
 
 	}
 	
+	/**
+	 * Use Bresenham algorithm to get the Garmin points which are close to the line
+	 * described by c1 and c2 
+	 * @param c1
+	 * @param c2
+	 * @return list with points 
+	 */
+
+	public static List<SplitPoint> rasterLine(Coord c1, Coord c2, Coord p){
+		int x0 = c1.getLongitude();
+		int y0 = c1.getLatitude();
+		int x1 = c2.getLongitude();
+		int y1 = c2.getLatitude();
+		Coord c1Dspl = c1.getDisplayedCoord();
+		Coord c2Dspl = c2.getDisplayedCoord();
+		int x = x0, y = y0;
+		int dx =  Math.abs(x1-x), sx = x<x1 ? 1 : -1;
+		int dy = -Math.abs(y1-y), sy = y<y1 ? 1 : -1;
+		int err = dx+dy, e2; /* error value e_xy */
+		
+		List<SplitPoint> splitPoints = new ArrayList<>();
+		for(;;){  /* loop */
+			Coord t = new Coord(y, x);
+			double distToTarget = t.distance(p);
+			Double distLine = t.distToLineSegment(c1Dspl, c2Dspl);
+			SplitPoint sp = new SplitPoint(t,distLine,distToTarget);
+			splitPoints.add(sp);
+
+			if (x==x1 && y==y1) 
+				break;
+			e2 = 2*err;
+			if (e2 > dy) { err += dy; x += sx; } /* e_xy+e_x > 0 */
+			if (e2 < dx) { err += dx; y += sy; } /* e_xy+e_y < 0 */
+		}
+		return splitPoints;
+	}
+	
 }
 
 
Index: src/uk/me/parabola/mkgmap/osmstyle/housenumber/HousenumberGroup.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/housenumber/HousenumberGroup.java	(revision 3659)
+++ src/uk/me/parabola/mkgmap/osmstyle/housenumber/HousenumberGroup.java	(working copy)
@@ -147,7 +147,7 @@
 		if (Math.min(len1, len2) < MIN_DISTANCE_TO_EXISTING_POINT){
 			pointToUse = (len1 <= len2) ? c1 : c2;
 		} else {
-			Coord optPoint = ExtNumbers.rasterLineNearPoint(c1, c2, pointToUse, true);
+			Coord optPoint = ExtNumbers.rasterLineNearPoint(c1, c2, pointToUse);
 			double opt1Dist = c1.distance(optPoint);
 			double opt2Dist = c2.distance(optPoint);
 			pointToUse = optPoint;
@@ -155,6 +155,10 @@
 				pointToUse = (opt1Dist < opt2Dist) ? c1 : c2;
 			}
 			else {
+				if (log.isInfoEnabled()){
+					double distLine = optPoint.distToLineSegment(c1.getDisplayedCoord(), c2.getDisplayedCoord());
+					log.info("adding number nodes at",pointToUse.toDegreeString(),"to optimize address search", "dist to line is", HousenumberGenerator.formatLen(distLine));
+				}
 				timesToAdd = 2;
 			}
 		}
Index: src/uk/me/parabola/mkgmap/osmstyle/housenumber/SplitPoint.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/housenumber/SplitPoint.java	(nonexistent)
+++ src/uk/me/parabola/mkgmap/osmstyle/housenumber/SplitPoint.java	(working copy)
@@ -0,0 +1,29 @@
+package uk.me.parabola.mkgmap.osmstyle.housenumber;
+
+import uk.me.parabola.imgfmt.app.Coord;
+import uk.me.parabola.util.Locatable;
+
+// helper class to find best place to split a road  
+public class SplitPoint implements Locatable{
+	private final Coord point;
+	private final double distToLine;
+	private final double distToTarget;
+	public SplitPoint(Coord co, Double distToLine, double distToTarget) {
+		this.point = co;
+		this.distToLine = distToLine;
+		this.distToTarget = distToTarget;
+	}
+	@Override
+	public String toString() {
+		return "SplitPoint [point=" + point + ", distToLine=" + HousenumberGenerator.formatLen(distToLine) + ", distToTarget=" + HousenumberGenerator.formatLen(distToTarget) + "]";
+	}
+	public double getDistToLine() {
+		return distToLine;
+	}
+	public double getDistToTarget() {
+		return distToTarget;
+	}
+	public Coord getLocation() {
+		return point;
+	}
+}
