From: Kaj-Michael Lang Date: Thu, 25 Oct 2007 20:49:15 +0000 (+0300) Subject: Add more POI types (shops). Try to set way isin. Use a hash table for way tags. X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=7aaee0233616c3d8848515f4959bb648976dcc2c;p=mapper Add more POI types (shops). Try to set way isin. Use a hash table for way tags. --- diff --git a/src/osm.c b/src/osm.c index cb80301..cb2869a 100644 --- a/src/osm.c +++ b/src/osm.c @@ -17,6 +17,22 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ + +/* + * Utility to read OSM planet XML file and store it in a sqlite3 database. + * Reads in all nodes (if used, skips nodes outside bounding box) + * Special POI nodes are stored in POI table. + * Place POI nodes are stored in place table. + * + * Ways are read in and their data (name, type, etc) are stored + * in way, way_name and way_ref tables. + * + * Nodes used by they ways are stored in way_n2n table. + * + * ... + * + */ + #define _GNU_SOURCE #include @@ -36,7 +52,9 @@ #include "osm.h" #include "latlon.h" -/* #define VERBOSE */ +#if 0 +#define VERBOSE +#endif /* #define VERBOSE_KEYS */ #define FILE_BUFFER 65535 @@ -77,6 +95,7 @@ struct _node { node_data *data; }; +/* Way data structure */ typedef struct _way_data way_data; struct _way_data { gchar *name; @@ -98,6 +117,7 @@ struct _way { GSList *nodes; }; +/* XML tag IDs */ typedef enum { START, IN_OSM_TAG, @@ -110,43 +130,92 @@ typedef enum { ERROR } tag_state_t; +/* Parent tag type */ typedef enum { IS_NONE, IS_NODE, IS_WAY } tag_parent_t; +/* Node types table */ +/* XXX: Add support for parent category */ struct _nodeinfo { gchar *k, *v; node_type_t type; } nodeinfo[] = { { "amenity", "fuel", NODE_AMENITY_FUEL }, + { "amenity", "parking", NODE_AMENITY_PARKING }, + { "amenity", "pub", NODE_AMENITY_PUB }, { "amenity", "biergarten", NODE_AMENITY_PUB }, { "amenity", "cafe", NODE_AMENITY_CAFE }, - { "amenity", "telephone", NODE_AMENITY_TELEPHONE }, - { "amenity", "toilets", NODE_AMENITY_WC }, { "amenity", "fast_food", NODE_AMENITY_FOOD }, { "amenity", "restaurant", NODE_AMENITY_FOOD }, - { "amenity", "parking", NODE_AMENITY_PARKING }, + + { "amenity", "telephone", NODE_AMENITY_TELEPHONE }, + { "amenity", "toilets", NODE_AMENITY_WC }, + { "amenity", "hospital", NODE_AMENITY_HOSPITAL }, { "amenity", "doctors", NODE_AMENITY_HOSPITAL }, { "amenity", "pharmacy", NODE_AMENITY_PHARMACY }, + { "amenity", "post_office", NODE_AMENITY_POST }, { "amenity", "post_box", NODE_AMENITY_POST_BOX }, + { "amenity", "cinema", NODE_AMENITY_CINEMA }, { "amenity", "theatre", NODE_AMENITY_THEATRE }, + { "amenity", "atm", NODE_AMENITY_ATM }, { "amenity", "bank", NODE_AMENITY_BANK }, + { "amenity", "police", NODE_AMENITY_POLICE }, { "amenity", "speed_trap", NODE_AMENITY_SPEEDCAM }, - { "amenity", "supermarket", NODE_AMENITY_SHOP }, - { "amenity", "shop", NODE_AMENITY_SHOP }, + { "amenity", "speed_camera", NODE_AMENITY_SPEEDCAM }, + { "amenity", "speed camera", NODE_AMENITY_SPEEDCAM }, + { "amenity", "place_of_worship",NODE_AMENITY_POW }, + { "amenity", "school", NODE_AMENITY_SCHOOL }, { "amenity", "college", NODE_AMENITY_COLLEGE }, { "amenity", "university", NODE_AMENITY_COLLEGE }, + { "amenity", "library", NODE_AMENITY_LIBRARY }, + { "amenity", "townhall", NODE_AMENITY_TOWNHALL }, + + { "amenity", "supermarket", NODE_AMENITY_SHOP }, + { "amenity", "shopping_centre", NODE_AMENITY_SHOP }, + { "amenity", "shop", NODE_AMENITY_SHOP }, + { "amenity", "shops", NODE_AMENITY_SHOP }, + { "amenity", "shopping", NODE_AMENITY_SHOP }, + { "amenity", "shopping_mall",NODE_AMENITY_SHOP }, + { "amenity", "cycle_shop", NODE_AMENITY_SHOP }, + { "amenity", "bike_shop", NODE_AMENITY_SHOP }, + { "amenity", "coffee_shop", NODE_AMENITY_SHOP }, + { "amenity", "indoor_shopping_centre", NODE_AMENITY_SHOP }, + { "amenity", "farm_shop", NODE_AMENITY_SHOP }, + { "amenity", "tea_shop", NODE_AMENITY_SHOP }, + + /* Shops */ + { "shop", "supermarket", NODE_AMENITY_SHOP }, + { "shop", "bakery", NODE_AMENITY_SHOP }, + { "shop", "alcohol", NODE_AMENITY_SHOP }, + { "shop", "butcher", NODE_AMENITY_SHOP }, + { "shop", "flowers", NODE_AMENITY_SHOP }, + { "shop", "clothing", NODE_AMENITY_SHOP }, + { "shop", "souvenir", NODE_AMENITY_SHOP }, + { "shop", "bicycles", NODE_AMENITY_SHOP }, + { "shop", "grocers", NODE_AMENITY_SHOP }, + { "shop", "newsagents", NODE_AMENITY_SHOP }, + { "shop", "convenience", NODE_AMENITY_SHOP }, + { "shop", "bakers", NODE_AMENITY_SHOP }, + { "shop", "garden_centre",NODE_AMENITY_SHOP }, + { "shop", "photography", NODE_AMENITY_SHOP }, + { "shop", "general_store",NODE_AMENITY_SHOP }, + { "shop", "food", NODE_AMENITY_SHOP }, + { "shop", "drinks", NODE_AMENITY_SHOP }, + { "shop", "pharmacy", NODE_AMENITY_PHARMACY }, + + /* Sport */ { "sport" , "swimming", NODE_SPORT_SWIMMING }, { "sport" , "golf", NODE_SPORT_GOLF }, { "sport" , "tennis", NODE_SPORT_TENNIS }, @@ -179,6 +248,7 @@ struct _nodeinfo { { "sport" , "multi", NODE_SPORT_OTHER }, { "leisure", "sport_centre",NODE_SPORT_CENTER }, + /* Tourism */ { "tourism", "information", NODE_TOURISM_INFO }, { "tourism", "camp_site", NODE_TOURISM_CAMP_SITE }, { "tourism", "caravan_site",NODE_TOURISM_CARAVAN_SITE }, @@ -188,12 +258,20 @@ struct _nodeinfo { { "tourism", "motel", NODE_TOURISM_MOTEL }, { "tourism", "hostel", NODE_TOURISM_HOSTEL }, { "tourism", "attraction", NODE_TOURISM_ATTRACTION }, + { "tourism", "zoo", NODE_TOURISM_ATTRACTION }, + + { "historic", "ruins", NODE_TOURISM_ATTRACTION }, + { "historic", "monument", NODE_TOURISM_ATTRACTION }, + { "historic", "memorial", NODE_TOURISM_ATTRACTION }, + { "historic", "museum", NODE_HISTORIC_MUSEUM }, + { "historic", "castle", NODE_HISTORIC_CASTLE }, { "railway", "station", NODE_RAILWAY_STATION }, { "railway", "halt", NODE_RAILWAY_HALT }, { "aeroway", "terminal", NODE_AIRPORT_TERMINAL }, - + + /* Places */ { "place", "city", NODE_PLACE_CITY }, { "place", "town", NODE_PLACE_TOWN }, { "place", "village", NODE_PLACE_VILLAGE }, @@ -227,10 +305,12 @@ struct _wayinfo { { "highway", "secondary_link",60,WAY_SECONDARY, FALSE, TRUE, FALSE, TRUE, TRUE }, { "highway", "tertiary",60,WAY_TERTIARY, FALSE, FALSE, FALSE, TRUE, TRUE }, { "highway", "unclassified",50,WAY_UNCLASSIFIED, FALSE, FALSE, FALSE, TRUE, TRUE }, + { "highway", "byway",40,WAY_UNCLASSIFIED, FALSE, FALSE, FALSE, TRUE, TRUE }, { "highway", "residential",40,WAY_RESIDENTIAL, FALSE, FALSE, FALSE, TRUE, TRUE }, { "highway", "service",20,WAY_SERVICE, FALSE, FALSE, FALSE, TRUE, TRUE }, { "highway", "track",20,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE }, { "highway", "unsurfaced",60,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE }, + { "highway", "minor",60,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE }, { "highway", "pedestrian",20,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE }, { "highway", "footway",1,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE }, { "highway", "steps",0,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE}, @@ -243,7 +323,7 @@ struct _wayinfo { { "waterway", "river",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE }, { "waterway", "canal",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE }, { "waterway", "stream",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE }, - { "building", "",0,WAY_UNWAYED, FALSE, FALSE, TRUE, FALSE, FALSE }, + { "building", "*",0,WAY_UNWAYED, FALSE, FALSE, TRUE, FALSE, FALSE }, { NULL, NULL, 0, WAY_UNWAYED, FALSE, FALSE, FALSE, FALSE, FALSE } }; @@ -388,11 +468,12 @@ print_way(way *w) { #ifdef VERBOSE g_assert(w); -g_printf("Way #%d(N:%d T:%d S:%d): %s [%s:%s:%s]\n", +g_printf("Way #%d(N:%d T:%d S:%d IS: %d): %s [%s:%s:%s]\n", w->id, g_slist_length(w->nodes), w->type, w->data ? w->data->speed : 0, + w->data ? w->data->isin : 0, w->data ? w->data->name ? w->data->name : "" : "", w->flags & W_ONEWAY ? "-" : "=", w->flags & W_ROUNDABOUT ? "O" : "-", @@ -405,9 +486,10 @@ print_node(node *n) { #ifdef VERBOSE g_assert(n); -g_printf("Node #%d: T:%d [%s]\n", +g_printf("Node #%d: T:%d IS: %d [%s]\n", n->id, n->type, + n->data ? n->data->isin : 0, n->data ? n->data->name : ""); #endif } @@ -597,7 +679,6 @@ static gboolean db_insert_way(way *w) { GSList *iter; -guint32 isin=0; if (!w) return FALSE; @@ -613,12 +694,13 @@ for (iter=w->nodes; iter!=NULL; iter=iter->next) { db_insert_way_n2n(w, iter->data, iter->next->data); } -print_way(w); - if (w->id==0) return FALSE; -/* isin=osm_find_way_place(w); */ +if (w->data) + w->data->isin=osm_find_way_place(w); + +print_way(w); sqlite3_bind_int(sql.insert_way_data, 1, w->id); sqlite3_bind_int(sql.insert_way_data, 2, w->ncnt); @@ -626,8 +708,8 @@ sqlite3_bind_int(sql.insert_way_data, 3, w->type); sqlite3_bind_int(sql.insert_way_data, 4, w->flags); if (w->data) { sqlite3_bind_int(sql.insert_way_data, 5, w->data->speed); + sqlite3_bind_int(sql.insert_way_data, 6, w->data->isin); } -sqlite3_bind_int(sql.insert_way_data, 6, isin); sqlite3_step(sql.insert_way_data); sqlite3_reset(sql.insert_way_data); @@ -854,24 +936,25 @@ while (*place!=NULL) { case NODE_PLACE_VILLAGE: case NODE_PLACE_HAMLET: t=g_hash_table_lookup(osm_place_region, ps); - if (t) { + if (t) return t->id; - } t=g_hash_table_lookup(osm_place_country, ps); - if (t) { + if (t) return t->id; - } break; case NODE_PLACE_SUBURB: t=g_hash_table_lookup(osm_place_city, ps); - if (t) { + if (t) return t->id; - } break; case NODE_PLACE_ISLAND: - default: return 0; break; + default: + t=g_hash_table_lookup(osm_place_city, ps); + if (t) + return t->id; + break; } place++; } @@ -882,7 +965,6 @@ return 0; guint32 osm_find_way_place(way *w) { -way *t; gchar **isin; gchar **place; @@ -892,14 +974,19 @@ if (!isin) place=isin; while (*place!=NULL) { + node *t; gchar *ps; + ps=g_strstrip(*place); +#ifdef VERBOSE + g_printf("Checking (%d) in [%s]\n",w->id, ps); +#endif + t=g_hash_table_lookup(osm_place_city, ps); - if (t) { - print_way(t); + if (t) return t->id; - } + place++; } return 0; @@ -949,7 +1036,9 @@ if (n->type>NODE_POI_START && n->typedata->name=g_strdup(v); - else if (strcasecmp(k, "ref")==0) - cway->data->ref=g_strdup(v); - else if (strcasecmp(k, "int_ref")==0) - cway->data->int_ref=g_strdup(v); - else if (strcasecmp(k, "oneway")==0) - cway->flags|=W_ONEWAY; - else if (strcasecmp(k, "noexit")==0) - cway->flags|=W_NOEXIT; - else if (strcasecmp(k, "layer")==0) - cway->data->layer=atoi(v); - else if (strcasecmp(k, "speedlimit")==0) - cway->data->speed=atoi(v); - else if (strcasecmp(k, "maxspeed")==0) - cway->data->speed=atoi(v); - else if ((strcasecmp(k, "junction")==0) && (strcasecmp(v, "roundabout")==0)) { - cway->flags|=W_ROUNDABOUT; - cway->flags|=W_ONEWAY; - } else if ((strcasecmp(k, "access")==0) && (strcasecmp(v, "private")==0)) { - cway->flags|=W_NOACCESS; - } else if ((strcasecmp(k, "junction")==0) && (strcasecmp(v, "mini_roundabout")==0)) { - /* Just in case */ - cway->flags|=W_ROUNDABOUT; - cway->flags|=W_ONEWAY; - } else if (cway->type==WAY_UNWAYED) { - for (i=0; wayinfo[i].k; i++) { - if (strcasecmp (wayinfo[i].k, k)==0 && strcasecmp (v, wayinfo[i].v)==0) { - if (wayinfo[i].link==TRUE) - cway->flags|=W_LINK; - if (wayinfo[i].area==TRUE) - cway->flags|=W_AREA; - if (wayinfo[i].oneway==TRUE) - cway->flags|=W_ONEWAY; - cway->type=wayinfo[i].type; - if (cway->data->speed==0) - cway->data->speed=wayinfo[i].defspeed; - break; - } - } - } else { -#ifdef VERBOSE_UNHANDLED_WAY_TAGS - g_printf("Unhandled tag: [%s == %s]\n", k, v); -#endif } + g_hash_table_insert(osm_way_tags, g_strdup(k), g_strdup(v)); + osm_new_way_data(cway); } break; } @@ -1234,7 +1270,7 @@ switch (t) { cnode->data->name=NULL; v=g_hash_table_lookup(osm_node_tags, "name"); if (v) - cnode->data->name=g_strdup(v); + cnode->data->name=g_strstrip(g_strdup(v)); } cnode->data->isin=0; @@ -1252,10 +1288,12 @@ switch (t) { if (cnode->data->name) { switch (cnode->type) { case NODE_PLACE_COUNTRY: + g_printf("Country: [%s] (%d)\n", cnode->data->name, cnode->id); g_hash_table_insert(osm_place_country, cnode->data->name, cnode); break; case NODE_PLACE_CITY: case NODE_PLACE_TOWN: + g_printf("City: [%s] (%d)\n", cnode->data->name, cnode->id); g_hash_table_insert(osm_place_city, cnode->data->name, cnode); break; case NODE_PLACE_SUBURB: @@ -1276,32 +1314,89 @@ switch (t) { cnode=NULL; break; case IN_WAY_TAG: + if (way_cnt % 1024==0) { + g_printf("Ways: %d\n", way_cnt); + } + cway->nodes=g_slist_reverse(cway->nodes); - print_way(cway); + for (i=0; wayinfo[i].k; i++) { + v=g_hash_table_lookup(osm_way_tags, wayinfo[i].k); + if (!v) + continue; + if (strcasecmp (v, wayinfo[i].v)==0) { + if (wayinfo[i].link==TRUE) + cway->flags|=W_LINK; + if (wayinfo[i].area==TRUE) + cway->flags|=W_AREA; + if (wayinfo[i].oneway==TRUE) + cway->flags|=W_ONEWAY; + cway->type=wayinfo[i].type; + if (cway->data->speed==0) + cway->data->speed=wayinfo[i].defspeed; + break; + } + } + + v=g_hash_table_lookup(osm_way_tags, "name"); + if (v) + cway->data->name=g_strdup(v); + + v=g_hash_table_lookup(osm_way_tags, "ref"); + if (v) + cway->data->ref=g_strdup(v); + v=g_hash_table_lookup(osm_way_tags, "int_ref"); + if (v) + cway->data->int_ref=g_strdup(v); + + v=g_hash_table_lookup(osm_way_tags, "oneway"); + if (v) + cway->flags|=W_ONEWAY; + v=g_hash_table_lookup(osm_way_tags, "noexit"); + if (v) + cway->flags|=W_NOEXIT; + + v=g_hash_table_lookup(osm_way_tags, "speedlimit"); + if (v) + cway->data->speed=atoi(v); + v=g_hash_table_lookup(osm_way_tags, "maxspeed"); + if (v) + cway->data->speed=atoi(v); #if 0 - v=g_hash_table_lookup(osm_node_tags, "is_in"); + v=g_hash_table_lookup(osm_way_tags, "layer"); + if (v) + cway->data->layer=atoi(v); +#endif + + v=g_hash_table_lookup(osm_way_tags, "junction"); + if (v && strcasecmp(v,"roundabout")==0) { + cway->flags|=W_ROUNDABOUT; + cway->flags|=W_ONEWAY; + } else if (v && strcasecmp(v,"mini_roundabout")==0) { + cway->flags|=W_ROUNDABOUT; + cway->flags|=W_ONEWAY; + } + v=g_hash_table_lookup(osm_way_tags, "access"); + if (v && (strcasecmp(v, "private")==0)) { + cway->flags|=W_NOACCESS; + } + + print_way(cway); + + v=g_hash_table_lookup(osm_way_tags, "is_in"); if (v) { gchar **isin; isin=g_strsplit(v, ",", 10); - g_hash_table_insert(osm_node_isin, GINT_TO_POINTER(cnode->id), isin); + g_hash_table_insert(osm_way_isin, GINT_TO_POINTER(cway->id), isin); } -#endif - /* XXX */ if (cway->data && cway->data->name==NULL && cway->data->ref==NULL && cway->data->int_ref==NULL && cway->data->layer==0 && cway->data->speed==0) osm_free_way_data(cway); if (cway->id!=0) osm_way_add_to_list(cway); - else - way_cnt--; - - if (way_cnt % 32767==0) { - g_printf("Ways: %d\n", way_cnt); - } cway=NULL; g_hash_table_destroy(osm_way_tags);