Index: uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(revision 1580)
+++ src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java	(working copy)
@@ -19,8 +19,10 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.IdentityHashMap;
 import java.util.List;
+import java.util.ListIterator;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Properties;
@@ -49,6 +51,7 @@
 import uk.me.parabola.mkgmap.general.RoadNetwork;
 import uk.me.parabola.mkgmap.reader.osm.CoordPOI;
 import uk.me.parabola.mkgmap.reader.osm.Element;
+import uk.me.parabola.mkgmap.reader.osm.FakeIdGenerator;
 import uk.me.parabola.mkgmap.reader.osm.GType;
 import uk.me.parabola.mkgmap.reader.osm.Node;
 import uk.me.parabola.mkgmap.reader.osm.OsmConverter;
@@ -173,6 +176,14 @@
 
 	private static final Pattern commaPattern = Pattern.compile(",");
 
+	private String makeKeyFromGType(GType type) {
+		String key = String.valueOf(type.getFeatureKind()) + "," + String.valueOf(type.getType()) + "," + String.valueOf(type.getMinResolution())
+			+ "," + String.valueOf(type.getMaxResolution());
+		if (type.isRoad())
+			key += "," + String.valueOf(type.getRoadClass()) + "," + String.valueOf(type.getRoadSpeed());
+		return key;
+	}
+
 	private GType makeGTypeFromTags(Element element) {
 		String[] vals = commaPattern.split(element.getTag("mkgmap:gtype"));
 
@@ -442,10 +453,38 @@
 	 *
 	 * @param relation The relation to convert.
 	 */
-	public void convertRelation(Relation relation) {
-		// Relations never resolve to a GType and so we ignore the return
-		// value.
-		relationRules.resolveType(relation, TypeResult.NULL_RESULT);
+	public void convertRelation(Relation relation, final Map<Long, Way> wayMap) {
+		// If the relation resolves to a GType of a way then add that way to the map
+		preConvertRules(relation);
+		relationRules.resolveType(relation, new TypeResult() {
+			public void add(Element el, GType type) {
+				Relation relation = (Relation) el;
+				postConvertRules(relation, type);
+
+				// Create a hash set from the relation elements. This makes sure that each element
+				// occurs at most once.
+				HashSet<Element> elements = new HashSet(relation.getElements().size());
+				for (Map.Entry<String,Element> mapEntry : relation.getElements()) {
+					elements.add(mapEntry.getValue());
+				}
+
+				// Extract all the ways that belong to the relation
+				List<Way> ways = new ArrayList<Way>(elements.size());
+				for (Element ele : elements) {
+					if (ele instanceof Way)
+						addWayToListAndChainIfPossible(ways, (Way) ele, type.isRoad()); // care about oneways if it is a road
+				}
+
+				for (Way w : ways) {
+					w.setName(relation.getName());
+					// Using mkgmap:gtype way to promote the attributes, so that the generated ways can go through the same
+					// process as the ways that come directly from the osm data
+					type.setFeatureKind(GType.POLYLINE);
+					w.addTag("mkgmap:gtype",makeKeyFromGType(type));
+					wayMap.put(FakeIdGenerator.makeFakeId(),w);
+				}
+			}
+		});
 
 		if(relation instanceof RestrictionRelation) {
 			RestrictionRelation rr = (RestrictionRelation)relation;
@@ -463,6 +502,133 @@
 		}
 	}
 
+	private void addWayToListAndChainIfPossible(List<Way> ways, Way newWay, boolean careAboutOneways) {
+		outer_loop: for (;;) {
+			List<Coord> newWayCoords = newWay.getPoints();
+			int newWayNumPoints = newWayCoords.size();
+			if (newWayNumPoints == 0) return;
+	
+			Coord newWayFirstCoord = newWayCoords.get(0);
+			Coord newWayLastCoord = newWayCoords.get(newWayNumPoints-1);
+	
+			ListIterator<Way> listIterator = ways.listIterator();
+			while (listIterator.hasNext()) {
+				Way existantWay = listIterator.next();
+				List<Coord> existantWayCoords = existantWay.getPoints();
+				int existantWayNumPoints = existantWayCoords.size();
+				if (existantWayNumPoints == 0) continue;
+	
+				Coord existantWayFirstCoord = existantWayCoords.get(0);
+				Coord existantWayLastCoord = existantWayCoords.get(existantWayNumPoints-1);
+	
+				// Test coordinates to see whether two way can be chained together
+				// If they are chained together the only tag we will copy is the oneway tag (if we care about them).
+				// Access tags will have to be set by the relation!
+				// TODO: Handle the oneway=-1 tag in a useful way, now it prevents chaining of the ways.
+	
+				// Both ways share the same first point. So the new way is connected in reverse, but if we care about oneways
+				// then only if none of them is one.
+				if (existantWayFirstCoord.equals(newWayFirstCoord) 
+					&& (!careAboutOneways || (!existantWay.isBoolTag("oneway") && !newWay.isBoolTag("oneway")))) {
+	
+					Way replacementWay = new Way(existantWay.getId());
+
+					// Add points of new way in reverse
+					ListIterator<Coord> newWayCoordIterator = newWayCoords.listIterator(newWayNumPoints);
+					while (newWayCoordIterator.hasPrevious()) {
+						replacementWay.addPoint(newWayCoordIterator.previous());
+					}
+					// And of the existant way in order (starting from the second point)
+					ListIterator<Coord> existantWayCoordIterator = existantWayCoords.listIterator(1);
+					while (existantWayCoordIterator.hasNext()) {
+						replacementWay.addPoint(existantWayCoordIterator.next());
+					}
+					// Remove the existant way that was chained to the new way and start the search again.
+					listIterator.remove();
+					newWay = replacementWay;
+					continue outer_loop;
+				// The last point of the existant way is the same as the first point of the new way, so they are
+				// connected in order, but if we care about oneways then only if they either both have the oneway tag or both have not.
+				} else if (existantWayLastCoord.equals(newWayFirstCoord)
+					&& (!careAboutOneways || !(existantWay.isBoolTag("oneway") ^ newWay.isBoolTag("oneway")))) {
+	
+					Way replacementWay = new Way(existantWay.getId());
+					if (careAboutOneways) {
+						String onewayValue = existantWay.getTag("oneway");
+						if (onewayValue != null)
+							replacementWay.addTag("oneway",onewayValue);
+					}
+
+					// Add points of existant way in order
+					ListIterator<Coord> existantWayCoordIterator = existantWayCoords.listIterator();
+					while (existantWayCoordIterator.hasNext()) {
+						replacementWay.addPoint(existantWayCoordIterator.next());
+					}
+					// And of the new way also in order (starting from the second point)
+					ListIterator<Coord> newWayCoordIterator = newWayCoords.listIterator(1);
+					while (newWayCoordIterator.hasNext()) {
+						replacementWay.addPoint(newWayCoordIterator.next());
+					}
+					// Remove the existant way that was chained to the new way and start the search again.
+					listIterator.remove();
+					newWay = replacementWay;
+					continue outer_loop;
+				// The first point of the existant way is the same as the last point of the new way, so connect them,
+				// but starting with the new way and if we care about oneways then only if they either both have the
+				// oneway tag or both have not.
+				} else if (existantWayFirstCoord.equals(newWayLastCoord)
+					&& (!careAboutOneways || (!(existantWay.isBoolTag("oneway") ^ newWay.isBoolTag("oneway"))))) {
+	
+					Way replacementWay = new Way(existantWay.getId());
+					if (careAboutOneways) {
+						String onewayValue = existantWay.getTag("oneway");
+						if (onewayValue != null)
+							replacementWay.addTag("oneway",onewayValue);
+					}
+
+					// Add points of the new way in order
+					ListIterator<Coord> newWayCoordIterator = newWayCoords.listIterator();
+					while (newWayCoordIterator.hasNext()) {
+						replacementWay.addPoint(newWayCoordIterator.next());
+					}
+					// And of the existant way also in order (starting from the second point)
+					ListIterator<Coord> existantWayCoordIterator = existantWayCoords.listIterator(1);
+					while (existantWayCoordIterator.hasNext()) {
+						replacementWay.addPoint(existantWayCoordIterator.next());
+					}
+					// Remove the existant way that was chained to the new way and start the search again.
+					listIterator.remove();
+					newWay = replacementWay;
+					continue outer_loop;
+				// The last points of the existant and the new way are the same. So the new way is connected in reverse,
+				// but if we care about oneways than only if neither of them has the oneway tag set.
+				} else if (existantWayLastCoord.equals(newWayLastCoord)
+					&& (!careAboutOneways || (!existantWay.isBoolTag("oneway") && !newWay.isBoolTag("oneway")))) {
+	
+					Way replacementWay = new Way(existantWay.getId());
+
+					// Add points of existant way in order
+					ListIterator<Coord> existantWayCoordIterator = existantWayCoords.listIterator();
+					while (existantWayCoordIterator.hasNext()) {
+						replacementWay.addPoint(existantWayCoordIterator.next());
+					}
+					// And of the new way in reverse (starting from the second last point)
+					ListIterator<Coord> newWayCoordIterator = newWayCoords.listIterator(newWayNumPoints-1);
+					while (newWayCoordIterator.hasPrevious()) {
+						replacementWay.addPoint(newWayCoordIterator.previous());
+					}
+					// Remove the existant way that was chained to the new way and start the search again.
+					listIterator.remove();
+					newWay = replacementWay;
+					continue outer_loop;
+				}
+			}
+			// If we get here no way was found anymore that we could chain to. Add the way and return.
+			ways.add(newWay);
+			return;
+		}
+	}
+
 	private void addLine(Way way, GType gt) {
 		List<Coord> wayPoints = way.getPoints();
 		List<Coord> points = new ArrayList<Coord>(wayPoints.size());
Index: src/uk/me/parabola/mkgmap/reader/osm/OsmConverter.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/OsmConverter.java	(revision 1580)
+++ src/uk/me/parabola/mkgmap/reader/osm/OsmConverter.java	(working copy)
@@ -16,6 +16,8 @@
  */
 package uk.me.parabola.mkgmap.reader.osm;
 
+import java.util.Map;
+
 import uk.me.parabola.imgfmt.app.Area;
 
 /**
@@ -52,7 +54,7 @@
 	 *
 	 * @param relation The relation to convert.
 	 */
-	public void convertRelation(Relation relation);
+	public void convertRelation(Relation relation, Map<Long, Way> wayMap);
 
 	/**
 	 * Set the bounding box for this map.  This should be set before any other
Index: src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java	(revision 1580)
+++ src/uk/me/parabola/mkgmap/reader/osm/xml/Osm5XmlHandler.java	(working copy)
@@ -623,7 +623,7 @@
 
 		long start = System.currentTimeMillis();
 		for (Relation r : relationMap.values())
-			converter.convertRelation(r);
+			converter.convertRelation(r, wayMap);
 
 		for (Node n : nodeMap.values())
 			converter.convertNode(n);
Index: src/uk/me/parabola/mkgmap/reader/osm/GType.java
===================================================================
--- src/uk/me/parabola/mkgmap/reader/osm/GType.java	(revision 1580)
+++ src/uk/me/parabola/mkgmap/reader/osm/GType.java	(working copy)
@@ -34,7 +34,7 @@
 	public static final int POLYLINE = 2;
 	public static final int POLYGON = 3;
 
-	private final int featureKind;
+	private int featureKind;
 	private final int type;
 
 	private int minResolution = 24;
@@ -79,6 +79,10 @@
 		}
 	}
 
+	public void setFeatureKind(int featureKind) {
+		this.featureKind = featureKind;
+	}
+
 	public int getFeatureKind() {
 		return featureKind;
 	}
Index: src/uk/me/parabola/mkgmap/main/StyleTester.java
===================================================================
--- src/uk/me/parabola/mkgmap/main/StyleTester.java	(revision 1580)
+++ src/uk/me/parabola/mkgmap/main/StyleTester.java	(working copy)
@@ -29,6 +29,7 @@
 import java.util.Formatter;
 import java.util.List;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Properties;
 import java.util.regex.Pattern;
 
@@ -273,8 +274,8 @@
 		converter.convertNode(node);
 	}
 
-	public void convertRelation(Relation relation) {
-		converter.convertRelation(relation);
+	public void convertRelation(Relation relation, Map<Long, Way> wayMap) {
+		converter.convertRelation(relation, wayMap);
 	}
 
 	public void setBoundingBox(Area bbox) {
