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.
25 #include <sys/types.h>
28 #include <glib/gstdio.h>
29 #include <glib/gi18n.h>
38 #include "osm-sql-tables.h"
40 /* #define DEBUG_OSM */
41 #define DEBUG_OSM_TIME
42 #define OSM_PLACE_CACHE_MAX_ITEMS (64)
44 #define OSM_DB_PROGRESS_NUM (30000)
46 /* Node search ranges */
47 #define OSM_RANGE_START (16384*2)
48 #define OSM_RANGE_STEP (8192)
49 #define OSM_RANGE_STOP (65535)
51 /* Way range for searching again */
52 #define OSM_RANGE_WAY (12000)
55 #define QT_START { g_timer_start(dbt); }
56 #define QT_END { g_timer_stop(dbt); g_debug("Query took: %f sec", g_timer_elapsed(dbt, &tms)); }
62 static sqlite3 *osmdb;
63 static gboolean osm_db_ok;
65 struct sql_select_stmt {
66 sqlite3_stmt *select_way;
67 sqlite3_stmt *select_way2;
68 sqlite3_stmt *select_way_next_seg;
69 sqlite3_stmt *select_way_prev_seg;
71 sqlite3_stmt *select_way_nodes;
72 sqlite3_stmt *select_way_name;
73 sqlite3_stmt *select_way_name_nls;
74 sqlite3_stmt *select_way_name_search;
75 sqlite3_stmt *select_way_ref;
76 sqlite3_stmt *select_place;
77 sqlite3_stmt *select_place_near;
78 sqlite3_stmt *select_place_search;
80 sqlite3_stmt *select_node_next;
81 sqlite3_stmt *select_node_prev;
83 static struct sql_select_stmt sql;
86 static GtkProgressBar *dbpw=NULL;
88 static const gchar *osm_tables[]={
93 OSM_TABLE_WAY_UPDATES,
97 OSM_TABLE_WAY_NAMES_NLS,
101 OSM_TABLE_POI_CATEGORY,
104 static const gchar *osm_indexes[]={
125 /* Cache hash tables */
126 struct osm_place_cache {
131 static struct osm_place_cache pcache;
133 static guint way_dist_range=OSM_RANGE_WAY;
136 osm_way_node *osm_way_get_prev_node(osm_way *w);
137 osm_way_node *osm_way_get_next_node(osm_way *w);
139 /*****************************************************************************/
142 osm_db_create(sqlite3 *db)
144 return db_exec_sql_array(db, osm_tables) && db_exec_sql_array(db, osm_indexes);
147 /*****************************************************************************/
150 osm_set_way_range(guint sr)
153 g_debug("way_range set to %d", sr);
157 osm_set_way_range_from_speed(gfloat speed)
159 osm_set_way_range(speed>54.0 ? OSM_RANGE_WAY : (OSM_RANGE_WAY-lrint((speed/4)*1000)));
162 /*****************************************************************************/
165 osm_progress_pulse(void)
169 gtk_progress_bar_pulse(dbpw);
174 osm_progress(void *ud)
176 g_debug("SQL: Running gtk mainloop");
178 while (gtk_events_pending())
179 gtk_main_iteration();
181 gtk_main_iteration_do(FALSE);
187 osm_progress_hide(sqlite3 *db)
191 gtk_progress_bar_set_text(dbpw, "");
192 gtk_progress_bar_set_fraction(dbpw, 0.0);
196 osm_progress_show(sqlite3 *db)
200 gtk_progress_bar_set_text(dbpw, _("Searching..."));
201 gtk_progress_bar_pulse(dbpw);
202 gtk_main_iteration_do(FALSE);
206 osm_progress_set_widget(sqlite3 *db, GtkProgressBar *w)
208 if (dbpw!=NULL && w==NULL) {
209 osm_progress_hide(db);
211 g_source_remove(sid);
218 osm_progress_show(db);
219 sid=g_timeout_add(330, (GSourceFunc)osm_progress_pulse, NULL);
223 /*****************************************************************************/
226 osm_db_prepare(sqlite3 *db)
232 /* Select nearest place inside lat,lon+-range */
233 DB_PREP(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d,"
234 " ilat,ilon,places.nid,isin_p,isin_c "
235 " from places,nodes where type=$TYPE "
236 " and nodes.nid=places.nid "
237 " and ilat between $LAT-$RANGE and $LAT+$RANGE "
238 " and ilon between $LON-$RANGE and $LON+$RANGE "
239 " order by d limit 1",
240 sql.select_place_near);
242 /* Select place name, distance, location, parent-place and type with given ID */
243 DB_PREP(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d,"
244 " ilat,ilon,type,isin_p,isin_c "
245 " from places,nodes where "
246 " nodes.nid=places.nid "
247 " and places.nid=$NID order by d limit 1",
250 /* Search place names */
251 DB_PREP(db, "select places.nid,name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d,"
252 " rlat,rlon,type,isin_p,isin_c "
253 " from places,nodes where "
254 " nodes.nid=places.nid "
255 " and name like $NAME order by d limit 200",
256 sql.select_place_search);
258 /***********************
259 * Way related queries *
260 ***********************/
262 /* Select nearest ways inside lat,lon+-range */
263 DB_PREP(db, "select w.wid,type,nodes,flags,"
264 "(($LAT-n.ilat)*($LAT-n.ilat))+(($LON-n.ilon)*($LON-n.ilon)) as d,wn.f,wn.t,n.ilat,n.ilon "
265 " from way as w,way_n2n as wn,nodes as n "
266 " where w.wid=wn.wid and wn.f=n.nid "
267 " and n.ilat between $LAT-$RANGE and $LAT+$RANGE "
268 " and n.ilon between $LON-$RANGE and $LON+$RANGE "
269 " and w.type between $WTS and $WTY "
273 /* Search way names inside bbox, using both primary and secondary language names */
274 DB_PREP(db, "select w.wid,w.name as name,"
275 "(($LAT-ww.lat)*($LAT-ww.lat))+(($LON-ww.lon)*($LON-ww.lon)) as d,ww.lat,ww.lon "
276 " from way_names as w,way as ww where "
277 " ww.type between $WTS and $WTY and w.wid=ww.wid and w.name like $NAME "
278 " and ww.lat between $LAT-$RANGE and $LAT+$RANGE "
279 " and ww.lon between $LON-$RANGE and $LON+$RANGE "
281 " select w.wid,n.name as name,"
282 "(($LAT-ww.lat)*($LAT-ww.lat))+(($LON-ww.lon)*($LON-ww.lon)) as d,ww.lat,ww.lon "
283 " from way_names as w, way as ww,way_names_nls as n on w.wid=n.wid where "
284 " ww.type between $WTS and $WTY and w.wid=ww.wid and n.name like $NAME "
285 " and ww.lat between $LAT-$RANGE and $LAT+$RANGE "
286 " and ww.lon between $LON-$RANGE and $LON+$RANGE "
287 " order by d, name limit 500",
288 sql.select_way_name_search);
290 /* Get way segment */
291 DB_PREP(db, "select wn.t,ilat,ilon from way_n2n as wn,nodes where wid=? and wn.f=? and wn.t=nodes.nid limit 1",
292 sql.select_way_next_seg);
294 /* Get way segment */
295 DB_PREP(db, "select wn.f,ilat,ilon from way_n2n as wn,nodes where wid=? and wn.t=? and wn.f=nodes.nid limit 1",
296 sql.select_way_prev_seg);
299 DB_PREP(db, "select name from way_names where wid=?", sql.select_way_name);
301 /* Get Way ref and int_ref */
302 DB_PREP(db, "select ref,int_ref from way_ref where rid=?", sql.select_way_ref);
304 /* Get way all way nodes */
305 DB_PREP(db, "select wn.f,ilat,ilon from way_n2n as wn,nodes where wid=? and wn.f=nodes.nid", sql.select_way_nodes);
307 /* Get next, prev node + way information. For routing. */
308 DB_PREP(db, "select w.wid,w.type,w.flags,w.speed,n.nid,n.rlat,n.rlon,nn.f,nn.t,n.f,n.l "
309 "from way as w, nodes as n, way_n2n as nn where w.wid=nn.wid and nn.f=n.nid and nn.f=?",
310 sql.select_node_next);
312 DB_PREP(db, "select w.wid,w.type,w.flags,w.speed,n.nid,n.rlat,n.rlon,nn.f,nn.t,n.f,n.l "
313 "from way as w, nodes as n, way_n2n as nn where w.wid=nn.wid and nn.f=n.nid and nn.t=?",
314 sql.select_node_prev);
323 if (sql.select_way_ref)
324 sqlite3_finalize(sql.select_way_ref);
325 if (sql.select_way_name)
326 sqlite3_finalize(sql.select_way_name);
327 if (sql.select_way_next_seg)
328 sqlite3_finalize(sql.select_way_next_seg);
329 if (sql.select_way_prev_seg)
330 sqlite3_finalize(sql.select_way_prev_seg);
331 if (sql.select_way_name_search)
332 sqlite3_finalize(sql.select_way_name_search);
334 sqlite3_finalize(sql.select_way2);
335 if (sql.select_place)
336 sqlite3_finalize(sql.select_place);
337 if (sql.select_place_near)
338 sqlite3_finalize(sql.select_place_near);
339 if (sql.select_node_next)
340 sqlite3_finalize(sql.select_node_next);
341 if (sql.select_node_prev)
342 sqlite3_finalize(sql.select_node_prev);
346 memset(&sql, 0, sizeof(sql));
347 g_hash_table_destroy(pcache.cache);
351 g_timer_destroy(dbt);
355 osm_init(sqlite3 **db)
358 pcache.cache=g_hash_table_new(g_direct_hash, g_direct_equal);
367 memset(&sql, 0, sizeof(sql));
368 if (osm_db_create(osmdb)==FALSE) {
369 g_printerr("Failed to create OSM tables or indexes: %s", sqlite3_errmsg(osmdb));
373 if (osm_db_prepare(osmdb)==FALSE) {
374 g_printerr("Failed to prepare OSM SQL statements: %s", sqlite3_errmsg(osmdb));
382 osm_db_enable_mainloop(sqlite3 *db, gboolean eml)
385 sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, NULL, NULL);
387 sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, osm_progress, NULL);
390 /*****************************************************************************/
393 osm_way_node_new(guint id, gint lat, gint lon, gint flags)
395 osm_way_node *n=g_slice_new(osm_way_node);
405 osm_way_node_free(osm_way_node *n)
408 g_slice_free(osm_way_node, n);
412 * Free way nodes list
415 osm_way_nodes_free(osm_way *w)
422 for (iter=w->nodes; iter!=NULL; iter=iter->next)
423 g_slice_free(osm_way_node, (osm_way_node*)iter->data);
425 g_list_free(w->nodes);
429 * Free a osm_way structure
432 osm_way_free(osm_way *w)
436 osm_way_nodes_free(w);
443 g_slice_free(osm_way, w);
446 /*****************************************************************************/
449 osm_place_free(osm_place *p)
453 g_slice_free(osm_place, p);
457 osm_place_remove(gpointer k, gpointer v, gpointer ud)
459 osm_place_free((osm_place *)v);
466 return g_slice_new0(osm_place);
470 osm_place_cache_lookup(guint32 id)
473 r=g_hash_table_lookup(pcache.cache, GINT_TO_POINTER(id));
479 g_debug("OSM: Cache %d/%d", pcache.hit, pcache.miss);
484 osm_place_cache_add(osm_place *p)
486 if (osm_place_cache_lookup(p->id)==NULL)
487 g_hash_table_insert(pcache.cache, GINT_TO_POINTER(p->id), p);
491 osm_place_cache_gc(void)
495 r=g_hash_table_foreach_remove(pcache.cache, osm_place_remove, NULL);
496 g_debug("OSM: Cache cleared (%d)", r);
502 osm_place_update_distance(osm_place *p, gint lat, gint lon)
506 lam=(gdouble)((lat-p->lat)*(lat-p->lat));
507 lom=(gdouble)((lon-p->lon)*(lon-p->lon));
509 p->dist=sqrt(lam+lom);
513 * Get place with given id and distance to current location
516 osm_place_get(guint32 id, gint lat, gint lon, osm_place **nr)
520 g_return_val_if_fail(sql.select_place, FALSE);
523 n=osm_place_cache_lookup(id);
525 osm_place_update_distance(n, lat, lon);
530 /* XXX: better place for this */
531 if (g_hash_table_size(pcache.cache)>OSM_PLACE_CACHE_MAX_ITEMS)
532 osm_place_cache_gc();
534 sqlite3_clear_bindings(sql.select_place);
535 sqlite3_reset(sql.select_place);
537 if (SQLITE_OK != sqlite3_bind_int(sql.select_place, 1, lat) ||
538 SQLITE_OK != sqlite3_bind_int(sql.select_place, 2, lon) ||
539 SQLITE_OK != sqlite3_bind_int(sql.select_place, 3, id)) {
540 g_warning("Failed to bind values for place");
545 if (SQLITE_ROW == sqlite3_step(sql.select_place)) {
550 place=sqlite3_column_text(sql.select_place, 0);
551 n->name=g_strdup(place);
552 dist=sqlite3_column_int(sql.select_place, 1);
553 n->dist=sqrt((double)dist);
554 n->lat=sqlite3_column_int(sql.select_place, 2);
555 n->lon=sqlite3_column_int(sql.select_place, 3);
556 n->type=sqlite3_column_int(sql.select_place, 4);
557 n->isin_p=sqlite3_column_int(sql.select_place, 5);
558 /* n->isin_c=sqlite3_column_int(sql.select_place, 6); */
566 * Search for the nearest place with given type
569 osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place **nr)
574 g_return_val_if_fail(sql.select_place_near, FALSE);
577 case NODE_PLACE_SUBURB:
580 case NODE_PLACE_CITY:
581 case NODE_PLACE_TOWN:
584 case NODE_PLACE_HAMLET:
585 case NODE_PLACE_VILLAGE:
593 sqlite3_clear_bindings(sql.select_place_near);
594 sqlite3_reset(sql.select_place_near);
596 if (SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 1, lat) ||
597 SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 2, lon) ||
598 SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 3, type) ||
599 SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 4, range)) {
600 g_warning("Failed to bind values for near place");
605 n->isin_p=n->lat=n->lon=n->dist=0;
607 if (SQLITE_ROW == sqlite3_step(sql.select_place_near)) {
611 place=sqlite3_column_text(sql.select_place_near, 0);
612 n->name=g_strdup(place);
613 dist=sqlite3_column_int(sql.select_place_near, 1);
614 n->dist=sqrt((double)dist);
615 n->lat=sqlite3_column_int(sql.select_place_near, 2);
616 n->lon=sqlite3_column_int(sql.select_place_near, 3);
617 n->id=sqlite3_column_int(sql.select_place_near, 4);
618 n->isin_p=sqlite3_column_int(sql.select_place_near, 5);
619 /* n->isin_c=sqlite3_column_int(sql.select_place_near, 6); */
623 osm_place_cache_add(n);
637 osm_find_nearest_way_nodes(gint lat, gint lon, guint range)
643 g_return_val_if_fail(sql.select_way2, NULL);
645 sqlite3_reset(sql.select_way2);
646 sqlite3_clear_bindings(sql.select_way2);
648 if (SQLITE_OK != sqlite3_bind_int(sql.select_way2, 1, lat) ||
649 SQLITE_OK != sqlite3_bind_int(sql.select_way2, 2, lon) ||
650 SQLITE_OK != sqlite3_bind_int(sql.select_way2, 3, range) ||
651 SQLITE_OK != sqlite3_bind_int(sql.select_way2, 4, WAY_ROAD_START) ||
652 SQLITE_OK != sqlite3_bind_int(sql.select_way2, 5, WAY_ROAD_END)) {
653 g_warning("Failed to bind values for way");
658 while (SQLITE_ROW == sqlite3_step(sql.select_way2)) {
663 w=g_slice_new0(osm_way);
664 w->id=sqlite3_column_int(sql.select_way2, 0);
665 w->type=sqlite3_column_int(sql.select_way2, 1);
666 w->nodecnt=sqlite3_column_int(sql.select_way2, 2);
667 w->flags=sqlite3_column_int(sql.select_way2, 3);
668 dist=sqlite3_column_int(sql.select_way2, 4);
669 w->dist=sqrt((gdouble)dist);
670 w->f=sqlite3_column_int(sql.select_way2, 5);
671 w->t=sqlite3_column_int(sql.select_way2, 6);
673 lat=sqlite3_column_int(sql.select_way2, 7);
674 lon=sqlite3_column_int(sql.select_way2, 8);
676 w->node_f=osm_way_node_new(w->f, lat, lon, 0);
678 ways=g_list_prepend(ways, w);
685 /*****************************************************************************/
688 osm_get_route_node(guint nid, osm_node_direction d)
693 sqlite3_stmt *psql=NULL;
695 g_return_val_if_fail(sql.select_node_next, FALSE);
696 g_return_val_if_fail(sql.select_node_prev, FALSE);
700 psql=sql.select_node_next;
703 psql=sql.select_node_prev;
706 g_assert_not_reached();
711 sqlite3_clear_bindings(psql);
713 if (SQLITE_OK != sqlite3_bind_int(psql, 1, nid)) {
714 g_warning("Failed to bind values for route node");
718 while (SQLITE_ROW == sqlite3_step(psql)) {
722 w=g_slice_new0(osm_way);
723 w->id=sqlite3_column_int(psql, 0);
724 w->type=sqlite3_column_int(psql, 1);
725 w->flags=sqlite3_column_int(psql, 2);
726 w->speed=sqlite3_column_int(psql, 3);
728 lat=sqlite3_column_double(psql, 5);
729 lon=sqlite3_column_double(psql, 6);
731 w->f=sqlite3_column_int(psql, 7);
732 w->t=sqlite3_column_int(psql, 8);
735 w->node->flags=sqlite3_column_int(psql, 9);
736 w->node->links=sqlite3_column_int(psql, 10);
739 r=g_slist_prepend(r, w);
746 /*****************************************************************************/
748 osm_way_distance(gint lat, gint lon, osm_way_node *f, osm_way_node *t, gdouble *d)
758 return distance_point_to_line((gdouble)lon, (gdouble)lat, (gdouble)f->lon, (gdouble)f->lat, (gdouble)t->lon, (gdouble)t->lat, d);
762 * Search for the nearest way (road)
763 * - First search for ways with nearest node
764 * - If only one is returned then we are done.
765 * - If more than one, go trough the results:
766 * - Load nodes for the way, check prev/next nodes
767 * - Store result if closer than before
768 * - Return closest way
771 #define START_DIST (900000.0)
774 osm_find_nearest_way(gint lat, gint lon)
778 guint range=OSM_RANGE_START;
781 gdouble pdist=START_DIST, dist_n, dist_p;
783 while ((w=osm_find_nearest_way_nodes(lat, lon, range))==NULL && range<=OSM_RANGE_STOP) {
784 range+=OSM_RANGE_STEP;
785 g_debug("Trying with range: %d", range);
787 found_ways=g_list_length(w);
788 g_debug("Found %d ways withing range %d", found_ways, range);
793 for (iter=w; iter!=NULL; iter=iter->next) {
796 osm_way *way=(osm_way*)iter->data;
800 wnn=osm_way_get_next_node(way);
801 if (osm_way_distance(lat, lon, way->node_f, wnn, &dist_n)==FALSE) {
802 osm_way_node_free(wnn);
804 } else if (dist_n<pdist) { /* Is it near ?*/
807 way->distance=dist_n;
813 g_debug("WayN: #%d (T:%d), %d nodes, near [%d-%d], D: %.2f (Valid: %s)",
814 way->id, way->type, way->nodecnt, way->f, way->t, dist_n, dist_n==START_DIST ? "F" : "T");
816 wnp=osm_way_get_prev_node(way);
817 if (osm_way_distance(lat, lon, way->node_f, wnp, &dist_p)==FALSE) {
818 osm_way_node_free(wnp);
820 } else if (dist_p<pdist) {
823 way->distance=dist_n;
825 osm_way_node_free(wnn);
832 g_debug("WayP: #%d (T:%d), %d nodes, near [%d-%d], D: %.2f (Valid: %s)",
833 way->id, way->type, way->nodecnt, way->f, way->t, dist_p, dist_p==START_DIST ? "F" : "T");
845 osm_way_get_name(cw);
846 if (cw->type==WAY_MOTORWAY || cw->type==WAY_TRUNK ||
847 cw->type==WAY_PRIMARY || cw->type==WAY_SECONDARY || cw->type==WAY_TERTIARY) {
850 osm_way_get_nodes(cw);
852 g_debug("Found: (#%d): [%s]:[%s][%s]", cw->id, cw->name, cw->ref, cw->int_ref);
853 g_debug("T: %d F: %d N#: %d D: %.2f", cw->type, cw->flags, cw->nodecnt, cw->dist);
854 g_debug("NF#: %d NT#: %d (DC: %.2f)", cw->f, cw->t, cw->distance);
859 /* XXX: These two should be combined to save memory */
861 * Get previous node/segment of given way node
865 osm_way_get_prev_node(osm_way *w)
867 g_return_val_if_fail(sql.select_way_prev_seg, NULL);
869 sqlite3_reset(sql.select_way_prev_seg);
870 sqlite3_clear_bindings(sql.select_way_prev_seg);
872 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_prev_seg, 1, w->id) ||
873 SQLITE_OK != sqlite3_bind_int(sql.select_way_prev_seg, 2, w->f) ) {
874 g_warning("Failed to bind values for prev seg");
878 if (SQLITE_ROW == sqlite3_step(sql.select_way_prev_seg)) {
879 return osm_way_node_new(
880 sqlite3_column_int(sql.select_way_prev_seg, 0),
881 sqlite3_column_int(sql.select_way_prev_seg, 1),
882 sqlite3_column_int(sql.select_way_prev_seg, 2),
890 * Get next node/segment of given way node
894 osm_way_get_next_node(osm_way *w)
896 g_return_val_if_fail(sql.select_way_next_seg, NULL);
898 sqlite3_reset(sql.select_way_next_seg);
899 sqlite3_clear_bindings(sql.select_way_next_seg);
901 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_next_seg, 1, w->id) ||
902 SQLITE_OK != sqlite3_bind_int(sql.select_way_next_seg, 2, w->f) ) {
903 g_warning("Failed to bind values for next seg");
907 if (SQLITE_ROW == sqlite3_step(sql.select_way_next_seg)) {
908 return osm_way_node_new(
909 sqlite3_column_int(sql.select_way_next_seg, 0),
910 sqlite3_column_int(sql.select_way_next_seg, 1),
911 sqlite3_column_int(sql.select_way_next_seg, 2),
919 * Get list of nodes for given way
923 osm_way_get_nodes(osm_way *w)
928 g_return_val_if_fail(sql.select_way_nodes, FALSE);
930 sqlite3_reset(sql.select_way_nodes);
931 sqlite3_clear_bindings(sql.select_way_nodes);
933 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_nodes, 1, w->id)) {
934 g_warning("Failed to bind values for way nodes");
938 while (SQLITE_ROW == sqlite3_step(sql.select_way_nodes)) {
941 n=g_slice_new(osm_way_node);
942 n->id=sqlite3_column_int(sql.select_way_nodes, 0);
943 n->lat=sqlite3_column_int(sql.select_way_nodes, 1);
944 n->lon=sqlite3_column_int(sql.select_way_nodes, 2);
945 w->nodes=g_list_append(w->nodes, n);
948 return (w->nodes==NULL) ? FALSE : TRUE;
956 osm_way_get_name(osm_way *w)
958 g_return_val_if_fail(sql.select_way_name, FALSE);
960 sqlite3_reset(sql.select_way_name);
961 sqlite3_clear_bindings(sql.select_way_name);
963 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name, 1, w->id)) {
964 g_warning("Failed to bind values for way name");
968 if (SQLITE_ROW == sqlite3_step(sql.select_way_name)) {
970 place=sqlite3_column_text(sql.select_way_name, 0);
971 w->name=g_strdup(place);
978 osm_way_get_name_nls(osm_way *w)
980 g_return_val_if_fail(sql.select_way_name_nls, FALSE);
982 sqlite3_reset(sql.select_way_name_nls);
983 sqlite3_clear_bindings(sql.select_way_name_nls);
985 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name_nls, 1, w->id) ||
986 SQLITE_OK != sqlite3_bind_) {
987 g_warning("Failed to bind values for way name nls");
991 if (SQLITE_ROW == sqlite3_step(sql.select_way_name_nls)) {
993 place=sqlite3_column_text(sql.select_way_name_nls, 0);
994 w->name=g_strdup(place);
1002 * Get Way ref and int_ref
1006 osm_way_get_ref(osm_way *w)
1008 g_return_val_if_fail(sql.select_way_ref, FALSE);
1010 sqlite3_reset(sql.select_way_ref);
1011 sqlite3_clear_bindings(sql.select_way_ref);
1013 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_ref, 1, w->id)) {
1014 g_warning("Failed to bind values for way ref");
1018 if (SQLITE_ROW == sqlite3_step(sql.select_way_ref)) {
1019 const gchar *ref, *int_ref;
1020 ref=sqlite3_column_text(sql.select_way_ref, 0);
1021 int_ref=sqlite3_column_text(sql.select_way_ref, 1);
1022 w->ref=g_strdup(ref);
1023 w->int_ref=g_strdup(int_ref);
1028 /******************************************************************************/
1031 * Check if we have moved away from the last known street
1034 osm_check_location(osm_location *map_loc, gint lat, gint lon)
1037 if (map_loc->street && osm_way_distance(lat, lon, map_loc->street->node_f, map_loc->street->node_t, &dist)==TRUE) {
1038 return (dist>(gdouble)way_dist_range) ? FALSE : TRUE;
1044 * Try to figure out where the given lat,lon is. Fills in the given struct,
1045 * with street, secondary (suburb) and primary (city,town,village) location.
1046 * Will try to minimize the amount of database access by skipping queries
1047 * if we haven't moved or if we don't know where we are.
1051 osm_get_location_data(gint lat, gint lon, gfloat heading, osm_location *map_loc)
1054 gboolean check_place=FALSE;
1057 /* Check 10 times, if location is not known then assume we are in here-be-dragons land */
1058 if (map_loc->nfcnt>10) {
1060 t=time(NULL)-map_loc->last_valid;
1062 g_debug("Here be dragons");
1065 g_debug("Trying again");
1066 map_loc->last_valid=time(NULL);
1068 map_loc->valid=FALSE;
1072 if (map_loc->valid==FALSE) {
1075 map_loc->valid=TRUE;
1078 d=calculate_idistance(lat,lon,map_loc->lat,map_loc->lon);
1081 /* Check if we are still near the same way as last time */
1082 if (map_loc->street && osm_way_distance(lat, lon, map_loc->street->node_f, map_loc->street->node_t, &dist)==TRUE) {
1083 /* We are probably on the same way as last time,
1084 but check if the distance is over a limit or our heading has changed significantly.
1086 if ( (dist>(gdouble)way_dist_range) || (fabs(angle_diff(heading, map_loc->heading))>15.0)) {
1087 /* We have moved a large amount, check way again */
1088 g_debug("Distance %.2f > %.2f range or angle %f > 15.0, checking location",
1089 dist, (gdouble)way_dist_range, fabs(heading-map_loc->heading));
1090 osm_way_free(map_loc->street);
1091 map_loc->street=osm_find_nearest_way(lat, lon);
1093 map_loc->changed=TRUE;
1095 g_debug("*** No change in location: %f %d", dist, way_dist_range);
1096 /* We are still on the same way as last time */
1098 map_loc->changed=FALSE;
1103 /* We didn't know our location, so check it, but only if we have moved */
1104 if (d>way_dist_range) {
1105 g_debug("*** Must check location");
1107 osm_way_free(map_loc->street);
1108 map_loc->street=osm_find_nearest_way(lat, lon);
1115 if (!map_loc->street) {
1116 g_debug("*** Street not known");
1118 map_loc->changed=TRUE;
1120 g_debug("*** Street known");
1122 map_loc->last_valid=time(NULL);
1123 map_loc->changed=TRUE;
1128 if (map_loc->changed==TRUE) {
1129 map_loc->heading=heading;
1132 g_debug("NotFoundCounter: %d", map_loc->nfcnt);
1133 g_debug("D: %ld %ld", d, (gulong)way_dist_range);
1135 if (check_place==TRUE || d>way_dist_range*4) {
1138 fs=osm_find_nearest_place(NODE_PLACE_SUBURB, lat, lon, &map_loc->secondary);
1139 if (fs==TRUE && map_loc->secondary && map_loc->secondary->isin_p!=0) {
1140 if (osm_place_get(map_loc->secondary->isin_p, lat, lon, &(map_loc->primary))==FALSE) {
1141 if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
1142 g_debug("Near city: %s", map_loc->primary->name);
1143 else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
1144 g_debug("Near town: %s", map_loc->primary->name);
1146 g_assert(map_loc->primary!=NULL);
1150 g_debug("In: %s", map_loc->primary ? map_loc->primary->name : "?");
1152 } else if (map_loc->street && map_loc->street->isin_p!=0) {
1153 if (osm_place_get(map_loc->street->isin_p, lat, lon, &map_loc->primary)==FALSE) {
1154 g_debug("Street location not know.");
1156 g_debug("Street is in: %s", map_loc->primary ? map_loc->primary->name : "?");
1159 if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
1160 g_debug("Near city: %s", map_loc->primary->name);
1161 else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
1162 g_debug("Near town: %s", map_loc->primary->name);
1164 g_assert(map_loc->primary!=NULL);
1170 return map_loc->street ? TRUE : FALSE;
1177 osm_place_search(gdouble lat, gdouble lon, gchar *text, GtkListStore **store)
1182 gchar tmp1[16], tmp2[16];
1185 g_return_val_if_fail(sql.select_place_search, FALSE);
1186 g_return_val_if_fail(text, FALSE);
1188 ltext=g_strdup_printf("%s%%", text);
1190 if (SQLITE_OK != sqlite3_bind_double(sql.select_place_search, 1, lat) ||
1191 SQLITE_OK != sqlite3_bind_double(sql.select_place_search, 2, lon) ||
1192 SQLITE_OK != sqlite3_bind_text(sql.select_place_search, 3, ltext, -1, SQLITE_TRANSIENT)) {
1193 g_warning("Failed to bind values for sql.select_place_search");
1194 sqlite3_clear_bindings(sql.select_place_search);
1202 *store = gtk_list_store_new(ITEM_NUM_COLUMNS,
1203 G_TYPE_INT, /* ID */
1205 G_TYPE_DOUBLE, /* Latitude */
1206 G_TYPE_DOUBLE, /* Longitude */
1207 G_TYPE_DOUBLE, /* Distance */
1208 G_TYPE_STRING, /* Lat/Lon */
1209 G_TYPE_STRING, /* Label */
1210 G_TYPE_STRING, /* Desc. */
1211 G_TYPE_STRING, /* Category */
1212 G_TYPE_STRING, /* Dummy */
1213 G_TYPE_STRING); /* Dummy */
1215 while (SQLITE_ROW == sqlite3_step(sql.select_place_search)) {
1216 gdouble rlat, rlon, dist;
1218 rlat=sqlite3_column_double(sql.select_place_search, 3);
1219 rlon=sqlite3_column_double(sql.select_place_search, 4);
1220 lat_format(_degformat, rlat, tmp1);
1221 lon_format(_degformat, rlon, tmp2);
1222 dist=calculate_distance(lat, lon, rlat, rlon) * UNITS_CONVERT[_units];
1224 gtk_list_store_append(*store, &iter);
1225 gtk_list_store_set(*store, &iter,
1226 ITEM_ID, sqlite3_column_int(sql.select_place_search, 0),
1230 ITEM_LATLON, g_strdup_printf("%s, %s", tmp1, tmp2),
1231 ITEM_LABEL, sqlite3_column_text(sql.select_place_search, 1),
1236 g_debug("Found: %d places", rows);
1238 sqlite3_reset(sql.select_place_search);
1239 sqlite3_clear_bindings(sql.select_place_search);
1247 * Search for a street(way) starting with given 'text', next given lat/lon
1251 osm_way_search(gdouble lat, gdouble lon, gchar *text, GtkListStore **store)
1256 gchar tmp1[16], tmp2[16];
1259 g_return_val_if_fail(sql.select_way_name_search, FALSE);
1260 g_return_val_if_fail(text, FALSE);
1262 g_debug("Way Search: [%s] around %.6f %.6f", text, lat, lon);
1264 ltext=g_strdup_printf("%s%%", text);
1266 if (SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 1, lat) ||
1267 SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 2, lon) ||
1268 SQLITE_OK != sqlite3_bind_int(sql.select_way_name_search, 3, WAY_ROAD_START) ||
1269 SQLITE_OK != sqlite3_bind_int(sql.select_way_name_search, 4, WAY_ROAD_END) ||
1270 SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 6, range) ||
1271 SQLITE_OK != sqlite3_bind_text(sql.select_way_name_search, 5, ltext, -1, SQLITE_TRANSIENT)) {
1272 g_warning("Failed to bind values for sql.select_way_name_search");
1273 sqlite3_clear_bindings(sql.select_way_name_search);
1281 *store = gtk_list_store_new(ITEM_NUM_COLUMNS,
1282 G_TYPE_INT, /* ID */
1284 G_TYPE_DOUBLE, /* Latitude */
1285 G_TYPE_DOUBLE, /* Longitude */
1286 G_TYPE_DOUBLE, /* Distance */
1287 G_TYPE_STRING, /* Lat/Lon */
1288 G_TYPE_STRING, /* Label */
1289 G_TYPE_STRING, /* Desc. */
1290 G_TYPE_STRING, /* Category */
1291 G_TYPE_STRING, /* Dummy */
1292 G_TYPE_STRING); /* Dummy */
1294 while (SQLITE_ROW == sqlite3_step(sql.select_way_name_search)) {
1295 gdouble rlat, rlon, dist;
1297 rlat=sqlite3_column_double(sql.select_way_name_search, 3);
1298 rlon=sqlite3_column_double(sql.select_way_name_search, 4);
1299 lat_format(_degformat, rlat, tmp1);
1300 lon_format(_degformat, rlon, tmp2);
1301 dist=calculate_distance(lat, lon, rlat, rlon) * UNITS_CONVERT[_units];
1303 gtk_list_store_append(*store, &iter);
1304 gtk_list_store_set(*store, &iter,
1305 ITEM_ID, sqlite3_column_int(sql.select_way_name_search, 0),
1309 ITEM_LATLON, g_strdup_printf("%s, %s", tmp1, tmp2),
1310 ITEM_LABEL, sqlite3_column_text(sql.select_way_name_search, 1),
1315 g_debug("Found: %d items", rows);
1317 sqlite3_reset(sql.select_way_name_search);
1318 sqlite3_clear_bindings(sql.select_way_name_search);