Hi I think the mkgmap internal handling of types/subtypes of points is obscure.
In the points style file, the type code is always full, ie type << 8 | subtype, but when the points are read back from the RGN file for the MDR processing, the representation is the same provided the subtype is not zero, otherwise it is just type! Logic then decides that if the value is <= 0xff it is because the subtype is zero. It is simpler and much clearer to preserve the original representation. This also allows unambiguous use of type 0 with subtypes, and, possibly, city with subtypes. It also allows the same function to be used to test a type for being in the 'city' range, regardless of the context. mkgmap wasn't consistent the ranges for the isCity test. City POI are written in a different manner to the RGN file. The old range for this was: type >= 0x0100 && type <= 0x1100 which I've kept, except changing to: ...& type < 0x1200. A similar range was used for MDR5. However, city POI are held in group 1 of MDR 9/10. This is used in Find > City 'By Name'. The old range was: type <= 0xf, where, if the subtype was zero, type is right shifted by 8 (see above), non-zero subtypes messed up the testing. Now it uses the same range as above. Actually neither of these ranges are correct for my Garmin devices. Find > City show nearby POI with types in the range 0x0100..0x0d1f, regardless of the img RGN or MDR. The eTrex Legend labels POIs in this range as {Large/Medium/Small} City/Town and points in the range 0x0e00..0x111f as "*". Find > City 'by-name' returns POI if in group 1 of MDR 9/10. I find it a useful feature to have a POI that can be searched for but doesn't flood the list of nearby points. Generally, non-zero subtypes for cities cause problems in the RGN structure and I've added a test for this to the style validation. There is also a fix to --make-poi-index, but I can't detect any effect of this option. This patch won't make any difference to the img output unless the there are points 0x1000, 0x1100. If this patch is accepted, I'll do the equivalent to the img display system. Regards Ticker
Index: src/uk/me/parabola/imgfmt/app/lbl/PlacesFile.java =================================================================== --- src/uk/me/parabola/imgfmt/app/lbl/PlacesFile.java (revision 4286) +++ src/uk/me/parabola/imgfmt/app/lbl/PlacesFile.java (working copy) @@ -305,7 +305,7 @@ if (t < MIN_INDEXED_POI_TYPE || t > MAX_INDEXED_POI_TYPE) return; - POIIndex pi = new POIIndex(name, index, group, type); + POIIndex pi = new POIIndex(name, index, group, type & 0xff); if(poiIndex[t] == null) poiIndex[t] = new ArrayList<POIIndex>(); poiIndex[t].add(pi); Index: src/uk/me/parabola/imgfmt/app/mdr/Mdr10.java =================================================================== --- src/uk/me/parabola/imgfmt/app/mdr/Mdr10.java (revision 4286) +++ src/uk/me/parabola/imgfmt/app/mdr/Mdr10.java (working copy) @@ -47,6 +47,9 @@ } } + /** + * display MdrCheck.java:toType() needs to be in-step with this + */ public void addPoiType(Mdr11Record poi) { Mdr10Record t = new Mdr10Record(); @@ -56,7 +59,7 @@ if (group == 0) return; if (group == 1) - t.setSubtype(fullType); + t.setSubtype(MdrUtils.getTypeFromFullType(fullType)); // cities else { t.setSubtype(MdrUtils.getSubtypeFromFullType(fullType)); } Index: src/uk/me/parabola/imgfmt/app/mdr/Mdr4.java =================================================================== --- src/uk/me/parabola/imgfmt/app/mdr/Mdr4.java (revision 4286) +++ src/uk/me/parabola/imgfmt/app/mdr/Mdr4.java (working copy) @@ -52,12 +52,9 @@ public void addType(int type) { Mdr4Record r = new Mdr4Record(); - if (type <= 0xff) - r.setType(type); - else { - r.setType((type >> 8) & 0xff); - r.setSubtype(type & 0xff); - } + r.setType((type >> 8) & 0xff); + r.setSubtype(type & 0xff); + r.setUnknown(0); poiTypes.add(r); Index: src/uk/me/parabola/imgfmt/app/mdr/MdrUtils.java =================================================================== --- src/uk/me/parabola/imgfmt/app/mdr/MdrUtils.java (revision 4286) +++ src/uk/me/parabola/imgfmt/app/mdr/MdrUtils.java (working copy) @@ -16,6 +16,7 @@ import java.util.Collections; import java.util.List; +import uk.me.parabola.mkgmap.general.MapPoint; import uk.me.parabola.imgfmt.app.srt.Sort; import uk.me.parabola.imgfmt.app.srt.SortKey; @@ -34,33 +35,38 @@ * * Not entirely sure about how this works yet. * @param fullType The primary type of the object. - * @return The group number. This is a number between 1 and 9 (and later - * perhaps higher numbers such as 0x40, so do not assume there are no - * gaps). - * Group / Filed under - * 1 Cities - * 2 Food & Drink - * 3 Lodging - * 4-5 Recreation / Entertainment / Attractions - * 6 Shopping - * 7 Auto Services - * 8 Community - * 9 ? - * + * @return The group number. This is a number between 1 and MAX_GROUP, later + * might be as high as 0x40, so do not assume there are no gaps. + * + * Group Type Filed under + * 1 Cities (actual range defined by isCityType) + * 2 0x2a Food and Drink + * 3 0x2b Lodgings + * 4 0x2c Attractions/Recreation/Community + * 5 0x2d Entertainment/Recreation + * 6 0x2e Shopping + * 7 0x2f Auto/Transport/Community/Other + * 8 0x30 Civic + * 9 0x28 Island. Reason for having this is no longer known + * 10 unused + * 11 0x64 Geographic > Manmade Places + * 12 0x65 Geographic > Water Features + * 13 0x66 Geographic > Land Features + * + * display MdrCheck.java:toType() needs to be in-step with this */ public static int getGroupForPoi(int fullType) { // We group pois based on their type. This may not be the final thoughts on this. int type = getTypeFromFullType(fullType); int group = 0; - if (fullType <= 0xf) + if (MapPoint.isCityType(fullType)) group = 1; - else if (type >= 0x2a && type <= 0x30) { - group = type - 0x28; - } else if (type == 0x28) { + else if (type >= 0x2a && type <= 0x30) + group = type - 0x2a + 2; + else if (type == 0x28) group = 9; - } else if (type >= 0x64 && type <= 0x66) { - group = type - 0x59; - } + else if (type >= 0x64 && type <= 0x66) + group = type - 0x64 + 11; assert group >= 0 && group <= MAX_GROUP : "invalid group " + Integer.toHexString(group); return group; } @@ -70,10 +76,7 @@ } public static int getTypeFromFullType(int fullType) { - if ((fullType & 0xfff00) > 0) - return (fullType>>8) & 0xfff; - else - return fullType & 0xff; + return (fullType>>8) & 0xfff; } /** @@ -82,7 +85,7 @@ * @return If there is a subtype, then it is returned, else 0. */ public static int getSubtypeFromFullType(int fullType) { - return fullType < 0xff ? 0 : fullType & 0xff; + return fullType & 0xff; } /** @@ -115,10 +118,8 @@ */ public static int fullTypeToNaturalType(int ftype) { int type = getTypeFromFullType(ftype); - int sub = 0; - if ((ftype & ~0xff) != 0) - sub = ftype & 0x1f; - + int sub = getSubtypeFromFullType(ftype); + assert sub <= 0x1f: "Subtype doesn't fit into 5 bits: " + uk.me.parabola.mkgmap.reader.osm.GType.formatType(ftype); return type << 5 | sub; } } Index: src/uk/me/parabola/imgfmt/app/trergn/Point.java =================================================================== --- src/uk/me/parabola/imgfmt/app/trergn/Point.java (revision 4286) +++ src/uk/me/parabola/imgfmt/app/trergn/Point.java (working copy) @@ -50,13 +50,11 @@ boolean hasSubtype = false; int type = getType(); int subtype = 0; - if (type > 0xff) { - if((type & 0xff) != 0) { - hasSubtype = true; - subtype = type & 0xff; - } - type >>= 8; + if ((type & 0xff) != 0) { + hasSubtype = true; + subtype = type & 0xff; } + type >>= 8; file.put1u(type); Index: src/uk/me/parabola/imgfmt/app/trergn/RGNFileReader.java =================================================================== --- src/uk/me/parabola/imgfmt/app/trergn/RGNFileReader.java (revision 4286) +++ src/uk/me/parabola/imgfmt/app/trergn/RGNFileReader.java (working copy) @@ -127,13 +127,13 @@ p.setDeltaLong(reader.get2s()); p.setDeltaLat(reader.get2s()); + t <<= 8; if (hasSubtype) { int st = reader.get1u(); - p.setType((t << 8) | st); + t |= st; //p.setHasSubtype(true); - } else { - p.setType(t); } + p.setType(t); p.setNumber(number++); points.add(p); Index: src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java =================================================================== --- src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java (revision 4286) +++ src/uk/me/parabola/mkgmap/combiners/MdrBuilder.java (working copy) @@ -47,6 +47,7 @@ import uk.me.parabola.imgfmt.sys.ImgFS; import uk.me.parabola.mkgmap.CommandArgs; import uk.me.parabola.mkgmap.srt.SrtTextReader; +import uk.me.parabola.mkgmap.general.MapPoint; /** * Create the global index file. This consists of an img file containing @@ -266,7 +267,7 @@ Mdr5Record mdrCity = null; boolean isCity; - if (p.getType() >= 0x1 && p.getType() <= 0x11) { + if (MapPoint.isCityType(p.getType())) { // This is itself a city, it gets a reference to its own MDR 5 record. // and we also use it to set the name of the city. mdrCity = maps.cities.get((p.getSubdiv().getNumber() << 8) + p.getNumber()); Index: src/uk/me/parabola/mkgmap/general/MapPoint.java =================================================================== --- src/uk/me/parabola/mkgmap/general/MapPoint.java (revision 4286) +++ src/uk/me/parabola/mkgmap/general/MapPoint.java (working copy) @@ -64,7 +64,7 @@ public static boolean isCityType(int type) { - return type >= 0x0100 && type <= 0x1100; + return type >= 0x0100 && type < 0x1200; } public boolean isExit() { Index: src/uk/me/parabola/mkgmap/reader/osm/GType.java =================================================================== --- src/uk/me/parabola/mkgmap/reader/osm/GType.java (revision 4286) +++ src/uk/me/parabola/mkgmap/reader/osm/GType.java (working copy) @@ -21,6 +21,7 @@ import uk.me.parabola.imgfmt.ExitException; import uk.me.parabola.log.Logger; import uk.me.parabola.mkgmap.general.LevelInfo; +import uk.me.parabola.mkgmap.general.MapPoint; /** * Holds the garmin type of an element and all the information that @@ -66,8 +67,13 @@ else if (featureKind == FeatureKind.POLYGON && (type> 0x7f || type == 0x4a)) return false; else if (featureKind == FeatureKind.POINT){ - if (type < 0x0100 || (type & 0x00ff) > 0x1f) + if (type < 0x0100) return false; + int subtype = type & 0xff; + if (subtype > 0x1f) + return false; + if (MapPoint.isCityType(type) && subtype != 0) + return false; } } return true; Index: src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java =================================================================== --- src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java (revision 4286) +++ src/uk/me/parabola/mkgmap/reader/polish/PolishMapDataSource.java (working copy) @@ -412,12 +412,13 @@ private void point(String name, String value) { if (name.equals("Type")) { int type = Integer.decode(value); + if (type <= 0xff) + type <<= 8; point.setType(type); } else if (name.equals("SubType")) { int subtype = Integer.decode(value); int type = point.getType(); - if (type <= 0xff) - point.setType((type << 8) | subtype); + point.setType(type | subtype); } else if (name.startsWith("Data") || name.startsWith("Origin")) { Coord co = makeCoord(value); setResolution(point, name);
_______________________________________________ mkgmap-dev mailing list mkgmap-dev@lists.mkgmap.org.uk http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev