-#define _GNU_SOURCE
+/*
+ * This file is part of mapper
+ *
+ * Copyright (C) 2007 Kaj-Michael Lang
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+#include "config.h"
#include <unistd.h>
#include <string.h>
#include <math.h>
#include <glib.h>
#include <glib/gstdio.h>
+#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <sqlite3.h>
#include "osm.h"
#include "latlon.h"
-
#include "osm-db.h"
+#include "settings.h"
/* #define DEBUG_OSM */
+/* #define DEBUG_OSM_TIME */
#define OSM_PLACE_CACHE_MAX_ITEMS (64)
-#define OSM_DB_PROGRESS_NUM (5000)
-#define OSM_RANGE_START (8192)
+
+#define OSM_DB_PROGRESS_NUM (15000)
+
+/* Node search ranges */
+#define OSM_RANGE_START (16384)
#define OSM_RANGE_STEP (8192)
-#define OSM_RANGE_STOP (49152)
+#define OSM_RANGE_STOP (65535)
+
+static sqlite3 *osmdb;
+static gboolean osm_db_ok;
struct sql_select_stmt {
sqlite3_stmt *select_way;
sqlite3_stmt *select_way_nodes;
sqlite3_stmt *select_way_name;
+ sqlite3_stmt *select_way_name_nls;
+ 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;
};
static struct sql_select_stmt sql;
static GTimer *dbt;
static GtkProgressBar *dbpw=NULL;
/* Cache hash tables */
-static GHashTable *_place_cache;
+struct osm_place_cache {
+ GHashTable *cache;
+ guint hit;
+ guint miss;
+};
+static struct osm_place_cache pcache;
-static gint way_dist_range=OSM_RANGE_WAY;
+static guint way_dist_range=OSM_RANGE_WAY;
+static gint sid=0;
osm_way_node *osm_way_get_prev_node(osm_way *w);
osm_way_node *osm_way_get_next_node(osm_way *w);
/*****************************************************************************/
void
-osm_set_way_range(gint sr)
+osm_set_way_range(guint sr)
{
way_dist_range=sr;
}
void
osm_set_way_range_from_speed(gfloat speed)
{
-if (speed>54)
- way_dist_range=9000;
+if (speed>54.0)
+ way_dist_range=OSM_RANGE_WAY;
else
- way_dist_range=OSM_RANGE_WAY-lrint((speed/3)*1000);
+ way_dist_range=OSM_RANGE_WAY-lrint((speed/4)*1000);
}
-static int
-osm_progress(void *ud)
+/*****************************************************************************/
+
+static gboolean
+osm_progress_pulse(void)
{
if (!dbpw)
- return 0;
+ return FALSE;
gtk_progress_bar_pulse(dbpw);
+return TRUE;
+}
+
+static int
+osm_progress(void *ud)
+{
gtk_main_iteration_do(FALSE);
return 0;
}
{
if (!dbpw)
return;
-gtk_widget_hide(GTK_WIDGET(dbpw));
+gtk_progress_bar_set_text(dbpw, "");
+gtk_progress_bar_set_fraction(dbpw, 0.0);
sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, NULL, NULL);
}
{
if (!dbpw)
return;
-gtk_widget_show(GTK_WIDGET(dbpw));
+gtk_progress_bar_set_text(dbpw, _("Searching..."));
+gtk_progress_bar_pulse(dbpw);
+gtk_main_iteration_do(FALSE);
sqlite3_progress_handler(db, OSM_DB_PROGRESS_NUM, osm_progress, NULL);
}
void
osm_progress_set_widget(sqlite3 *db, GtkProgressBar *w)
{
-if (dbpw!=NULL && w==NULL)
+if (dbpw!=NULL && w==NULL) {
osm_progress_hide(db);
+ if (sid!=0)
+ g_source_remove(sid);
+ sid=0;
+ dbpw=NULL;
+ return;
+}
dbpw=w;
-if (w!=NULL)
+if (w!=NULL) {
osm_progress_show(db);
+ sid=g_timeout_add(200, osm_progress_pulse, NULL);
+}
}
+/*****************************************************************************/
+
gboolean
osm_db_prepare(sqlite3 *db)
{
-/* Place */
/* Select nearest place inside lat,lon+-range */
-if (sqlite3_prepare_v2(db, "select name,(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist,"
- " lat,lon,places.nid,isin "
+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 lat between $LAT-$RANGE and $LAT+$RANGE"
- " and lon between $LON-$RANGE and $LON+$RANGE order by dist limit 1",
- -1, &sql.select_near_place, NULL)!=SQLITE_OK)
+ " and ilat between $LAT-$RANGE and $LAT+$RANGE"
+ " 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-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist,"
- " lat,lon,type,isin "
+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 neareset ways inside lat,lon+-range */
-if (sqlite3_prepare_v2(db, "select wid,type,nodes,flags,"
- "(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as d,f,t,lat,lon "
- " from way as w,way_s2s as ws,nodes as n "
- " where w.wid=ws.wsid and ws.f=n.nid "
- " and n.lat between $LAT-$RANGE and $LAT+$RANGE "
- " and n.lon between $LON-$RANGE and $LON+$RANGE "
+/* Select nearest ways inside lat,lon+-range */
+if (sqlite3_prepare_v2(db, "select w.wid,type,nodes,flags,"
+ "(($LAT-n.ilat)*($LAT-n.ilat))+(($LON-n.ilon)*($LON-n.ilon)) as d,wn.f,wn.t,n.ilat,n.ilon "
+ " from way as w,way_n2n as wn,nodes as n "
+ " where w.wid=wn.wid and wn.f=n.nid "
+ " and n.ilat between $LAT-$RANGE and $LAT+$RANGE "
+ " and n.ilon between $LON-$RANGE and $LON+$RANGE "
" and w.type between $WTS and $WTY "
" order by d",
-1, &sql.select_way2, NULL)!=SQLITE_OK)
return FALSE;
-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",
+if (sqlite3_prepare_v2(db, "select w.wid,w.name as name,"
+ "(($LAT-ww.lat)*($LAT-ww.lat))+(($LON-ww.lon)*($LON-ww.lon)) as d,ww.lat,ww.lon "
+ " from way_names as w,way as ww where "
+ " ww.type between $WTS and $WTY and w.wid=ww.wid and w.name like $NAME "
+ " and ww.lat between $LAT-$RANGE and $LAT+$RANGE "
+ " and ww.lon between $LON-$RANGE and $LON+$RANGE "
+ " union "
+ " select w.wid,n.name as name,"
+ "(($LAT-ww.lat)*($LAT-ww.lat))+(($LON-ww.lon)*($LON-ww.lon)) as d,ww.lat,ww.lon "
+ " from way_names as w, way as ww,way_names_nls as n on w.wid=n.wid where "
+ " 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 200",
+ -1, &sql.select_way_name_search, NULL)!=SQLITE_OK)
+ return FALSE;
+
+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",
-1, &sql.select_way_next_seg, NULL)!=SQLITE_OK)
return FALSE;
-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",
+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",
-1, &sql.select_way_prev_seg, NULL)!=SQLITE_OK)
return FALSE;
/* Way name */
-if (sqlite3_prepare_v2(db, "select name from way_names where wid=?",
- -1, &sql.select_way_name, NULL)!=SQLITE_OK)
+if (sqlite3_prepare_v2(db, "select name from way_names where wid=?", -1, &sql.select_way_name, NULL)!=SQLITE_OK)
return FALSE;
/* Way ref and int_ref */
-if (sqlite3_prepare_v2(db, "select ref,int_ref from way_ref where rid=?",
- -1, &sql.select_way_ref, NULL)!=SQLITE_OK)
+if (sqlite3_prepare_v2(db, "select ref,int_ref from way_ref where rid=?", -1, &sql.select_way_ref, NULL)!=SQLITE_OK)
return FALSE;
-return TRUE;
-}
+/* Get next, prev node + way information. For routing. */
+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 "
+ "from way as w, nodes as n, way_n2n as nn where w.wid=nn.wid and nn.f=n.nid and nn.f=?",
+ -1, &sql.select_node_next, NULL)!=SQLITE_OK)
+ return FALSE;
+
+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 "
+ "from way as w, nodes as n, way_n2n as nn where w.wid=nn.wid and nn.f=n.nid and nn.t=?",
+ -1, &sql.select_node_prev, NULL)!=SQLITE_OK)
+ return FALSE;
-gboolean
-osm_init(void)
-{
-_place_cache=g_hash_table_new(g_direct_hash, g_direct_equal);
-dbt=g_timer_new();
return TRUE;
}
void
osm_deinit(void)
{
-g_hash_table_destroy(_place_cache);
+if (osmdb) {
+ if (sql.select_way_ref)
+ sqlite3_finalize(sql.select_way_ref);
+ if (sql.select_way_name)
+ sqlite3_finalize(sql.select_way_name);
+ if (sql.select_way_next_seg)
+ sqlite3_finalize(sql.select_way_next_seg);
+ if (sql.select_way_prev_seg)
+ sqlite3_finalize(sql.select_way_prev_seg);
+ if (sql.select_way_name_search)
+ sqlite3_finalize(sql.select_way_name_search);
+ if (sql.select_way2)
+ sqlite3_finalize(sql.select_way2);
+ if (sql.select_place)
+ sqlite3_finalize(sql.select_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)
+ sqlite3_finalize(sql.select_node_prev);
+}
+osmdb=NULL;
+osm_db_ok=FALSE;
+memset(&sql, 0, sizeof(sql));
+g_hash_table_destroy(pcache.cache);
+pcache.hit=0;
+pcache.miss=0;
g_timer_destroy(dbt);
}
+gboolean
+osm_init(sqlite3 **db)
+{
+osm_db_ok=FALSE;
+pcache.cache=g_hash_table_new(g_direct_hash, g_direct_equal);
+dbt=g_timer_new();
+
+if (!db || !*db) {
+ osmdb=NULL;
+ return FALSE;
+}
+
+osmdb=*db;
+memset(&sql, 0, sizeof(sql));
+if (osm_db_prepare(osmdb)==FALSE) {
+ g_printerr("Failed to prepare OSM SQL statements:");
+ g_printf("SQLITE: %s\n", sqlite3_errmsg(osmdb));
+ return FALSE;
+}
+osm_db_ok=TRUE;
+return TRUE;
+}
+
/*****************************************************************************/
osm_way_node *
static osm_place *
osm_place_cache_lookup(guint32 id)
{
-return g_hash_table_lookup(_place_cache, GINT_TO_POINTER(id));
+osm_place *r;
+r=g_hash_table_lookup(pcache.cache, GINT_TO_POINTER(id));
+if (r)
+ pcache.hit++;
+else
+ pcache.miss++;
+
+g_debug("OSM: Cache %d/%d", pcache.hit, pcache.miss);
+return r;
}
static void
osm_place_cache_add(osm_place *p)
{
if (osm_place_cache_lookup(p->id)==NULL)
- g_hash_table_insert(_place_cache, GINT_TO_POINTER(p->id), p);
+ g_hash_table_insert(pcache.cache, GINT_TO_POINTER(p->id), p);
}
static void
osm_place_cache_gc(void)
{
-gint r;
-r=g_hash_table_foreach_remove(_place_cache, osm_place_remove, NULL);
+guint r;
+
+r=g_hash_table_foreach_remove(pcache.cache, osm_place_remove, NULL);
+g_debug("OSM: Cache cleared (%d)", r);
+pcache.hit=0;
+pcache.miss=0;
}
static void
n=NULL;
/* XXX: better place for this */
-if (g_hash_table_size(_place_cache)>OSM_PLACE_CACHE_MAX_ITEMS)
+if (g_hash_table_size(pcache.cache)>OSM_PLACE_CACHE_MAX_ITEMS)
osm_place_cache_gc();
sqlite3_clear_bindings(sql.select_place);
n->lat=sqlite3_column_int(sql.select_place, 2);
n->lon=sqlite3_column_int(sql.select_place, 3);
n->type=sqlite3_column_int(sql.select_place, 4);
- n->isin=sqlite3_column_int(sql.select_place, 5);
+ n->isin_p=sqlite3_column_int(sql.select_place, 5);
+/* n->isin_c=sqlite3_column_int(sql.select_place, 6); */
return TRUE;
}
return FALSE;
}
/**
- * Search for the nearest place, type
+ * Search for the nearest place with given type
*/
gboolean
osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place **nr)
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=n->lat=n->lon=n->dist=0;
-if (SQLITE_ROW == sqlite3_step(sql.select_near_place)) {
+n->isin_p=n->lat=n->lon=n->dist=0;
+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=sqlite3_column_int(sql.select_near_place, 5);
+ 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);
return FALSE;
}
-#if 0
-/* Way helper */
-static GList *
-osm_find_nearest_way_nodes(gint lat, gint lon, guint range)
-{
-GList *ways=NULL;
-osm_way *w;
-gulong tms;
-gint wc=0;
-
-sqlite3_reset(sql.select_way);
-sqlite3_clear_bindings(sql.select_way);
-
-if (SQLITE_OK != sqlite3_bind_int(sql.select_way, 1, lat) ||
- SQLITE_OK != sqlite3_bind_int(sql.select_way, 2, lon) ||
- SQLITE_OK != sqlite3_bind_int(sql.select_way, 3, range) ||
- SQLITE_OK != sqlite3_bind_int(sql.select_way, 4, WAY_ROAD_START) ||
- SQLITE_OK != sqlite3_bind_int(sql.select_way, 5, WAY_ROAD_END)) {
- g_printerr("Failed to bind values for way\n");
- return NULL;
-}
-
-g_timer_start(dbt);
-
-while (SQLITE_ROW == sqlite3_step(sql.select_way)) {
- guint32 dist;
-
- wc++;
- w=g_slice_new0(osm_way);
- w->id=sqlite3_column_int(sql.select_way, 0);
- w->type=sqlite3_column_int(sql.select_way, 1);
- w->nodecnt=sqlite3_column_int(sql.select_way, 2);
- w->flags=sqlite3_column_int(sql.select_way, 3);
- dist=sqlite3_column_int(sql.select_way, 4);
- w->dist=sqrt((gdouble)dist);
- w->node_num=sqlite3_column_int(sql.select_way, 5);
- ways=g_list_prepend(ways, w);
-}
-
-g_timer_stop(dbt);
-g_printf("Query took: %f sec, found: %d ways\n", g_timer_elapsed(dbt, &tms), wc);
-
-return ways;
-}
-
-#else
-
-/* Way helper */
+/*
+ * Way helper
+ *
+ */
static GList *
osm_find_nearest_way_nodes(gint lat, gint lon, guint range)
{
GList *ways=NULL;
osm_way *w;
gulong tms;
-gint wc=0;
+guint wc=0;
sqlite3_reset(sql.select_way2);
sqlite3_clear_bindings(sql.select_way2);
return NULL;
}
+#ifdef DEBUG_OSM_TIME
g_timer_start(dbt);
+#endif
while (SQLITE_ROW == sqlite3_step(sql.select_way2)) {
guint32 dist;
ways=g_list_prepend(ways, w);
}
+#ifdef DEBUG_OSM_TIME
g_timer_stop(dbt);
g_printf("Query took: %f sec, found: %d ways\n", g_timer_elapsed(dbt, &tms), wc);
+#endif
return ways;
}
-#endif
-
/*****************************************************************************/
-inline gdouble
-magnitude(gdouble x1, gdouble y1, gdouble x2, gdouble y2)
+GSList *
+osm_get_route_node(guint nid, osm_node_direction d)
{
-gdouble x,y;
-x=x2-x1;
-y=y2-y1;
+GSList *r=NULL;
+osm_way *w;
+guint wc=0;
+sqlite3_stmt *psql=NULL;
-return sqrt((x*x)+(y*y));
+switch (d) {
+ case OSM_NODE_NEXT:
+ psql=sql.select_node_next;
+ break;
+ case OSM_NODE_PREV:
+ psql=sql.select_node_prev;
+ break;
+ default:
+ g_assert_not_reached();
+ break;
}
-static gboolean
-distance_point_to_line(gdouble x, gdouble y, gdouble x1, gdouble y1, gdouble x2, gdouble y2, gdouble *d)
-{
-gdouble lm,u,tmp;
-gdouble ix,iy;
+sqlite3_reset(psql);
+sqlite3_clear_bindings(psql);
-lm=magnitude(x1,y1,x2,y2);
-if (lm==0.0f)
- return FALSE;
+if (SQLITE_OK != sqlite3_bind_int(psql, 1, nid)) {
+ g_printerr("Failed to bind values for route node\n");
+ return NULL;
+}
-tmp=((x-x1)*(x2-x1))+((y-y1)*(y2-y1));
-u=tmp/(lm*lm);
+while (SQLITE_ROW == sqlite3_step(psql)) {
+ gdouble lat, lon;
-if (u<0.0f || u>1.0f)
- return FALSE;
-
-ix=x1+u*(x2-x1);
-iy=y1+u*(y2-y1);
-
-*d=magnitude(x,y, ix, iy);
-
-return TRUE;
+ wc++;
+ w=g_slice_new0(osm_way);
+ w->id=sqlite3_column_int(psql, 0);
+ w->type=sqlite3_column_int(psql, 1);
+ w->flags=sqlite3_column_int(psql, 2);
+ w->speed=sqlite3_column_int(psql, 3);
+
+ lat=sqlite3_column_double(psql, 5);
+ lon=sqlite3_column_double(psql, 6);
+
+ w->f=sqlite3_column_int(psql, 7);
+ w->t=sqlite3_column_int(psql, 8);
+#if 0
+ w->node=
+ w->node->flags=sqlite3_column_int(psql, 9);
+ w->node->links=sqlite3_column_int(psql, 10);
+#endif
+
+ r=g_slist_prepend(r, w);
+}
+
+return r;
}
+
+/*****************************************************************************/
gboolean
osm_way_distance(gint lat, gint lon, osm_way_node *f, osm_way_node *t, gdouble *d)
{
range+=OSM_RANGE_STEP;
g_printf("Trying with range: %d\n", range);
}
-
#ifdef DEBUG_OSM
-g_printf("Found ways: %d\n", g_list_length(w));
+g_printf("Found %d ways withing range %d\n", g_list_length(w), range);
#endif
if (g_list_length(w)==0)
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\n",
- way->id, way->type, way->nodecnt, way->f);
-#endif
+ g_debug("Way: %d (%d) has %d nodes, nearest is %d,%d",
+ way->id, way->type, way->nodecnt, way->f, way->t);
way->node_t=NULL;
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);
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);
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("\tT: %d F: %d N: %d D: %f\n",
- cw->type, cw->flags, cw->nodecnt, cw->dist);
-g_printf("\tNF: %d NT: %d DT %f\n",
- cw->node_f->num,
- cw->node_t->num, 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;
}
+/* XXX: These two should be combined to save memory */
+/**
+ * Get previous node/segment of given way node
+ *
+ */
osm_way_node *
osm_way_get_prev_node(osm_way *w)
{
return NULL;
}
+/**
+ * Get next node/segment of given way node
+ *
+ */
osm_way_node *
osm_way_get_next_node(osm_way *w)
{
/**
* Get list of nodes for given way
+ *
*/
gboolean
osm_way_get_nodes(osm_way *w)
}
/**
- * Get way name (primary name only for now)
+ * Get way name
+ *
*/
gboolean
osm_way_get_name(osm_way *w)
return FALSE;
}
+#if 0
+gboolean
+osm_way_get_name_nls(osm_way *w)
+{
+sqlite3_reset(sql.select_way_name_nls);
+sqlite3_clear_bindings(sql.select_way_name_nls);
+
+if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name_nls, 1, w->id) ||
+ SQLITE_OK != sqlite3_bind_) {
+ g_printerr("Failed to bind values for way name nls\n");
+ return FALSE;
+}
+
+if (SQLITE_ROW == sqlite3_step(sql.select_way_name_nls)) {
+ const gchar *place;
+ place=sqlite3_column_text(sql.select_way_name_nls, 0);
+ w->name=g_strdup(place);
+}
+return FALSE;
+}
+#endif
+
/**
* Get Way ref and int_ref
+ *
*/
gboolean
osm_way_get_ref(osm_way *w)
/******************************************************************************/
+/**
+ * Try to figure out where the given lat,lon is. Fills in the given struct,
+ * with street, secondary (suburb) and primary (city,town,village) location.
+ * Will try to minimize the amount of database access by skipping queries
+ * if we haven't moved or if we don't know where we are.
+ *
+ */
gboolean
-osm_get_location_data(gint lat, gint lon, osm_location *map_loc)
+osm_get_location_data(gint lat, gint lon, gfloat heading, osm_location *map_loc)
{
gdouble dist;
-gboolean fs, check_place=FALSE;
-static gboolean inp=FALSE;
+gboolean check_place=FALSE;
+gulong d;
+
+if (map_loc->valid==FALSE) {
+ map_loc->lat=lat;
+ map_loc->lon=lon;
+ map_loc->valid=TRUE;
+ d=way_dist_range*5;
+} else {
+ d=calculate_idistance(lat,lon,map_loc->lat,map_loc->lon);
+}
/* Check if we are still near the same way as last time */
if (map_loc->street && osm_way_distance(lat, lon, map_loc->street->node_f, map_loc->street->node_t, &dist)==TRUE) {
- if (dist>way_dist_range) {
+ /* We are probably on the same way as last time */
+ if ( (dist>(gdouble)way_dist_range) || (fabs(heading-map_loc->heading)>10.0)) {
+ /* We have moved a large amount, check way again */
+ g_debug("Distance %f > %f range or angle %f > 10.0, checking location",
+ dist, way_dist_range, fabs(heading-map_loc->heading));
osm_way_free(map_loc->street);
map_loc->street=osm_find_nearest_way(lat, lon);
- check_place=FALSE;
+ check_place=TRUE;
+ map_loc->changed=TRUE;
} else {
+#if 0
+ g_printf("*** No change in location: %f %d\n", dist, way_dist_range);
+#endif
+ /* We are still on the same way as last time */
check_place=FALSE;
+ map_loc->changed=FALSE;
}
+ map_loc->lat=lat;
+ map_loc->lon=lon;
} else {
- osm_way_free(map_loc->street);
- map_loc->street=osm_find_nearest_way(lat, lon);
- check_place=TRUE;
+ /* We didn't know our location, so check it, but only if we have moved */
+ if (d>way_dist_range) {
+ g_print("*** Must check location\n");
+ check_place=TRUE;
+ osm_way_free(map_loc->street);
+ map_loc->street=osm_find_nearest_way(lat, lon);
+#if 0
+ map_loc->lat=lat;
+ map_loc->lon=lon;
+#endif
+ }
+
+ if (!map_loc->street) {
+ g_print("*** Street not known\n");
+ map_loc->nfcnt++;
+ map_loc->changed=TRUE;
+ } else {
+ g_print("*** Street known\n");
+ map_loc->nfcnt=0;
+ map_loc->changed=TRUE;
+ check_place=TRUE;
+ }
}
-if (check_place==TRUE) {
-fs=osm_find_nearest_place(NODE_PLACE_SUBURB, lat, lon, &map_loc->secondary);
-if (fs==TRUE && map_loc->secondary && map_loc->secondary->isin!=0) {
- if (osm_place_get(map_loc->secondary->isin, lat, lon, &(map_loc->primary))==FALSE) {
+if (map_loc->changed==TRUE) {
+ map_loc->heading=heading;
+}
+
+#if 0
+g_printf("NFC: %d\n", map_loc->nfcnt);
+g_printf("D: %ld %ld\n", d,(gulong)way_dist_range);
+#endif
+
+if (check_place==TRUE && d>way_dist_range*4) {
+ gboolean fs;
+
+ fs=osm_find_nearest_place(NODE_PLACE_SUBURB, lat, lon, &map_loc->secondary);
+ if (fs==TRUE && map_loc->secondary && map_loc->secondary->isin_p!=0) {
+ if (osm_place_get(map_loc->secondary->isin_p, lat, lon, &(map_loc->primary))==FALSE) {
+ if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
+ g_printf("Near city: %s\n", map_loc->primary->name);
+ else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
+ g_printf("Near town: %s\n", map_loc->primary->name);
+ else
+ g_printf("Unknown\n");
+ } else {
+ g_printf("In: %s\n", map_loc->primary ? map_loc->primary->name : "?");
+ }
+ } else if (map_loc->street && map_loc->street->isin_p!=0) {
+ if (osm_place_get(map_loc->street->isin_p, lat, lon, &map_loc->primary)==FALSE) {
+ g_printf("Street location not know.\n");
+ } else {
+ g_printf("Street is in: %s\n", map_loc->primary ? map_loc->primary->name : "?");
+ }
+ } else {
if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
g_printf("Near city: %s\n", map_loc->primary->name);
else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
g_printf("Near town: %s\n", map_loc->primary->name);
else
g_printf("Unknown\n");
- } else {
- g_printf("In: %s\n", map_loc->primary ? map_loc->primary->name : "?");
- }
-} else if (map_loc->street && map_loc->street->isin!=0) {
- if (osm_place_get(map_loc->street->isin, lat, lon, &map_loc->primary)==FALSE) {
- g_printf("Street location not know.\n");
- } else {
- g_printf("Street is in: %s\n", map_loc->primary ? map_loc->primary->name : "?");
+
}
-} else {
- if (osm_find_nearest_place(NODE_PLACE_CITY, lat, lon, &map_loc->primary)==TRUE)
- g_printf("Near city: %s\n", map_loc->primary->name);
- else if (osm_find_nearest_place(NODE_PLACE_TOWN, lat, lon, &map_loc->primary)==TRUE)
- g_printf("Near town: %s\n", map_loc->primary->name);
- else
- g_printf("Unknown\n");
+}
+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;
}
-return map_loc->street ? TRUE : 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
+ *
+ * Search for a street(way) starting with given 'text', next given lat/lon
+ *
+ */
+gboolean
+osm_way_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;
+
+g_printf("Way Search: [%s] around %.6f %.6f\n", text, lat, lon);
+
+ltext=g_strdup_printf("%s%%", text);
+
+if (SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 1, lat) ||
+ SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 2, lon) ||
+ SQLITE_OK != sqlite3_bind_int(sql.select_way_name_search, 3, WAY_ROAD_START) ||
+ SQLITE_OK != sqlite3_bind_int(sql.select_way_name_search, 4, WAY_ROAD_END) ||
+ SQLITE_OK != sqlite3_bind_double(sql.select_way_name_search, 6, range) ||
+ SQLITE_OK != sqlite3_bind_text(sql.select_way_name_search, 5, ltext, -1, SQLITE_TRANSIENT)) {
+ g_printerr("Failed to bind values for sql.select_way_name_search\n");
+ sqlite3_clear_bindings(sql.select_way_name_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_way_name_search)) {
+ gdouble rlat, rlon, dist;
+
+ rlat=sqlite3_column_double(sql.select_way_name_search, 3);
+ rlon=sqlite3_column_double(sql.select_way_name_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_way_name_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_way_name_search, 1),
+ -1);
+ rows++;
+}
+
+g_printf("Found: %d items\n", rows);
+
+sqlite3_reset(sql.select_way_name_search);
+sqlite3_clear_bindings(sql.select_way_name_search);
+
+return TRUE;
+}