]> err.no Git - mapper/commitdiff
Way search and display works.
authorKaj-Michael Lang <milang@angel.tal.org>
Sun, 22 Jul 2007 23:57:49 +0000 (02:57 +0300)
committerKaj-Michael Lang <milang@angel.tal.org>
Sun, 22 Jul 2007 23:57:49 +0000 (02:57 +0300)
src/latlon.c
src/map.c
src/osm-db.c
src/osm-db.h
src/osm.c
src/osm.h

index ea4b2191f2d42eeeb398cf671086e2270a7272e2..01f46d40b7fc8e5e947da6ae8198a389b7250bc4 100644 (file)
@@ -29,11 +29,18 @@ lon2mp_int(gdouble lon)
 return lrint(lon/180*LATLON_MAX);
 }
 
+gint
+calculate_idistance(gint lat1, gint lon1, gint lat2, gint lon2)
+{
+return lrint(sqrt((double)((lat1-lat2)*(lat1-lat2)+(lon1-lon2)*(lon1-lon2))));
+}
+
 /**
  * Calculate the distance between two lat/lon pairs.  The distance is returned
  * in kilometer.
  */
-gfloat calculate_distance(gfloat lat1, gfloat lon1, gfloat lat2, gfloat lon2)
+gfloat
+calculate_distance(gfloat lat1, gfloat lon1, gfloat lat2, gfloat lon2)
 {
 gdouble dlat, dlon, slat, slon, a;
 
index b75d1bfebec0811920d17dd2ba585e35f99ffc5b..5fa88205800714b4914f79efea1b4d0b21259f96 100644 (file)
--- a/src/map.c
+++ b/src/map.c
@@ -1356,17 +1356,17 @@ static void map_draw_track(gint x, gint y)
 }
 
 void
-map_set_place_information(osm_place *s, osm_place *mp, osm_place *sp, PoiInfo *p)
+map_set_place_information(osm_way *s, osm_place *mp, osm_place *sp, PoiInfo *p)
 {
 gchar buffer[256];
 
 snprintf(buffer, sizeof(buffer), "On %s%s%s%s%s%s%s", 
-       s->name ? s->name : "Unknown street",
+       s ? s->name ? s->name : "unknown" : "?",
        (p && p->label) ? " near " : "",
        (p && p->label) ? p->label : "",
        sp->name ? " in " : "",
        sp->name ? sp->name : "",
-       mp->name ? " in City " : "",
+       mp->name ? " in " : "",
        mp->name ? mp->name : "");
 gtk_label_set_label(GTK_LABEL(_info_banner), buffer);
 }
@@ -1377,7 +1377,7 @@ static void map_print_int_latlon(gint x, gint y)
 gint ux, uy;
 gint ilat, ilon;
 gdouble lat,lon;
-osm_place street;
+osm_way *street;
 osm_place mplace;
 osm_place splace;
 PoiInfo *p;
@@ -1389,23 +1389,21 @@ unit2latlon(ux, uy, lat, lon);
 ilat=lat2mp_int(lat);
 ilon=lon2mp_int(lon);
 
-street.name=NULL;
-street.isin=0;
 mplace.name=NULL;
 splace.name=NULL;
 
 g_printf("IntPos: %d , %d\n", ilat, ilon);
 
-#if 0
-osm_find_nearest_way(ilat, ilon, &street);
-#endif
+street=osm_find_nearest_way(ilat, ilon);
+if (street)
+       g_printf("WAY: %d %s %s\n", street->id, street->name, street->ref);
 
 p=poi_find_nearest(lat, lon);
 
 if (osm_find_nearest_place(NODE_PLACE_SUBURB, ilat, ilon, &splace)==TRUE)
        g_printf("Near suburb: %s (%d)\n", splace.name, splace.isin);
 
