diff --git a/src/uk/me/parabola/imgfmt/app/net/NODFile.java b/src/uk/me/parabola/imgfmt/app/net/NODFile.java
index e877ce9..23fdc25 100644
--- a/src/uk/me/parabola/imgfmt/app/net/NODFile.java
+++ b/src/uk/me/parabola/imgfmt/app/net/NODFile.java
@@ -18,6 +18,7 @@ package uk.me.parabola.imgfmt.app.net;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Collections;
 
 import uk.me.parabola.imgfmt.app.BufferedImgFileReader;
 import uk.me.parabola.imgfmt.app.BufferedImgFileWriter;
@@ -126,6 +127,8 @@ public class NODFile extends ImgFile {
 	private void writeBoundary() {
 		log.info("writeBoundary");
 
+		Collections.sort(boundary);
+
 		ImgFileWriter writer = new SectionWriter(getWriter(), nodHeader.getBoundarySection());
 
 		for (RouteNode node : boundary) {
diff --git a/src/uk/me/parabola/imgfmt/app/net/RouteNode.java b/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
index accfff3..977a8d7 100644
--- a/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
+++ b/src/uk/me/parabola/imgfmt/app/net/RouteNode.java
@@ -28,7 +28,7 @@ import uk.me.parabola.log.Logger;
  *
  * @author Steve Ratcliffe
  */
-public class RouteNode {
+public class RouteNode implements Comparable {
 	private static final Logger log = Logger.getLogger(RouteNode.class);
 
 	/*
@@ -244,4 +244,16 @@ public class RouteNode {
 	public String toString() {
 		return nodeId + "";
 	}
+
+	/*
+	 * For sorting node entries in NOD 3.
+	 */
+	public int compareTo(Object o) {
+		Coord other = ((RouteNode) o).getCoord();
+		int lon = coord.getLongitude();
+		int lat = coord.getLatitude();
+		int lon2 = other.getLongitude();
+		int lat2 = other.getLatitude();
+		return (lon - lon2 == 0) ? (lat - lat2) : (lon - lon2);
+	}
 }
diff --git a/src/uk/me/parabola/mkgmap/build/MapBuilder.java b/src/uk/me/parabola/mkgmap/build/MapBuilder.java
index 5e73ca9..c72b482 100644
--- a/src/uk/me/parabola/mkgmap/build/MapBuilder.java
+++ b/src/uk/me/parabola/mkgmap/build/MapBuilder.java
@@ -603,7 +603,8 @@ public class MapBuilder implements Configurable {
 
 			pl.setType(line.getType());
 
-			if (doRoads && line.isRoad()) {
+			if (doRoads && line.isRoad() &&
+			    div.getZoom().getLevel() == 0) {
 				if (log.isDebugEnabled())
 					log.debug("adding road def: " + line.getName());
 				RoadDef roaddef = ((MapRoad) line).getRoadDef();
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index 12f4e3f..2c04c79 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -28,6 +28,7 @@ import uk.me.parabola.log.Logger;
 import uk.me.parabola.mkgmap.general.AreaClipper;
 import uk.me.parabola.mkgmap.general.Clipper;
 import uk.me.parabola.mkgmap.general.LineAdder;
+import uk.me.parabola.mkgmap.general.LineClipper;
 import uk.me.parabola.mkgmap.general.MapCollector;
 import uk.me.parabola.mkgmap.general.MapElement;
 import uk.me.parabola.mkgmap.general.MapLine;
@@ -59,11 +60,14 @@ public class StyledConverter implements OsmConverter {
 	private final MapCollector collector;
 
 	private Clipper clipper = Clipper.NULL_CLIPPER;
+	private Area bbox = null;
 
 	private int roadId;
 
 	private final int MAX_NODES_IN_WAY = 16;
 
+	private final double MIN_DISTANCE_BETWEEN_NODES = 5.5;
+
 	// nodeIdMap maps a Coord into a nodeId
 	private final Map<Coord, Integer> nodeIdMap = new HashMap<Coord, Integer>();
 	private int nextNodeId;
@@ -191,6 +195,7 @@ public class StyledConverter implements OsmConverter {
 	 */
 	public void setBoundingBox(Area bbox) {
 		this.clipper = new AreaClipper(bbox);
+		this.bbox = bbox;
 	}
 
 	/**
@@ -261,6 +266,87 @@ public class StyledConverter implements OsmConverter {
 			}
 		}
 
+		// if there is a bounding box, clip the way with it
+
+		List<Way> clippedWays = null;
+
+		if(bbox != null) {
+			List<List<Coord>> lineSegs = LineClipper.clip(bbox, way.getPoints());
+
+			if (lineSegs != null) {
+
+				clippedWays = new ArrayList<Way>();
+
+				for (List<Coord> lco : lineSegs) {
+					// if the clipper introduced a
+					// new start or end node to
+					// the clipped way and that
+					// node is too close to an
+					// existing node, throw the
+					// new node away and warn user
+					Coord end = lco.get(0);
+					if(end.getHighwayCount() == 0) {
+						boolean trashed = false;
+						for(int i = 1; !trashed && i < lco.size(); ++i) {
+							Coord ci = lco.get(i);
+							if(ci.getHighwayCount() > 1 &&
+							   end.distance(ci) < MIN_DISTANCE_BETWEEN_NODES) {
+								trashed = true;
+							}
+						}
+						if(trashed) {
+							System.err.println("Throwing away boundary node at " + end.toDegreeString() + " because it is too close to an existing node");
+							lco.remove(0);
+							if(lco.size() < 2)
+								continue;
+						}
+					}
+					end = lco.get(lco.size() - 1);
+					if(end.getHighwayCount() == 0) {
+						boolean trashed = false;
+						for(int i = lco.size() - 2; !trashed && i >= 0; --i) {
+							Coord ci = lco.get(i);
+							if(ci.getHighwayCount() > 1 &&
+							   end.distance(ci) < MIN_DISTANCE_BETWEEN_NODES) {
+								trashed = true;
+							}
+						}
+						if(trashed) {
+							System.err.println("Throwing away boundary node at " + end.toDegreeString() + " because it is too close to an existing node");
+							lco.remove(lco.size() - 1);
+							if(lco.size() < 2)
+								continue;
+						}
+					}
+					Way nWay = new Way();
+					nWay.setName(way.getName());
+					nWay.copyTags(way);
+					// note that points added by
+					// the clipper will have a
+					// highway count of zero and
+					// we can use this fact to
+					// distinguish them later
+					for(Coord co : lco) {
+						nWay.addPoint(co);
+					}
+					clippedWays.add(nWay);
+				}
+			}
+		}
+
+		if(clippedWays != null) {
+			for(Way cw : clippedWays) {
+				addRoadAfterSplittingLoops(cw, gt);
+			}
+		}
+		else {
+			// no bounding box or way was not clipped
+			addRoadAfterSplittingLoops(way, gt);
+		}
+	}
+
+	void addRoadAfterSplittingLoops(Way way, GType gt) {
+
 		// check if the way is a loop or intersects with itself
 
 		boolean wayWasSplit = true; // aka rescan required
@@ -312,6 +398,23 @@ public class StyledConverter implements OsmConverter {
 		List<Integer> nodeIndices = new ArrayList<Integer>();
 		List<Coord> points = way.getPoints();
 		Way trailingWay = null;
+		boolean[] isBoundaryNode = new boolean[points.size()];
+
+		// if either of the end points has a highway count of
+		// zero it means that it has been generated by the
+		// clipper - in that case, remember the fact that the
+		// point is on the boundary and increment the highway
+		// count so that a node will be created
+		if(points.get(0).getHighwayCount() == 0) {
+			points.get(0).incHighwayCount();
+			isBoundaryNode[0] = true;
+			System.err.println("Way " + way.getName() + "'s first point at " + points.get(0).toDegreeString() + " is a boundary node");
+		}
+		if(points.get(points.size() - 1).getHighwayCount() == 0) {
+			points.get(points.size() - 1).incHighwayCount();
+			isBoundaryNode[points.size() - 1] = true;
+			System.err.println("Way " + way.getName() + "'s last point at " + points.get(points.size() - 1).toDegreeString() + " is a boundary node");
+		}
 
 		// make sure the way has nodes at each end
 		points.get(0).incHighwayCount();
@@ -454,7 +557,7 @@ public class StyledConverter implements OsmConverter {
 					hasInternalNodes = true;
 				Coord coord = points.get(n);
 				Integer nodeId = nodeIdMap.get(coord);
-				boolean boundary = way.isBoolTag("mkgmap:boundary_node");
+				boolean boundary = isBoundaryNode[n];
 				points.set(n, new CoordNode(coord.getLatitude(), coord.getLongitude(), nodeId, boundary));
 				//		System.err.println("Road " + road.getRoadId() + " node[" + i + "] " + nodeId + " at " + coord.toDegreeString());
 			}
@@ -550,10 +653,9 @@ public class StyledConverter implements OsmConverter {
 				Coord newPoint = new Coord(newLat, newLon);
 				double d1 = p1.distance(newPoint);
 				double d2 = p2.distance(newPoint);
-				double minDistance = 5.5;
 				double maxDistance = 100;
-				if(d1 >= minDistance && d1 <= maxDistance &&
-				   d2 >= minDistance && d2 <= maxDistance) {
+				if(d1 >= MIN_DISTANCE_BETWEEN_NODES && d1 <= maxDistance &&
+				   d2 >= MIN_DISTANCE_BETWEEN_NODES && d2 <= maxDistance) {
 				    newPoint.incHighwayCount();
 				    wayPoints.add(i + 1, newPoint);
 				}
