From 12d3a56a3993d551f3f98f06a55cdec19af89bec Mon Sep 17 00:00:00 2001 From: Kaj-Michael Lang Date: Tue, 19 Feb 2008 16:20:34 +0200 Subject: [PATCH] Add place (city, town, etc) search --- src/osm-db.c | 149 +++++++++++++++++++++++++++++++++++++-------------- src/osm-db.h | 1 + src/search.c | 3 +- 3 files changed, 110 insertions(+), 43 deletions(-) diff --git a/src/osm-db.c b/src/osm-db.c index 9b9be2e..be90808 100644 --- a/src/osm-db.c +++ b/src/osm-db.c @@ -61,7 +61,8 @@ struct sql_select_stmt { sqlite3_stmt *select_way_name_search; sqlite3_stmt *select_way_ref; sqlite3_stmt *select_place; - sqlite3_stmt *select_near_place; + sqlite3_stmt *select_place_near; + sqlite3_stmt *select_place_search; sqlite3_stmt *select_node_next; sqlite3_stmt *select_node_prev; @@ -147,24 +148,33 @@ gboolean osm_db_prepare(sqlite3 *db) { /* Select nearest place inside lat,lon+-range */ -if (sqlite3_prepare_v2(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as dist," +if (sqlite3_prepare_v2(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d," " ilat,ilon,places.nid,isin_p,isin_c " " from places,nodes where type=$TYPE " " and nodes.nid=places.nid " " and ilat between $LAT-$RANGE and $LAT+$RANGE" - " and ilon between $LON-$RANGE and $LON+$RANGE order by dist limit 1", - -1, &sql.select_near_place, NULL)!=SQLITE_OK) + " and ilon between $LON-$RANGE and $LON+$RANGE order by d limit 1", + -1, &sql.select_place_near, NULL)!=SQLITE_OK) return FALSE; /* Select place name, distance, location, parent-place and type with given ID */ -if (sqlite3_prepare_v2(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as dist," +if (sqlite3_prepare_v2(db, "select name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d," " ilat,ilon,type,isin_p,isin_c " " from places,nodes where " " nodes.nid=places.nid " - " and places.nid=$NID order by dist limit 1", + " and places.nid=$NID order by d limit 1", -1, &sql.select_place, NULL)!=SQLITE_OK) return FALSE; +/* Search */ +if (sqlite3_prepare_v2(db, "select places.nid,name,(($LAT-ilat)*($LAT-ilat))+(($LON-ilon)*($LON-ilon)) as d," + " rlat,rlon,type,isin_p,isin_c " + " from places,nodes where " + " nodes.nid=places.nid " + " and name like $NAME order by d limit 200", + -1, &sql.select_place_search, NULL)!=SQLITE_OK) + return FALSE; + /* Ways */ /* Select nearest ways inside lat,lon+-range */ if (sqlite3_prepare_v2(db, "select w.wid,type,nodes,flags," @@ -191,7 +201,7 @@ if (sqlite3_prepare_v2(db, "select w.wid,w.name as name," " ww.type between $WTS and $WTY and w.wid=ww.wid and n.name like $NAME " " and ww.lat between $LAT-$RANGE and $LAT+$RANGE " " and ww.lon between $LON-$RANGE and $LON+$RANGE " - " order by name limit 100", + " order by name limit 200", -1, &sql.select_way_name_search, NULL)!=SQLITE_OK) return FALSE; @@ -243,8 +253,8 @@ if (osmdb) { sqlite3_finalize(sql.select_way2); if (sql.select_place) sqlite3_finalize(sql.select_place); - if (sql.select_near_place) - sqlite3_finalize(sql.select_near_place); + if (sql.select_place_near) + sqlite3_finalize(sql.select_place_near); if (sql.select_node_next) sqlite3_finalize(sql.select_node_next); if (sql.select_node_prev) @@ -479,32 +489,32 @@ switch (type) { break; } -sqlite3_clear_bindings(sql.select_near_place); -sqlite3_reset(sql.select_near_place); +sqlite3_clear_bindings(sql.select_place_near); +sqlite3_reset(sql.select_place_near); -if (SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 1, lat) || - SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 2, lon) || - SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 3, type) || - SQLITE_OK != sqlite3_bind_int(sql.select_near_place, 4, range)) { +if (SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 1, lat) || + SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 2, lon) || + SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 3, type) || + SQLITE_OK != sqlite3_bind_int(sql.select_place_near, 4, range)) { g_printerr("Failed to bind values for near place\n"); return FALSE; } n=osm_place_new(); n->isin_p=n->lat=n->lon=n->dist=0; -if (SQLITE_ROW == sqlite3_step(sql.select_near_place)) { +if (SQLITE_ROW == sqlite3_step(sql.select_place_near)) { const gchar *place; guint32 dist; - place=sqlite3_column_text(sql.select_near_place, 0); + place=sqlite3_column_text(sql.select_place_near, 0); n->name=g_strdup(place); - dist=sqlite3_column_int(sql.select_near_place, 1); + dist=sqlite3_column_int(sql.select_place_near, 1); n->dist=sqrt((double)dist); - n->lat=sqlite3_column_int(sql.select_near_place, 2); - n->lon=sqlite3_column_int(sql.select_near_place, 3); - n->id=sqlite3_column_int(sql.select_near_place, 4); - n->isin_p=sqlite3_column_int(sql.select_near_place, 5); -/* n->isin_c=sqlite3_column_int(sql.select_near_place, 6); */ + n->lat=sqlite3_column_int(sql.select_place_near, 2); + n->lon=sqlite3_column_int(sql.select_place_near, 3); + n->id=sqlite3_column_int(sql.select_place_near, 4); + n->isin_p=sqlite3_column_int(sql.select_place_near, 5); +/* n->isin_c=sqlite3_column_int(sql.select_place_near, 6); */ n->type=type; osm_place_cache_add(n); @@ -685,10 +695,8 @@ for (iter=w; iter!=NULL; iter=iter->next) { osm_way_node *wnp; osm_way *way=(osm_way*)iter->data; -#ifdef DEBUG_OSM - g_printf("Way: %d (%d) has %d nodes, nearest is %d,%d\n", + g_debug("Way: %d (%d) has %d nodes, nearest is %d,%d", way->id, way->type, way->nodecnt, way->f, way->t); -#endif way->node_t=NULL; @@ -701,7 +709,7 @@ for (iter=w; iter!=NULL; iter=iter->next) { cw=way; way->distance=dist_n; way->node_t=wnn; - g_printf("#1 distance: %f (%f)\n", dist_n, pdist); + g_debug("#1 distance: %f (%f)", dist_n, pdist); } wnp=osm_way_get_prev_node(way); @@ -716,12 +724,10 @@ for (iter=w; iter!=NULL; iter=iter->next) { osm_way_node_free(wnn); } way->node_t=wnp; - g_printf("#2 distance: %f (%f)\n", dist_p, pdist); + g_debug("#2 distance: %f (%f)", dist_p, pdist); } -#ifdef DEBUG_OSM - g_printf("Found close way, distance: %f %f (%f)\n", dist_n, dist_p, pdist); -#endif + g_debug("Found close way, distance: %f %f (%f)", dist_n, dist_p, pdist); if (!cw) { osm_way_free(way); @@ -740,16 +746,9 @@ if (cw->type==WAY_MOTORWAY || cw->type==WAY_TRUNK || osm_way_get_ref(cw); } -#ifdef DEBUG_OSM -g_printf("BEST WAY(%d): %s [%s][%s]\n", - cw->id, cw->name, cw->ref, cw->int_ref); -g_printf("\tType: %d Flags: %d Nodes: %d Dist: %f\n", - cw->type, cw->flags, cw->nodecnt, cw->dist); -g_printf("\tNF: %d NT: %d Distance: %f\n", - cw->f, - cw->t, - cw->distance); -#endif +g_debug("Found way: (ID: %d): [%s]:[%s][%s]", cw->id, cw->name, cw->ref, cw->int_ref); +g_debug("T: %d F: %d N#: %d D: %f", cw->type, cw->flags, cw->nodecnt, cw->dist); +g_debug("\tNF#: %d NT#: %d (D: %f)", cw->f, cw->t, cw->distance); return cw; } @@ -1025,6 +1024,74 @@ if (check_place==TRUE && d>way_dist_range*4) { return map_loc->street ? TRUE : FALSE; } +/** + * osm_place_search + */ +gboolean +osm_place_search(gdouble lat, gdouble lon, gchar *text, GtkListStore **store) +{ +GtkTreeIter iter; +gchar *ltext=NULL; +guint rows=0; +gchar tmp1[16], tmp2[16]; +gdouble range=6; + +ltext=g_strdup_printf("%s%%", text); + +if (SQLITE_OK != sqlite3_bind_double(sql.select_place_search, 1, lat) || + SQLITE_OK != sqlite3_bind_double(sql.select_place_search, 2, lon) || + SQLITE_OK != sqlite3_bind_text(sql.select_place_search, 3, ltext, -1, SQLITE_TRANSIENT)) { + g_printerr("Failed to bind values for sql.select_place_search\n"); + sqlite3_clear_bindings(sql.select_place_search); + g_free(ltext); + return FALSE; +} + +if (ltext) + g_free(ltext); + +*store = gtk_list_store_new(ITEM_NUM_COLUMNS, + G_TYPE_INT, /* ID */ + G_TYPE_INT, /* */ + G_TYPE_DOUBLE, /* Latitude */ + G_TYPE_DOUBLE, /* Longitude */ + G_TYPE_DOUBLE, /* Distance */ + G_TYPE_STRING, /* Lat/Lon */ + G_TYPE_STRING, /* Label */ + G_TYPE_STRING, /* Desc. */ + G_TYPE_STRING, /* Category */ + G_TYPE_STRING, /* Dummy */ + G_TYPE_STRING); /* Dummy */ + +while (SQLITE_ROW == sqlite3_step(sql.select_place_search)) { + gdouble rlat, rlon, dist; + + rlat=sqlite3_column_double(sql.select_place_search, 3); + rlon=sqlite3_column_double(sql.select_place_search, 4); + lat_format(_degformat, rlat, tmp1); + lon_format(_degformat, rlon, tmp2); + dist=calculate_distance(lat, lon, rlat, rlon) * UNITS_CONVERT[_units]; + + gtk_list_store_append(*store, &iter); + gtk_list_store_set(*store, &iter, + ITEM_ID, sqlite3_column_int(sql.select_place_search, 0), + ITEM_LAT, rlat, + ITEM_LON, rlon, + ITEM_DIST, dist, + ITEM_LATLON, g_strdup_printf("%s, %s", tmp1, tmp2), + ITEM_LABEL, sqlite3_column_text(sql.select_place_search, 1), + -1); + rows++; +} + +g_printf("Found: %d places\n", rows); + +sqlite3_reset(sql.select_place_search); +sqlite3_clear_bindings(sql.select_place_search); + +return TRUE; +} + /** * osm_way_search * diff --git a/src/osm-db.h b/src/osm-db.h index a836622..6da5f70 100644 --- a/src/osm-db.h +++ b/src/osm-db.h @@ -54,6 +54,7 @@ gboolean osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place osm_way *osm_find_nearest_way(gint lat, gint lon); gboolean osm_way_distance(gint lat, gint lon, osm_way_node *f, osm_way_node *t, gdouble *d); +gboolean osm_place_search(gdouble lat, gdouble lon, gchar *text, GtkListStore **store); gboolean osm_place_get(guint32 id, gint lat, gint lon, osm_place **nr); gboolean osm_get_location_data(gint lat, gint lon, gfloat heading, osm_location *map_loc); diff --git a/src/search.c b/src/search.c index 5c688ea..59ae62d 100644 --- a/src/search.c +++ b/src/search.c @@ -113,8 +113,7 @@ switch (s->stype) { sres=osm_way_search(s->lat, s->lon, st, &s->store); break; case SEARCH_TYPE_PLACE: - popup_error(s->dialog, "Not yet implemented"); - sres=FALSE; + sres=osm_place_search(s->lat, s->lon, st, &s->store); break; } -- 2.39.5