-if (splace.isin!=0 && street.isin==0) {
+if (splace.isin!=0) {
        if (osm_place_get(splace.isin, ilat, ilon, &mplace)==FALSE) {
                if (osm_find_nearest_place(NODE_PLACE_CITY, ilat, ilon, &mplace)==TRUE)
                        g_printf("Near city: %s\n", mplace.name);
@@ -1416,8 +1414,8 @@ if (splace.isin!=0 && street.isin==0) {
        } else {
                g_printf("In %s\n", mplace.name);
        }
-} else if (street.isin!=0) {
-       if (osm_place_get(street.isin, ilat, ilon, &mplace)==FALSE) {
+} else if (street && street->isin!=0) {
+       if (osm_place_get(street->isin, ilat, ilon, &mplace)==FALSE) {
 
        } else {
                g_printf("In %s\n", mplace.name);
@@ -1432,7 +1430,7 @@ if (splace.isin!=0 && street.isin==0) {
 
 }
 
-map_set_place_information(&street, &mplace, &splace, p);
+map_set_place_information(street, &mplace, &splace, p);
 }
 
 gboolean map_cb_scroll_event(GtkWidget * widget, GdkEventScroll * event)
index b41062329466ac6eb14118b3d5655e5a4e2bb57b..c7656eedec4348066a995e1a471f466af041e6aa 100644 (file)
@@ -24,6 +24,8 @@ struct sql_select_stmt {
 };
 static struct sql_select_stmt sql;
 
+gboolean osm_way_get_nodes(osm_way *w);
+
 gboolean
 osm_db_prepare(sqlite3 *db)
 {
@@ -47,16 +49,16 @@ if (sqlite3_prepare_v2(db, "select name,(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LO
                    -1, &sql.select_place, NULL)!=SQLITE_OK)
        return FALSE;
 
-return TRUE;
 /* Ways */
 /* Select neareset ways inside lat,lon+-range */
-if (sqlite3_prepare_v2(db, "select wid from way,way_seg,nodes,"
-                                       "(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist"
+if (sqlite3_prepare_v2(db, "select wid,type,nodes,flags,"
+                                       "(($LAT-lat)*($LAT-lat))+(($LON-lon)*($LON-lon)) as dist, num"
+                                       " from way,way_seg,nodes"
                                        " where wid=wsid and way_seg.node=nodes.nid "
-                                       " and nodes.lat between $LAT-$RANGE and $LAT+$RANGE "
-                                       " and nodes.lon between $LON-$RANGE and $LON+$RANGE "
+                                       " and lat between $LAT-$RANGE and $LAT+$RANGE "
+                                       " and lon between $LON-$RANGE and $LON+$RANGE "
                                        " order by dist",
-                   -1, &sql.select_way_name, NULL)!=SQLITE_OK)
+                   -1, &sql.select_way, NULL)!=SQLITE_OK)
        return FALSE;
 
 /* Select way nodes */
@@ -94,7 +96,7 @@ sqlite3_reset(sql.select_place);
 if (SQLITE_OK != sqlite3_bind_int(sql.select_place, 1, lat) ||
     SQLITE_OK != sqlite3_bind_int(sql.select_place, 2, lon) ||
     SQLITE_OK != sqlite3_bind_int(sql.select_place, 3, id)) {
-       g_printerr("Failed to bind values\n");
+       g_printerr("Failed to bind values for place\n");
        return FALSE;
 }
 
@@ -104,8 +106,8 @@ if (SQLITE_ROW == sqlite3_step(sql.select_place)) {
 
        place=sqlite3_column_text(sql.select_place, 0);
        n->name=g_strdup(place);
-       n->dist=sqlite3_column_int(sql.select_place, 1);
-       n->dist=sqrt(n->dist);
+       dist=sqlite3_column_int(sql.select_place, 1);
+       n->dist=sqrt((double)dist);
        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);
@@ -147,7 +149,7 @@ 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)) {
-       g_printerr("Failed to bind values\n");
+       g_printerr("Failed to bind values for near place\n");
        return FALSE;
 }
 
@@ -162,8 +164,8 @@ if (SQLITE_ROW == sqlite3_step(sql.select_near_place)) {
 
        place=sqlite3_column_text(sql.select_near_place, 0);
        n->name=g_strdup(place);
-       n->dist=sqlite3_column_int(sql.select_near_place, 1);
-       n->dist=sqrt((double)n->dist);
+       dist=sqlite3_column_int(sql.select_near_place, 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);
@@ -176,6 +178,89 @@ if (SQLITE_ROW == sqlite3_step(sql.select_near_place)) {
 return FALSE;
 }
 
+/* Way helper */
+static GList *
+osm_find_nearest_way_nodes(gint lat, gint lon, guint range)
+{
+GList *ways=NULL;
+osm_way *w;
+
+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)) {
+       g_printerr("Failed to bind values for way\n");
+       return NULL;
+}
+
+while (SQLITE_ROW == sqlite3_step(sql.select_way)) {
+       guint32 dist;
+
+       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);
+}
+
+return ways;
+}
+
+static gdouble magnitude(gdouble x1, gdouble y1, gdouble x2, gdouble y2)
+{
+gdouble x,y;
+x=x2-x1;
+y=y2-y1;
+
+return sqrt((x*x)+(y*y));
+}
+
+gboolean distance_point_to_line(gint x, gint y, gint x1, gint y1, gint x2, gint y2, gdouble *d)
+{
+gdouble lm,u;
+gdouble ix,iy;
+gdouble tmp,tx1,tx2,ty1,ty2;
+
+#if 0
+if (x1>x2) {
+       tx1=x2;
+       ty1=y2;
+       x2=x1;
+       y2=y1;
+       x1=tx1;
+       y1=ty1;
+}
+#endif
+
+lm=magnitude((gdouble)x1,(gdouble)y1,(gdouble)x2,(gdouble)y2);
+tmp=(gdouble)((x-x1)*(x2-x1))+((y-y1)*(y2-y1));
+u=tmp/(lm*lm);
+
+g_printf("DPL: tmp %f u %f lm %f\n", tmp, u, lm);
+
+g_printf("DPLX: (%d/%d) (%d %d)-(%d %d)\n",
+       x,y,
+       x1,y1,
+       x2,y2);
+
+if (u<0.0f || u>1.0f)
+       return FALSE;
+ix=(gdouble)x1+u*(gdouble)(x2-x1);
+iy=(gdouble)y1+u*(gdouble)(y2-y1);
+*d=magnitude((gdouble)x,(gdouble)y, ix, iy);
+return TRUE;
+}
+
 /**
  * Search for the nearest way (road)
  * - First search for ways with nearest node
@@ -188,7 +273,108 @@ return FALSE;
 osm_way *
 osm_find_nearest_way(gint lat, gint lon)
 {
+GList *iter;
+GList *w=NULL;
+guint range=8192;
+osm_way *cw=NULL;
 
+while ((w=osm_find_nearest_way_nodes(lat, lon, range))==NULL && range<=65536) {
+       range=range<<1;
+       g_printf("Trying with range: %d\n", range);
+}
+
+g_printf("Found ways: %d\n", g_list_length(w));
+
+switch (g_list_length(w)) {
+       case 0:
+               return NULL;
+       break;
+       case 1:
+               cw=w->data;
+       break;
+       default:
+       {
+               gint dist=900000, ndist;
+               gdouble pdist=900000.0, pndist=9000000.0;
+
+               for (iter=w; iter!=NULL; iter=iter->next) {
+                       osm_way_node *wnf;
+                       osm_way_node *wnt;
+
+                       osm_way *way=(osm_way*)iter->data;
+
+                       g_printf("C*** WAY %d (%d) HAS %d NODES, nearest is %d\n", 
+                               way->id, way->type, way->nodecnt, way->node_num);
+
+                       if (osm_way_get_nodes(way)==FALSE)
+                               continue;
+
+                       if (way->nodes==0) {
+                               g_printerr("Way with 0 nodes ? Skipping\n");
+                               continue;
+                       }
+
+                       wnf=g_list_nth_data(way->nodes, way->node_num);
+                       if (!wnf)
+                               continue;
+
+                       g_printf("----EVAL-START:\n");
+                       if (way->node_num==way->nodecnt) {
+                               g_print("  <- Last\n");
+                               wnt=g_list_nth_data(way->nodes, way->nodecnt-1);
+                               if (!wnt)
+                                       continue;
+                               if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE)
+                                       continue;
+                       } else if (way->node_num==0) {
+                               g_print("  First %d ->\n", wnf->num);
+                               wnt=g_list_nth_data(way->nodes, 1);
+                               if (!wnt)
+                                       continue;
+                               if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE)
+                                       continue;
+                       } else {
+                               g_print("  <->\n");
+                               wnt=g_list_nth_data(way->nodes, way->node_num-1);
+                               if (!wnt)
+                                       continue;
+                               if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE) {
+                                       wnt=g_list_nth_data(way->nodes, way->node_num+1);
+                                       if (!wnt)
+                                               continue;
+                                       if (distance_point_to_line(lon, lat, wnf->lon, wnf->lat, wnt->lon, wnt->lat, &pndist)==FALSE)
+                                               continue;
+                               }
+                       }
+                       g_printf("----EVAL-DONE: %d <-> %d\n", wnf->num, wnt->num);
+
+                       g_printf("WD: New: %f Prev:%f\n", pndist, pdist);
+                       if (pndist<pdist) {
+                               pdist=pndist;
+                               cw=way;
+                       }
+               }
+       }
+       break;
+}
+
+g_list_free(w);
+if (cw==NULL)
+       return NULL;
+
+osm_way_get_name(cw);
+if (cw->type==WAY_MOTORWAY || cw->type==WAY_TRUNK || 
+       cw->type==WAY_PRIMARY || cw->type==WAY_SECONDARY ||
+       cw->type==WAY_TERTIARY) {
+               osm_way_get_ref(cw);
+}
+
+g_printf("Way: %d %d %d %d: %s %s %s\n", 
+       cw->id, cw->type, cw->flags,
+       cw->nodes, cw->dist, cw->name, 
+       cw->ref, cw->int_ref);
+
+return cw;
 }
 
 /**
@@ -199,9 +385,78 @@ osm_way_get_nodes(osm_way *w)
 {
 if (w->nodes!=NULL)
        return TRUE;
+
+sqlite3_reset(sql.select_way_nodes);
+sqlite3_clear_bindings(sql.select_way_nodes);
+
+if (SQLITE_OK != sqlite3_bind_int(sql.select_way_nodes, 1, w->id)) {
+       g_printerr("Failed to bind values way nodes\n");
+       return FALSE;
+}
+
+while (SQLITE_ROW == sqlite3_step(sql.select_way_nodes)) {
+       osm_way_node *n;
+
+       n=g_slice_new(osm_way_node);
+       n->num=sqlite3_column_int(sql.select_way_nodes, 0);
+       n->lat=sqlite3_column_int(sql.select_way_nodes, 1);
+       n->lon=sqlite3_column_int(sql.select_way_nodes, 2);
+       w->nodes=g_list_append(w->nodes, n);
+}
+
+return (w->nodes==NULL) ? FALSE : TRUE;
+}
+
+gboolean
+osm_way_get_name(osm_way *w)
+{
+sqlite3_reset(sql.select_way_name);
+sqlite3_clear_bindings(sql.select_way_name);
+
+if (SQLITE_OK != sqlite3_bind_int(sql.select_way_name, 1, w->id)) {
+       g_printerr("Failed to bind values for way name\n");
+       return FALSE;
+}
+
+if (SQLITE_ROW == sqlite3_step(sql.select_way_name)) {
+       const gchar *place;
+       place=sqlite3_column_text(sql.select_way_name, 0);
+       w->name=g_strdup(place);
+}
+return FALSE;
+}
+
+gboolean
+osm_way_get_ref(osm_way *w)
+{
+sqlite3_reset(sql.select_way_ref);
+sqlite3_clear_bindings(sql.select_way_ref);
+
+if (SQLITE_OK != sqlite3_bind_int(sql.select_way_ref, 1, w->id)) {
+       g_printerr("Failed to bind values for way ref\n");
+       return FALSE;
+}
+
+if (SQLITE_ROW == sqlite3_step(sql.select_way_ref)) {
+       const gchar *ref, *int_ref;
+       ref=sqlite3_column_text(sql.select_way_ref, 0);
+       int_ref=sqlite3_column_text(sql.select_way_ref, 1);
+       w->ref=g_strdup(ref);
+       w->int_ref=g_strdup(int_ref);
+}
+return FALSE;
 }
 
 void
 osm_way_free(osm_way *w)
 {
+if (w->nodes)
+       g_list_free(w->nodes);
+if (w->name)
+       g_free(w->name);
+if (w->ref)
+       g_free(w->ref);
+if (w->int_ref)
+       g_free(w->int_ref);
+g_slice_free(osm_way, w);
 }
index fe43e4529657f7c26b40f18d7e80c53f224d280b..ef63d549c7282ba4b5cd6d4e946deaee3611dd03 100644 (file)
@@ -2,4 +2,4 @@
 #include "osm.h"
 
 gboolean osm_find_nearest_place(node_type_t type, gint lat, gint lon, osm_place *n);
-
+osm_way *osm_find_nearest_way(gint lat, gint lon);
index 6e5f268b58d4f3fe0239b5861377afd2a934b59c..331c20c4d47bfc5f994ae8d422149adfe6b61123 100644 (file)
--- a/src/osm.c
+++ b/src/osm.c
@@ -39,8 +39,8 @@ struct _node_data {
 typedef struct _node node;
 struct _node {
        guint32 id;
-       gfloat lat;
-       gfloat lon;
+       gdouble lat;
+       gdouble lon;
        node_data *data;
 };
 
@@ -697,7 +697,7 @@ node *t;
 node *r;
 gchar **isin;
 gchar **place;
-gfloat dist;
+gdouble dist;
 
 if (!n->data)
        return 0;
index a1cff5c198b4880ae7e9e0ccd62dd80909e2ecd8..a3dc6bc6732d99d2d8049d9e3dc670cd229923a5 100644 (file)
--- a/src/osm.h
+++ b/src/osm.h
@@ -119,9 +119,23 @@ struct _osm_place {
 typedef struct _osm_way osm_way;
 struct _osm_way {
        guint32 id;
-       gshort type;
+       guint type;
        guint flags;
+       guint nodecnt;
+       guint32 isin;
+       guint node_num;
+       gdouble dist;
+       gchar *name;
+       gchar *ref;
+       gchar *int_ref;
        GList *nodes;
 };
 
+typedef struct _osm_way_node osm_way_node;
+struct _osm_way_node {
+       guint num;
+       gint lat;
+       gint lon;
+};
+
 #endif