]> err.no Git - mapper/blob - src/osm-db.c
Split out the import code from osm.c to osm-db-import.c and make osm.c just a simple...
[mapper] / src / osm-db.c
1 /*
2  * This file is part of mapper
3  *
4  * Copyright (C) 2007 Kaj-Michael Lang
5  *
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.
10  *
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.
15  *
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.
19  */
20 #include "config.h"
21
22 #include <unistd.h>
23 #include <string.h>
24 #include <strings.h>
25 #include <sys/types.h>
26 #include <math.h>
27 #include <glib.h>
28 #include <glib/gstdio.h>
29 #include <glib/gi18n.h>
30 #include <gtk/gtk.h>
31 #include <sqlite3.h>
32
33 #include "osm.h"
34 #include "latlon.h"
35 #include "osm-db.h"
36 #include "settings.h"
37
38 /* #define DEBUG_OSM */
39 /* #define DEBUG_OSM_TIME */
40 #define OSM_PLACE_CACHE_MAX_ITEMS (64)
41
42 #define OSM_DB_PROGRESS_NUM (20000)
43
44 /* Node search ranges */
45 #define OSM_RANGE_START (16384)
46 #define OSM_RANGE_STEP  (8192)
47 #define OSM_RANGE_STOP  (65535)
48
49 static sqlite3 *osmdb;
50 static gboolean osm_db_ok;
51
52 struct sql_select_stmt {
53         sqlite3_stmt *select_way;
54         sqlite3_stmt *select_way2;
55         sqlite3_stmt *select_way_next_seg;
56         sqlite3_stmt *select_way_prev_seg;
57
58         sqlite3_stmt *select_way_nodes;
59         sqlite3_stmt *select_way_name;
60         sqlite3_stmt *select_way_name_nls;
61         sqlite3_stmt *select_way_name_search;
62         sqlite3_stmt *select_way_ref;
63         sqlite3_stmt *select_place;
64         sqlite3_stmt *select_near_place;
65
66         sqlite3_stmt *select_node_next;
67         sqlite3_stmt *select_node_prev;
68 };
69 static struct sql_select_stmt sql;
70 static GTimer *dbt;
71 static GtkProgressBar *dbpw=NULL;
72
73 /* Cache hash tables */
74 struct osm_place_cache {
75         GHashTable *cache;
76         guint hit;
77         guint miss;
78 };
79 static struct osm_place_cache pcache;
80
81 static guint way_dist_range=OSM_RANGE_WAY;
82
83 osm_way_node *osm_way_get_prev_node(osm_way *w);
84 osm_way_node *osm_way_get_next_node(osm_way *w);
85
86 /*****************************************************************************/
87
88 void
89 osm_set_way_range(guint sr)
90 {
91 way_dist_range=sr;
92 }
93
94 void
95 osm_set_way_range_from_speed(gfloat speed)
96 {
97 if (speed>54.0)
98         way_dist_range=OSM_RANGE_WAY*2;
99 else
100         way_dist_range=OSM_RANGE_WAY-lrint((speed/4)*1000);
101 }
102
103 /*****************************************************************************/
104
105 static int
106 osm_progress(void *ud)
107 {
108 if (!dbpw)
109         return 0;
110 gtk_progress_bar_pulse(dbpw);
111 gtk_main_iteration_do(FALSE);
112 return 0;
113 }
114
115 static void
116 osm_progress_hide(sqlite3 *db)
117 {
118 if (!dbpw)
119         return;
120 gtk_progress_bar_set_text(dbpw, "");
121 gtk_progress_bar_set_fraction(dbpw, 0.0);
122 sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, NULL, NULL);
123 }
124
125 static void
126 osm_progress_show(sqlite3 *db)
127 {
128 if (!dbpw)
129         return;
130 gtk_progress_bar_set_text(dbpw, _("Searching..."));
131 sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, osm_progress, NULL);
132 }
133
134 void
135 osm_progress_set_widget(sqlite3 *db, GtkProgressBar *w)
136 {
137 if (dbpw!=NULL && w==NULL)
138         osm_progress_hide(db);
139 dbpw=w;
140 if (w!=NULL)
141         osm_progress_show(db);
142 }
143
144 /*****************************************************************************/
145
146 gboolean
147 osm_db_prepare(sqlite3 *db)
148 {
149 /* Select nearest place inside lat,lon+-range */
150 if (sqlite3_prepare_v2(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as dist,"
151                                         " ilat,ilon,places.nid,isin_p,isin_c "
152                                         " from places,nodes where type=$TYPE "
153                                         " and nodes.nid=places.nid "
154                                         " and ilat between $LAT-$RANGE and $LAT+$RANGE"
155                                         " and ilon between $LON-$RANGE and $LON+$RANGE order by dist limit 1",
156                     -1, &sql.select_near_place, NULL)!=SQLITE_OK)
157         return FALSE;
158
159 /* Select place name, distance, location, parent-place and type with given ID */
160 if (sqlite3_prepare_v2(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as dist,"
161                                         " ilat,ilon,type,isin_p,isin_c "
162                                         " from places,nodes where "
163                                         " nodes.nid=places.nid "
164                                         " and places.nid=$NID order by dist limit 1",
165                     -1, &sql.select_place, NULL)!=SQLITE_OK)
166         return FALSE;
167
168 /* Ways */
169 /* Select nearest ways inside lat,lon+-range */
170 if (sqlite3_prepare_v2(db, "select w.wid,type,nodes,flags,"
171                                         "(($LAT-n.ilat)*($LAT-n.ilat))+(($LON-n.ilon)*($LON-n.ilon)) as d,wn.f,wn.t,n.ilat,n.ilon "
172                                         " from way as w,way_n2n as wn,nodes as n "
173                                         " where w.wid=wn.wid and wn.f=n.nid "
174                                         " and n.ilat between $LAT-$RANGE and $LAT+$RANGE "
175                                         " and n.ilon between $LON-$RANGE and $LON+$RANGE "
176                                         " and w.type between $WTS and $WTY " 
177                                         " order by d",
178                     -1, &sql.select_way2, NULL)!=SQLITE_OK)
179         return FALSE;
180
181 if (sqlite3_prepare_v2(db, "select w.wid,w.name as name,"
182                                         "(($LAT-ww.lat)*($LAT-ww.lat))+(($LON-ww.lon)*($LON-ww.lon)) as d,ww.lat,ww.lon "
183                                         " from way_names as w,way as ww where "
184                                         " ww.type between $WTS and $WTY and w.wid=ww.wid and w.name like $NAME "
185                                         " and ww.lat between $LAT-$RANGE and $LAT+$RANGE "
186                                         " and ww.lon between $LON-$RANGE and $LON+$RANGE "
187                                         " union "
188                                         " select w.wid,n.name as name,"
189                                         "(($LAT-ww.lat)*($LAT-ww.lat))+(($LON-ww.lon)*($LON-ww.lon)) as d,ww.lat,ww.lon "
190                                         " from way_names as w, way as ww,way_names_nls as n on w.wid=n.wid where "
191                                         " ww.type between $WTS and $WTY and w.wid=ww.wid and n.name like $NAME "
192                                         " and ww.lat between $LAT-$RANGE and $LAT+$RANGE "
193                                         " and ww.lon between $LON-$RANGE and $LON+$RANGE "
194                                         " order by name limit 100",
195                         -1, &sql.select_way_name_search, NULL)!=SQLITE_OK)
196         return FALSE;
197
198 if (sqlite3_prepare_v2(db, "select wn.t,ilat,ilon from way_n2n as wn,nodes where wid=? and wn.f=? and wn.t=nodes.nid limit 1",
199                     -1, &sql.select_way_next_seg, NULL)!=SQLITE_OK)
200         return FALSE;
201
202 if (sqlite3_prepare_v2(db, "select wn.f,ilat,ilon from way_n2n as wn,nodes where wid=? and wn.t=? and wn.f=nodes.nid limit 1",
203                     -1, &sql.select_way_prev_seg, NULL)!=SQLITE_OK)
204         return FALSE;
205
206 /* Way name */
207 if (sqlite3_prepare_v2(db, "select name from way_names where wid=?", -1, &sql.select_way_name, NULL)!=SQLITE_OK)
208         return FALSE;
209
210 /* Way ref and int_ref */
211 if (sqlite3_prepare_v2(db, "select ref,int_ref from way_ref where rid=?", -1, &sql.select_way_ref, NULL)!=SQLITE_OK)
212         return FALSE;
213
214 /* Get next, prev node + way information. For routing. */
215 if (sqlite3_prepare_v2(db, "select w.wid,w.type,w.flags,w.speed,n.nid,n.rlat,n.rlon,nn.f,nn.t,n.f,n.l "
216                         "from way as w, nodes as n, way_n2n as nn where w.wid=nn.wid and nn.f=n.nid and nn.f=?",
217                     -1, &sql.select_node_next, NULL)!=SQLITE_OK)
218         return FALSE;
219
220 if (sqlite3_prepare_v2(db, "select w.wid,w.type,w.flags,w.speed,n.nid,n.rlat,n.rlon,nn.f,nn.t,n.f,n.l "
221                         "from way as w, nodes as n, way_n2n as nn where w.wid=nn.wid and nn.f=n.nid and nn.t=?",
222                     -1, &sql.select_node_prev, NULL)!=SQLITE_OK)
223         return FALSE;
224
225 return TRUE;
226 }
227
228 void
229 osm_deinit(void)
230 {
231 if (osmdb) {
232         if (sql.select_way_ref)
233                 sqlite3_finalize(sql.select_way_ref);
234         if (sql.select_way_name)
235                 sqlite3_finalize(sql.select_way_name);
236         if (sql.select_way_next_seg)
237                 sqlite3_finalize(sql.select_way_next_seg);
238         if (sql.select_way_prev_seg)
239                 sqlite3_finalize(sql.select_way_prev_seg);
240         if (sql.select_way_name_search)
241                 sqlite3_finalize(sql.select_way_name_search);
242         if (sql.select_way2)
243                 sqlite3_finalize(sql.select_way2);
244         if (sql.select_place)
245                 sqlite3_finalize(sql.select_place);
246         if (sql.select_near_place)
247                 sqlite3_finalize(sql.select_near_place);
248         if (sql.select_node_next)
249                 sqlite3_finalize(sql.select_node_next);
250         if (sql.select_node_prev)
251                 sqlite3_finalize(sql.select_node_prev);
252 }
253 osmdb=NULL;
254 osm_db_ok=FALSE;
255 memset(&sql, 0, sizeof(sql));
256 g_hash_table_destroy(pcache.cache);
257 pcache.hit=0;
258 pcache.miss=0;
259 g_timer_destroy(dbt);
260 }
261
262 gboolean
263 osm_init(sqlite3 **db)
264 {
265 osm_db_ok=FALSE;
266 pcache.cache=g_hash_table_new(g_direct_hash, g_direct_equal);
267 dbt=g_timer_new();
268
269 if (!db || !*db) {
270         osmdb=NULL;
271         return FALSE;
272 }
273
274 osmdb=*db;
275 memset(&sql, 0, sizeof(sql));
276 if (osm_db_prepare(osmdb)==FALSE) {
277         g_printerr("Failed to prepare OSM SQL statements:");
278         g_printf("SQLITE: %s\n", sqlite3_errmsg(osmdb));
279         return FALSE;
280 }
281 osm_db_ok=TRUE;
282 return TRUE;
283 }
284
285 /*****************************************************************************/
286
287 osm_way_node *
288 osm_way_node_new(guint id, gint lat, gint lon, gint flags)
289 {
290 osm_way_node *n=g_slice_new(osm_way_node);
291
292 n->id=id;
293 n->lat=lat;
294 n->lon=lon;
295 n->flags=flags;
296 return n;
297 }
298
299 void
300 osm_way_node_free(osm_way_node *n)
301 {
302 if (n)
303         g_slice_free(osm_way_node, n);
304 }
305
306 /**
307  * Free way nodes list 
308  */
309 void
310 osm_way_nodes_free(osm_way *w)
311 {
312 GList *iter;
313
314 if (!w->nodes) 
315         return;
316
317 for (iter=w->nodes; iter!=NULL; iter=iter->next)
318         g_slice_free(osm_way_node, (osm_way_node*)iter->data);
319
320 g_list_free(w->nodes);
321 }
322
323 /**
324  * Free a osm_way structure
325  */
326 void
327 osm_way_free(osm_way *w)
328 {
329 if (!w)
330         return;
331 osm_way_nodes_free(w);
332 if (w->name)
333         g_free(w->name);
334 if (w->ref)
335         g_free(w->ref);
336 if (w->int_ref)
337         g_free(w->int_ref);
338 g_slice_free(osm_way, w);
339 }
340
341 /*****************************************************************************/
342
343 static void
344 osm_place_free(osm_place *p)
345 {
346 if (p->name)
347         g_free(p->name);
348 g_slice_free(osm_place, p);
349 }
350
351 static gboolean
352 osm_place_remove(gpointer k, gpointer v, gpointer ud)
353 {
354 osm_place_free((osm_place *)v);
355 return TRUE;
356 }
357
358 static osm_place *
359 osm_place_new(void)
360 {
361 return g_slice_new0(osm_place);
362 }
363
364 static osm_place *
365 osm_place_cache_lookup(guint32 id)
366 {
367 osm_place *r;
368 r=g_hash_table_lookup(pcache.cache, GINT_TO_POINTER(id));
369 if (r) 
370         pcache.hit++; 
371 else 
372         pcache.miss++;
373
374 g_debug("OSM: Cache %d/%d", pcache.hit, pcache.miss);
375 return r;
376 }
377
378 static void
379 osm_place_cache_add(osm_place *p)
380 {
381 if (osm_place_cache_lookup(p->id)==NULL)
382         g_hash_table_insert(pcache.cache, GINT_TO_POINTER(p->id), p);
383 }
384
385 static void
386 osm_place_cache_gc(void)
387 {
388 guint r;
389
390 r=g_hash_table_foreach_remove(pcache.cache, osm_place_remove, NULL);
391 g_debug("OSM: Cache cleared (%d)", r);
392 pcache.hit=0;
393 pcache.miss=0;
394 }
395
396 static void
397 osm_place_update_distance(osm_place *p, gint lat, gint lon)
398 {
399 gdouble lam, lom;
400
401 lam=(gdouble)((lat-p->lat)*(lat-p->lat));
402 lom=(gdouble)((lon-p->lon)*(lon-p->lon));
403
404 p->dist=sqrt(lam+lom);
405 }
406
407 /**
408  * Get place with given id and distance to current location
409  */
410 gboolean
411 osm_place_get(guint32 id, gint lat, gint lon, osm_place **nr)
412 {
413 osm_place *n;
414
415 n=*nr;
416 n=osm_place_cache_lookup(id);
417 if (n) {
418         osm_place_update_distance(n, lat, lon);
419         return TRUE;
420 }
421 n=NULL;
422
423 /* XXX: better place for this */
424 if (g_hash_table_size(pcache.cache)>OSM_PLACE_CACHE_MAX_ITEMS)
425         osm_place_cache_gc();
426
427 sqlite3_clear_bindings(sql.select_place);
428 sqlite3_reset(sql.select_place);
429
430 if (SQLITE_OK != sqlite3_bind_int(sql.select_place, 1, lat) ||
431     SQLITE_OK != sqlite3_bind_int(sql.select_place, 2, lon) ||
432     SQLITE_OK != sqlite3_bind_int(sql.select_place, 3, id)) {
433         g_printerr("Failed to bind values for place\n");
434         return FALSE;
435 }
436
437 if (SQLITE_ROW == sqlite3_step(sql.select_place)) {
438         const gchar *place;
439         guint32 dist;
440
441         n=osm_place_new();
442         place=sqlite3_column_text(sql.select_place, 0);
443         n->name=g_strdup(place);
444         dist=sqlite3_column_int(sql.select_place, 1);
445         n->dist=sqrt((double)dist);
446         n->lat=sqlite3_column_int(sql.select_place, 2);
447         n->lon=sqlite3_column_int(sql.select_place, 3);
448         n->type=sqlite3_column_int(sql.select_place, 4);
449         n->isin_p=sqlite3_column_int(sql.select_place, 5);
450 /*      n->isin_c=sqlite3_column_int(sql.select_place, 6); */
451         return TRUE;
452 }
453 return FALSE;
454 }
455
456 /**
457  * Search for the nearest place with given type
458  */
459 gboolean
460 osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place **nr)
461 {
462 gint range;
463 osm_place *n=NULL;
464
465 switch (type) {
466         case NODE_PLACE_SUBURB:
467                 range=95000;
468         break;
469         case NODE_PLACE_CITY:
470         case NODE_PLACE_TOWN:
471                 range=250000;
472         break;
473         case NODE_PLACE_HAMLET:
474         case NODE_PLACE_VILLAGE:
475                 range=100000;
476         break;
477         default:
478                 range=90000;
479         break;
480 }
481
482 sqlite3_clear_bindings(sql.select_near_place);
483 sqlite3_reset(sql.select_near_place);
484
485 if (SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 1, lat) ||
486     SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 2, lon) ||
487     SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 3, type) ||
488     SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 4, range)) {
489         g_printerr("Failed to bind values for near place\n");
490         return FALSE;
491 }
492
493 n=osm_place_new();
494 n->isin_p=n->lat=n->lon=n->dist=0;
495 if (SQLITE_ROW == sqlite3_step(sql.select_near_place)) {
496         const gchar *place;
497         guint32 dist;
498
499         place=sqlite3_column_text(sql.select_near_place, 0);
500         n->name=g_strdup(place);
501         dist=sqlite3_column_int(sql.select_near_place, 1);
502         n->dist=sqrt((double)dist);
503         n->lat=sqlite3_column_int(sql.select_near_place, 2);
504         n->lon=sqlite3_column_int(sql.select_near_place, 3);
505         n->id=sqlite3_column_int(sql.select_near_place, 4);
506         n->isin_p=sqlite3_column_int(sql.select_near_place, 5);
507 /*      n->isin_c=sqlite3_column_int(sql.select_near_place, 6); */
508         n->type=type;
509
510         osm_place_cache_add(n);
511
512         *nr=n;
513         return TRUE;
514 }
515 *nr=n;
516 return FALSE;
517 }
518
519 /*
520  * Way helper 
521  *
522  */
523 static GList *
524 osm_find_nearest_way_nodes(gint lat, gint lon, guint range)
525 {
526 GList *ways=NULL;
527 osm_way *w;
528 gulong tms;
529 guint wc=0;
530
531 sqlite3_reset(sql.select_way2);
532 sqlite3_clear_bindings(sql.select_way2);
533
534 if (SQLITE_OK != sqlite3_bind_int(sql.select_way2, 1, lat) ||
535     SQLITE_OK != sqlite3_bind_int(sql.select_way2, 2, lon) ||
536     SQLITE_OK != sqlite3_bind_int(sql.select_way2, 3, range) ||
537     SQLITE_OK != sqlite3_bind_int(sql.select_way2, 4, WAY_ROAD_START) ||
538     SQLITE_OK != sqlite3_bind_int(sql.select_way2, 5, WAY_ROAD_END)) {
539         g_printerr("Failed to bind values for way\n");
540         return NULL;
541 }
542
543 #ifdef DEBUG_OSM_TIME
544 g_timer_start(dbt);
545 #endif
546
547 while (SQLITE_ROW == sqlite3_step(sql.select_way2)) {
548         guint32 dist;
549         gint lat, lon;
550
551         wc++;
552         w=g_slice_new0(osm_way);
553         w->id=sqlite3_column_int(sql.select_way2, 0);
554         w->type=sqlite3_column_int(sql.select_way2, 1);
555         w->nodecnt=sqlite3_column_int(sql.select_way2, 2);
556         w->flags=sqlite3_column_int(sql.select_way2, 3);
557         dist=sqlite3_column_int(sql.select_way2, 4);
558         w->dist=sqrt((gdouble)dist);
559         w->f=sqlite3_column_int(sql.select_way2, 5);
560         w->t=sqlite3_column_int(sql.select_way2, 6);
561
562         lat=sqlite3_column_int(sql.select_way2, 7);
563         lon=sqlite3_column_int(sql.select_way2, 8);
564
565         w->node_f=osm_way_node_new(w->f, lat, lon, 0);
566
567         ways=g_list_prepend(ways, w);
568 }
569
570 #ifdef DEBUG_OSM_TIME
571 g_timer_stop(dbt);
572 g_printf("Query took: %f sec, found: %d ways\n", g_timer_elapsed(dbt, &tms), wc);
573 #endif
574
575 return ways;
576 }
577
578 /*****************************************************************************/
579
580 GSList *
581 osm_get_route_node(guint nid, osm_node_direction d)
582 {
583 GSList *r=NULL;
584 osm_way *w;
585 guint wc=0;
586 sqlite3_stmt *psql=NULL;
587
588 switch (d) {
589         case OSM_NODE_NEXT:
590                 psql=sql.select_node_next;
591         break;
592         case OSM_NODE_PREV:
593                 psql=sql.select_node_prev;
594         break;
595         default:
596                 g_assert_not_reached();
597         break;
598 }
599
600 sqlite3_reset(psql);
601 sqlite3_clear_bindings(psql);
602
603 if (SQLITE_OK != sqlite3_bind_int(psql, 1, nid)) {
604         g_printerr("Failed to bind values for route node\n");
605         return NULL;
606 }
607
608 while (SQLITE_ROW == sqlite3_step(psql)) {
609         gdouble lat, lon;
610
611         wc++;
612         w=g_slice_new0(osm_way);
613         w->id=sqlite3_column_int(psql, 0);
614         w->type=sqlite3_column_int(psql, 1);
615         w->flags=sqlite3_column_int(psql, 2);
616         w->speed=sqlite3_column_int(psql, 3);
617
618         lat=sqlite3_column_double(psql, 5);
619         lon=sqlite3_column_double(psql, 6);
620
621         w->f=sqlite3_column_int(psql, 7);
622         w->t=sqlite3_column_int(psql, 8);
623 #if 0
624         w->node=
625         w->node->flags=sqlite3_column_int(psql, 9);
626         w->node->links=sqlite3_column_int(psql, 10);
627 #endif
628
629         r=g_slist_prepend(r, w);
630 }
631
632 return r;
633 }
634
635
636 /*****************************************************************************/
637 gboolean 
638 osm_way_distance(gint lat, gint lon, osm_way_node *f, osm_way_node *t, gdouble *d)
639 {
640 if (!f) {
641         return FALSE;
642 }
643
644 if (!t) {
645         return FALSE;
646 }
647
648 return distance_point_to_line((gdouble)lon, (gdouble)lat, (gdouble)f->lon, (gdouble)f->lat, (gdouble)t->lon, (gdouble)t->lat, d);
649 }
650
651 /**
652  * Search for the nearest way (road)
653  * - First search for ways with nearest node
654  * - If only one is returned then we are done.
655  * - If more than one, go trough the results:
656  *   - Load nodes for the way, check prev/next nodes
657  *   - Store result if closer than before
658  * - Return closest way
659  */
660
661 #define START_DIST (900000.0)
662
663 osm_way *
664 osm_find_nearest_way(gint lat, gint lon)
665 {
666 GList *iter;
667 GList *w=NULL;
668 guint range=OSM_RANGE_START;
669 osm_way *cw=NULL;
670 gdouble pdist=START_DIST, dist_n, dist_p;
671
672 while ((w=osm_find_nearest_way_nodes(lat, lon, range))==NULL && range<=OSM_RANGE_STOP) {
673         range+=OSM_RANGE_STEP;
674         g_printf("Trying with range: %d\n", range);
675 }
676 #ifdef DEBUG_OSM
677 g_printf("Found %d ways withing range %d\n", g_list_length(w), range);
678 #endif
679
680 if (g_list_length(w)==0)
681         return NULL;
682
683 for (iter=w; iter!=NULL; iter=iter->next) {
684         osm_way_node *wnn;
685         osm_way_node *wnp;
686         osm_way *way=(osm_way*)iter->data;
687
688 #ifdef DEBUG_OSM
689         g_printf("Way: %d (%d) has %d nodes, nearest is %d,%d\n", 
690                 way->id, way->type, way->nodecnt, way->f, way->t);
691 #endif
692
693         way->node_t=NULL;
694
695         wnn=osm_way_get_next_node(way);
696         if (osm_way_distance(lat, lon, way->node_f, wnn, &dist_n)==FALSE) {
697                 osm_way_node_free(wnn);
698                 dist_n=START_DIST;
699         } else if (dist_n<pdist) {
700                 pdist=dist_n;
701                 cw=way;
702                 way->distance=dist_n;
703                 way->node_t=wnn;
704                 g_printf("#1 distance: %f (%f)\n", dist_n, pdist);
705         }
706
707         wnp=osm_way_get_prev_node(way);
708         if (osm_way_distance(lat, lon, way->node_f, wnp, &dist_p)==FALSE) {
709                 osm_way_node_free(wnp);
710                 dist_p=START_DIST;
711         } else if (dist_p<pdist) {
712                 pdist=dist_p;
713                 cw=way;
714                 way->distance=dist_n;
715                 if (way->node_t) {
716                         osm_way_node_free(wnn);
717                 }
718                 way->node_t=wnp;
719                 g_printf("#2 distance: %f (%f)\n", dist_p, pdist);
720         }
721
722 #ifdef DEBUG_OSM
723         g_printf("Found close way, distance: %f %f (%f)\n", dist_n, dist_p, pdist);
724 #endif
725
726         if (!cw) {
727                 osm_way_free(way);
728                 way=NULL;
729         }
730 }
731
732 g_list_free(w);
733 if (cw==NULL)
734         return NULL;
735
736 osm_way_get_name(cw);
737 if (cw->type==WAY_MOTORWAY || cw->type==WAY_TRUNK || 
738         cw->type==WAY_PRIMARY || cw->type==WAY_SECONDARY ||
739         cw->type==WAY_TERTIARY) {
740                 osm_way_get_ref(cw);
741 }
742
743 #ifdef DEBUG_OSM
744 g_printf("BEST WAY(%d): %s [%s][%s]\n", 
745         cw->id, cw->name, cw->ref, cw->int_ref);
746 g_printf("\tType: %d Flags: %d Nodes: %d Dist: %f\n", 
747         cw->type, cw->flags, cw->nodecnt, cw->dist);
748 g_printf("\tNF: %d NT: %d Distance: %f\n", 
749         cw->f, 
750         cw->t, 
751         cw->distance);
752 #endif
753
754 return cw;
755 }
756
757 /* XXX: These two should be combined to save memory */
758 /**
759  * Get previous node/segment of given way node
760  *
761  */
762 osm_way_node *
763 osm_way_get_prev_node(osm_way *w)
764 {
765 sqlite3_reset(sql.select_way_prev_seg);
766 sqlite3_clear_bindings(sql.select_way_prev_seg);
767
768 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_prev_seg, 1, w->id) ||
769         SQLITE_OK != sqlite3_bind_int(sql.select_way_prev_seg, 2, w->f)  ) {
770         g_printerr("Failed to bind values for prev seg\n");
771         return NULL;
772 }
773
774 if (SQLITE_ROW == sqlite3_step(sql.select_way_prev_seg)) {
775         return osm_way_node_new(
776                 sqlite3_column_int(sql.select_way_prev_seg, 0),
777                 sqlite3_column_int(sql.select_way_prev_seg, 1),
778                 sqlite3_column_int(sql.select_way_prev_seg, 2),
779                 0);
780 }
781
782 return NULL;
783 }
784
785 /**
786  * Get next node/segment of given way node
787  *
788  */
789 osm_way_node *
790 osm_way_get_next_node(osm_way *w)
791 {
792 sqlite3_reset(sql.select_way_next_seg);
793 sqlite3_clear_bindings(sql.select_way_next_seg);
794
795 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_next_seg, 1, w->id) ||
796         SQLITE_OK != sqlite3_bind_int(sql.select_way_next_seg, 2, w->f)  ) {
797         g_printerr("Failed to bind values for next seg\n");
798         return NULL;
799 }
800
801 if (SQLITE_ROW == sqlite3_step(sql.select_way_next_seg)) {
802         return osm_way_node_new(
803                 sqlite3_column_int(sql.select_way_next_seg, 0),
804                 sqlite3_column_int(sql.select_way_next_seg, 1),
805                 sqlite3_column_int(sql.select_way_next_seg, 2),
806                 0);
807 }
808
809 return NULL;
810 }
811
812 /**
813  * Get list of nodes for given way
814  *
815  */
816 gboolean
817 osm_way_get_nodes(osm_way *w)
818 {
819 if (w->nodes!=NULL)
820         return TRUE;
821
822 sqlite3_reset(sql.select_way_nodes);
823 sqlite3_clear_bindings(sql.select_way_nodes);
824
825 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_nodes, 1, w->id)) {
826         g_printerr("Failed to bind values way nodes\n");
827         return FALSE;
828 }
829
830 while (SQLITE_ROW == sqlite3_step(sql.select_way_nodes)) {
831         osm_way_node *n;
832
833         n=g_slice_new(osm_way_node);
834         n->id=sqlite3_column_int(sql.select_way_nodes, 0);
835         n->lat=sqlite3_column_int(sql.select_way_nodes, 1);
836         n->lon=sqlite3_column_int(sql.select_way_nodes, 2);
837         w->nodes=g_list_append(w->nodes, n);
838 }
839
840 return (w->nodes==NULL) ? FALSE : TRUE;
841 }
842
843 /**
844  * Get way name
845  *
846  */
847 gboolean
848 osm_way_get_name(osm_way *w)
849 {
850 sqlite3_reset(sql.select_way_name);
851 sqlite3_clear_bindings(sql.select_way_name);
852
853 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name, 1, w->id)) {
854         g_printerr("Failed to bind values for way name\n");
855         return FALSE;
856 }
857
858 if (SQLITE_ROW == sqlite3_step(sql.select_way_name)) {
859         const gchar *place;
860         place=sqlite3_column_text(sql.select_way_name, 0);
861         w->name=g_strdup(place);
862 }
863 return FALSE;
864 }
865
866 #if 0
867 gboolean
868 osm_way_get_name_nls(osm_way *w)
869 {
870 sqlite3_reset(sql.select_way_name_nls);
871 sqlite3_clear_bindings(sql.select_way_name_nls);
872
873 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name_nls, 1, w->id) ||
874         SQLITE_OK != sqlite3_bind_) {
875         g_printerr("Failed to bind values for way name nls\n");
876         return FALSE;
877 }
878
879 if (SQLITE_ROW == sqlite3_step(sql.select_way_name_nls)) {
880         const gchar *place;
881         place=sqlite3_column_text(sql.select_way_name_nls, 0);
882         w->name=g_strdup(place);
883 }
884 return FALSE;
885 }
886 #endif
887
888
889 /**
890  * Get Way ref and int_ref
891  *
892  */
893 gboolean
894 osm_way_get_ref(osm_way *w)
895 {
896 sqlite3_reset(sql.select_way_ref);
897 sqlite3_clear_bindings(sql.select_way_ref);
898
899 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_ref, 1, w->id)) {
900         g_printerr("Failed to bind values for way ref\n");
901         return FALSE;
902 }
903
904 if (SQLITE_ROW == sqlite3_step(sql.select_way_ref)) {
905         const gchar *ref, *int_ref;
906         ref=sqlite3_column_text(sql.select_way_ref, 0);
907         int_ref=sqlite3_column_text(sql.select_way_ref, 1);
908         w->ref=g_strdup(ref);
909         w->int_ref=g_strdup(int_ref);
910 }
911 return FALSE;
912 }
913
914 /******************************************************************************/
915
916 /**
917  * Try to figure out where the given lat,lon is. Fills in the given struct,
918  * with street, secondary (suburb) and primary (city,town,village) location.
919  * Will try to minimize the amount of database access by skipping queries
920  * if we haven't moved or if we don't know where we are.
921  *
922  */
923 gboolean 
924 osm_get_location_data(gint lat, gint lon, gfloat heading, osm_location *map_loc)
925 {
926 gdouble dist;
927 gboolean check_place=FALSE;
928 gulong d;
929
930 if (map_loc->valid==FALSE) {
931         map_loc->lat=lat;
932         map_loc->lon=lon;
933         map_loc->valid=TRUE;
934         d=way_dist_range*5;
935 } else {
936         d=calculate_idistance(lat,lon,map_loc->lat,map_loc->lon);
937 }
938
939 /* Check if we are still near the same way as last time */
940 if (map_loc->street && osm_way_distance(lat, lon, map_loc->street->node_f, map_loc->street->node_t, &dist)==TRUE) {
941         /* We are probably on the same way as last time */
942         if ( (dist>(gdouble)way_dist_range) || (fabs(heading-map_loc->heading)>10.0)) {
943                 /* We have moved a large amount, check way again */
944                 g_printf("*** dist %f over range, checking again\n", dist);
945                 osm_way_free(map_loc->street);
946                 map_loc->street=osm_find_nearest_way(lat, lon);
947                 check_place=TRUE;
948                 map_loc->changed=TRUE;
949         } else {
950 #if 0
951                 g_printf("*** No change in location: %f %d\n", dist, way_dist_range);
952 #endif
953                 /* We are still on the same way as last time */
954                 check_place=FALSE;
955                 map_loc->changed=FALSE;
956         }
957         map_loc->lat=lat;
958         map_loc->lon=lon;
959 } else {
960         /* We didn't know our location, so check it, but only if we have moved */
961         if (d>way_dist_range) {
962                 g_print("*** Must check location\n");
963                 check_place=TRUE;
964                 osm_way_free(map_loc->street);
965                 map_loc->street=osm_find_nearest_way(lat, lon);
966 #if 0
967                 map_loc->lat=lat;
968                 map_loc->lon=lon;
969 #endif
970         } 
971
972         if (!map_loc->street) {
973                 g_print("*** Street not known\n");
974                 map_loc->nfcnt++;
975                 map_loc->changed=TRUE;
976         } else {
977                 g_print("*** Street known\n");
978                 map_loc->nfcnt=0;
979                 map_loc->changed=TRUE;
980                 check_place=TRUE;
981         }
982 }
983
984 if (map_loc->changed==TRUE) {
985         map_loc->heading=heading;
986 }
987
988 #if 0
989 g_printf("NFC: %d\n", map_loc->nfcnt);
990 g_printf("D: %ld %ld\n", d,(gulong)way_dist_range);
991 #endif
992
993 if (check_place==TRUE && d>way_dist_range*4) {
994         gboolean fs;
995
996         fs=osm_find_nearest_place(NODE_PLACE_SUBURB, lat, lon, &map_loc->secondary);
997         if (fs==TRUE && map_loc->secondary && map_loc->secondary->isin_p!=0) {
998                 if (osm_place_get(map_loc->secondary->isin_p, lat, lon, &(map_loc->primary))==FALSE) {
999                         if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
1000                                 g_printf("Near city: %s\n", map_loc->primary->name);
1001                         else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
1002                                 g_printf("Near town: %s\n", map_loc->primary->name);
1003                         else
1004                                 g_printf("Unknown\n");
1005                 } else {
1006                         g_printf("In: %s\n", map_loc->primary ? map_loc->primary->name : "?");
1007                 }
1008         } else if (map_loc->street && map_loc->street->isin_p!=0) {
1009                 if (osm_place_get(map_loc->street->isin_p, lat, lon, &map_loc->primary)==FALSE) {
1010                         g_printf("Street location not know.\n");
1011                 } else {
1012                         g_printf("Street is in: %s\n", map_loc->primary ? map_loc->primary->name : "?");
1013                 }
1014         } else {
1015                 if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
1016                         g_printf("Near city: %s\n", map_loc->primary->name);
1017                 else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
1018                         g_printf("Near town: %s\n", map_loc->primary->name);
1019                 else
1020                         g_printf("Unknown\n");
1021
1022         }
1023 }
1024
1025 return map_loc->street ? TRUE : FALSE;
1026 }
1027
1028 /**
1029  * osm_way_search
1030  *
1031  * Search for a street(way) starting with given 'text', next given lat/lon
1032  *
1033  */
1034 gboolean
1035 osm_way_search(gdouble lat, gdouble lon, gchar *text, GtkListStore **store)
1036 {
1037 GtkTreeIter iter;
1038 gchar *ltext=NULL;
1039 guint rows=0;
1040 gchar tmp1[16], tmp2[16];
1041 gdouble range=6;
1042
1043 g_printf("Way Search: [%s] around %.6f %.6f\n", text, lat, lon);
1044
1045 ltext=g_strdup_printf("%s%%", text);
1046
1047 if (SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 1, lat) ||
1048     SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 2, lon) ||
1049     SQLITE_OK != sqlite3_bind_int(sql.select_way_name_search,    3, WAY_ROAD_START) ||
1050     SQLITE_OK != sqlite3_bind_int(sql.select_way_name_search,    4, WAY_ROAD_END) ||
1051     SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 6, range) ||
1052         SQLITE_OK != sqlite3_bind_text(sql.select_way_name_search,   5, ltext, -1, SQLITE_TRANSIENT)) {
1053                 g_printerr("Failed to bind values for sql.select_way_name_search\n");
1054                 sqlite3_clear_bindings(sql.select_way_name_search);
1055                 g_free(ltext);
1056                 return FALSE;
1057 }
1058
1059 if (ltext)
1060         g_free(ltext);
1061
1062 *store = gtk_list_store_new(ITEM_NUM_COLUMNS, 
1063                                 G_TYPE_INT,             /* ID */
1064                                 G_TYPE_INT,             /*  */
1065                                 G_TYPE_DOUBLE,  /* Latitude */
1066                                 G_TYPE_DOUBLE,  /* Longitude */
1067                                 G_TYPE_DOUBLE,  /* Distance */
1068                                 G_TYPE_STRING,  /* Lat/Lon */
1069                                 G_TYPE_STRING,  /* Label */
1070                                 G_TYPE_STRING,  /* Desc. */
1071                                 G_TYPE_STRING,  /* Category */
1072                                 G_TYPE_STRING,  /* Dummy */
1073                                 G_TYPE_STRING); /* Dummy */
1074
1075 while (SQLITE_ROW == sqlite3_step(sql.select_way_name_search)) {
1076         gdouble rlat, rlon, dist;
1077
1078         rlat=sqlite3_column_double(sql.select_way_name_search, 3);
1079         rlon=sqlite3_column_double(sql.select_way_name_search, 4);
1080         lat_format(_degformat, rlat, tmp1);
1081         lon_format(_degformat, rlon, tmp2);
1082         dist=calculate_distance(lat, lon, rlat, rlon) * UNITS_CONVERT[_units];
1083
1084         gtk_list_store_append(*store, &iter);
1085         gtk_list_store_set(*store, &iter,
1086                 ITEM_ID, sqlite3_column_int(sql.select_way_name_search, 0),
1087                 ITEM_LAT, rlat,
1088                 ITEM_LON, rlon,
1089                 ITEM_DIST, dist,
1090                 ITEM_LATLON, g_strdup_printf("%s, %s", tmp1, tmp2),
1091                 ITEM_LABEL, sqlite3_column_text(sql.select_way_name_search, 1),
1092                 -1);
1093         rows++;
1094 }
1095
1096 g_printf("Found: %d items\n", rows);
1097
1098 sqlite3_reset(sql.select_way_name_search);
1099 sqlite3_clear_bindings(sql.select_way_name_search);
1100
1101 return TRUE;
1102 }