Add:maptool:Experimental support for boundary relations
authormartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Sun, 10 Jul 2011 19:29:52 +0000 (19:29 +0000)
committermartin-s <martin-s@ffa7fe5e-494d-0410-b361-a75ebd5db220>
Sun, 10 Jul 2011 19:29:52 +0000 (19:29 +0000)
git-svn-id: https://navit.svn.sourceforge.net/svnroot/navit/trunk@4618 ffa7fe5e-494d-0410-b361-a75ebd5db220

navit/navit/maptool/boundaries.c
navit/navit/maptool/maptool.c
navit/navit/maptool/maptool.h
navit/navit/maptool/osm.c

index e83fb4e..54f1b0e 100644 (file)
 #include <string.h>
 #include "maptool.h"
 
-struct boundary {
-       struct item_bin *ib;
-       GList *segments,*sorted_segments;
-       GList *children;
-       struct rect r;
-};
-
 struct boundary_member {
        long long wayid;
        enum geom_poly_segment_type role;
@@ -51,16 +44,23 @@ boundary_member_equal(gconstpointer a, gconstpointer b)
 GHashTable *member_hash;
 
 static char *
-osm_tag_name(struct item_bin *ib)
+osm_tag_value(struct item_bin *ib, char *key)
 {
        char *tag=NULL;
+       int len=strlen(key);
        while ((tag=item_bin_get_attr(ib, attr_osm_tag, tag))) {
-               if (!strncmp(tag,"name=",5))
-                       return tag+5;
+               if (!strncmp(tag,key,len) && tag[len] == '=')
+                       return tag+len+1;
        }
        return NULL;
 }
 
+static char *
+osm_tag_name(struct item_bin *ib)
+{
+       return osm_tag_value(ib, "name");
+}
+
 static GList *
 build_boundaries(FILE *boundaries)
 {
@@ -70,6 +70,17 @@ build_boundaries(FILE *boundaries)
        while ((ib=read_item(boundaries))) {
                char *member=NULL;
                struct boundary *boundary=g_new0(struct boundary, 1);
+               char *admin_level=osm_tag_value(ib, "admin_level");
+               char *iso=osm_tag_value(ib, "ISO3166-1");
+               if (admin_level && !strcmp(admin_level, "2")) {
+                       if (iso) {
+                               struct country_table *country=country_from_iso2(iso);   
+                               if (!country) 
+                                       osm_warning("relation",item_bin_get_relationid(ib),0,"Country Boundary contains unknown ISO3166-1 value '%s'\n",iso);
+                               boundary->country=country;
+                       } else 
+                               osm_warning("relation",item_bin_get_relationid(ib),0,"Country Boundary doesn't contain an ISO3166-1 tag\n");
+               }
                while ((member=item_bin_get_attr(ib, attr_osm_member, member))) {
                        long long wayid;
                        int read=0;
@@ -98,19 +109,20 @@ build_boundaries(FILE *boundaries)
        return boundaries_list;
 }
 
-static void
-find_matches(GList *l, struct coord *c)
+GList *
+boundary_find_matches(GList *l, struct coord *c)
 {
+       GList *ret=NULL;
        while (l) {
                struct boundary *boundary=l->data;
                if (bbox_contains_coord(&boundary->r, c)) {
-                       struct item_bin *ib=boundary->ib;
                        if (geom_poly_segments_point_inside(boundary->sorted_segments,c)) 
-                               printf("%s,",osm_tag_name(ib));
-                       find_matches(boundary->children, c);
+                               ret=g_list_prepend(ret, boundary);
+                       ret=g_list_concat(ret,boundary_find_matches(boundary->children, c));
                }
                l=g_list_next(l);
        }
+       return ret;
 }
 
 static void
@@ -123,7 +135,7 @@ test(GList *boundaries_list)
                struct coord *c=(struct coord *)(ib+1);
                char *name=item_bin_get_attr(ib, attr_town_name, NULL);
                printf("%s:",name);
-               find_matches(boundaries_list, c);
+               boundary_find_matches(boundaries_list, c);
                printf("\n");
        }
        fclose(f);
@@ -158,7 +170,7 @@ boundary_bbox_compare(gconstpointer a, gconstpointer b)
        return 0;
 }
 
-int
+GList *
 process_boundaries(FILE *boundaries, FILE *ways)
 {
        struct item_bin *ib;
@@ -201,7 +213,9 @@ process_boundaries(FILE *boundaries, FILE *ways)
                l=g_list_next(l);
                
        }
+#if 0
        printf("hierarchy\n");
+#endif
        boundaries_list=g_list_sort(boundaries_list, boundary_bbox_compare);
        l=boundaries_list;
        while (l) {
@@ -212,16 +226,20 @@ process_boundaries(FILE *boundaries, FILE *ways)
                        if (bbox_contains_bbox(&boundary2->r, &boundary->r)) {
                                boundaries_list=g_list_remove(boundaries_list, boundary);
                                boundary2->children=g_list_append(boundary2->children, boundary);
+#if 0
                                printf("found\n");
+#endif
                                break;
                        }
                        l2=g_list_next(l2);
                }
                l=ln;
        }
