2 * This file is part of mapper
4 * Copyright (C) 2007 Kaj-Michael Lang
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 * Utility to read OSM planet XML file and store it in a sqlite3 database.
23 * Reads in all nodes (if used, skips nodes outside bounding box)
24 * Special POI nodes are stored in POI table.
25 * Place POI nodes are stored in place table.
27 * Ways are read in and their data (name, type, etc) are stored
28 * in way, way_name and way_ref tables.
30 * Nodes used by they ways are stored in way_n2n table.
42 #include <sys/types.h>
47 #include <glib/gstdio.h>
59 /* #define VERBOSE_KEYS */
61 #define FILE_BUFFER 65535
63 #define OSM_DB_FILE "osm-planet.db"
65 /* Store pre-mercator projected integers for lat/lon for nodes */
66 #define INTEGER_LATLON
68 static guint node_cnt=0;
69 static guint node_skip_cnt=0;
70 static guint noded_cnt=0;
71 static guint way_cnt=0;
72 static guint way_names=0;
73 static guint way_refs=0;
75 static guint dbnode_cnt=0;
76 static guint dbnoded_cnt=0;
77 static guint dbway_cnt=0;
79 static gboolean is_update=FALSE;
82 /* POI or Place node extra data */
83 typedef struct _node_data node_data;
90 typedef struct _node node;
99 /* Way data structure */
100 typedef struct _way_data way_data;
112 typedef struct _way way;
137 /* Parent tag type */
145 /* Node types table */
146 /* XXX: Add support for parent category */
151 { "amenity", "fuel", NODE_AMENITY_FUEL },
152 { "amenity", "parking", NODE_AMENITY_PARKING },
154 { "amenity", "pub", NODE_AMENITY_PUB },
155 { "amenity", "biergarten", NODE_AMENITY_PUB },
156 { "amenity", "cafe", NODE_AMENITY_CAFE },
157 { "amenity", "fast_food", NODE_AMENITY_FOOD },
158 { "amenity", "restaurant", NODE_AMENITY_FOOD },
160 { "amenity", "telephone", NODE_AMENITY_TELEPHONE },
161 { "amenity", "toilets", NODE_AMENITY_WC },
163 { "amenity", "hospital", NODE_AMENITY_HOSPITAL },
164 { "amenity", "doctors", NODE_AMENITY_HOSPITAL },
165 { "amenity", "pharmacy", NODE_AMENITY_PHARMACY },
167 { "amenity", "post_office", NODE_AMENITY_POST },
168 { "amenity", "post_box", NODE_AMENITY_POST_BOX },
170 { "amenity", "cinema", NODE_AMENITY_CINEMA },
171 { "amenity", "theatre", NODE_AMENITY_THEATRE },
173 { "amenity", "atm", NODE_AMENITY_ATM },
174 { "amenity", "bank", NODE_AMENITY_BANK },
176 { "amenity", "police", NODE_AMENITY_POLICE },
177 { "amenity", "speed_trap", NODE_AMENITY_SPEEDCAM },
178 { "amenity", "speed_camera", NODE_AMENITY_SPEEDCAM },
179 { "amenity", "speed camera", NODE_AMENITY_SPEEDCAM },
181 { "amenity", "place_of_worship",NODE_AMENITY_POW },
183 { "amenity", "school", NODE_AMENITY_SCHOOL },
184 { "amenity", "college", NODE_AMENITY_COLLEGE },
185 { "amenity", "university", NODE_AMENITY_COLLEGE },
187 { "amenity", "library", NODE_AMENITY_LIBRARY },
188 { "amenity", "townhall", NODE_AMENITY_TOWNHALL },
190 { "amenity", "supermarket", NODE_AMENITY_SHOP },
191 { "amenity", "shopping_centre", NODE_AMENITY_SHOP },
192 { "amenity", "shop", NODE_AMENITY_SHOP },
193 { "amenity", "shops", NODE_AMENITY_SHOP },
194 { "amenity", "shopping", NODE_AMENITY_SHOP },
195 { "amenity", "shopping_mall",NODE_AMENITY_SHOP },
196 { "amenity", "cycle_shop", NODE_AMENITY_SHOP },
197 { "amenity", "bike_shop", NODE_AMENITY_SHOP },
198 { "amenity", "coffee_shop", NODE_AMENITY_SHOP },
199 { "amenity", "indoor_shopping_centre", NODE_AMENITY_SHOP },
200 { "amenity", "farm_shop", NODE_AMENITY_SHOP },
201 { "amenity", "tea_shop", NODE_AMENITY_SHOP },
204 { "shop", "supermarket", NODE_AMENITY_SHOP },
205 { "shop", "bakery", NODE_AMENITY_SHOP },
206 { "shop", "alcohol", NODE_AMENITY_SHOP },
207 { "shop", "butcher", NODE_AMENITY_SHOP },
208 { "shop", "flowers", NODE_AMENITY_SHOP },
209 { "shop", "clothing", NODE_AMENITY_SHOP },
210 { "shop", "souvenir", NODE_AMENITY_SHOP },
211 { "shop", "bicycles", NODE_AMENITY_SHOP },
212 { "shop", "grocers", NODE_AMENITY_SHOP },
213 { "shop", "newsagents", NODE_AMENITY_SHOP },
214 { "shop", "convenience", NODE_AMENITY_SHOP },
215 { "shop", "bakers", NODE_AMENITY_SHOP },
216 { "shop", "garden_centre",NODE_AMENITY_SHOP },
217 { "shop", "photography", NODE_AMENITY_SHOP },
218 { "shop", "general_store",NODE_AMENITY_SHOP },
219 { "shop", "food", NODE_AMENITY_SHOP },
220 { "shop", "drinks", NODE_AMENITY_SHOP },
221 { "shop", "pharmacy", NODE_AMENITY_PHARMACY },
224 { "sport" , "swimming", NODE_SPORT_SWIMMING },
225 { "sport" , "golf", NODE_SPORT_GOLF },
226 { "sport" , "tennis", NODE_SPORT_TENNIS },
227 { "sport" , "football", NODE_SPORT_FOOTBALL },
228 { "sport" , "soccer", NODE_SPORT_SOCCER },
229 { "sport" , "baskteball", NODE_SPORT_BASKETBALL },
230 { "sport" , "rugby", NODE_SPORT_RUGBY },
231 { "sport" , "skating", NODE_SPORT_SKATING },
232 { "sport" , "hockey", NODE_SPORT_HOCKEY },
233 { "sport" , "skateboard", NODE_SPORT_SKATEBOARD },
234 { "sport" , "bowling", NODE_SPORT_BOWLING },
235 { "sport" , "10pin", NODE_SPORT_BOWLING },
236 { "sport" , "motor", NODE_SPORT_MOTOR },
237 { "sport" , "shooting_range",NODE_SPORT_SHOOTING },
238 { "sport" , "paintball", NODE_SPORT_PAINTBALL },
239 { "sport" , "horse_racing",NODE_SPORT_HORSES },
240 { "sport" , "horse", NODE_SPORT_HORSES },
241 { "sport" , "horses", NODE_SPORT_HORSES },
242 { "sport" , "dog_racing", NODE_SPORT_DOG },
243 { "sport" , "pelota", NODE_SPORT_PELOTA },
244 { "sport" , "racquet", NODE_SPORT_RACQUET },
245 { "sport" , "equestrian", NODE_SPORT_HORSES },
246 { "sport" , "baseball", NODE_SPORT_BASEBALL },
247 { "sport" , "cricket", NODE_SPORT_CRICKET },
248 { "sport" , "croquet", NODE_SPORT_CROQUET },
249 { "sport" , "cycling", NODE_SPORT_CYCLING },
250 { "sport" , "bowls", NODE_SPORT_BOWLS },
251 { "sport" , "athletics", NODE_SPORT_ATHLETICS },
252 { "sport" , "gymnastics", NODE_SPORT_GYMNASTICS },
253 { "sport" , "multi", NODE_SPORT_OTHER },
254 { "leisure", "sport_centre",NODE_SPORT_CENTER },
257 { "tourism", "information", NODE_TOURISM_INFO },
258 { "tourism", "camp_site", NODE_TOURISM_CAMP_SITE },
259 { "tourism", "caravan_site",NODE_TOURISM_CARAVAN_SITE },
260 { "tourism", "picnic_site", NODE_TOURISM_PICNIC_SITE },
261 { "tourism", "theme_park", NODE_TOURISM_THEME_PARK },
262 { "tourism", "hotel", NODE_TOURISM_HOTEL },
263 { "tourism", "motel", NODE_TOURISM_MOTEL },
264 { "tourism", "hostel", NODE_TOURISM_HOSTEL },
265 { "tourism", "attraction", NODE_TOURISM_ATTRACTION },
266 { "tourism", "zoo", NODE_TOURISM_ATTRACTION },
268 { "historic", "ruins", NODE_TOURISM_ATTRACTION },
269 { "historic", "monument", NODE_TOURISM_ATTRACTION },
270 { "historic", "memorial", NODE_TOURISM_ATTRACTION },
271 { "historic", "museum", NODE_HISTORIC_MUSEUM },
272 { "historic", "castle", NODE_HISTORIC_CASTLE },
274 { "railway", "station", NODE_RAILWAY_STATION },
275 { "railway", "halt", NODE_RAILWAY_HALT },
277 { "aeroway", "terminal", NODE_AIRPORT_TERMINAL },
280 { "place", "city", NODE_PLACE_CITY },
281 { "place", "town", NODE_PLACE_TOWN },
282 { "place", "village", NODE_PLACE_VILLAGE },
283 { "place", "hamlet", NODE_PLACE_HAMLET },
284 { "place", "suburb", NODE_PLACE_SUBURB },
285 { "place", "island", NODE_PLACE_ISLAND },
287 { "highway", "traffic_signals", NODE_TRAFFIC_SIGNALS },
288 { "highway", "motorway_junction", NODE_JUNCTION },
289 { "highway", "services", NODE_AMENITY_PARKING },
290 { "highway", "toll_booth", NODE_TOLLBOOTH },
291 { "highway", "gate", NODE_GATE },
293 { NULL, NULL, NODE_PLAIN }
296 /* Array to get id number and defaults for ways of different types */
301 gboolean oneway, link, area, car, foot;
303 { "highway", "motorway",120,WAY_MOTORWAY, TRUE, FALSE, FALSE, TRUE, FALSE },
304 { "highway", "motorway_link",120,WAY_MOTORWAY, TRUE, TRUE, FALSE, TRUE, FALSE },
305 { "highway", "trunk",100,WAY_TRUNK, FALSE, FALSE, FALSE, TRUE, FALSE },
306 { "highway", "trunk_link",100,WAY_TRUNK, FALSE, TRUE, FALSE, TRUE, FALSE },
307 { "highway", "primary",80,WAY_PRIMARY, FALSE, FALSE, FALSE, TRUE, TRUE },
308 { "highway", "primary_link",60,WAY_PRIMARY, FALSE, TRUE, FALSE, TRUE, TRUE },
309 { "highway", "secondary",80,WAY_SECONDARY, FALSE, FALSE, FALSE, TRUE, TRUE },
310 { "highway", "secondary_link",60,WAY_SECONDARY, FALSE, TRUE, FALSE, TRUE, TRUE },
311 { "highway", "tertiary",60,WAY_TERTIARY, FALSE, FALSE, FALSE, TRUE, TRUE },
312 { "highway", "unclassified",50,WAY_UNCLASSIFIED, FALSE, FALSE, FALSE, TRUE, TRUE },
313 { "highway", "byway",40,WAY_UNCLASSIFIED, FALSE, FALSE, FALSE, TRUE, TRUE },
314 { "highway", "residential",40,WAY_RESIDENTIAL, FALSE, FALSE, FALSE, TRUE, TRUE },
315 { "highway", "service",20,WAY_SERVICE, FALSE, FALSE, FALSE, TRUE, TRUE },
316 { "highway", "track",20,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE },
317 { "highway", "unsurfaced",60,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE },
318 { "highway", "minor",60,WAY_TRACK, FALSE, FALSE, FALSE, TRUE, TRUE },
319 { "highway", "pedestrian",20,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
320 { "highway", "footway",1,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
321 { "highway", "steps",0,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE},
322 { "highway", "bridleway",10,WAY_FOOTWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
323 { "highway", "cycleway",10,WAY_CYCLEWAY, FALSE, FALSE, FALSE, FALSE, TRUE },
324 { "railway", "rail",0,WAY_RAIL, FALSE, FALSE, FALSE, FALSE, FALSE },
325 { "aeroway", "runway",0,WAY_RUNWAY, FALSE, FALSE, FALSE, FALSE, FALSE },
326 { "aeroway", "taxiway",0,WAY_TAXIWAY, FALSE, FALSE, FALSE, FALSE, FALSE },
327 { "natural", "water",0,WAY_WATER, FALSE, FALSE, TRUE, FALSE, FALSE },
328 { "waterway", "river",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE },
329 { "waterway", "canal",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE },
330 { "waterway", "stream",0,WAY_WATER, FALSE, FALSE, FALSE, FALSE, FALSE },
331 { "building", "*",0,WAY_UNWAYED, FALSE, FALSE, TRUE, FALSE, FALSE },
332 { NULL, NULL, 0, WAY_UNWAYED, FALSE, FALSE, FALSE, FALSE, FALSE }
336 tag_parent_t tag_parent=IS_NONE;
338 static GHashTable *osm_nodes;
339 static GHashTable *osm_node_tags;
340 static GHashTable *osm_way_tags;
341 static GSList *osm_ways;
342 static GSList *osm_poi;
344 static GHashTable *osm_place_country;
345 static GHashTable *osm_place_region;
346 static GHashTable *osm_place_city;
347 static GHashTable *osm_place_suburb;
348 static GHashTable *osm_place_village;
349 static GHashTable *osm_node_isin;
350 static GHashTable *osm_way_isin;
352 static node *cnode=NULL;
353 static way *cway=NULL;
356 sqlite3_stmt *insert_poi;
357 sqlite3_stmt *delete_osm_poi;
359 sqlite3_stmt *insert_node;
360 sqlite3_stmt *delete_nodes;
361 sqlite3_stmt *select_node;
362 sqlite3_stmt *update_node;
364 sqlite3_stmt *insert_way_data;
365 sqlite3_stmt *insert_way_ref;
366 sqlite3_stmt *insert_way_name;
367 sqlite3_stmt *insert_way_names_nls;
368 sqlite3_stmt *insert_way_n2n;
369 sqlite3_stmt *delete_way;
370 sqlite3_stmt *delete_way_n2n;
371 sqlite3_stmt *delete_way_seg_wsid;
372 sqlite3_stmt *delete_way_name;
373 sqlite3_stmt *delete_way_names_nls;
374 sqlite3_stmt *delete_way_ref;
376 sqlite3_stmt *insert_place;
377 sqlite3_stmt *delete_place;
379 static struct sql_stmt sql;
387 static struct map_bbox bbox;
388 static gboolean use_bbox;
390 void osm_free_way_data(way *w);
391 void print_way(way *w);
393 void db_prepare(void);
394 gboolean db_insert_node(node *n);
395 guint32 osm_find_way_place(way *w);
397 /****************************************************/
399 /****************************************************/
404 sqlite3_finalize(sql.insert_poi);
405 sqlite3_finalize(sql.delete_osm_poi);
407 sqlite3_finalize(sql.insert_node);
408 sqlite3_finalize(sql.select_node);
409 sqlite3_finalize(sql.delete_nodes);
410 sqlite3_finalize(sql.update_node);
412 sqlite3_finalize(sql.insert_place);
413 sqlite3_finalize(sql.delete_place);
415 sqlite3_finalize(sql.delete_way);
416 sqlite3_finalize(sql.insert_way_data);
418 sqlite3_finalize(sql.delete_way_name);
419 sqlite3_finalize(sql.insert_way_name);
421 sqlite3_finalize(sql.delete_way_n2n);
422 sqlite3_finalize(sql.insert_way_n2n);
424 sqlite3_finalize(sql.delete_way_names_nls);
425 sqlite3_finalize(sql.insert_way_names_nls);
432 sqlite3_prepare_v2(db, "insert or replace into nodes (nid,lat,lon,l,f) values (?,?,?,0,?)", -1, &sql.insert_node, NULL);
433 sqlite3_prepare_v2(db, "select lat,lon,l from nodes where nid=?", -1, &sql.select_node, NULL);
434 sqlite3_prepare_v2(db, "delete from nodes", -1, &sql.delete_nodes, NULL);
435 sqlite3_prepare_v2(db, "update nodes set l=l+1 where nid=?", -1, &sql.update_node, NULL);
438 sqlite3_prepare_v2(db, "insert or replace into places (nid,type,name,isin) values (?, ?, ?, ?)", -1, &sql.insert_place, NULL);
439 sqlite3_prepare_v2(db, "delete from places", -1, &sql.delete_place, NULL);
442 sqlite3_prepare_v2(db, "insert or replace into poi (osm_id, lat, lon, label, cat_id, public, source, priority, isin, desc) values (?, ?, ?, ?, ?, 1, 1, ?, ?, ?)",
443 -1, &sql.insert_poi, NULL);
444 sqlite3_prepare_v2(db, "delete from poi where osm_id>0", -1, &sql.delete_osm_poi, NULL);
447 sqlite3_prepare_v2(db, "insert or replace into way (wid,nodes,type,flags,speed,isin) values (?, ?, ?, ?, ?, ?)", -1, &sql.insert_way_data, NULL);
448 sqlite3_prepare_v2(db, "delete from way", -1, &sql.delete_way, NULL);
451 sqlite3_prepare_v2(db, "insert into way_n2n (wsid,f,t) values (?,?,?)", -1, &sql.insert_way_n2n, NULL);
452 sqlite3_prepare_v2(db, "delete from way_n2n where wsid=?", -1, &sql.delete_way_n2n, NULL);
455 sqlite3_prepare_v2(db, "insert or replace into way_names (wid,name) values (?, ?)", -1, &sql.insert_way_name, NULL);
456 sqlite3_prepare_v2(db, "delete from way_names", -1, &sql.delete_way_name, NULL);
458 /* Other language names for ways */
459 sqlite3_prepare_v2(db, "insert into way_names_nls (wid,lang,name) values (?, ?, ?)", -1, &sql.insert_way_names_nls, NULL);
460 sqlite3_prepare_v2(db, "delete from way_names_nls where wid=?", -1, &sql.delete_way_names_nls, NULL);
462 /* Way ref and int_ref */
463 sqlite3_prepare_v2(db, "insert or replace into way_ref (rid,ref,int_ref) values (?, ?, ?)", -1, &sql.insert_way_ref, NULL);
464 sqlite3_prepare_v2(db, "delete from way_ref", -1, &sql.delete_way_ref, NULL);
467 /********************************************************************/
474 g_printf("Way #%d(N:%d T:%d S:%d IS: %d): %s [%s:%s:%s]\n",
476 g_slist_length(w->nodes),
478 w->data ? w->data->speed : 0,
479 w->data ? w->data->isin : 0,
480 w->data ? w->data->name ? w->data->name : "" : "",
481 w->flags & W_ONEWAY ? "-" : "=",
482 w->flags & W_ROUNDABOUT ? "O" : "-",
483 w->flags & W_LINK ? "|" : " ");
492 g_printf("Node #%d: T:%d IS: %d [%s]\n",
495 n->data ? n->data->isin : 0,
496 n->data ? n->data->name : "");
500 /********************************************************************/
503 db_insert_node(node *n)
507 sqlite3_bind_int(sql.insert_node, 1, n->id);
509 #ifdef INTEGER_LATLON
510 lat=lat2mp_int(n->lat);
511 lon=lon2mp_int(n->lon);
512 sqlite3_bind_int(sql.insert_node, 2, lat);
513 sqlite3_bind_int(sql.insert_node, 3, lon);
515 sqlite3_bind_double(sql.insert_node, 2, lat);
516 sqlite3_bind_double(sql.insert_node, 3, lon);
519 sqlite3_bind_int(sql.insert_node, 4, n->type);
520 sqlite3_step(sql.insert_node);
521 sqlite3_reset(sql.insert_node);
522 sqlite3_clear_bindings(sql.insert_node);
528 db_insert_place(node *n)
534 sqlite3_bind_int(sql.insert_place, 1, n->id);
535 sqlite3_bind_int(sql.insert_place, 2, n->type);
536 sqlite3_bind_text(sql.insert_place, 3, n->data->name, -1, SQLITE_TRANSIENT);
537 sqlite3_bind_int(sql.insert_place, 4, n->data->isin);
539 return db_exec(sql.insert_place);
543 db_insert_poi(node *n)
545 sqlite3_bind_int(sql.insert_poi, 1, n->id);
546 sqlite3_bind_double(sql.insert_poi, 2, n->lat);
547 sqlite3_bind_double(sql.insert_poi, 3, n->lon);
549 sqlite3_bind_text(sql.insert_poi, 4, n->data->name, -1, SQLITE_TRANSIENT);
551 sqlite3_bind_text(sql.insert_poi, 4, "", -1, SQLITE_TRANSIENT);
552 sqlite3_bind_int(sql.insert_poi, 5, n->type);
553 sqlite3_bind_int(sql.insert_poi, 6, n->type/100);
554 sqlite3_bind_int(sql.insert_poi, 7, n->data->isin);
558 sqlite3_bind_text(sql.insert_poi, 8, n->data->desc, -1, SQLITE_TRANSIENT);
560 sqlite3_bind_text(sql.insert_poi, 9, n->data->url, -1, SQLITE_TRANSIENT);
563 return db_exec(sql.insert_poi);
567 * Update node usage count
570 db_update_node_links(node *n)
572 sqlite3_bind_int(sql.update_node, 1, n->id);
574 return db_exec(sql.update_node);
578 * Insert way,node1,node2 triplet
581 db_insert_way_n2n(way *w, node *nf, node *nt)
584 g_printf("NULL WAY\n");
589 g_printf("NULL NODE 1\n");
594 g_printf("NULL NODE 2\n");
598 sqlite3_bind_int(sql.insert_way_n2n, 1, w->id);
599 sqlite3_bind_int(sql.insert_way_n2n, 2, nf->id);
600 sqlite3_bind_int(sql.insert_way_n2n, 3, nt->id);
603 g_printf("%d [%d - %d]\n", w->id, nf->id, nt->id);
606 db_exec(sql.insert_way_n2n);
607 db_update_node_links(nf);
608 db_update_node_links(nt);
613 * Insert way ref and int_ref
616 db_insert_way_ref(way *w)
621 if (!w->data->ref && !w->data->int_ref)
626 sqlite3_bind_int(sql.insert_way_ref, 1, w->id);
628 sqlite3_bind_text(sql.insert_way_ref, 2, w->data->ref, -1, SQLITE_TRANSIENT);
629 if (w->data->int_ref)
630 sqlite3_bind_text(sql.insert_way_ref, 3, w->data->int_ref, -1, SQLITE_TRANSIENT);
632 db_exec(sql.insert_way_ref);
639 db_insert_way_name(way *w)
648 sqlite3_bind_int(sql.insert_way_name, 1, w->id);
649 sqlite3_bind_text(sql.insert_way_name, 2, w->data->name, -1, SQLITE_TRANSIENT);
651 db_exec(sql.insert_way_name);
655 db_delete_way_names_nls(way *w)
657 sqlite3_bind_int(sql.delete_way_names_nls, 1, w->id);
659 sqlite3_step(sql.delete_way_names_nls);
660 sqlite3_reset(sql.delete_way_names_nls);
661 sqlite3_clear_bindings(sql.delete_way_names_nls);
665 db_insert_way_names_nls_cb(gpointer key, gpointer value, gpointer user_data)
667 way *w=(way *)user_data;
669 sqlite3_bind_int(sql.insert_way_names_nls, 1, w->id);
670 sqlite3_bind_text(sql.insert_way_names_nls, 2, (gchar *)key, -1, SQLITE_TRANSIENT);
671 sqlite3_bind_text(sql.insert_way_names_nls, 3, (gchar *)value, -1, SQLITE_TRANSIENT);
673 db_exec(sql.insert_way_names_nls);
677 db_insert_way_names_nls(way *w)
684 g_hash_table_foreach(w->data->names, db_insert_way_names_nls_cb, w);
688 * Insert all data for the given way
695 db_insert_way(way *w)
702 /* Skip things we don't use (yet) */
703 if (w->type==WAY_UNWAYED || w->type>WAY_ROAD_END)
707 for (iter=w->nodes; iter!=NULL; iter=iter->next) {
710 db_insert_way_n2n(w, iter->data, iter->next->data);
717 w->data->isin=osm_find_way_place(w);
721 sqlite3_bind_int(sql.insert_way_data, 1, w->id);
722 sqlite3_bind_int(sql.insert_way_data, 2, w->ncnt);
723 sqlite3_bind_int(sql.insert_way_data, 3, w->type);
724 sqlite3_bind_int(sql.insert_way_data, 4, w->flags);
726 sqlite3_bind_int(sql.insert_way_data, 5, w->data->speed);
727 sqlite3_bind_int(sql.insert_way_data, 6, w->data->isin);
730 db_exec(sql.insert_way_data);
732 db_insert_way_ref(w);
733 db_insert_way_name(w);
734 db_insert_way_names_nls(w);
736 osm_free_way_data(w);
740 /********************************************************************/
743 get_attr_key_value(const gchar **p, gchar *key)
749 if (strncmp(*d, key, strlen(key))==0) {
760 check_tag(const gchar *tag)
762 if (strcmp(tag,"node")==0) return IN_NODE_TAG;
763 else if (strcmp(tag,"nd")==0) return IN_WNODE_TAG;
764 else if (strcmp(tag,"way")==0) return IN_WAY_TAG;
765 else if (strcmp(tag,"tag")==0) return IN_KEY_TAG;
766 else if (strcmp(tag,"osm")==0) return IN_OSM_TAG;
767 else if (strcmp(tag,"bound")==0) return IN_BOUND_TAG;
768 else if (strcmp(tag,"relation")==0) return IN_RELATION_TAG;
769 else if (strcmp(tag,"member")==0) return IN_MEMBER_TAG;
774 find_nls_names(gpointer key, gpointer value, gpointer user_data)
782 nls=(GHashTable *)user_data;
784 /* Check if it is a name key, return if not. */
785 if (g_str_has_prefix(k, "name:")==FALSE)
788 tmp=g_strrstr(k, ":");
794 g_hash_table_insert(nls, g_strdup(tmp), g_strdup(v));
796 g_printf("NLS(%s): [%s]\n", tmp, v);
800 /********************************************************************/
807 g_printf("N: %d [%f:%f][%s](%d)\n",
808 n->id, n->lat, n->lon,
809 n->data->name ? n->data->name : "-",
812 g_printf("N: %d [%f:%f]\n",
813 n->id, n->lat, n->lon);
819 dump_array(const gchar **p)
825 g_printf("[%s]", *d);
833 osm_node_check_box(gdouble nlat, gdouble nlon)
837 return (nlat > bbox.lat_min && nlat < bbox.lat_max && nlon > bbox.lon_min && nlon < bbox.lon_max) ? TRUE : FALSE;
841 osm_new_node_data(node *n)
844 if (n->data!=NULL) return;
845 n->data=g_slice_new(node_data);
852 osm_free_node_data(node *n)
857 g_free(n->data->name);
858 g_slice_free(node_data, n->data);
864 osm_new_node(gint id, gdouble lat, gdouble lon)
873 n->data=(node_data *)NULL;
874 g_hash_table_insert(osm_nodes, GINT_TO_POINTER(id), n);
879 osm_find_node(guint32 nid)
882 n=g_hash_table_lookup(osm_nodes, GINT_TO_POINTER(nid));
885 g_printerr("ERROR: Node %d not found!\n", nid);
891 osm_new_way_data(way *w)
894 if (w->data!=NULL) return;
896 w->data=g_slice_new(way_data);
900 w->data->int_ref=NULL;
906 osm_free_way_data(way *w)
911 g_free(w->data->name);
913 g_free(w->data->ref);
914 if (w->data->int_ref)
915 g_free(w->data->int_ref);
916 g_slice_free(way_data, w->data);
933 /* Add to list of ways */
938 osm_way_add_to_list(way *w)
940 osm_ways=g_slist_prepend(osm_ways, w);
944 osm_way_new_node(way *w, gint nid)
948 n=osm_find_node(nid);
949 w->nodes=g_slist_prepend(w->nodes, n);
954 * Search the place hash table for the location of the node.
958 osm_find_node_place(node *n)
967 isin=g_hash_table_lookup(osm_node_isin, GINT_TO_POINTER(n->id));
973 while (*place!=NULL) {
975 ps=g_strstrip(*place);
977 g_printf("Checking (%d) [%s] in [%s]\n",n->type, n->data->name, ps);
980 case NODE_PLACE_CITY:
981 case NODE_PLACE_TOWN:
982 case NODE_PLACE_VILLAGE:
983 case NODE_PLACE_HAMLET:
984 t=g_hash_table_lookup(osm_place_region, ps);
987 t=g_hash_table_lookup(osm_place_country, ps);
991 case NODE_PLACE_SUBURB:
992 t=g_hash_table_lookup(osm_place_city, ps);
996 case NODE_PLACE_ISLAND:
1000 t=g_hash_table_lookup(osm_place_city, ps);
1012 osm_find_way_place(way *w)
1017 isin=g_hash_table_lookup(osm_way_isin, GINT_TO_POINTER(w->id));
1022 while (*place!=NULL) {
1026 ps=g_strstrip(*place);
1029 g_printf("Checking (%d) in [%s]\n",w->id, ps);
1032 t=g_hash_table_lookup(osm_place_city, ps);
1041 /***********************************************************************/
1044 osm_node_save_node(gint key, gpointer value, gpointer user_data)
1046 node *n=(node *)value;
1050 if (dbnode_cnt % 26214==0)
1051 g_printf("Nodes: %f%%\n",((float)dbnode_cnt/(float)node_cnt)*100);
1055 * Check node type and insert as POI or Place
1056 * Discard extra data after insert.
1059 osm_node_save_poi(node *n, gpointer user_data)
1062 g_printerr("ERROR: null poi\n");
1067 g_printerr("POI node with no data ?\n");
1071 n->data->isin=osm_find_node_place(n);
1073 if (n->type>NODE_POI_START && n->type<NODE_POI_END) {
1076 } else if (n->type>NODE_PLACE_START && n->type<NODE_PLACE_END) {
1080 osm_free_node_data(n);
1084 /* Free the extra info, we don't need it anymore */
1086 osm_free_node_data(n);
1092 osm_planet_poi_clear_nodes(void)
1094 g_print("Removing old OSM POIs...\n");
1095 sqlite3_exec(db, "begin;", NULL, NULL, NULL);
1096 sqlite3_step(sql.delete_osm_poi);
1097 sqlite3_step(sql.delete_place);
1098 sqlite3_exec(db, "commit;", NULL, NULL, NULL);
1102 osm_planet_poi_save_nodes(void)
1104 g_print("Storing new POIs...\n");
1105 sqlite3_exec(db, "begin;", NULL, NULL, NULL);
1106 g_slist_foreach(osm_poi, osm_node_save_poi, NULL);
1107 sqlite3_exec(db, "commit;", NULL, NULL, NULL);
1108 g_slist_free(osm_poi);
1111 /*********************************************************************/
1114 osm_planet_clear_nodes(void)
1116 g_print("Clearing old nodes\n");
1117 sqlite3_step(sql.delete_nodes);
1121 osm_planet_save_nodes(void)
1123 g_print("Storing nodes...\n");
1125 sqlite3_exec(db, "begin;", NULL, NULL, NULL);
1126 g_hash_table_foreach(osm_nodes, osm_node_save_node, NULL);
1127 sqlite3_exec(db, "commit;", NULL, NULL, NULL);
1130 /*********************************************************************/
1133 osm_way_save(way *value, gpointer user_data)
1136 db_insert_way(value);
1137 if (dbway_cnt % 8192==0 && dbway_cnt>0) {
1138 g_printf("Ways: %f%%\n",(((float)dbway_cnt/(float)way_cnt)*100));
1144 osm_planet_clear_ways(void)
1146 g_print("Clearing old data:\n");
1147 sqlite3_step(sql.delete_way);
1148 sqlite3_step(sql.delete_way_name);
1149 sqlite3_step(sql.delete_way_ref);
1150 sqlite3_step(sql.delete_way_n2n);
1154 osm_planet_save_ways(void)
1156 g_print("Inserting new ways:\n");
1157 sqlite3_exec(db, "begin;", NULL, NULL, NULL);
1158 g_slist_foreach(osm_ways, osm_way_save, NULL);
1159 sqlite3_exec(db, "commit;", NULL, NULL, NULL);
1162 /*********************************************************************/
1165 osm_planet_save_all_nodes(void)
1167 g_printf("Saving planet nodes to database:\n");
1169 osm_planet_poi_clear_nodes();
1170 osm_planet_poi_save_nodes();
1173 osm_planet_clear_nodes();
1174 osm_planet_clear_ways();
1176 osm_planet_save_nodes();
1180 osm_planet_save_all_ways(void)
1182 g_printf("Saving planet way to database:\n");
1184 osm_planet_save_ways();
1187 /***********************************************************************/
1190 _osm_tag_start(void *userData, const char *name, const char **atts)
1200 g_printf("Starting...\n");
1206 id=atoi(get_attr_key_value(atts, "id"));
1207 nlat=atof(get_attr_key_value(atts, "lat"));
1208 nlon=atof(get_attr_key_value(atts, "lon"));
1210 /* Check if node is used */
1211 if (osm_node_check_box(nlat, nlon)==TRUE) {
1212 cnode=osm_new_node(id, nlat, nlon);
1213 osm_node_tags=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1222 id=atoi(get_attr_key_value(atts, "id"));
1223 cway=osm_new_way(id);
1224 osm_way_tags=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1227 ndref=atoi(get_attr_key_value(atts, "ref"));
1228 if (use_bbox==TRUE) {
1229 if (osm_find_node(ndref)==NULL) {
1234 osm_way_new_node(cway, ndref);
1237 k=get_attr_key_value(atts, "k");
1238 if (strcmp(k,"created_by")==0)
1240 if (strcmp(k,"source")==0)
1243 v=get_attr_key_value(atts, "v");
1245 g_printf("TAG: K=[%s] V=[%s]\n", k, v);
1248 switch (tag_parent) {
1250 g_printf("Tag key/value pair but unknown owner\n");
1257 /* Insert key/value pairs into hash table */
1259 g_printerr("In node tags but node is NULL!\n");
1262 g_hash_table_insert(osm_node_tags, g_strdup(k), g_strdup(v));
1268 g_printerr("In way tags but way is NULL!\n");
1271 g_hash_table_insert(osm_way_tags, g_strdup(k), g_strdup(v));
1272 osm_new_way_data(cway);
1281 /* Ignore for now */
1282 g_printf("Ignoring bound tag\n");
1284 case IN_RELATION_TAG:
1285 tag_parent=IS_RELATION;
1293 g_printf("Unknown tag: %s\n", name);
1299 _osm_tag_end(void *userData, const char *name)
1307 if (node_cnt % 262140==0) {
1308 g_printf("Nodes: %d of %d, POIs: %d, Outside box: %d\n", node_cnt-node_skip_cnt, node_cnt, noded_cnt, node_skip_cnt);
1314 osm_new_node_data(cnode);
1316 for (i=0; nodeinfo[i].k; i++) {
1317 v=g_hash_table_lookup(osm_node_tags, nodeinfo[i].k);
1320 if (strcasecmp (v, nodeinfo[i].v)==0) {
1321 cnode->type=nodeinfo[i].type;
1326 if (cnode->type!=NODE_PLAIN) {
1327 cnode->data->name=NULL;
1328 v=g_hash_table_lookup(osm_node_tags, "name");
1330 cnode->data->name=g_strstrip(g_strdup(v));
1333 cnode->data->isin=0;
1334 v=g_hash_table_lookup(osm_node_tags, "is_in");
1337 isin=g_strsplit(v, ",", 10);
1338 g_hash_table_insert(osm_node_isin, GINT_TO_POINTER(cnode->id), isin);
1341 if (cnode->type==NODE_PLAIN) {
1342 osm_free_node_data(cnode);
1344 osm_poi=g_slist_prepend(osm_poi, cnode);
1345 if (cnode->data->name) {
1346 switch (cnode->type) {
1347 case NODE_PLACE_COUNTRY:
1348 g_printf("Country: [%s] (%d)\n", cnode->data->name, cnode->id);
1349 g_hash_table_insert(osm_place_country, cnode->data->name, cnode);
1351 case NODE_PLACE_CITY:
1352 case NODE_PLACE_TOWN:
1353 g_printf("City: [%s] (%d)\n", cnode->data->name, cnode->id);
1354 g_hash_table_insert(osm_place_city, cnode->data->name, cnode);
1356 case NODE_PLACE_SUBURB:
1357 g_hash_table_insert(osm_place_suburb, cnode->data->name, cnode);
1359 case NODE_PLACE_VILLAGE:
1360 case NODE_PLACE_HAMLET:
1361 g_hash_table_insert(osm_place_village, cnode->data->name, cnode);
1363 case NODE_PLACE_ISLAND:
1364 /* Ignore for now */
1370 g_hash_table_destroy(osm_node_tags);
1374 if (way_cnt % 1024==0) {
1375 g_printf("Ways: %d\n", way_cnt);
1378 cway->nodes=g_slist_reverse(cway->nodes);
1380 for (i=0; wayinfo[i].k; i++) {
1381 v=g_hash_table_lookup(osm_way_tags, wayinfo[i].k);
1384 if (strcasecmp (v, wayinfo[i].v)==0) {
1385 if (wayinfo[i].link==TRUE)
1386 cway->flags|=W_LINK;
1387 if (wayinfo[i].area==TRUE)
1388 cway->flags|=W_AREA;
1389 if (wayinfo[i].oneway==TRUE)
1390 cway->flags|=W_ONEWAY;
1391 cway->type=wayinfo[i].type;
1392 if (cway->data->speed==0)
1393 cway->data->speed=wayinfo[i].defspeed;
1398 v=g_hash_table_lookup(osm_way_tags, "name");
1400 cway->data->name=g_strdup(v);
1401 /* Try to find other language names */
1402 cway->data->names=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
1403 g_hash_table_foreach(osm_way_tags, find_nls_names, cway->data->names);
1404 if (g_hash_table_size(cway->data->names)==0) {
1405 g_hash_table_destroy(cway->data->names);
1406 cway->data->names=NULL;
1410 v=g_hash_table_lookup(osm_way_tags, "ref");
1412 cway->data->ref=g_strdup(v);
1413 v=g_hash_table_lookup(osm_way_tags, "int_ref");
1415 cway->data->int_ref=g_strdup(v);
1417 v=g_hash_table_lookup(osm_way_tags, "oneway");
1419 cway->flags|=W_ONEWAY;
1420 v=g_hash_table_lookup(osm_way_tags, "noexit");
1422 cway->flags|=W_NOEXIT;
1424 v=g_hash_table_lookup(osm_way_tags, "speedlimit");
1426 cway->data->speed=atoi(v);
1427 v=g_hash_table_lookup(osm_way_tags, "maxspeed");
1429 cway->data->speed=atoi(v);
1432 v=g_hash_table_lookup(osm_way_tags, "layer");
1434 cway->data->layer=atoi(v);
1437 v=g_hash_table_lookup(osm_way_tags, "junction");
1438 if (v && strcasecmp(v,"roundabout")==0) {
1439 cway->flags|=W_ROUNDABOUT;
1440 cway->flags|=W_ONEWAY;
1441 } else if (v && strcasecmp(v,"mini_roundabout")==0) {
1442 cway->flags|=W_ROUNDABOUT;
1443 cway->flags|=W_ONEWAY;
1446 /* XXX: Should check keys */
1447 v=g_hash_table_lookup(osm_way_tags, "access");
1448 if (v && (strcasecmp(v, "private")==0)) {
1449 cway->flags|=W_NOACCESS;
1454 v=g_hash_table_lookup(osm_way_tags, "is_in");
1457 isin=g_strsplit(v, ",", 10);
1458 g_hash_table_insert(osm_way_isin, GINT_TO_POINTER(cway->id), isin);
1461 if (cway->data && cway->data->name==NULL && cway->data->ref==NULL &&
1462 cway->data->int_ref==NULL && cway->data->layer==0 && cway->data->speed==0)
1463 osm_free_way_data(cway);
1466 osm_way_add_to_list(cway);
1469 g_hash_table_destroy(osm_way_tags);
1475 g_printf("Planet loaded.\n");
1481 /************************************************************************/
1486 osm_nodes=g_hash_table_new(g_direct_hash, g_direct_equal);
1488 osm_place_country=g_hash_table_new(g_str_hash, g_str_equal);
1489 osm_place_city=g_hash_table_new(g_str_hash, g_str_equal);
1490 osm_place_suburb=g_hash_table_new(g_str_hash, g_str_equal);
1491 osm_place_village=g_hash_table_new(g_str_hash, g_str_equal);
1492 osm_place_region=g_hash_table_new(g_str_hash, g_str_equal);
1493 osm_node_isin=g_hash_table_new(g_direct_hash, g_direct_equal);
1494 osm_way_isin=g_hash_table_new(g_direct_hash, g_direct_equal);
1500 g_hash_table_destroy(osm_nodes);
1502 g_hash_table_destroy(osm_place_country);
1503 g_hash_table_destroy(osm_place_city);
1504 g_hash_table_destroy(osm_place_suburb);
1505 g_hash_table_destroy(osm_place_village);
1506 g_hash_table_destroy(osm_place_region);
1507 g_hash_table_destroy(osm_node_isin);
1511 osm_planet_parser_init(void)
1513 xp=XML_ParserCreate(NULL);
1514 XML_SetElementHandler(xp, _osm_tag_start, _osm_tag_end);
1519 osm_planet_parser_deinit(void)
1526 osm_planet_parse_buffer(gchar *buffer, size_t r)
1528 if (XML_Parse(xp, buffer, r, r>0 ? 0:1) == XML_STATUS_ERROR) {
1529 g_printerr("Parse error at line %d:\n%s\n",
1530 XML_GetCurrentLineNumber(xp),
1531 XML_ErrorString(XML_GetErrorCode(xp)));
1538 osm_planet_parse_file(gchar *pfile)
1544 gchar buffer[FILE_BUFFER];
1547 f=fopen(pfile, "r");
1551 b=BZ2_bzReadOpen(&bzerror, f, 0, 0, NULL, 0);
1552 if (bzerror != BZ_OK) {
1553 BZ2_bzReadClose(&bzerror, b);
1558 r=BZ2_bzRead(&bzerror, b, buffer, FILE_BUFFER);
1559 if ((bzerror!=BZ_STREAM_END) && (bzerror!=BZ_OK)) {
1563 if (!osm_planet_parse_buffer(buffer, r)) {
1567 } while (bzerror==BZ_OK);
1569 BZ2_bzReadClose(&bzerror, b);
1574 /************************************************************************/
1577 print_fail(const gchar *msg, gint ret)
1579 g_printerr("ERROR: %s\n", msg);
1583 /************************************************************************/
1586 print_memory_usage(void)
1588 g_print("Memory usage per item:\n");
1589 g_printf("Node size: %d\n", (int)sizeof(node));
1590 g_printf("NodeD size: %d\n", (int)sizeof(node_data));
1591 g_printf("Way size: %d\n", (int)sizeof(way));
1592 g_printf("WayD size: %d\n", (int)sizeof(way_data));
1595 /************************************************************************/
1597 int main (int argc, char **argv)
1600 return print_fail("Give bzip2 compressed planet XML file as argument", 1);
1602 g_printf("Using file: %s\n", argv[1]);
1607 bbox.lat_min=atof(argv[2]);
1608 bbox.lon_min=atof(argv[3]);
1609 bbox.lat_max=atof(argv[4]);
1610 bbox.lon_max=atof(argv[5]);
1611 g_printf("Skipping data outside of box: %f,%f - %f,%f\n",
1612 bbox.lat_min, bbox.lon_min,
1613 bbox.lat_max, bbox.lon_max);
1614 g_print("Note: missing nodes can't be reported.\n");
1615 } else use_bbox=FALSE;
1617 if (db_connect(&db, OSM_DB_FILE)!=TRUE)
1618 return print_fail("Database open failed", 2);
1621 print_memory_usage();
1623 osm_planet_parser_init();
1624 if (osm_planet_parse_file(argv[1])==FALSE)
1627 g_printf("Total nodes %d, POIs: %d and Ways %d.\n", node_cnt, noded_cnt, way_cnt);
1628 g_printf("Cities/Towns: %d\n", g_hash_table_size(osm_place_city));
1629 g_printf("Villages/Hamlets: %d\n", g_hash_table_size(osm_place_village));
1630 g_printf("Suburbs: %d\n", g_hash_table_size(osm_place_suburb));
1632 osm_planet_save_all_nodes();
1633 osm_planet_save_all_ways();
1634 osm_planet_parser_deinit();
1637 g_printf("Named ways: %d, Numbered ways: %d\n", way_names, way_refs);