summaryrefslogtreecommitdiff
path: root/data
diff options
context:
space:
mode:
authorzaxl <zaxl@ffa7fe5e-494d-0410-b361-a75ebd5db220>2007-10-25 09:23:14 +0000
committerzaxl <zaxl@ffa7fe5e-494d-0410-b361-a75ebd5db220>2007-10-25 09:23:14 +0000
commitccd79b531ac482cafbaf35ebf4beb5cf98177557 (patch)
tree08bff01053507f0fd17326a9085499eaebe799d1 /data
parent3c8319f750d1b2d2eb9c6f5663ca72366c5786e5 (diff)
downloadnavit-svn-ccd79b531ac482cafbaf35ebf4beb5cf98177557.tar.gz
Add garmin driver
git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit/src@470 ffa7fe5e-494d-0410-b361-a75ebd5db220
Diffstat (limited to 'data')
-rw-r--r--data/garmin/Makefile.am7
-rw-r--r--data/garmin/gar2navit.c267
-rw-r--r--data/garmin/gar2navit.h30
-rw-r--r--data/garmin/garmin.c661
-rw-r--r--data/garmin/garmin.h10
-rw-r--r--data/garmin/garmintypes.txt412
6 files changed, 1387 insertions, 0 deletions
diff --git a/data/garmin/Makefile.am b/data/garmin/Makefile.am
new file mode 100644
index 00000000..fa1801c3
--- /dev/null
+++ b/data/garmin/Makefile.am
@@ -0,0 +1,7 @@
+include $(top_srcdir)/Makefile.inc
+AM_CPPFLAGS = @NAVIT_CFLAGS@ -I$(top_srcdir)/src -DMODULE=\"data_garmin\"
+AM_CPPFLAGS+= @LIBGARMIN_CFLAGS@
+INCLUDES=-I$(top_srcdir)/src/data/garmin/libgarmin
+moduledata_LTLIBRARIES = libdata_garmin.la
+libdata_garmin_la_SOURCES = garmin.c garmin.h gar2navit.c gar2navit.h
+libdata_garmin_la_LIBADD = @LIBGARMIN_LIBS@
diff --git a/data/garmin/gar2navit.c b/data/garmin/gar2navit.c
new file mode 100644
index 00000000..33838bee
--- /dev/null
+++ b/data/garmin/gar2navit.c
@@ -0,0 +1,267 @@
+/*
+ Street's are routable by:
+ ALL - by all
+ W pedestrian (1<<0)
+ B bycycle (1<<1)
+ M motorcycle (1<<2)
+ C car (1<<3)
+ T truck (1<<4)
+ L largetruck (1<<5)
+File format is:
+
+POINT
+0x0100 = town_label_1e5, Megapolis (10M +)
+0x0200 = town_label_5e4, Megapolis (5-10M)
+...
+0x1e00-0x1e3f = district_label, District, Province, State Name
+...
+POLYLINE
+0x00 = ALL, street_1_land, Road
+0x01 = MCTL, highway_land, Major HWY thick
+0x02 = MCTL, street_4_land, Principal HWY-thick
+0x03 = MCTL, street_2_land, Principal HWY-medium
+....
+POLYGONE
+0x01 = town_poly, City (>200k)
+0x02 = town_poly, City (<200k)
+0x03 = town_poly, Village
+
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include "item.h"
+#include "attr.h"
+#include "garmin.h"
+#include "gar2navit.h"
+
+static int add_def(struct gar2nav_conv *conv, int type, unsigned short minid,
+ unsigned short maxid, unsigned int routable, char *ntype,
+ char *descr)
+{
+ enum item_type it;
+ struct gar2navit *g2n;
+ dlog(11, "type=%d routable=%u min=%04X max=%04X ntype=%s descr=%s\n",
+ type, routable, minid, maxid, ntype, descr);
+ it = item_from_name(ntype);
+ if (it==type_none) {
+ dlog(1, "Please define: %s\n", ntype);
+ }
+ g2n = calloc(1, sizeof(*g2n));
+ if (!g2n)
+ return -1;
+ g2n->id = minid;
+ g2n->maxid = maxid;
+ g2n->ntype = it;
+ g2n->descr = strdup(descr);
+ g2n->routable = routable;
+ if (type == 1) {
+ g2n->next = conv->points;
+ conv->points = g2n;
+ } else if (type == 2) {
+ g2n->next = conv->polylines;
+ conv->polylines = g2n;
+ } else if (type == 3) {
+ g2n->next = conv->polygons;
+ conv->polygons = g2n;
+ }
+ return 0;
+}
+
+static unsigned int get_rtmask(char *p)
+{
+ char *cp;
+ unsigned int mask = 0;
+ cp = p;
+ while (*cp) {
+ if (!strcasecmp(cp, "none"))
+ return 0;
+ if (!strcasecmp(cp, "all")) {
+ mask = ~0;
+ break;
+ } if (*cp == 'W')
+ mask |= RT_PEDESTRIAN;
+ else if (*cp == 'B')
+ mask |= RT_BYCYCLE;
+ else if (*cp == 'M')
+ mask |= RT_MOTORCYCLE;
+ else if (*cp == 'C')
+ mask |= RT_CAR;
+ else if (*cp == 'T')
+ mask |= RT_TRUCK;
+ else if (*cp == 'L')
+ mask |= RT_LONGTRUCK;
+ cp++;
+ }
+ return mask;
+}
+
+static int load_types_file(char *file, struct gar2nav_conv *conv)
+{
+ char buf[4096];
+ char descr[4096];
+ char ntype[4096];
+ char rtby[4096];
+ FILE *fp;
+ unsigned int minid, maxid, routable;
+ int rc;
+ int type = -1;
+
+ fp = fopen(file, "r");
+ if (!fp)
+ return -1;
+ while (fgets(buf, sizeof(buf), fp)) {
+ if (*buf == '#' || *buf == '\n')
+ continue;
+ routable = 0;
+ if (!strncasecmp(buf, "POINT", 5)) {
+ type = 1;
+ continue;
+ } else if (!strncasecmp(buf, "POI", 3)) {
+ type = 1;
+ continue;
+ } else if (!strncasecmp(buf, "POLYLINE", 8)) {
+ type = 2;
+ continue;
+ } else if (!strncasecmp(buf, "POLYGONE", 8)) {
+ type = 3;
+ continue;
+ }
+ // assume only lines are routable
+ if (type == 2) {
+ rc = sscanf(buf, "0x%04X = %[^\t, ] , %[^\t, ], %[^\n]",
+ &minid, rtby, ntype, descr);
+ if (rc != 4) {
+ dlog(1, "Invalid line rc=%d:[%s]\n",rc, buf);
+ dlog(1, "minid=%04X ntype=[%s] des=[%s]\n",
+ minid, ntype, descr);
+ continue;
+ }
+ routable = get_rtmask(rtby);
+ } else {
+ rc = sscanf(buf, "0x%04X - 0x%04X = %[^\t , ] , %[^\n]",
+ &minid, &maxid, ntype, descr);
+ if (rc != 4) {
+ maxid = 0;
+ rc = sscanf(buf, "0x%04X = %[^\t, ], %[^\n]",
+ &minid, ntype, descr);
+ if (rc != 3) {
+ dlog(1, "Invalid line rc=%d:[%s]\n",rc, buf);
+ dlog(1, "minid=%04X ntype=[%s] des=[%s]\n",
+ minid, ntype, descr);
+ continue;
+ }
+ }
+ }
+ add_def(conv, type, minid, maxid, routable, ntype, descr);
+ }
+ fclose(fp);
+ return 1;
+}
+
+struct gar2nav_conv *g2n_conv_load(char *file)
+{
+ struct gar2nav_conv *c;
+ int rc;
+
+ c = calloc(1, sizeof(*c));
+ if (!c)
+ return c;
+ rc = load_types_file(file, c);
+ if (rc < 0) {
+ dlog(1, "Failed to load: [%s]\n", file);
+ free(c);
+ return NULL;
+ }
+ return c;
+}
+
+enum item_type g2n_get_type(struct gar2nav_conv *c, int type, unsigned short id)
+{
+ struct gar2navit *def = NULL;
+ if (type == G2N_POINT)
+ def = c->points;
+ else if (type == G2N_POLYLINE)
+ def = c->polylines;
+ else if (type == G2N_POLYGONE)
+ def = c->polygons;
+ else {
+ dlog(1, "Unknown conversion type:%d\n", type);
+ return type_none;
+ }
+
+ if (!def) {
+ dlog(5, "No conversion data for %d\n", type);
+ return type_none;
+ }
+
+ while (def) {
+ if ((!def->maxid && def->id == id) ||
+ (def->id <= id && def->maxid))
+ return def->ntype;
+ def = def->next;
+ }
+ dlog(5, "Type[%d]:ID:[%04X] unknown\n", type, id);
+ return type_none;
+}
+
+int g2n_get_routable(struct gar2nav_conv *c, int type, unsigned short id)
+{
+ struct gar2navit *def = NULL;
+ if (type == G2N_POINT)
+ def = c->points;
+ else if (type == G2N_POLYLINE)
+ def = c->polylines;
+ else if (type == G2N_POLYGONE)
+ def = c->polygons;
+ else {
+ dlog(1, "Unknown conversion type:%d\n", type);
+ return type_none;
+ }
+
+ if (!def) {
+ dlog(5, "No conversion data for %d\n", type);
+ return type_none;
+ }
+
+ while (def) {
+ if ((!def->maxid && def->id == id) ||
+ (def->id <= id && def->maxid))
+ return def->routable;
+ def = def->next;
+ }
+ dlog(5, "Type[%d]:ID:[%04X] unknown\n", type, id);
+ return 0;
+}
+
+char *g2n_get_descr(struct gar2nav_conv *c, int type, unsigned short id)
+{
+ struct gar2navit *def = NULL;
+ if (type == G2N_POINT)
+ def = c->points;
+ else if (type == G2N_POLYLINE)
+ def = c->polylines;
+ else if (type == G2N_POLYGONE)
+ def = c->polygons;
+ else {
+ dlog(1, "Unknown conversion type:%d\n", type);
+ return NULL;
+ }
+ while (def) {
+ if ((!def->maxid && def->id == id) ||
+ (def->id <= id && def->maxid))
+ return def->descr;
+ def = def->next;
+ }
+ dlog(5, "Type[%d]:ID:[%04X] unknown\n", type, id);
+ return NULL;
+}
+
+#if 0
+int main(int argc, char **argv)
+{
+ load_types_file(argv[1], NULL);
+ return 0;
+}
+#endif
diff --git a/data/garmin/gar2navit.h b/data/garmin/gar2navit.h
new file mode 100644
index 00000000..3292b1a9
--- /dev/null
+++ b/data/garmin/gar2navit.h
@@ -0,0 +1,30 @@
+#define RT_PEDESTRIAN (1<<0)
+#define RT_BYCYCLE (1<<1)
+#define RT_MOTORCYCLE (1<<2)
+#define RT_CAR (1<<3)
+#define RT_TRUCK (1<<4)
+#define RT_LONGTRUCK (1<<5)
+
+struct gar2navit {
+ unsigned short id;
+ unsigned short maxid;
+ enum item_type ntype;
+ int routable;
+ char *descr;
+ struct gar2navit *next;
+};
+
+#define G2N_POINT 1
+#define G2N_POLYLINE 2
+#define G2N_POLYGONE 3
+
+struct gar2nav_conv {
+ struct gar2navit *points;
+ struct gar2navit *polylines;
+ struct gar2navit *polygons;
+};
+
+struct gar2nav_conv *g2n_conv_load(char *file);
+enum item_type g2n_get_type(struct gar2nav_conv *c, int type, unsigned short id);
+char *g2n_get_descr(struct gar2nav_conv *c, int type, unsigned short id);
+int g2n_get_routable(struct gar2nav_conv *c, int type, unsigned short id);
diff --git a/data/garmin/garmin.c b/data/garmin/garmin.c
new file mode 100644
index 00000000..f30e3133
--- /dev/null
+++ b/data/garmin/garmin.c
@@ -0,0 +1,661 @@
+#include <glib.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "plugin.h"
+#include "data.h"
+#include "projection.h"
+#include "map.h"
+#include "maptype.h"
+#include "item.h"
+#include "attr.h"
+#include "coord.h"
+#include "transform.h"
+#include <stdio.h>
+#include "attr.h"
+#include "coord.h"
+#include <libgarmin.h>
+#include "garmin.h"
+#include "gar2navit.h"
+
+
+static int map_id;
+
+struct map_priv {
+ int id;
+ char *filename;
+ struct gar2nav_conv *conv;
+ struct gar *g;
+};
+
+struct map_rect_priv {
+ int id;
+ struct coord_rect r;
+ char *label; // FIXME: Register all strings for searches
+ int limit;
+ struct map_priv *mpriv;
+ struct gmap *gmap;
+ struct gobject *cobj;
+ struct gobject *objs;
+ struct item item;
+ unsigned int last_coord;
+ void *last_itterated;
+ struct coord last_c;
+ void *last_oattr;
+ unsigned int last_attr;
+};
+
+int garmin_debug = 10;
+void
+logfn(char *file, int line, int level, char *fmt, ...)
+{
+ va_list ap;
+ if (level > garmin_debug)
+ return;
+ va_start(ap, fmt);
+ fprintf(stdout, "%s:%d:%d|", file, line, level);
+ vfprintf(stdout, fmt, ap);
+ va_end(ap);
+}
+// need a base map and a map
+struct gscale {
+ char *label;
+ float scale;
+ int bits;
+};
+
+static struct gscale mapscales[] = {
+ {"7000 km", 70000.0, 8}
+ ,{"5000 km", 50000.0, 8}
+ ,{"3000 km", 30000.0, 9}
+ ,{"2000 km", 20000.0, 9}
+ ,{"1500 km", 15000.0, 10}
+ ,{"1000 km", 10000.0, 10}
+ ,{"700 km", 7000.0, 11}
+ ,{"500 km", 5000.0, 11}
+ ,{"300 km", 3000.0, 13}
+ ,{"200 km", 2000.0, 13}
+ ,{"150 km", 1500.0, 13}
+ ,{"100 km", 1000.0, 14}
+ ,{"70 km", 700.0, 15}
+ ,{"50 km", 500.0, 16}
+ ,{"30 km", 300.0, 16}
+ ,{"20 km", 200.0, 17}
+ ,{"15 km", 150.0, 17}
+ ,{"10 km", 100.0, 18}
+ ,{"7 km", 70.0, 18}
+ ,{"5 km", 50.0, 19}
+ ,{"3 km", 30.0, 19}
+ ,{"2 km", 20.0, 20}
+ ,{"1.5 km", 15.0, 22}
+ ,{"1 km", 10.0, 24}
+ ,{"700 m", 7.0, 24}
+ ,{"500 m", 5.0, 24}
+ ,{"300 m", 3.0, 24}
+ ,{"200 m", 2.0, 24}
+ ,{"150 m", 1.5, 24}
+ ,{"100 m", 1.0, 24}
+ ,{"70 m", 0.7, 24}
+ ,{"50 m", 0.5, 24}
+ ,{"30 m", 0.3, 24}
+ ,{"20 m", 0.2, 24}
+ ,{"15 m", 0.1, 24}
+ ,{"10 m", 0.15, 24}
+};
+
+
+static int
+garmin_object_label(struct gobject *o, struct attr *attr)
+{
+ struct map_rect_priv *mr = o->priv_data;
+ if (!mr) {
+ dlog(1, "Error object do not have priv_data!!\n");
+ return 0;
+ }
+ if (mr->label)
+ free(mr->label);
+ mr->label = gar_get_object_lbl(o);
+#warning FIXME Process label and give only the visible part
+ if (mr->label) {
+ char *cp = mr->label;
+ if (*mr->label == '@' || *mr->label == '^')
+ cp++;
+ attr->u.str = cp;
+ return 1;
+ }
+ return 0;
+}
+
+static int
+garmin_object_debug(struct gobject *o, struct attr *attr)
+{
+ struct map_rect_priv *mr = o->priv_data;
+ if (!mr) {
+ dlog(1, "Error object do not have priv_data!!\n");
+ return 0;
+ }
+ if (mr->label)
+ free(mr->label);
+ mr->label = gar_object_debug_str(o);
+ if (mr->label) {
+ attr->u.str = mr->label;
+ return 1;
+ }
+ return 0;
+}
+
+
+static struct map_search_priv *
+gmap_search_new(struct map_priv *map, struct item *item, struct attr *search, int partial)
+{
+ return NULL;
+}
+
+static void
+gmap_search_destroy(struct map_search_priv *ms)
+{
+}
+
+static struct item *
+gmap_search_get_item(struct map_search_priv *ms)
+{
+ return NULL;
+}
+
+
+/* Assumes that only one item will be itterated at time! */
+static void
+coord_rewind(void *priv_data)
+{
+ struct gobject *g = priv_data;
+ struct map_rect_priv *mr = g->priv_data;
+ mr->last_coord = 0;
+};
+
+static void
+attr_rewind(void *priv_data)
+{
+ struct gobject *g = priv_data;
+ struct map_rect_priv *mr = g->priv_data;
+ mr->last_attr = 0;
+};
+
+static int
+point_coord_get(void *priv_data, struct coord *c, int count)
+{
+ struct gobject *g = priv_data;
+ struct map_rect_priv *mr = g->priv_data;
+ struct gcoord gc;
+ if (!count)
+ return 0;
+ if (g != mr->last_itterated) {
+ mr->last_itterated = g;
+ mr->last_coord = 0;
+ }
+
+ if (mr->last_coord > 0)
+ return 0;
+
+ gar_get_object_coord(mr->gmap, g, &gc);
+ c->x = gc.x;
+ c->y = gc.y;
+ mr->last_coord++;
+// dlog(1,"point: x=%d y=%d\n", c->x, c->y);
+ // dlog(1, "point: x=%f y=%f\n", GARDEG(c->x), GARDEG(c->y));
+ return 1;
+}
+
+static int
+poly_coord_get(void *priv_data, struct coord *c, int count)
+{
+ struct gobject *g = priv_data;
+ struct map_rect_priv *mr = g->priv_data;
+ int ndeltas = 0, total = 0;
+ struct gcoord dc;
+
+ if (!count)
+ return 0;
+
+ if (g != mr->last_itterated) {
+ mr->last_itterated = g;
+ mr->last_coord = 0;
+ }
+ ndeltas = gar_get_object_deltas(g);
+ if (mr->last_coord > ndeltas + 1)
+ return 0;
+ while (count --) {
+ if (mr->last_coord == 0) {
+ gar_get_object_coord(mr->gmap, g, &dc);
+ mr->last_c.x = dc.x;
+ mr->last_c.y = dc.y;
+ } else {
+ if (!gar_get_object_dcoord(mr->gmap, g, mr->last_coord - 1, &dc)) {
+ mr->last_coord = ndeltas + 2;
+ return total;
+ }
+ mr->last_c.x += dc.x;
+ mr->last_c.y += dc.y;
+ }
+ c->x = mr->last_c.x;
+ c->y = mr->last_c.y;
+ ddlog(1, "poly: x=%f y=%f\n", GARDEG(c->x), GARDEG(c->y));
+// dlog(1,"poly: x=%d y=%d\n", c->x, c->y);
+ c++;
+ total++;
+ total++;
+ mr->last_coord ++;
+ }
+ return total;
+}
+
+// for _any we must return one by one
+static int
+point_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
+{
+ struct gobject *g = priv_data;
+ struct map_rect_priv *mr = g->priv_data;
+ int rc;
+ switch (attr_type) {
+ case attr_any:
+ if (g != mr->last_oattr) {
+ mr->last_oattr = g;
+ mr->last_attr = 0;
+ }
+ switch(mr->last_attr) {
+ case 0:
+ mr->last_attr++;
+ attr->type = attr_label;
+ rc = garmin_object_label(g, attr);
+ if (rc)
+ return rc;
+ case 1:
+ mr->last_attr++;
+ attr->type = attr_debug;
+ rc = garmin_object_debug(g, attr);
+ if (rc)
+ return rc;
+ default:
+ return 0;
+ }
+ break;
+ case attr_label:
+ attr->type = attr_label;
+ return garmin_object_label(g, attr);
+ case attr_limit:
+ return 0;
+ default:
+ dlog(1, "Dont know about attribute %d[%04X]=%s yet\n", attr_type,attr_type, attr_to_name(attr_type));
+ }
+
+ return 0;
+}
+
+static struct item_methods methods_garmin_point = {
+ coord_rewind,
+ point_coord_get,
+ attr_rewind,
+ point_attr_get,
+};
+
+static struct item_methods methods_garmin_poly = {
+ coord_rewind,
+ poly_coord_get,
+ attr_rewind, // point_attr_rewind,
+ point_attr_get, // poly_attr_get,
+};
+
+static struct item *
+garmin_poi2item(struct map_rect_priv *mr, struct gobject *o, unsigned char otype)
+{
+ int subtype;
+
+ subtype = gar_object_subtype(o);
+ mr->item.id_hi = otype << 8 | subtype;
+ if (mr->mpriv->conv)
+ mr->item.type = g2n_get_type(mr->mpriv->conv, G2N_POINT, mr->item.id_hi);
+ mr->item.meth = &methods_garmin_point;
+ return &mr->item;
+}
+
+static struct item *
+garmin_pl2item(struct map_rect_priv *mr, struct gobject *o, unsigned char otype)
+{
+ mr->item.id_hi = otype;
+ if (mr->mpriv->conv)
+ mr->item.type = g2n_get_type(mr->mpriv->conv, G2N_POLYLINE, otype);
+ mr->item.meth = &methods_garmin_poly;
+ return &mr->item;
+}
+
+static struct item *
+garmin_pg2item(struct map_rect_priv *mr, struct gobject *o, unsigned char otype)
+{
+ mr->item.id_hi = otype;
+ if (mr->mpriv->conv)
+ mr->item.type = g2n_get_type(mr->mpriv->conv, G2N_POLYGONE, otype);
+ mr->item.meth = &methods_garmin_poly;
+ return &mr->item;
+}
+
+static struct item *
+garmin_obj2item(struct map_rect_priv *mr, struct gobject *o)
+{
+ unsigned char otype;
+ otype = gar_obj_type(o);
+ mr->item.type = type_none;
+ switch (o->type) {
+ case GO_POINT:
+ case GO_POI:
+ return garmin_poi2item(mr, o, otype);
+ case GO_POLYLINE:
+ return garmin_pl2item(mr, o, otype);
+ case GO_POLYGON:
+ return garmin_pg2item(mr, o, otype);
+ default:
+ dlog(1, "Unknown garmin object type:%d\n",
+ o->type);
+ }
+ return NULL;
+}
+
+static struct item *
+gmap_rect_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
+{
+ struct gobject *o;
+ o = mr->objs = gar_get_object(mr->mpriv->g, (void *)id_lo);
+ if (!o) {
+ dlog(1, "Can not find object\n");
+ return NULL;
+ }
+
+ mr->item.id_hi = (int)mr;
+ mr->item.id_lo = (int)o->gptr;
+ mr->item.priv_data = o;
+ mr->item.type = type_none;
+ o->priv_data = mr;
+ if (!garmin_obj2item(mr, o))
+ return NULL;
+ return &mr->item;
+}
+
+static struct item *
+gmap_rect_get_item(struct map_rect_priv *mr)
+{
+ struct gobject *o;
+ if (!mr->objs)
+ return NULL;
+ if (!mr->cobj)
+ return NULL;
+ // mr->cobj = mr->objs;
+ o = mr->cobj;
+// dlog(1, "gi:o=%p\n", o);
+ mr->cobj = mr->cobj->next;
+ if (o) {
+ mr->item.id_hi = (int)mr;
+ mr->item.id_lo = (int)o->gptr;
+ mr->item.priv_data = o;
+ mr->item.type = type_none;
+ o->priv_data = mr;
+ if (!garmin_obj2item(mr, o))
+ return NULL;
+ return &mr->item;
+ }
+ return NULL;
+}
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+struct nl2gl_t {
+ int g;
+ int bits;
+ char *descr;
+};
+
+struct nl2gl_t nl2gl_1[] = {
+ { /* 0 */ .g = 12, .descr = "0-120m", },
+ { /* 1 */ .g = 11, .descr = "0-120m", },
+ { /* 2 */ .g = 10, .descr = "0-120m", },
+ { /* 3 */ .g = 9, .descr = "0-120m", },
+ { /* 4 */ .g = 8, .descr = "0-120m", },
+ { /* 5 */ .g = 7, .descr = "0-120m", },
+ { /* 6 */ .g = 6, .descr = "0-120m", },
+ { /* 7 */ .g = 5, .descr = "0-120m", },
+ { /* 8 */ .g = 4, .descr = "0-120m", },
+ { /* 9 */ .g = 4, .descr = "0-120m", },
+ { /* 10 */ .g = 3, .descr = "0-120m", },
+ { /* 11 */ .g = 3, .descr = "0-120m", },
+ { /* 12 */ .g = 2, .descr = "0-120m", },
+ { /* 13 */ .g = 2, .descr = "0-120m", },
+ { /* 14 */ .g = 2, .descr = "0-120m", },
+ { /* 15 */ .g = 1, .descr = "0-120m", },
+ { /* 16 */ .g = 1, .descr = "0-120m", },
+ { /* 17 */ .g = 1, .descr = "0-120m", },
+ { /* 18 */ .g = 0, .descr = "0-120m", },
+};
+
+struct nl2gl_t nl2gl[] = {
+ { /* 0 */ .g = 9, .descr = "0-120m", },
+ { /* 1 */ .g = 9, .descr = "0-120m", },
+ { /* 2 */ .g = 8, .descr = "0-120m", },
+ { /* 3 */ .g = 8, .descr = "0-120m", },
+ { /* 4 */ .g = 7, .descr = "0-120m", },
+ { /* 5 */ .g = 7, .descr = "0-120m", },
+ { /* 6 */ .g = 6, .descr = "0-120m", },
+ { /* 7 */ .g = 6, .descr = "0-120m", },
+ { /* 8 */ .g = 5, .descr = "0-120m", },
+ { /* 9 */ .g = 5, .descr = "0-120m", },
+ { /* 10 */ .g = 4, .descr = "0-120m", },
+ { /* 11 */ .g = 4, .descr = "0-120m", },
+ { /* 12 */ .g = 3, .descr = "0-120m", },
+ { /* 13 */ .g = 3, .descr = "0-120m", },
+ { /* 14 */ .g = 2, .descr = "0-120m", },
+ { /* 15 */ .g = 2, .descr = "0-120m", },
+ { /* 16 */ .g = 1, .descr = "0-120m", },
+ { /* 17 */ .g = 1, .descr = "0-120m", },
+ { /* 18 */ .g = 0, .descr = "0-120m", },
+};
+
+static int
+get_level(struct map_selection *sel)
+{
+ int l;
+ l = max(sel->order[layer_town], sel->order[layer_street]);
+ l = max(l, sel->order[layer_poly]);
+ return l;
+}
+
+static int
+garmin_get_selection(struct map_rect_priv *map, struct map_selection *sel)
+{
+ struct gar_rect r;
+ struct gmap *gm;
+ struct gobject **glast = NULL;
+ int rc;
+ int sl, el;
+ int level = 0; // 18; /* max level for maps, overview maps can have bigger
+ /* levels we do not deal w/ them
+ */
+ int flags = 0;
+ if (sel && sel->order[layer_town] == 0 && sel->order[layer_poly] == 0
+ && sel->order[layer_street]) {
+ // Get all roads
+ flags = GO_GET_ROUTABLE;
+ } else if (sel)
+ flags = GO_GET_SORTED;
+
+ if (sel) {
+ r.lulat = sel->rect.lu.y;
+ r.lulong = sel->rect.lu.x;
+ r.rllat = sel->rect.rl.y;
+ r.rllong = sel->rect.rl.x;
+ level = get_level(sel);
+// level = nl2gl[level].g;
+ printf("Looking level=%d for %f %f %f %f\n",
+ level, r.lulat, r.lulong, r.rllat, r.rllong);
+ }
+ gm = gar_find_subfiles(map->mpriv->g, sel ? &r : NULL);
+ if (!gm) {
+ dlog(1, "Can not find map data\n");
+ return -1;
+ }
+#if 0
+ sl = (18-(gm->maxlevel - gm->minlevel))/2;
+ el = sl + (gm->maxlevel - gm->minlevel);
+ if (level < sl)
+ level = sl;
+ if (level > el)
+ level = el;
+ level = level - sl;
+ level = (gm->maxlevel - gm->minlevel) - level;
+ dlog(1, "sl=%d el=%d level=%d\n", sl, el, level);
+#endif
+ sl = (18-gm->zoomlevels)/2;
+ el = sl + gm->zoomlevels;
+ if (level < sl)
+ level = sl;
+ if (level > el)
+ level = el;
+ level = level - sl;
+ level = gm->basebits + level;
+ dlog(1, "sl=%d el=%d level=%d\n", sl, el, level);
+ map->gmap = gm;
+ glast = &map->objs;
+ while (*glast) {
+ if ((*glast)->next) {
+ *glast = (*glast)->next;
+ } else
+ break;
+ }
+ rc = gar_get_objects(gm, level, sel ? &r : NULL, glast, flags);
+ if (rc < 0) {
+ dlog(1, "Error loading objects\n");
+ return -1;
+ }
+ map->cobj = map->objs;
+ dlog(1, "Loaded %d objects\n", rc);
+ return rc;
+}
+// Can not return NULL, navit segfaults
+static struct map_rect_priv *
+gmap_rect_new(struct map_priv *map, struct map_selection *sel)
+{
+ struct map_selection *ms = sel;
+ struct map_rect_priv *mr;
+
+ mr = calloc(1, sizeof(*mr));
+ if (!mr)
+ return mr;
+ mr->mpriv = map;
+ if (!sel) {
+ return mr;
+ } else {
+ while (ms) {
+ dlog(1, "order town:%d street=%d poly=%d\n",
+ ms->order[layer_town],
+ ms->order[layer_street],
+ ms->order[layer_poly]);
+ if (garmin_get_selection(mr, ms) < 0) {
+ // free(mr);
+ // return NULL;
+ }
+ ms = ms->next;
+ }
+ }
+ return mr;
+}
+
+static void
+gmap_rect_destroy(struct map_rect_priv *mr)
+{
+ dlog(11,"destroy maprect\n");
+ if (mr->gmap)
+ gar_free_gmap(mr->gmap);
+ if (mr->objs)
+ gar_free_objects(mr->objs);
+ if (mr->label)
+ free(mr->label);
+ free(mr);
+}
+
+static void
+gmap_destroy(struct map_priv *m)
+{
+ dlog(1, "garmin_map_destroy\n");
+ if (m->g)
+ gar_free(m->g);
+ if (m->filename)
+ free(m->filename);
+ free(m);
+}
+
+static struct map_methods map_methods = {
+ projection_garmin,
+ NULL,
+// "iso8859-1", // update from the map
+ gmap_destroy, //
+ gmap_rect_new,
+ gmap_rect_destroy,
+ gmap_rect_get_item,
+ gmap_rect_get_item_byid,
+ gmap_search_new,
+ gmap_search_destroy,
+ gmap_search_get_item,
+};
+
+static struct map_priv *
+gmap_new(struct map_methods *meth, struct attr **attrs)
+{
+ struct map_priv *m;
+ struct attr *data;
+ char buf[PATH_MAX];
+
+ data=attr_search(attrs, NULL, attr_data);
+ if (! data)
+ return NULL;
+ m=g_new(struct map_priv, 1);
+ m->id=++map_id;
+ m->filename = strdup(data->u.str);
+ if (!m->filename) {
+ g_free(m);
+ return NULL;
+ }
+ m->g = gar_init(NULL, logfn);
+ if (!m->g) {
+ g_free(m->filename);
+ g_free(m);
+ return NULL;
+ }
+ // we want the data now, later we can load only what's necessery
+ if (gar_img_load(m->g, m->filename, 1) < 0) {
+ gar_free(m->g);
+ g_free(m->filename);
+ g_free(m);
+ return NULL;
+ }
+ snprintf(buf, sizeof(buf), "%s.types", m->filename);
+ dlog(1, "Looking for types in %s\n", buf);
+ m->conv = g2n_conv_load(buf);
+ if (!m->conv) {
+ char *cp;
+ strcpy(buf, m->filename);
+ cp = strrchr(buf ,'/');
+ if (cp) {
+ cp ++;
+ *cp = '\0';
+ strcat(buf, "garmintypes.txt");
+ dlog(1, "Looking for types in %s\n", buf);
+ m->conv = g2n_conv_load(buf);
+ }
+ }
+ if (!m->conv) {
+ dlog(1, "Failed to load map types\n");
+ }
+ *meth=map_methods;
+ return m;
+}
+
+void
+plugin_init(void)
+{
+ plugin_register_map_type("garmin", gmap_new);
+}
diff --git a/data/garmin/garmin.h b/data/garmin/garmin.h
new file mode 100644
index 00000000..50935b05
--- /dev/null
+++ b/data/garmin/garmin.h
@@ -0,0 +1,10 @@
+#define dlog(x,y ...) logfn(__FILE__,__LINE__,x, ##y)
+#ifdef HARDDEBUG
+#define ddlog(x,y ...) logfn(__FILE__,__LINE__,x, ##y)
+#else
+#define ddlog(x,y ...)
+#endif
+
+extern int garmin_debug;
+void logfn(char *file, int line, int level, char *fmt, ...);
+
diff --git a/data/garmin/garmintypes.txt b/data/garmin/garmintypes.txt
new file mode 100644
index 00000000..be6054c8
--- /dev/null
+++ b/data/garmin/garmintypes.txt
@@ -0,0 +1,412 @@
+#
+#
+#
+POINT
+0x0000 = label_unkn, Unknown label
+0x0100 = town_label_1e5, Megapolis (10M +)
+0x0200 = town_label_5e4, Megapolis (5-10M)
+0x0300 = town_label_2e4, Big City (2-5M)
+0x0400 = town_label_1e4, Big City (1-2M)
+0x0500 = town_label_5e3, Big City (0.5-1M)
+0x0600 = town_label_2e3, City (200-500k)
+0x0700 = town_label_1e3, City (100-200k)
+0x0800 = town_label_5e2, City (50-100k)
+0x0900 = town_label_2e2, City (20-50k)
+0x0a00 = town_label_1e2, City (10-20k)
+0x0b00 = town_label_5e1, Small City (5-10k)
+0x0c00 = town_label_2e1, Small City (2-5k)
+0x0d00 = town_label_1e1, Village (1-2k)
+0x0e00 = town_label_5e0, Village (500-1000)
+0x0f00 = town_label_2e0, Village (200-500)
+0x1000 = town_label_1e0, Village (100-200)
+0x1100 = town_label_0e0, Village (0-100)
+
+0x1200 = port_label, Port with services
+0x1300 = label_unkn, Unknown label2
+0x1400-0x14FF = country_label, Large Country Name
+0x1500-0x15FF = country_label, Country Name
+0x1c00 = poi_wreck, Unclassified Obstruction
+0x1c01 = poi_wreck, Wreck
+0x1c02 = poi_dangerous, submerged wreck, dangerous
+0x1c03 = poi_nondangerous, submerged wreck, non-dangerous
+0x1c04 = poi_wreck, Wreck, cleared by wire drag
+0x1c05 = poi_rock, Obstruction, visible at high water
+0x1c06 = poi_rock, Obstruction, awash
+0x1c07 = poi_rock, Obstruction, submerged
+0x1c08 = poi_rock, Obstruction, cleared by wire drag
+0x1c09 = poi_rock, Rock, awash
+0x1c0a = poi_rock, Rock, submerged at low Water
+0x1c0b = poi_sounding, Sounding
+0x1d00 = poi_tide, Tide Prediction
+
+0x1e00-0x1e3f = district_label, District, Province, State Name
+0x1f00 = district_label_0e0, Region, District Name
+
+# Fixme if it has label how to change to highway_exit_with_label ??
+0x2000-0x203F = highway_exit, Exit
+0x2100-0x213F = highway_exit, Exit with Services
+0x2200-0x223F = highway_exit, Exit with Restroom
+0x2300-0x233F = highway_exit, Exit with Convinience Store
+0x2400-0x243F = highway_exit, Exit with Weight Station
+0x2500-0x253F = highway_exit, Exit with Toolbooth Booth
+0x2600-0x263F = highway_exit, Exit with Information
+0x2700-0x273F = highway_exit, Exit
+
+0x2800-0x283F = district_label_1e0, Region Name
+
+0x2900 = poi_public_utilities, Services
+
+0x2A00 = poi_dining, Dining(Other)
+0x2A01 = poi_dining, Dining(American)
+0x2A02 = poi_dining, Dining(Asian)
+0x2A03 = poi_dining, Dining(Barbecue)
+0x2A04 = poi_dining, Dining(Chinese)
+0x2A05 = poi_dining, Dining(Deli/Bakery)
+0x2A06 = poi_dining, Dining(International)
+0x2A07 = poi_fastfood, Fast Food
+0x2A08 = poi_dining, Dining(Italian)
+0x2A09 = poi_dining, Dining(Mexican)
+0x2A0A = poi_dining, Dining(Pizza)
+0x2A0B = poi_dining, Dining(Sea Food)
+0x2A0C = poi_dining, Dining(Steak/Grill)
+0x2A0D = poi_dining, Dining(Bagel/Donut)
+0x2A0E = poi_dining, Dining(Cafe/Diner)
+0x2A0F = poi_dining, Dining(French)
+0x2A10 = poi_dining, Dining(German)
+0x2A11 = poi_dining, Dining(British Isles)
+0x2A12 = poi_dining, Dining(Special Foods)
+
+0x2B00 = poi_hotel, Hotel(Other)
+0x2B01 = poi_hotel, Hotel/Motel
+0x2B02 = poi_hotel, Bed & Breakfast inn
+0x2B03 = poi_camp_rv, Camping/RV-Park
+0x2B04 = poi_resort, Resort
+
+0x2C00 = poi_attraction, Amusement Park
+0x2C01 = poi_attraction, Amusement Park
+0x2C02 = poi_museum_history, Museum/History
+0x2C03 = poi_library, Libraries
+0x2C04 = poi_landmark, Land Mark
+0x2C05 = poi_school, School
+0x2C06 = poi_park, Park
+0x2C07 = poi_zoo, Zoo
+0x2C08 = poi_stadium, Sportpark, Stadium,(point)
+0x2C09 = poi_fair, Fair, Conference(point)
+0x2C0A = poi_wine, Wine restaurant(point)
+0x2C0B = poi_worship, Place of Worship
+0x2C0C = poi_hotspring, Hot Spring
+
+0x2D00 = poi_theater, Theater
+0x2D01 = poi_theater, Theater
+0x2D02 = poi_bar, Bar
+0x2D03 = poi_cinema, Cinema
+0x2D04 = poi_casino, Casino
+0x2D05 = poi_golf, Golf
+0x2D06 = poi_skiing, Skiing Center
+0x2D07 = poi_bowling, Bowling
+0x2D08 = poi_icesport, Ice/Sporting
+0x2D09 = poi_swimming, Swimming
+0x2D0A = poi_sport, Sports(point)
+0x2D0B = poi_sailing, Sailing Airport
+
+0x2E00 = poi_shopping, Shoping general
+0x2E01 = poi_shop_department, Department Store
+0x2E02 = poi_shop_grocery, Grocery
+0x2E03 = poi_shop_merchandise, General Merchandiser
+0x2E04 = poi_mall, Shopping Center
+0x2E05 = poi_pharmacy, Pharmacy
+0x2E06 = poi_shopping, Convenience
+0x2E07 = poi_shop_apparel, Apparel
+0x2E08 = poi_shop_handg, House and Garden
+0x2E09 = poi_shop_furnish, Home Furnishing
+0x2E0a = poi_shop_retail, Special Retail
+0x2E0b = poi_shop_computer, Computer/Software
+
+0x2F00 = poi_service, generic service
+0x2F01 = poi_fuel, Fuel/Gas
+0x2F02 = poi_car_rent, Car Rental
+0x2F03 = poi_autoservice, Car Repair
+0x2F04 = poi_airport, Airport
+0x2F05 = poi_post, Post Office
+0x2F06 = poi_bank, Bank
+0x2F07 = poi_car_dealer_parts, Car Dealer(point)
+0x2F08 = poi_bus_station, Bus Station
+0x2F09 = poi_marina, Marina
+0x2F0A = poi_wrecker, Wrecker Service
+0x2F0B = poi_car_parking, Parking
+0x2F0C = poi_rest_room, Restroom
+0x2F0D = poi_auto_club, Automobile Club
+0x2F0E = poi_car_wash, Car Wash
+0x2F0F = poi_garmin, Garmin Dealer
+0x2F10 = poi_personal_service, Personal Service
+0x2F11 = poi_bussines_service, Business Service
+0x2F12 = poi_communication, Communication
+0x2F13 = poi_repair_service, Repair Service
+0x2F14 = poi_social_service, Social Service
+0x2F15 = poi_public_utilities, Utility
+0x2F16 = poi_truck_stop, Truck Stop
+0x2F17 = poi_bus_stop, Bus Stop
+
+0x3000 = poi_emergency, generic emergency/government
+0x3001 = poi_police, Police Station
+0x3002 = poi_hospital, Hospital
+0x3003 = poi_public_office, Public Office
+0x3004 = poi_justice, Justice
+0x3005 = poi_concert, Concert hall(point)
+0x3006 = poi_border_station, Border Station(point)
+0x3007 = poi_goverment_building, Goverment Building
+0x3008 = poi_firebrigade, FireFighters Station
+
+0x4000-0x403F = poi_golf, Golf
+0x4100-0x413F = poi_fish, Fish
+0x4200-0x423F = poi_wreck, Wreck
+0x4300-0x433F = poi_marina, Marina
+0x4400-0x443F = poi_fuel, Gas
+0x4500-0x453F = poi_restaurant, Restaurant
+0x4600-0x463F = poi_bar, Bar
+0x4700-0x473F = poi_boat_ramp, Boat Ramp
+0x4800-0x483F = poi_camping, Camping
+0x4900-0x493F = poi_park, Park
+0x4A00-0x4A3F = poi_picnic, Picnic Area
+0x4B00-0x4B3F = poi_hospital, Hospital
+0x4C00-0x4C3F = poi_information, Information
+0x4D00-0x4D3F = poi_car_parking, Parking
+0x4E00-0x4E3F = poi_restroom, Restroom
+0x4F00-0x4F3F = poi_shower, Shower
+0x5000-0x503F = poi_drinking_water, Drinking Water
+0x5100-0x513F = poi_telephone, Telephone
+0x5200-0x523F = poi_scenic_area, Scenic Area
+0x5300-0x533F = poi_skiing, Skiing
+0x5400-0x543F = poi_swimming, Swimming
+0x5500-0x553F = poi_dam, Dam
+
+0x5600-0x563F = poi_forbiden_area, Forbiden Area
+0x5700-0x573F = poi_danger_area, Danger Area
+0x5800-0x583F = poi_restricted_area, Restricted Area
+
+0x5900 = poi_airport, Generic Airport
+0x5901 = poi_airport, Large Airport
+0x5902 = poi_airport, Medium Airport
+0x5903 = poi_airport, Small Airport
+0x5904 = poi_heliport, Heliport
+0x5905-0x593F = poi_airport, Airport
+
+0x5a00 = poi_mark, Kilometer Pole
+0x5b00 = poi_mark, Kolokol
+0x5c00 = poi_diving, Diving Place
+
+0x5D00-0x5D3F = poi_daymark, Daymark,Green Square
+0x5E00-0x5E3F = poi_daymark, Daymark,Red Triangle
+
+0x6000 = poi_loudspeaker, LoudSpeaker
+0x6100 = poi_building, House
+
+0x6200 = poi_height, Height with point in feet one decimal place
+0x6300 = poi_height, Height without point in feet no decimal place
+0x6400 = poi_manmade_feature, Manmade Feature
+0x6401 = poi_bridge, Bridge
+0x6402 = poi_building, Building
+0x6403 = poi_cemetery, Cemetery
+0x6404 = poi_church, Church
+0x6405 = poi_civil, Civil
+0x6406 = poi_crossing, Crossing
+0x6407 = poi_dam, Dam
+0x6408 = poi_hospital, Hospital
+0x6409 = poi_levee, Levee
+0x640A = poi_locale, Locale
+0x640B = poi_military, Military
+0x640C = poi_mine, Mine
+0x640D = poi_oil_field, Oil Field
+0x640E = poi_park, Park
+0x640F = poi_post, Post
+0x6410 = poi_school, School
+0x6411 = poi_tower, Tower
+0x6412 = poi_trail, Trail
+0x6413 = poi_tunnel, Tunnel
+0x6414 = poi_drinking_water, Drink water
+0x6415 = town_ghost, Ghost Town
+0x6416 = poi_subdivision, Subdivision
+
+0x6500 = poi_water_feature, Water Feature
+0x6501 = poi_water_feature, Arroyo
+0x6502 = poi_water_feature, Sand Bar
+0x6503 = poi_bay, Bay
+0x6504 = poi_bend, Bend
+0x6505 = poi_water_feature, Canal
+0x6506 = poi_water_feature, Channel
+0x6507 = poi_cove, Cove
+0x6508 = poi_water_feature, Falls
+0x6509 = poi_water_feature, Geyser
+0x650A = poi_water_feature, Glacier
+0x650B = poi_marine, Harbour
+0x650C = poi_island, Island
+0x650D = poi_water_feature, Lake
+0x650E = poi_water_feature, Rapids
+0x650F = poi_water_feature, Reservoir
+0x6510 = poi_water_feature, Sea
+0x6511 = poi_water_feature, Spring
+0x6512 = poi_water_feature, Stream
+0x6513 = poi_water_feature, Swamp
+
+0x6600 = poi_land_feature, Land Feature
+0x6601 = poi_land_feature, Arch
+0x6602 = poi_land_feature, Area
+0x6603 = poi_land_feature, Basin
+0x6604 = poi_land_feature, Beach
+0x6605 = poi_land_feature, Bench
+0x6606 = poi_land_feature, Cape
+0x6607 = poi_land_feature, Cliff
+0x6608 = poi_land_feature, Crater
+0x6609 = poi_land_feature, Flat
+0x660A = poi_land_feature, Forest
+0x660B = poi_land_feature, Gap
+0x660C = poi_land_feature, Gut
+0x660D = poi_land_feature, Isthmus
+0x660E = poi_land_feature, Lava
+0x660F = poi_land_feature, Pillar
+0x6610 = poi_land_feature, Plain
+0x6611 = poi_land_feature, Range
+0x6612 = poi_land_feature, Reserve
+0x6613 = poi_land_feature, Ridge
+0x6614 = poi_land_feature, Rock
+0x6615 = poi_land_feature, Slope
+0x6616 = poi_land_feature, Summit
+0x6617 = poi_land_feature, Valley
+0x6618 = poi_land_feature, Woods
+
+# This are dublicated to 0x1700, 0x1800, 0x1900, 0x1A00, 0x1B00
+# fix them if you need them
+0x1600 = poi_marine_type, Beakon
+0x1601 = poi_marine_type, Fog Horn
+0x1602 = poi_marine_type, Radio Beacon
+0x1603 = poi_marine_type, Racon
+0x1604 = poi_marine_type, Day Beacon, red triangle
+0x1605 = poi_marine_type, Day Beacon, green square
+0x1606 = poi_marine_type, Day Beacon, white diamond
+0x1607 = poi_marine_type, unlit Navaid, white
+0x1608 = poi_marine_type, unlit Navaid, red
+0x1609 = poi_marine_type, unlit Navaid, green
+0x160a = poi_marine_type, unlit Navaid, black
+0x160b = poi_marine_type, unlit Navaid, yellow or amber
+0x160c = poi_marine_type, unlit Navaid, orange
+0x160d = poi_marine_type, unlit Navaid, multi colored
+0x160e = poi_marine_type, Navaid, unknown
+0x160f = poi_marine_type, lighted Navaid, white
+0x1610 = poi_marine_type, lighted Navaid, red
+0x1611 = poi_marine_type, lighted Navaid, green
+0x1612 = poi_marine_type, lighted Navaid, yellow or amber
+0x1613 = poi_marine_type, lighted Navaid, orange
+0x1614 = poi_marine_type, lighted Navaid, violet
+0x1615 = poi_marine_type, lighted Navaid, blue
+0x1616 = poi_marine_type, lighted Navaid, multi colored
+
+#
+# Street's are routable by:
+# ALL - by all
+# W pedestrian
+# B bycycle
+# M motorcycle
+# C car
+# T truck
+# L largetruck
+# this is probably, encoded into the map
+
+POLYLINE
+0x00 = ALL, street_1_land, Road
+0x01 = MCTL, highway_land, Major HWY thick
+0x02 = MCTL, street_4_land, Principal HWY-thick
+0x03 = MCTL, street_2_land, Principal HWY-medium
+0x04 = MCTL, street_3_city, Arterial Road-medium
+0x05 = MCTL, street_4_city, Arterial Road-thick
+0x06 = MCTL, street_2_city, Road-thin
+0x07 = MCTL, street_1_city, Alley-thick
+0x08 = MCTL, ramp, Ramp
+0x09 = MCTL, ramp, Ramp highspeed
+0x0a = MCTL, street_0, Unpaved Road-thin
+0x0b = MCTL, ramp, Major HWY Connector-thick
+0x0c = MCTL, roundabout, Roundabout
+0x0d = MCTL, street_unkn, Reservation/Zapovednik?
+0x0e = MCTL, street_unkn, Unknown Element 0x0e
+0x0f = NONE, street_unkn, Unknown Element 0x0f
+0x10 = NONE, street_unkn, Unknown Element 0x10
+0x11 = NONE, street_unkn, Unknown Element 0x11
+0x12 = NONE, street_unkn, Unknown Element 0x12
+0x13 = NONE, street_unkn, Unknown Element 0x13
+0x14 = NONE, rail, Railroad
+0x15 = NONE, water_line, Shoreline
+0x16 = W, street_nopass, Trail
+0x18 = NONE, water_line, Stream-thin
+0x19 = NONE, time_zone, Time-Zone
+0x1a = ALL, ferry, Ferry
+0x1b = ALL, ferry, Ferry
+0x1c = NONE, border_country, Political Boundary
+0x1d = NONE, border_country, County Boundary
+0x1e = NONE, border_country, Intl. Boundary
+0x1f = NONE, water_line, River
+0x20 = NONE, height_line_1, Land Contour (thin) Height in feet
+0x21 = NONE, height_line_2, Land Contour (medium) Height in feet
+0x22 = NONE, height_line_3, Land Contour (thick) Height in feet
+0x23 = NONE, depth_line_1, Depth Contour (thin) Depth in feet
+0x24 = NONE, depth_line_2, Depth Contour (medium) Depth in feet
+0x25 = NONE, depth_line_3, Depth Contour (thick) Depth in feet
+0x26 = NONE, water_line, Intermittent River
+0x27 = NONE, street_nopass, Airport Runway
+0x28 = NONE, pipeline, Pipeline
+0x29 = NONE, powerline, Powerline
+0x2a = NONE, marine_boundary, Marine Boundary (no line)
+0x2b = NONE, marine_hazard, Marine Hazard (no line)
+
+POLYGONE
+0x01 = town_poly, City (>200k)
+0x02 = town_poly, City (<200k)
+0x03 = town_poly, Village
+0x04 = military_zone, Military
+0x05 = parking_lot_poly, Parking Lot
+0x06 = parking_lot_poly, Parking Garage
+0x07 = airport_poly, Airport
+0x08 = commercial_center, Shopping Center
+0x09 = marine_poly, Marina
+0x0a = university, University/College
+0x0b = hospital_poly, Hospital
+0x0c = industry_poly, Industrial
+0x0d = area, Reservation
+0x0e = airport_poly, Airport Runway
+0x13 = area_unspecified, Man made area
+0x14 = park_poly, National park
+0x15 = park_poly, National park
+0x16 = park_poly, National park
+0x17 = park_poly, City Park
+0x18 = golf_course, Golf
+0x19 = sport_poly, Sport
+0x1a = cemetery_poly, Cemetery
+0x1e = park_poly, State Park
+0x1f = park_poly, State Park
+0x20 = park_poly, State Park
+0x28 = water_poly, Ocean
+0x29 = water_poly, Water Reservour
+0x32 = water_poly, Sea
+0x3b = water_poly, Water Reservour
+0x3c = water_poly, Lake (250-600 km2)
+0x3d = water_poly, Lake (77-250 km2)
+0x3e = water_poly, Lake (25-77 km2)
+0x3f = water_poly, Lake (11-25 km2)
+0x40 = water_poly, Lake (0.25-11 km2)
+0x41 = water_poly, Lake (<0.25 km2)
+0x42 = water_poly, Lake (>3.3k km2)
+0x43 = water_poly, Lake (1.1-3.3k km2)
+0x44 = water_poly, Lake (0.6-1.1k km2)
+0x45 = water_poly, Water Reservour
+0x46 = water_poly, River (>1km)
+0x47 = water_poly, River (200m-1km)
+0x48 = water_poly, River (40-200m)
+0x49 = water_poly, River (<40m)
+0x4a = area, Definition Area
+0x4b = area, Background
+0x4c = water_poly, Intermittent River/Lake
+0x4d = water_poly, Glaciers
+0x4e = plantation, Orchard or plantation
+0x4f = scrub, Scrub
+0x50 = wood, Woods
+0x51 = water_poly, Wetland
+0x52 = tundra, Tundra
+0x53 = flats, Flats