12 #include <glib/gstdio.h>
19 struct sql_select_stmt {
20 sqlite3_stmt *select_way;
21 sqlite3_stmt *select_way_nodes;
22 sqlite3_stmt *select_way_name;
23 sqlite3_stmt *select_way_ref;
24 sqlite3_stmt *select_place;
25 sqlite3_stmt *select_near_place;
27 static struct sql_select_stmt sql;
29 gboolean osm_way_get_nodes(osm_way *w);
30 gboolean osm_way_get_name(osm_way *w);
31 gboolean osm_way_get_ref(osm_way *w);
34 osm_db_prepare(sqlite3 *db)
37 /* Select nearest place inside lat,lon+-range */
38 if (sqlite3_prepare_v2(db, "select name,(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist,"
39 " lat,lon,places.nid,isin "
40 " from places,nodes where type=$TYPE "
41 " and nodes.nid=places.nid "
42 " and lat between $LAT-$RANGE and $LAT+$RANGE"
43 " and lon between $LON-$RANGE and $LON+$RANGE order by dist limit 1",
44 -1, &sql.select_near_place, NULL)!=SQLITE_OK)
46 /* Select place name, distance, location, parent-place and type with given ID */
48 if (sqlite3_prepare_v2(db, "select name,(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist,"
50 " from places,nodes where "
51 " nodes.nid=places.nid "
52 " and places.nid=$NID order by dist limit 1",
53 -1, &sql.select_place, NULL)!=SQLITE_OK)
57 /* Select neareset ways inside lat,lon+-range */
58 if (sqlite3_prepare_v2(db, "select wid,type,nodes,flags,"
59 "(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist, num"
60 " from way,way_seg,nodes"
61 " where wid=wsid and way_seg.node=nodes.nid "
62 " and lat between $LAT-$RANGE and $LAT+$RANGE "
63 " and lon between $LON-$RANGE and $LON+$RANGE "
65 -1, &sql.select_way, NULL)!=SQLITE_OK)
68 /* Select way nodes */
69 if (sqlite3_prepare_v2(db, "select num,lat,lon from way_seg,nodes where wsid=? and way_seg.node=nodes.nid order by num",
70 -1, &sql.select_way_nodes, NULL)!=SQLITE_OK)
73 /* Way name and ref */
74 if (sqlite3_prepare_v2(db, "select name from way_names where wid=?",
75 -1, &sql.select_way_name, NULL)!=SQLITE_OK)
78 if (sqlite3_prepare_v2(db, "select ref,int_ref from way_ref where rid=?",
79 -1, &sql.select_way_ref, NULL)!=SQLITE_OK)
95 osm_way_nodes_free(osm_way *w)
102 for (iter=w->nodes; iter!=NULL; iter=iter->next)
103 g_slice_free(osm_way_node, (osm_way_node*)iter->data);
105 g_list_free(w->nodes);
109 * Free a osm_way structure
112 osm_way_free(osm_way *w)
116 osm_way_nodes_free(w);
123 g_slice_free(osm_way, w);
127 * Get place with given id and distance to current location
130 osm_place_get(guint32 id, gint lat, gint lon, osm_place *n)
132 sqlite3_clear_bindings(sql.select_place);
133 sqlite3_reset(sql.select_place);
135 if (SQLITE_OK != sqlite3_bind_int(sql.select_place, 1, lat) ||
136 SQLITE_OK != sqlite3_bind_int(sql.select_place, 2, lon) ||
137 SQLITE_OK != sqlite3_bind_int(sql.select_place, 3, id)) {
138 g_printerr("Failed to bind values for place\n");
142 if (SQLITE_ROW == sqlite3_step(sql.select_place)) {
146 place=sqlite3_column_text(sql.select_place, 0);
147 n->name=g_strdup(place);
148 dist=sqlite3_column_int(sql.select_place, 1);
149 n->dist=sqrt((double)dist);
150 n->lat=sqlite3_column_int(sql.select_place, 2);
151 n->lon=sqlite3_column_int(sql.select_place, 3);
152 n->type=sqlite3_column_int(sql.select_place, 4);
153 n->isin=sqlite3_column_int(sql.select_place, 5);
160 * Search for the nearest place, type
163 osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place *n)
168 case NODE_PLACE_SUBURB:
171 case NODE_PLACE_CITY:
172 case NODE_PLACE_TOWN:
175 case NODE_PLACE_HAMLET:
176 case NODE_PLACE_VILLAGE:
184 sqlite3_clear_bindings(sql.select_near_place);
185 sqlite3_reset(sql.select_near_place);
187 if (SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 1, lat) ||
188 SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 2, lon) ||
189 SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 3, type) ||
190 SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 4, range)) {
191 g_printerr("Failed to bind values for near place\n");
199 n->isin=n->lat=n->lon=n->dist=0;
200 if (SQLITE_ROW == sqlite3_step(sql.select_near_place)) {
204 place=sqlite3_column_text(sql.select_near_place, 0);
205 n->name=g_strdup(place);
206 dist=sqlite3_column_int(sql.select_near_place, 1);
207 n->dist=sqrt((double)dist);
208 n->lat=sqlite3_column_int(sql.select_near_place, 2);
209 n->lon=sqlite3_column_int(sql.select_near_place, 3);
210 n->id=sqlite3_column_int(sql.select_near_place, 4);
211 n->isin=sqlite3_column_int(sql.select_near_place, 5);
221 osm_find_nearest_way_nodes(gint lat, gint lon, guint range)
226 sqlite3_reset(sql.select_way);
227 sqlite3_clear_bindings(sql.select_way);
229 if (SQLITE_OK != sqlite3_bind_int(sql.select_way, 1, lat) ||
230 SQLITE_OK != sqlite3_bind_int(sql.select_way, 2, lon) ||
231 SQLITE_OK != sqlite3_bind_int(sql.select_way, 3, range)) {
232 g_printerr("Failed to bind values for way\n");
236 while (SQLITE_ROW == sqlite3_step(sql.select_way)) {
239 w=g_slice_new0(osm_way);
240 w->id=sqlite3_column_int(sql.select_way, 0);
241 w->type=sqlite3_column_int(sql.select_way, 1);
242 w->nodecnt=sqlite3_column_int(sql.select_way, 2);
243 w->flags=sqlite3_column_int(sql.select_way, 3);
244 dist=sqlite3_column_int(sql.select_way, 4);
245 w->dist=sqrt((gdouble)dist);
246 w->node_num=sqlite3_column_int(sql.select_way, 5);
247 ways=g_list_prepend(ways, w);
253 static gdouble magnitude(gdouble x1, gdouble y1, gdouble x2, gdouble y2)
259 return sqrt((x*x)+(y*y));
262 gboolean distance_point_to_line(gint x, gint y, gint x1, gint y1, gint x2, gint y2, gdouble *d)
267 lm=magnitude((gdouble)x1,(gdouble)y1,(gdouble)x2,(gdouble)y2);
269 tmp=(gdouble)((x-x1)*(x2-x1))+((y-y1)*(y2-y1));
272 if (u<0.0f || u>1.0f)
275 ix=(gdouble)x1+u*(gdouble)(x2-x1);
276 iy=(gdouble)y1+u*(gdouble)(y2-y1);
278 *d=magnitude((gdouble)x,(gdouble)y, ix, iy);
283 gboolean osm_way_distance(gint lat, gint lon, osm_way_node *f, osm_way_node *t, gdouble *d)
288 return distance_point_to_line(lon, lat, f->lon, f->lat, t->lon, t->lat, d);
292 * Search for the nearest way (road)
293 * - First search for ways with nearest node
294 * - If only one is returned then we are done.
295 * - If more than one, go trough the results:
296 * - Load nodes for the way, check prev/next nodes
297 * - Store result if closer than before
298 * - Return closest way
301 osm_find_nearest_way(gint lat, gint lon)
308 while ((w=osm_find_nearest_way_nodes(lat, lon, range))==NULL && range<=65536) {
310 g_printf("Trying with range: %d\n", range);
313 g_printf("Found ways: %d\n", g_list_length(w));
315 switch (g_list_length(w)) {
321 gdouble pdist=900000.0, pndist=9000000.0;
323 for (iter=w; iter!=NULL; iter=iter->next) {
327 osm_way *way=(osm_way*)iter->data;
329 g_printf("WAY %d (%d) HAS %d NODES, nearest is %d\n",
330 way->id, way->type, way->nodecnt, way->node_num);
332 if (osm_way_get_nodes(way)==FALSE)
336 g_printerr("Way with 0 nodes ? Skipping\n");
340 wnf=g_list_nth_data(way->nodes, way->node_num);
346 if ( (way->node_num==way->nodecnt) || (way->node_num==0)) {
347 wnt=g_list_nth_data(way->nodes, way->node_num==way->nodecnt ? way->nodecnt-1 : 1);
348 if (osm_way_distance(lat, lon, wnf, wnt, &pndist)==FALSE) {
353 wnt=g_list_nth_data(way->nodes, way->node_num-1);
354 if (osm_way_distance(lat, lon, wnf, wnt, &pndist)==FALSE) {
355 wnt=g_list_nth_data(way->nodes, way->node_num+1);
356 if (osm_way_distance(lat, lon, wnf, wnt, &pndist)==FALSE) {
364 g_printf("Found close way, distance: %f (Previous distance: %f)\n", pndist, pdist);
368 way->distance=pndist;
371 g_printf("Way is not closer, freeing\n");
384 osm_way_get_name(cw);
385 if (cw->type==WAY_MOTORWAY || cw->type==WAY_TRUNK ||
386 cw->type==WAY_PRIMARY || cw->type==WAY_SECONDARY ||
387 cw->type==WAY_TERTIARY) {
391 g_printf("BEST WAY(%d): %s (%s,%s)\n",
392 cw->id, cw->name, cw->ref, cw->int_ref);
393 g_printf("\tT: %d F: %d N: %d D: %f\n",
394 cw->type, cw->flags, cw->nodecnt, cw->dist);
395 g_printf("\tNF: %d NT: %d DT %f\n",
397 cw->node_t->num, cw->distance);
403 * Get list of nodes for given way
406 osm_way_get_nodes(osm_way *w)
411 sqlite3_reset(sql.select_way_nodes);
412 sqlite3_clear_bindings(sql.select_way_nodes);
414 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_nodes, 1, w->id)) {
415 g_printerr("Failed to bind values way nodes\n");
419 while (SQLITE_ROW == sqlite3_step(sql.select_way_nodes)) {
422 n=g_slice_new(osm_way_node);
423 n->num=sqlite3_column_int(sql.select_way_nodes, 0);
424 n->lat=sqlite3_column_int(sql.select_way_nodes, 1);
425 n->lon=sqlite3_column_int(sql.select_way_nodes, 2);
426 w->nodes=g_list_append(w->nodes, n);
429 return (w->nodes==NULL) ? FALSE : TRUE;
433 osm_way_get_name(osm_way *w)
435 sqlite3_reset(sql.select_way_name);
436 sqlite3_clear_bindings(sql.select_way_name);
438 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name, 1, w->id)) {
439 g_printerr("Failed to bind values for way name\n");
443 if (SQLITE_ROW == sqlite3_step(sql.select_way_name)) {
445 place=sqlite3_column_text(sql.select_way_name, 0);
446 w->name=g_strdup(place);
452 osm_way_get_ref(osm_way *w)
454 sqlite3_reset(sql.select_way_ref);
455 sqlite3_clear_bindings(sql.select_way_ref);
457 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_ref, 1, w->id)) {
458 g_printerr("Failed to bind values for way ref\n");
462 if (SQLITE_ROW == sqlite3_step(sql.select_way_ref)) {
463 const gchar *ref, *int_ref;
464 ref=sqlite3_column_text(sql.select_way_ref, 0);
465 int_ref=sqlite3_column_text(sql.select_way_ref, 1);
466 w->ref=g_strdup(ref);
467 w->int_ref=g_strdup(int_ref);