+#if 0
        printf("hierarchy done\n");
        dump_hierarchy(boundaries_list,"");
        printf("test\n");
        test(boundaries_list);
-       return 1;
+#endif
+       return boundaries_list;
 }
index 859334b..622d78c 100644 (file)
@@ -53,6 +53,7 @@ int slices;
 int unknown_country;
 int doway2poi=1;
 char ch_suffix[] ="r"; /* Used to make compiler happy due to Bug 35903 in gcc */
+int experimental;
 
 struct buffer node_buffer = {
        64*1024*1024,
@@ -124,6 +125,7 @@ usage(FILE *f)
        fprintf(f,"-d (--db) <conn. string>          : get osm data out of a postgresql database with osm simple scheme and given connect string\n");
 #endif
        fprintf(f,"-e (--end) <phase>                : end at specified phase\n");
+       fprintf(f,"-E (--experimental)               : Enable experimental features\n");
        fprintf(f,"-i (--input-file) <file>          : specify the input file name (OSM), overrules default stdin\n");
        fprintf(f,"-k (--keep-tmpfiles)              : do not delete tmp files after processing. useful to reuse them\n\n");
        fprintf(f,"-M (--o5m)                        : input file os o5m\n");
@@ -200,6 +202,7 @@ parse_option(struct maptool_params *p, char **argv, int argc, int *option_index)
                {"dump", 0, 0, 'D'},
                {"dump-coordinates", 0, 0, 'c'},
                {"end", 1, 0, 'e'},
+               {"experimental", 0, 0, 'E'},
                {"help", 0, 0, 'h'},
                {"keep-tmpfiles", 0, 0, 'k'},
                {"nodes-only", 0, 0, 'N'},
@@ -218,7 +221,7 @@ parse_option(struct maptool_params *p, char **argv, int argc, int *option_index)
                {"unknown-country", 0, 0, 'U'},
                {0, 0, 0, 0}
        };
