17 struct sql_select_stmt {
18 sqlite3_stmt *select_way;
19 sqlite3_stmt *select_way_nodes;
20 sqlite3_stmt *select_way_name;
21 sqlite3_stmt *select_way_ref;
22 sqlite3_stmt *select_place;
23 sqlite3_stmt *select_near_place;
25 static struct sql_select_stmt sql;
27 gboolean osm_way_get_nodes(osm_way *w);
30 osm_db_prepare(sqlite3 *db)
33 /* Select nearest place inside lat,lon+-range */
34 if (sqlite3_prepare_v2(db, "select name,(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist,"
35 " lat,lon,places.nid,isin "
36 " from places,nodes where type=$TYPE "
37 " and nodes.nid=places.nid "
38 " and lat between $LAT-$RANGE and $LAT+$RANGE"
39 " and lon between $LON-$RANGE and $LON+$RANGE order by dist limit 1",
40 -1, &sql.select_near_place, NULL)!=SQLITE_OK)
42 /* Select place name, distance, location, parent-place and type with given ID */
44 if (sqlite3_prepare_v2(db, "select name,(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist,"
46 " from places,nodes where "
47 " nodes.nid=places.nid "
48 " and places.nid=$NID order by dist limit 1",
49 -1, &sql.select_place, NULL)!=SQLITE_OK)
53 /* Select neareset ways inside lat,lon+-range */
54 if (sqlite3_prepare_v2(db, "select wid,type,nodes,flags,"
55 "(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist, num"
56 " from way,way_seg,nodes"
57 " where wid=wsid and way_seg.node=nodes.nid "
58 " and lat between $LAT-$RANGE and $LAT+$RANGE "
59 " and lon between $LON-$RANGE and $LON+$RANGE "
61 -1, &sql.select_way, NULL)!=SQLITE_OK)
64 /* Select way nodes */
65 if (sqlite3_prepare_v2(db, "select num,lat,lon from way_seg,nodes where wsid=? and way_seg.node=nodes.nid order by num",
66 -1, &sql.select_way_nodes, NULL)!=SQLITE_OK)
69 /* Way name and ref */
70 if (sqlite3_prepare_v2(db, "select name from way_names where wid=?",
71 -1, &sql.select_way_name, NULL)!=SQLITE_OK)
74 if (sqlite3_prepare_v2(db, "select ref,int_ref from way_ref where rid=?",
75 -1, &sql.select_way_ref, NULL)!=SQLITE_OK)
91 osm_way_nodes_free(osm_way *w)
98 for (iter=w->nodes; iter!=NULL; iter=iter->next)
99 g_slice_free(osm_way_node, (osm_way_node*)iter->data);
101 g_list_free(w->nodes);
105 * Free a osm_way structure
108 osm_way_free(osm_way *w)
112 osm_way_nodes_free(w);
119 g_slice_free(osm_way, w);
123 * Get place with given id and distance to current location
126 osm_place_get(guint32 id, gint lat, gint lon, osm_place *n)
128 sqlite3_clear_bindings(sql.select_place);
129 sqlite3_reset(sql.select_place);
131 if (SQLITE_OK != sqlite3_bind_int(sql.select_place, 1, lat) ||
132 SQLITE_OK != sqlite3_bind_int(sql.select_place, 2, lon) ||
133 SQLITE_OK != sqlite3_bind_int(sql.select_place, 3, id)) {
134 g_printerr("Failed to bind values for place\n");
138 if (SQLITE_ROW == sqlite3_step(sql.select_place)) {
142 place=sqlite3_column_text(sql.select_place, 0);
143 n->name=g_strdup(place);
144 dist=sqlite3_column_int(sql.select_place, 1);
145 n->dist=sqrt((double)dist);
146 n->lat=sqlite3_column_int(sql.select_place, 2);
147 n->lon=sqlite3_column_int(sql.select_place, 3);
148 n->type=sqlite3_column_int(sql.select_place, 4);
149 n->isin=sqlite3_column_int(sql.select_place, 5);
156 * Search for the nearest place, type
159 osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place *n)
164 case NODE_PLACE_SUBURB:
167 case NODE_PLACE_CITY:
168 case NODE_PLACE_TOWN:
171 case NODE_PLACE_HAMLET:
172 case NODE_PLACE_VILLAGE:
180 sqlite3_clear_bindings(sql.select_near_place);
181 sqlite3_reset(sql.select_near_place);
183 if (SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 1, lat) ||
184 SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 2, lon) ||
185 SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 3, type) ||
186 SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 4, range)) {
187 g_printerr("Failed to bind values for near place\n");
195 n->isin=n->lat=n->lon=n->dist=0;
196 if (SQLITE_ROW == sqlite3_step(sql.select_near_place)) {
200 place=sqlite3_column_text(sql.select_near_place, 0);
201 n->name=g_strdup(place);
202 dist=sqlite3_column_int(sql.select_near_place, 1);
203 n->dist=sqrt((double)dist);
204 n->lat=sqlite3_column_int(sql.select_near_place, 2);
205 n->lon=sqlite3_column_int(sql.select_near_place, 3);
206 n->id=sqlite3_column_int(sql.select_near_place, 4);
207 n->isin=sqlite3_column_int(sql.select_near_place, 5);
217 osm_find_nearest_way_nodes(gint lat, gint lon, guint range)
222 sqlite3_reset(sql.select_way);
223 sqlite3_clear_bindings(sql.select_way);
225 if (SQLITE_OK != sqlite3_bind_int(sql.select_way, 1, lat) ||
226 SQLITE_OK != sqlite3_bind_int(sql.select_way, 2, lon) ||
227 SQLITE_OK != sqlite3_bind_int(sql.select_way, 3, range)) {
228 g_printerr("Failed to bind values for way\n");
232 while (SQLITE_ROW == sqlite3_step(sql.select_way)) {
235 w=g_slice_new0(osm_way);
236 w->id=sqlite3_column_int(sql.select_way, 0);
237 w->type=sqlite3_column_int(sql.select_way, 1);
238 w->nodecnt=sqlite3_column_int(sql.select_way, 2);
239 w->flags=sqlite3_column_int(sql.select_way, 3);
240 dist=sqlite3_column_int(sql.select_way, 4);
241 w->dist=sqrt((gdouble)dist);
242 w->node_num=sqlite3_column_int(sql.select_way, 5);
243 ways=g_list_prepend(ways, w);
249 static gdouble magnitude(gdouble x1, gdouble y1, gdouble x2, gdouble y2)
255 return sqrt((x*x)+(y*y));
258 gboolean distance_point_to_line(gint x, gint y, gint x1, gint y1, gint x2, gint y2, gdouble *d)
263 lm=magnitude((gdouble)x1,(gdouble)y1,(gdouble)x2,(gdouble)y2);
265 tmp=(gdouble)((x-x1)*(x2-x1))+((y-y1)*(y2-y1));
268 if (u<0.0f || u>1.0f)
271 ix=(gdouble)x1+u*(gdouble)(x2-x1);
272 iy=(gdouble)y1+u*(gdouble)(y2-y1);
274 *d=magnitude((gdouble)x,(gdouble)y, ix, iy);
280 * Search for the nearest way (road)
281 * - First search for ways with nearest node
282 * - If only one is returned then we are done.
283 * - If more than one, go trough the results:
284 * - Load nodes for the way, check prev/next nodes
285 * - Store result if closer than before
286 * - Return closest way
289 osm_find_nearest_way(gint lat, gint lon)
296 while ((w=osm_find_nearest_way_nodes(lat, lon, range))==NULL && range<=65536) {
298 g_printf("Trying with range: %d\n", range);
301 g_printf("Found ways: %d\n", g_list_length(w));
303 switch (g_list_length(w)) {
312 gint dist=900000, ndist;
313 gdouble pdist=900000.0, pndist=9000000.0;
315 for (iter=w; iter!=NULL; iter=iter->next) {
319 osm_way *way=(osm_way*)iter->data;
321 g_printf("WAY %d (%d) HAS %d NODES, nearest is %d\n",
322 way->id, way->type, way->nodecnt, way->node_num);
324 if (osm_way_get_nodes(way)==FALSE)
328 g_printerr("Way with 0 nodes ? Skipping\n");
332 wnf=g_list_nth_data(way->nodes, way->node_num);
338 if ( (way->node_num==way->nodecnt) || (way->node_num==0)) {
339 wnt=g_list_nth_data(way->nodes, way->node_num==way->nodecnt ? way->nodecnt-1 : 1);
344 if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE) {
349 wnt=g_list_nth_data(way->nodes, way->node_num-1);
354 if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE) {
355 wnt=g_list_nth_data(way->nodes, way->node_num+1);
360 if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE) {
368 g_printf("Found close way, distance: %f (Previous distance: %f)\n", pndist, pdist);
372 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 %d %d %d: %s %s %s\n",
392 cw->id, cw->type, cw->flags,
393 cw->nodes, cw->dist, cw->name,
394 cw->ref, cw->int_ref);
400 * Get list of nodes for given way
403 osm_way_get_nodes(osm_way *w)
408 sqlite3_reset(sql.select_way_nodes);
409 sqlite3_clear_bindings(sql.select_way_nodes);
411 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_nodes, 1, w->id)) {
412 g_printerr("Failed to bind values way nodes\n");
416 while (SQLITE_ROW == sqlite3_step(sql.select_way_nodes)) {
419 n=g_slice_new(osm_way_node);
420 n->num=sqlite3_column_int(sql.select_way_nodes, 0);
421 n->lat=sqlite3_column_int(sql.select_way_nodes, 1);
422 n->lon=sqlite3_column_int(sql.select_way_nodes, 2);
423 w->nodes=g_list_append(w->nodes, n);
426 return (w->nodes==NULL) ? FALSE : TRUE;
430 osm_way_get_name(osm_way *w)
432 sqlite3_reset(sql.select_way_name);
433 sqlite3_clear_bindings(sql.select_way_name);
435 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name, 1, w->id)) {
436 g_printerr("Failed to bind values for way name\n");
440 if (SQLITE_ROW == sqlite3_step(sql.select_way_name)) {
442 place=sqlite3_column_text(sql.select_way_name, 0);
443 w->name=g_strdup(place);
449 osm_way_get_ref(osm_way *w)
451 sqlite3_reset(sql.select_way_ref);
452 sqlite3_clear_bindings(sql.select_way_ref);
454 if (SQLITE_OK != sqlite3_bind_int(sql.select_way_ref, 1, w->id)) {
455 g_printerr("Failed to bind values for way ref\n");
459 if (SQLITE_ROW == sqlite3_step(sql.select_way_ref)) {
460 const gchar *ref, *int_ref;
461 ref=sqlite3_column_text(sql.select_way_ref, 0);
462 int_ref=sqlite3_column_text(sql.select_way_ref, 1);
463 w->ref=g_strdup(ref);
464 w->int_ref=g_strdup(int_ref);