9 #include <glib/gstdio.h>
18 /* #define DEBUG_OSM */
19 #define OSM_PLACE_CACHE_MAX_ITEMS (64)
20 #define OSM_DB_PROGRESS_NUM (5000)
21 #define OSM_RANGE_START (8192)
22 #define OSM_RANGE_STEP (8192)
23 #define OSM_RANGE_STOP (49152)
25 struct sql_select_stmt {
26 sqlite3_stmt *select_way;
27 sqlite3_stmt *select_way2;
28 sqlite3_stmt *select_way_next_seg;
29 sqlite3_stmt *select_way_prev_seg;
31 sqlite3_stmt *select_way_nodes;
32 sqlite3_stmt *select_way_name;
33 sqlite3_stmt *select_way_name_nls;
34 sqlite3_stmt *select_way_ref;
35 sqlite3_stmt *select_place;
36 sqlite3_stmt *select_near_place;
38 static struct sql_select_stmt sql;
40 static GtkProgressBar *dbpw=NULL;
42 /* Cache hash tables */
43 static GHashTable *_place_cache;
45 static guint way_dist_range=OSM_RANGE_WAY;
47 osm_way_node *osm_way_get_prev_node(osm_way *w);
48 osm_way_node *osm_way_get_next_node(osm_way *w);
50 /*****************************************************************************/
53 osm_set_way_range(guint sr)
59 osm_set_way_range_from_speed(gfloat speed)
62 way_dist_range=OSM_RANGE_WAY*2;
64 way_dist_range=OSM_RANGE_WAY-lrint((speed/4)*1000);
68 osm_progress(void *ud)
72 gtk_progress_bar_pulse(dbpw);
73 gtk_main_iteration_do(FALSE);
78 osm_progress_hide(sqlite3 *db)
82 gtk_widget_hide(GTK_WIDGET(dbpw));
83 sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, NULL, NULL);
87 osm_progress_show(sqlite3 *db)
91 gtk_widget_show(GTK_WIDGET(dbpw));
92 sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, osm_progress, NULL);
96 osm_progress_set_widget(sqlite3 *db, GtkProgressBar *w)
98 if (dbpw!=NULL && w==NULL)
99 osm_progress_hide(db);
102 osm_progress_show(db);
106 osm_db_prepare(sqlite3 *db)
109 /* Select nearest place inside lat,lon+-range */
110 if (sqlite3_prepare_v2(db, "select name,(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist,"
111 " lat,lon,places.nid,isin "
112 " from places,nodes where type=$TYPE "
113 " and nodes.nid=places.nid "
114 " and lat between $LAT-$RANGE and $LAT+$RANGE"
115 " and lon between $LON-$RANGE and $LON+$RANGE order by dist limit 1",
116 -1, &sql.select_near_place, NULL)!=SQLITE_OK)
119 /* Select place name, distance, location, parent-place and type with given ID */
120 if (sqlite3_prepare_v2(db, "select name,(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist,"
121 " lat,lon,type,isin "
122 " from places,nodes where "
123 " nodes.nid=places.nid "
124 " and places.nid=$NID order by dist limit 1",
125 -1, &sql.select_place, NULL)!=SQLITE_OK)
129 /* Select neareset ways inside lat,lon+-range */
130 if (sqlite3_prepare_v2(db, "select wid,type,nodes,flags,"
131 "(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as d,f,t,lat,lon "
132 " from way as w,way_s2s as ws,nodes as n "
133 " where w.wid=ws.wsid and ws.f=n.nid "
134 " and n.lat between $LAT-$RANGE and $LAT+$RANGE "
135 " and n.lon between $LON-$RANGE and $LON+$RANGE "
136 " and w.type between $WTS and $WTY "
138 -1, &sql.select_way2, NULL)!=SQLITE_OK)
141 if (sqlite3_prepare_v2(db, "select t,lat,lon from way_s2s,nodes where wsid=? and f=? and way_s2s.t=nodes.nid limit 1",
142 -1, &sql.select_way_next_seg, NULL)!=SQLITE_OK)
145 if (sqlite3_prepare_v2(db, "select f,lat,lon from way_s2s,nodes where wsid=? and t=? and way_s2s.f=nodes.nid limit 1",
146 -1, &sql.select_way_prev_seg, NULL)!=SQLITE_OK)
150 if (sqlite3_prepare_v2(db, "select name from way_names where wid=?",
151 -1, &sql.select_way_name, NULL)!=SQLITE_OK)
154 if (sqlite3_prepare_v2(db, "select name from way_names_nls where wid=? and lang=?",
155 -1, &sql.select_way_name, NULL)!=SQLITE_OK)
159 /* Way ref and int_ref */
160 if (sqlite3_prepare_v2(db, "select ref,int_ref from way_ref where rid=?",
161 -1, &sql.select_way_ref, NULL)!=SQLITE_OK)
170 _place_cache=g_hash_table_new(g_direct_hash, g_direct_equal);
178 g_hash_table_destroy(_place_cache);
179 g_timer_destroy(dbt);
182 /*****************************************************************************/
185 osm_way_node_new(guint id, gint lat, gint lon, gint flags)
187 osm_way_node *n=g_slice_new(osm_way_node);
197 osm_way_node_free(osm_way_node *n)
200 g_slice_free(osm_way_node, n);
204 * Free way nodes list
207 osm_way_nodes_free(osm_way *w)
214 for (iter=w->nodes; iter!=NULL; iter=iter->next)
215 g_slice_free(osm_way_node, (osm_way_node*)iter->data);
217 g_list_free(w->nodes);
221 * Free a osm_way structure
224 osm_way_free(osm_way *w)
228 osm_way_nodes_free(w);
235 g_slice_free(osm_way, w);
238 /*****************************************************************************/
241 osm_place_free(osm_place *p)
245 g_slice_free(osm_place, p);
249 osm_place_remove(gpointer k, gpointer v, gpointer ud)
251 osm_place_free((osm_place *)v);
258 return g_slice_new0(osm_place);
262 osm_place_cache_lookup(guint32 id)
264 return g_hash_table_lookup(_place_cache, GINT_TO_POINTER(id));
268 osm_place_cache_add(osm_place *p)
270 if (osm_place_cache_lookup(p->id)==NULL)
271 g_hash_table_insert(_place_cache, GINT_TO_POINTER(p->id), p);
275 osm_place_cache_gc(void)
278 r=g_hash_table_foreach_remove(_place_cache, osm_place_remove, NULL);
282 osm_place_update_distance(osm_place *p, gint lat, gint lon)
286 lam=(gdouble)((lat-p->lat)*(lat-p->lat));
287 lom=(gdouble)((lon-p->lon)*(lon-p->lon));
289 p->dist=sqrt(lam+lom);
293 * Get place with given id and distance to current location
296 osm_place_get(guint32 id, gint lat, gint lon, osm_place **nr)
301 n=osm_place_cache_lookup(id);
304 osm_place_update_distance(n, lat, lon);
309 /* XXX: better place for this */
310 if (g_hash_table_size(_place_cache)>OSM_PLACE_CACHE_MAX_ITEMS)
311 osm_place_cache_gc();
313 sqlite3_clear_bindings(sql.select_place);
314 sqlite3_reset(sql.select_place);
316 if (SQLITE_OK != sqlite3_bind_int(sql.select_place, 1, lat) ||
317 SQLITE_OK != sqlite3_bind_int(sql.select_place, 2, lon) ||
318 SQLITE_OK != sqlite3_bind_int(sql.select_place, 3, id)) {
319 g_printerr("Failed to bind values for place\n");
323 if (SQLITE_ROW == sqlite3_step(sql.select_place)) {
328 place=sqlite3_column_text(sql.select_place, 0);
329 n->name=g_strdup(place);
330 dist=sqlite3_column_int(sql.select_place, 1);
331 n->dist=sqrt((double)dist);
332 n->lat=sqlite3_column_int(sql.select_place, 2);
333 n->lon=sqlite3_column_int(sql.select_place, 3);
334 n->type=sqlite3_column_int(sql.select_place, 4);
335 n->isin=sqlite3_column_int(sql.select_place, 5);
342 * Search for the nearest place, type
345 osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place **nr)
351 case NODE_PLACE_SUBURB:
354 case NODE_PLACE_CITY:
355 case NODE_PLACE_TOWN:
358 case NODE_PLACE_HAMLET:
359 case NODE_PLACE_VILLAGE:
367 sqlite3_clear_bindings(sql.select_near_place);
368 sqlite3_reset(sql.select_near_place);
370 if (SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 1, lat) ||
371 SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 2, lon) ||
372 SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 3, type) ||
373 SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 4, range)) {
374 g_printerr("Failed to bind values for near place\n");
379 n->isin=n->lat=n->lon=n->dist=0;
380 if (SQLITE_ROW == sqlite3_step(sql.select_near_place)) {
384 place=sqlite3_column_text(sql.select_near_place, 0);
385 n->name=g_strdup(place);
386 dist=sqlite3_column_int(sql.select_near_place, 1);
387 n->dist=sqrt((double)dist);
388 n->lat=sqlite3_column_int(sql.select_near_place, 2);
389 n->lon=sqlite3_column_int(sql.select_near_place, 3);
390 n->id=sqlite3_column_int(sql.select_near_place, 4);
391 n->isin=sqlite3_column_int(sql.select_near_place, 5);
394 osm_place_cache_add(n);
405 osm_find_nearest_way_nodes(gint lat, gint lon, guint range)
412 sqlite3_reset(sql.select_way2);
413 sqlite3_clear_bindings(sql.select_way2);
415 if (SQLITE_OK != sqlite3_bind_int(sql.select_way2, 1, lat) ||
416 SQLITE_OK != sqlite3_bind_int(sql.select_way2, 2, lon) ||
417 SQLITE_OK != sqlite3_bind_int(sql.select_way2, 3, range) ||
418 SQLITE_OK != sqlite3_bind_int(sql.select_way2, 4, WAY_ROAD_START) ||
419 SQLITE_OK != sqlite3_bind_int(sql.select_way2, 5, WAY_ROAD_END)) {
420 g_printerr("Failed to bind values for way\n");
426 while (SQLITE_ROW == sqlite3_step(sql.select_way2)) {
431 w=g_slice_new0(osm_way);
432 w->id=sqlite3_column_int(sql.select_way2, 0);
433 w->type=sqlite3_column_int(sql.select_way2, 1);
434 w->nodecnt=sqlite3_column_int(sql.select_way2, 2);
435 w->flags=sqlite3_column_int(sql.select_way2, 3);
436 dist=sqlite3_column_int(sql.select_way2, 4);
437 w->dist=sqrt((gdouble)dist);
438 w->f=sqlite3_column_int(sql.select_way2, 5);
439 w->t=sqlite3_column_int(sql.select_way2, 6);
441 lat=sqlite3_column_int(sql.select_way2, 7);
442 lon=sqlite3_column_int(sql.select_way2, 8);
444 w->node_f=osm_way_node_new(w->f, lat, lon, 0);
446 ways=g_list_prepend(ways, w);
450 g_printf("Query took: %f sec, found: %d ways\n", g_timer_elapsed(dbt, &tms), wc);
455 /*****************************************************************************/
457 static inline gdouble
458 magnitude(gdouble x1, gdouble y1, gdouble x2, gdouble y2)
464 return sqrt((x*x)+(y*y));
468 distance_point_to_line(gdouble x, gdouble y, gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble *d)
473 lm=magnitude(x1,y1,x2,y2);
477 tmp=((x-x1)*(x2-x1))+((y-y1)*(y2-y1));
480 if (u<0.0f || u>1.0f)
486 *d=magnitude(x,y, ix, iy);
492 osm_way_distance(gint lat, gint lon, osm_way_node *f, osm_way_node *t, gdouble *d)
502 return distance_point_to_line((gdouble)lon, (gdouble)lat, (gdouble)f->lon, (gdouble)f->lat, (gdouble)t->lon, (gdouble)t->lat, d);
506 * Search for the nearest way (road)
507 * - First search for ways with nearest node
508 * - If only one is returned then we are done.
509 * - If more than one, go trough the results:
510 * - Load nodes for the way, check prev/next nodes
511 * - Store result if closer than before
512 * - Return closest way
515 #define START_DIST (900000.0)
518 osm_find_nearest_way(gint lat, gint lon)
522 guint range=OSM_RANGE_START;
524 gdouble pdist=START_DIST, dist_n, dist_p;
526 while ((w=osm_find_nearest_way_nodes(lat, lon, range))==NULL && range<=OSM_RANGE_STOP) {
527 range+=OSM_RANGE_STEP;
528 g_printf("Trying with range: %d\n", range);
532 g_printf("Found ways: %d\n", g_list_length(w));
535 if (g_list_length(w)==0)
538 for (iter=w; iter!=NULL; iter=iter->next) {
541 osm_way *way=(osm_way*)iter->data;
544 g_printf("WAY %d (%d) HAS %d NODES, nearest is %d\n",
545 way->id, way->type, way->nodecnt, way->f);
550 wnn=osm_way_get_next_node(way);
551 if (osm_way_distance(lat, lon, way->node_f, wnn, &dist_n)==FALSE) {
552 osm_way_node_free(wnn);
554 } else if (dist_n<pdist) {
557 way->distance=dist_n;
559 g_printf("#1 distance: %f (%f)\n", dist_n, pdist);
562 wnp=osm_way_get_prev_node(way);
563 if (osm_way_distance(lat, lon, way->node_f, wnp, &dist_p)==FALSE) {
564 osm_way_node_free(wnp);
566 } else if (dist_p<pdist) {
569 way->distance=dist_n;
571 osm_way_node_free(wnn);
574 g_printf("#2 distance: %f (%f)\n", dist_p, pdist);
578 g_printf("Found close way, distance: %f %f (%f)\n", dist_n, dist_p, pdist);
591 osm_way_get_name(cw);
592 if (cw->type==WAY_MOTORWAY || cw->type==WAY_TRUNK ||
593 cw->type==WAY_PRIMARY || cw->type==WAY_SECONDARY ||
594 cw->type==WAY_TERTIARY) {
599 g_printf("BEST WAY(%d): %s (%s,%s)\n",
600 cw->id, cw->name, cw->ref, cw->int_ref);
601 g_printf("\tT: %d F: %d N: %d D: %f\n",
602 cw->type, cw->flags, cw->nodecnt, cw->dist);
603 g_printf("\tNF: %d NT: %d DT %f\n",
605 cw->node_t->num, cw->distance);
612 osm_way_get_prev_node(osm_way *w)
614 sqlite3_reset(sql.select_way_prev_seg);
615 sqlite3_clear_bindings(sql.select_way_prev_seg);
617 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_prev_seg, 1, w->id) ||
618 SQLITE_OK != sqlite3_bind_int(sql.select_way_prev_seg, 2, w->f) ) {
619 g_printerr("Failed to bind values for prev seg\n");
623 if (SQLITE_ROW == sqlite3_step(sql.select_way_prev_seg)) {
624 return osm_way_node_new(
625 sqlite3_column_int(sql.select_way_prev_seg, 0),
626 sqlite3_column_int(sql.select_way_prev_seg, 1),
627 sqlite3_column_int(sql.select_way_prev_seg, 2),
635 osm_way_get_next_node(osm_way *w)
637 sqlite3_reset(sql.select_way_next_seg);
638 sqlite3_clear_bindings(sql.select_way_next_seg);
640 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_next_seg, 1, w->id) ||
641 SQLITE_OK != sqlite3_bind_int(sql.select_way_next_seg, 2, w->f) ) {
642 g_printerr("Failed to bind values for next seg\n");
646 if (SQLITE_ROW == sqlite3_step(sql.select_way_next_seg)) {
647 return osm_way_node_new(
648 sqlite3_column_int(sql.select_way_next_seg, 0),
649 sqlite3_column_int(sql.select_way_next_seg, 1),
650 sqlite3_column_int(sql.select_way_next_seg, 2),
658 * Get list of nodes for given way
661 osm_way_get_nodes(osm_way *w)
666 sqlite3_reset(sql.select_way_nodes);
667 sqlite3_clear_bindings(sql.select_way_nodes);
669 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_nodes, 1, w->id)) {
670 g_printerr("Failed to bind values way nodes\n");
674 while (SQLITE_ROW == sqlite3_step(sql.select_way_nodes)) {
677 n=g_slice_new(osm_way_node);
678 n->id=sqlite3_column_int(sql.select_way_nodes, 0);
679 n->lat=sqlite3_column_int(sql.select_way_nodes, 1);
680 n->lon=sqlite3_column_int(sql.select_way_nodes, 2);
681 w->nodes=g_list_append(w->nodes, n);
684 return (w->nodes==NULL) ? FALSE : TRUE;
691 osm_way_get_name(osm_way *w)
693 sqlite3_reset(sql.select_way_name);
694 sqlite3_clear_bindings(sql.select_way_name);
696 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name, 1, w->id)) {
697 g_printerr("Failed to bind values for way name\n");
701 if (SQLITE_ROW == sqlite3_step(sql.select_way_name)) {
703 place=sqlite3_column_text(sql.select_way_name, 0);
704 w->name=g_strdup(place);
711 osm_way_get_name_nls(osm_way *w)
713 sqlite3_reset(sql.select_way_name_nls);
714 sqlite3_clear_bindings(sql.select_way_name_nls);
716 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name_nls, 1, w->id) ||
717 SQLITE_OK != sqlite3_bind_) {
718 g_printerr("Failed to bind values for way name nls\n");
722 if (SQLITE_ROW == sqlite3_step(sql.select_way_name_nls)) {
724 place=sqlite3_column_text(sql.select_way_name_nls, 0);
725 w->name=g_strdup(place);
733 * Get Way ref and int_ref
736 osm_way_get_ref(osm_way *w)
738 sqlite3_reset(sql.select_way_ref);
739 sqlite3_clear_bindings(sql.select_way_ref);
741 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_ref, 1, w->id)) {
742 g_printerr("Failed to bind values for way ref\n");
746 if (SQLITE_ROW == sqlite3_step(sql.select_way_ref)) {
747 const gchar *ref, *int_ref;
748 ref=sqlite3_column_text(sql.select_way_ref, 0);
749 int_ref=sqlite3_column_text(sql.select_way_ref, 1);
750 w->ref=g_strdup(ref);
751 w->int_ref=g_strdup(int_ref);
756 /******************************************************************************/
759 * Try to figure out where the given lat,lon is. Fills in the given struct,
760 * with street, secondary (suburb) and primary (city,town,village) location.
761 * Will try to minimize the amount of database access by skipping queries
762 * if we haven't moved or if we don't know where we are.
766 osm_get_location_data(gint lat, gint lon, osm_location *map_loc)
769 gboolean check_place=FALSE;
772 if (map_loc->valid==FALSE) {
778 d=calculate_idistance(lat,lon,map_loc->lat,map_loc->lon);
781 /* Check if we are still near the same way as last time */
782 if (map_loc->street && osm_way_distance(lat, lon, map_loc->street->node_f, map_loc->street->node_t, &dist)==TRUE) {
783 /* We are probably on the same way as last time */
784 if ( (dist>(gdouble)way_dist_range) || (fabs(_gps.heading-map_loc->heading)>10.0)) {
785 /* We have moved a large amount, check way again */
786 g_printf("*** dist %f over range, checking again\n", dist);
787 osm_way_free(map_loc->street);
788 map_loc->street=osm_find_nearest_way(lat, lon);
790 map_loc->changed=TRUE;
792 g_printf("*** No change in location: %f %d\n", dist, way_dist_range);
793 /* We are still on the same way as last time */
795 map_loc->changed=FALSE;
800 /* We didn't know our location, so check it, but only if we have moved */
801 if (d>way_dist_range) {
802 g_print("*** Must check location\n");
803 osm_way_free(map_loc->street);
804 map_loc->street=osm_find_nearest_way(lat, lon);
811 if (!map_loc->street) {
812 g_print("*** Street not known\n");
813 map_loc->changed=TRUE;
815 g_print("*** Street known\n");
816 map_loc->changed=TRUE;
821 if (map_loc->changed==TRUE) {
822 map_loc->heading=_gps.heading;
823 map_loc->speed=_gps.speed;
826 g_printf("D: %ld %ld\n", d,(gulong)way_dist_range);
828 if (check_place==TRUE && d>way_dist_range*4) {
831 fs=osm_find_nearest_place(NODE_PLACE_SUBURB, lat, lon, &map_loc->secondary);
832 if (fs==TRUE && map_loc->secondary && map_loc->secondary->isin!=0) {
833 if (osm_place_get(map_loc->secondary->isin, lat, lon, &(map_loc->primary))==FALSE) {
834 if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
835 g_printf("Near city: %s\n", map_loc->primary->name);
836 else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
837 g_printf("Near town: %s\n", map_loc->primary->name);
839 g_printf("Unknown\n");
841 g_printf("In: %s\n", map_loc->primary ? map_loc->primary->name : "?");
843 } else if (map_loc->street && map_loc->street->isin!=0) {
844 if (osm_place_get(map_loc->street->isin, lat, lon, &map_loc->primary)==FALSE) {
845 g_printf("Street location not know.\n");
847 g_printf("Street is in: %s\n", map_loc->primary ? map_loc->primary->name : "?");
850 if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
851 g_printf("Near city: %s\n", map_loc->primary->name);
852 else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
853 g_printf("Near town: %s\n", map_loc->primary->name);
855 g_printf("Unknown\n");
860 g_print("------\n\n");
862 return map_loc->street ? TRUE : FALSE;