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/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/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)); }
_______________________________________________ mkgmap-dev mailing list mkgmap-dev@lists.mkgmap.org.uk http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev