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

Reply via email to