-       c = getopt_long (argc, argv, "5:6B:DMNO:PS:Wa:bc"
+       c = getopt_long (argc, argv, "5:6B:DEMNO:PS:Wa:bc"
 #ifdef HAVE_POSTGRESQL
                                      "d:"
 #endif
@@ -238,6 +241,9 @@ parse_option(struct maptool_params *p, char **argv, int argc, int *option_index)
        case 'D':
                p->output=1;
                break;
+       case 'E':
+               experimental=1;
+               break;
        case 'M':
                p->o5m=1;
                break;  
@@ -810,9 +816,17 @@ int main(int argc, char **argv)
        }
        phase++;
        if (p.start <= phase && p.end >= phase) {
-               FILE *towns=tempfile(suffix,"towns",0);
+               FILE *towns=tempfile(suffix,"towns",0),*boundaries=NULL,*ways=NULL;
+               if (experimental) {
+                       boundaries=tempfile(suffix,"boundaries",0);
+                       ways=tempfile(suffix,"ways_split",0);
+               }
                fprintf(stderr,"PROGRESS: Phase %d: assinging towns to countries\n",phase);
-               osm_process_towns(towns);
+               osm_process_towns(towns,boundaries,ways);
+               if (experimental) {
+                       fclose(ways);
+                       fclose(boundaries);
+               }
                fclose(towns);
                if(!p.keep_tmpfiles)
                        tempfile_unlink(suffix,"towns");
index 0886dde..a487b43 100644 (file)
@@ -102,9 +102,21 @@ struct item_bin_sink {
 
 struct zip_info;
 
+struct country_table;
+
 /* boundaries.c */
 
-int process_boundaries(FILE *boundaries, FILE *ways);
+struct boundary {
+       struct item_bin *ib;
+       struct country_table *country;
+       GList *segments,*sorted_segments;
+       GList *children;
+       struct rect r;
+};
+
+GList *process_boundaries(FILE *boundaries, FILE *ways);
+
+GList *boundary_find_matches(GList *bl, struct coord *c);
 
 /* buffer.c */
 struct buffer {
@@ -211,6 +223,7 @@ extern struct item_bin *item_bin;
 extern int bytes_read;
 extern int overlap;
 extern int unknown_country;
+extern int experimental;
 void sig_alrm(int sig);
 void sig_alrm_end(void);
 
@@ -245,6 +258,7 @@ struct maptool_osm {
        FILE *towns;
 };
 
+void osm_warning(char *type, long long id, int cont, char *fmt, ...);
 void osm_add_tag(char *k, char *v);
 void osm_add_node(osmid id, double lat, double lon);
 void osm_add_way(osmid id);
@@ -261,13 +275,17 @@ void process_turn_restrictions(FILE *in, FILE *coords, FILE *ways, FILE *ways_in
 void clear_node_item_buffer(void);
 void ref_ways(FILE *in);
 void resolve_ways(FILE *in, FILE *out);
+long long item_bin_get_nodeid(struct item_bin *ib);
+long long item_bin_get_wayid(struct item_bin *ib);
+long long item_bin_get_relationid(struct item_bin *ib);
 FILE *resolve_ways_file(FILE *in, char *suffix, char *filename);
 void process_way2poi(FILE *in, FILE *out, int type);
 int map_find_intersections(FILE *in, FILE *out, FILE *out_index, FILE *out_graph, FILE *out_coastline, int final);
 void write_countrydir(struct zip_info *zip_info);
-void osm_process_towns(FILE *in);
+void osm_process_towns(FILE *in, FILE *boundaries, FILE *ways);
 void load_countries(void);
 void remove_countryfiles(void);
+struct country_table * country_from_iso2(char *iso);
 void osm_init(FILE*);
 
 /* osm_o5m.c */
index 7d11df0..045342e 100644 (file)
@@ -23,6 +23,7 @@
 #include "maptool.h"
 #include "debug.h"
 #include "linguistics.h"
+#include "country.h"
 #include "file.h"
 
 extern int doway2poi;
@@ -822,7 +823,8 @@ build_countrytable(void)
                }
        }
 }
-static void
+
+void
 osm_warning(char *type, long long id, int cont, char *fmt, ...)
 {
        char str[4096];
@@ -848,7 +850,7 @@ attr_strings_save(enum attr_strings id, char *str)
        attr_strings_buffer_len+=strlen(str)+1;
 }
 
-static long long
+long long
 item_bin_get_nodeid(struct item_bin *ib)
 {
        long long *ret=item_bin_get_attr(ib, attr_osm_nodeid, NULL);
@@ -857,7 +859,7 @@ item_bin_get_nodeid(struct item_bin *ib)
        return 0;
 }
 
-static long long
+long long
 item_bin_get_wayid(struct item_bin *ib)
 {
        long long *ret=item_bin_get_attr(ib, attr_osm_wayid, NULL);
@@ -866,7 +868,7 @@ item_bin_get_wayid(struct item_bin *ib)
        return 0;
 }
 
-static long long
+long long
 item_bin_get_relationid(struct item_bin *ib)
 {
        long long *ret=item_bin_get_attr(ib, attr_osm_relationid, NULL);
@@ -1436,6 +1438,43 @@ osm_add_relation(osmid id)
        item_bin_add_attr_longlong(item_bin, attr_osm_relationid, current_id);
 }
 
+static int
+country_id_from_iso2(char *iso)
+{
+       int ret=0;
+       if (iso) {
+               struct country_search *search;
+               struct attr country_iso2,country_id;
+               struct item *item;
+               country_iso2.type=attr_country_iso2;
+               country_iso2.u.str=iso;
+               search=country_search_new(&country_iso2,0);
+               if ((item=country_search_get_item(search)) && item_attr_get(item, attr_country_id, &country_id))
+                       ret=country_id.u.num;
+                       
+               country_search_destroy(search);
+       }
+       return ret;
+}
+
+static struct country_table *
+country_from_countryid(int id)
+{
+       int i;
+       for (i = 0 ; i < sizeof(country_table)/sizeof(struct country_table) ; i++) {
+               if (country_table[i].countryid == id)
+                       return &country_table[i];
+       }
+       return NULL;
+}
+
+struct country_table *
+country_from_iso2(char *iso)
+{
+       return country_from_countryid(country_id_from_iso2(iso));
+}
+
+
 void
 osm_end_relation(struct maptool_osm *osm)
 {
@@ -1500,13 +1539,13 @@ relation_add_tag(char *k, char *v)
        } else if (!strcmp(k,"ISO3166-1")) {
                strcpy(iso_code, v);
        }
-#if 0
-       if (add_tag) {
-               char tag[strlen(k)+strlen(v)+2];
-               sprintf(tag,"%s=%s",k,v);
-               item_bin_add_attr_string(item_bin, attr_osm_tag, tag);
+       if (experimental) {
+               if (add_tag) {
+                       char tag[strlen(k)+strlen(v)+2];
+                       sprintf(tag,"%s=%s",k,v);
+                       item_bin_add_attr_string(item_bin, attr_osm_tag, tag);
+               }
        }
-#endif
 }
 
 
@@ -1685,30 +1724,77 @@ osm_end_node(struct maptool_osm *osm)
        attr_longest_match_clear();
 }
 
+static struct country_table *
+osm_process_town_unknown_country(void)
+{
+       static struct country_table *unknown;
+       if (!unknown)
+               unknown=country_from_countryid(999);
+
+       return unknown;
+}
+
+static struct country_table *
+osm_process_town_by_is_in(char *is_in)
+{
+       struct country_table *result=NULL, *lookup;
+       char *tok,*dup=g_strdup(is_in),*buf=dup;
+       int conflict;
+
+       while ((tok=strtok(buf, ",;"))) {
+               while (*tok==' ')
+                       tok++;
+               lookup=g_hash_table_lookup(country_table_hash,tok);
+               if (lookup) {
+                       if (result && result->countryid != lookup->countryid) {
+                               osm_warning("node",nodeid,0,"conflict for %s %s country %d vs %d\n", attr_strings[attr_string_label], debug_attr_buffer, lookup->countryid, result->countryid);
+                               conflict=1;
+                       }
+                       result=lookup;
+               }
+               buf=NULL;
+       }
+       g_free(dup);
+       return result;
+}
+
+static struct country_table *
+osm_process_town_by_boundary(GList *bl, struct coord *c)
+{
+       GList *l,*matches=boundary_find_matches(bl, c);
+       struct country_table *match=NULL;
+
+       l=matches;
+       while (l) {
+               struct boundary *b=l->data;
+               if (b->country) {
+                       if (match)
+                               printf("conflict %d vs %d\n",b->country->countryid,match->countryid);
+                       match=b->country;
+               }
+               l=g_list_next(l);
+       }
+       return match; 
+}
+
 void
-osm_process_towns(FILE *in)
+osm_process_towns(FILE *in, FILE *boundaries, FILE *ways)
 {
        struct item_bin *ib;
+       GList *bl=NULL;
 
+       if (experimental) 
+               bl=process_boundaries(boundaries, ways);
        while ((ib=read_item(in)))  {
-               struct country_table *result=NULL, *lookup;
-               char *tok,*is_in=item_bin_get_attr(ib, attr_osm_is_in, NULL), *buf=g_strdup(is_in);
-               int conflict;
-               if (!buf && unknown_country)
-                       buf=g_strdup("Unknown");
-               while ((tok=strtok(buf, ",;"))) {
-                       while (*tok==' ')
-                               tok++;
-                       lookup=g_hash_table_lookup(country_table_hash,tok);
-                       if (lookup) {
-                               if (result && result->countryid != lookup->countryid) {
-                                       osm_warning("node",nodeid,0,"conflict for %s %s country %d vs %d\n", attr_strings[attr_string_label], debug_attr_buffer, lookup->countryid, result->countryid);
-                                       conflict=1;
-                               }
-                               result=lookup;
-                       }
-                       buf=NULL;
-               }
+               struct coord *c=(struct coord *)(ib+1);
+               struct country_table *result=NULL;
+               char *is_in=item_bin_get_attr(ib, attr_osm_is_in, NULL);
+               if (experimental)
+                       result=osm_process_town_by_boundary(bl, c);
+               if (!result)
+                       result=osm_process_town_by_is_in(is_in);
+               if (!result && unknown_country)
+                       result=osm_process_town_unknown_country();
                if (result) {
                        if (!result->file) {
                                char *name=g_strdup_printf("country_%d.unsorted.tmp", result->countryid);
@@ -1721,7 +1807,6 @@ osm_process_towns(FILE *in)
                                item_bin_write_match(ib, attr_town_name, attr_town_name_match, result->file);
                        }
                }
-               g_free(buf);
        }
 }
 
@@ -2006,6 +2091,7 @@ process_turn_restrictions(FILE *in, FILE *coords, FILE *ways, FILE *ways_index,
        }
 }
 
+#if 0
 static void
 process_countries(FILE *way, FILE *ways_index)
 {
@@ -2056,6 +2142,7 @@ process_countries(FILE *way, FILE *ways_index)
        fclose(tmp);
        fclose(in);
 }
+#endif
 
 static void
 node_ref_way(osmid node)