v2 - remove more duplicate labels that only differ in letter case -
remove leading spaces from labels even if they start with a Garmin code.

Still something wrong with motorway names because on the UK map, only
the M74 appears in the mapsource road names - all other motorways are
missing - very odd.

-------

This patch codes around the problems introduced by highway
shields with regard to the sorted roads:

1 - the sort order should now be much improved

2 - no duplicate symbols (shield version + non-shield version)

It also includes a fix to the label reading code so that labels with a
highway shield prefix are read in correctly when generating the MDR
file.

For me, in mapsource, road search for roads with highway shields now
works apart from motorways which don't seem to searchable - perhaps
that's deliberate on Garmin's part?


All feedback appreciated.

Mark
diff --git a/src/uk/me/parabola/imgfmt/app/Label.java b/src/uk/me/parabola/imgfmt/app/Label.java
index c7ca3a3..bbf7549 100644
--- a/src/uk/me/parabola/imgfmt/app/Label.java
+++ b/src/uk/me/parabola/imgfmt/app/Label.java
@@ -56,6 +56,16 @@ public class Label implements Comparable<Label> {
 		return text;
 	}
 
+	public String getTextSansGarminCodes() {
+		return stripGarminCodes(text);
+	}
+
+	public static String stripGarminCodes(String s) {
+		if(s == null)
+			return null;
+		return s.replaceAll("[\u0001-\u0006\u001b-\u001f]","");
+	}
+
 	/**
 	 * The offset of this label in the LBL file.  The first byte of this file
 	 * is zero and an offset of zero means that the label has a zero length/is
diff --git a/src/uk/me/parabola/imgfmt/app/labelenc/BaseEncoder.java b/src/uk/me/parabola/imgfmt/app/labelenc/BaseEncoder.java
index 0dc8390..fd06368 100644
--- a/src/uk/me/parabola/imgfmt/app/labelenc/BaseEncoder.java
+++ b/src/uk/me/parabola/imgfmt/app/labelenc/BaseEncoder.java
@@ -65,7 +65,7 @@ public class BaseEncoder {
 		return new EncodedText(out, out.length);
 	}
 
-	protected boolean isUpperCase() {
+	public boolean isUpperCase() {
 		return upperCase;
 	}
 
diff --git a/src/uk/me/parabola/imgfmt/app/labelenc/Format6Encoder.java b/src/uk/me/parabola/imgfmt/app/labelenc/Format6Encoder.java
index ec226a1..d1a267d 100644
--- a/src/uk/me/parabola/imgfmt/app/labelenc/Format6Encoder.java
+++ b/src/uk/me/parabola/imgfmt/app/labelenc/Format6Encoder.java
@@ -41,7 +41,7 @@ public class Format6Encoder extends BaseEncoder implements CharacterEncoder {
 	public static final String LETTERS =
 		" ABCDEFGHIJKLMNO" +	// 0x00-0x0F
 		"PQRSTUVWXYZxx   " +	// 0x10-0x1F
-		"0123456789xxxxxx";	// 0x20-0x2F
+		"0123456789\u0001\u0002\u0003\u0004\u0005\u0006";	// 0x20-0x2F
 
 	public static final String SYMBOLS =
 		"@!\"#$%&'()*+,-./" +	// 0x00-0x0F
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/City.java b/src/uk/me/parabola/imgfmt/app/lbl/City.java
index 4fc7939..2ae6389 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/City.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/City.java
@@ -118,7 +118,7 @@ public class City implements Comparable<City> {
 		if(label != null)
 			result += label.getText();
 		if (subdivision != null)
-			result += subdivision.getNumber() + "/" + pointIndex;
+			result += " " + subdivision.getNumber() + "/" + pointIndex;
 		if(country != null)
 			result += " in country " + (0 + country.getIndex());
 		if(region != null)
diff --git a/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java b/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
index 4d88bab..a2422ea 100644
--- a/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
+++ b/src/uk/me/parabola/imgfmt/app/lbl/LBLFile.java
@@ -17,6 +17,7 @@
 package uk.me.parabola.imgfmt.app.lbl;
 
 import java.util.HashMap;
+import java.util.Locale;
 import java.util.Map;
 
 import uk.me.parabola.imgfmt.Utils;
@@ -27,6 +28,7 @@ import uk.me.parabola.imgfmt.app.Label;
 import uk.me.parabola.imgfmt.app.labelenc.BaseEncoder;
 import uk.me.parabola.imgfmt.app.labelenc.CharacterEncoder;
 import uk.me.parabola.imgfmt.app.labelenc.CodeFunctions;
+import uk.me.parabola.imgfmt.app.labelenc.Format6Encoder;
 import uk.me.parabola.imgfmt.app.trergn.Subdivision;
 import uk.me.parabola.imgfmt.fs.ImgChannel;
 import uk.me.parabola.log.Logger;
@@ -107,6 +109,13 @@ public class LBLFile extends ImgFile {
 	 * @return A reference to the created label.
 	 */
 	public Label newLabel(String text) {
+		// if required, fold case now so that labelCache doesn't
+		// contain multiple labels that only differ in letter case
+		if(text != null &&
+		   (textEncoder instanceof Format6Encoder ||
+			textEncoder instanceof BaseEncoder &&
+			((BaseEncoder)textEncoder).isUpperCase()))
+			text = text.toUpperCase(Locale.ENGLISH);
 		Label l = labelCache.get(text);
 		if (l == null) {
 			l = new Label(text);
diff --git a/src/uk/me/parabola/imgfmt/app/net/NETFile.java b/src/uk/me/parabola/imgfmt/app/net/NETFile.java
index 82f220b..e7abf26 100644
--- a/src/uk/me/parabola/imgfmt/app/net/NETFile.java
+++ b/src/uk/me/parabola/imgfmt/app/net/NETFile.java
@@ -18,8 +18,11 @@ package uk.me.parabola.imgfmt.app.net;
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
+import java.util.Map;
 
 import uk.me.parabola.imgfmt.Utils;
 import uk.me.parabola.imgfmt.app.BufferedImgFileWriter;
@@ -61,23 +64,44 @@ public class NETFile extends ImgFile {
 
 	public void writePost(ImgFileWriter rgn, boolean sortRoads) {
 		List<Sortable<Label, RoadDef>> sortedRoads = new ArrayList<Sortable<Label, RoadDef>>(roads.size());
+		// cleanedLabels holds "cleaned up" versions of the Label
+		// strings that are used when sorting the road names - the
+		// hope is that retrieving the String from the Map is faster than
+		// cleaning the Label text for each comparison in the sort
+		final Map<Label, String> cleanedLabels = new HashMap<Label, String>();
 
 		for (RoadDef rd : roads) {
 			rd.writeRgnOffsets(rgn);
 			if(sortRoads) {
 				Label[] l = rd.getLabels();
-				for(int i = 0; i < l.length && l[i] != null; ++i)
-					if(l[i].getLength() != 0)
+				for(int i = 0; i < l.length && l[i] != null; ++i) {
+					if(l[i].getLength() != 0) {
+						cleanedLabels.put(l[i], l[i].getTextSansGarminCodes());
+						//	System.err.println("Road " + rd + " has label " + l[i]);
 						sortedRoads.add(new Sortable<Label, RoadDef>(l[i], rd));
+					}
+				}
 			}
 		}
 
 		if(sortedRoads.size() > 0) {
-			Collections.sort(sortedRoads);
+			Collections.sort(sortedRoads, new Comparator<Sortable<Label, RoadDef>>() {
+					public int compare(Sortable<Label, RoadDef> a, Sortable<Label, RoadDef> b) {
+						// sort using cleaned versions of the labels
+						int diff = cleanedLabels.get(a.getKey()).compareToIgnoreCase(cleanedLabels.get(b.getKey()));
+						if(diff != 0)
+							return diff;
+						// the labels were the same, sort on the
+						// RoadDefs
+						return a.getValue().compareTo(b.getValue());
+					}
+				});
 			sortedRoads = simplifySortedRoads(new LinkedList<Sortable<Label, RoadDef>>(sortedRoads));
 			ImgFileWriter writer = netHeader.makeSortedRoadWriter(getWriter());
-			for(Sortable<Label, RoadDef> srd : sortedRoads)
+			for(Sortable<Label, RoadDef> srd : sortedRoads) {
+				//System.err.println("Road " + srd.getKey() + " is " + srd.getValue() + " " + srd.getValue().getCity());
 				srd.getValue().putSortedRoadEntry(writer, srd.getKey());
+			}
 			Utils.closeFile(writer);
 		}
 
@@ -95,7 +119,7 @@ public class NETFile extends ImgFile {
 	private List<Sortable<Label, RoadDef>> simplifySortedRoads(LinkedList<Sortable<Label, RoadDef>> in) {
 		List<Sortable<Label, RoadDef>> out = new ArrayList<Sortable<Label, RoadDef>>(in.size());
 		while(in.size() > 0) {
-			Label name0 = in.get(0).getKey();
+			String name0 = in.get(0).getKey().getTextSansGarminCodes();
 			RoadDef road0 = in.get(0).getValue();
 			City city0 = road0.getCity();
 			// transfer the 0'th entry to the output
@@ -104,7 +128,7 @@ public class NETFile extends ImgFile {
 			// firstly determine the entries whose name and city match
 			// name0 and city0
 			for(n = 0; (n < in.size() &&
-						name0 == in.get(n).getKey() &&
+						name0.equalsIgnoreCase(in.get(n).getKey().getTextSansGarminCodes()) &&
 						city0 == in.get(n).getValue().getCity()); ++n) {
 				// relax
 			}
diff --git a/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java b/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
index 1202186..a2620b5 100644
--- a/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
+++ b/src/uk/me/parabola/imgfmt/app/trergn/Subdivision.java
@@ -274,15 +274,20 @@ public class Subdivision {
 	}
 
 	public Polyline createLine(String name, String ref) {
+		// don't be tempted to "trim()" the name as it zaps the highway shields
 		Label label = lblFile.newLabel(name);
+		String nameSansGC = Label.stripGarminCodes(name);
 		Polyline pl = new Polyline(this);
 
 		pl.setLabel(label);
+
 		if(ref != null) {
 			// ref may contain multiple ids separated by ";"
 			for(String r : ref.split(";")) {
 				String tr = r.trim();
-				if(tr.length() > 0) {
+				String trSansGC = Label.stripGarminCodes(tr);
+				if(trSansGC.length() > 0 &&
+				   !trSansGC.equalsIgnoreCase(nameSansGC)) {
 					//System.err.println("Adding ref " + tr + " to road " + name);
 					pl.addRefLabel(lblFile.newLabel(tr));
 				}
diff --git a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
index 58500ef..de58e11 100644
--- a/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
+++ b/src/uk/me/parabola/mkgmap/osmstyle/StyledConverter.java
@@ -599,6 +599,24 @@ public class StyledConverter implements OsmConverter {
 			// use first ref as name
 			name = SEMI_PATTERN.split(refs)[0].trim();
 		}
+		else if(name != null) {
+			// remove leading spaces (don't use trim() to avoid zapping
+			// shield codes)
+			char leadingCode = 0;
+			if(name.length() > 1 &&
+			   name.charAt(0) < 0x20 &&
+			   name.charAt(1) == ' ') {
+				leadingCode = name.charAt(0);
+				name = name.substring(2);
+			}
+				
+			while(name.length() > 0 && name.charAt(0) == ' ')
+				name = name.substring(1);
+
+			if(leadingCode != 0)
+				name = new Character(leadingCode) + name;
+		}
+
 		if(name != null)
 			ms.setName(name);
 		if(refs != null)
_______________________________________________
mkgmap-dev mailing list
mkgmap-dev@lists.mkgmap.org.uk
http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev

Reply via email to