diff options
Diffstat (limited to 'navit/maptool/boundaries.c')
-rw-r--r-- | navit/maptool/boundaries.c | 604 |
1 files changed, 276 insertions, 328 deletions
diff --git a/navit/maptool/boundaries.c b/navit/maptool/boundaries.c index 605b6fb7b..2f64d092c 100644 --- a/navit/maptool/boundaries.c +++ b/navit/maptool/boundaries.c @@ -23,364 +23,312 @@ #define strcasecmp _stricmp #endif -char * -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,key,len) && tag[len] == '=') - return tag+len+1; - } - return NULL; +char *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,key,len) && tag[len] == '=') + return tag+len+1; + } + return NULL; } #if 0 -static char * -osm_tag_name(struct item_bin *ib) -{ - return osm_tag_value(ib, "name"); +static char *osm_tag_name(struct item_bin *ib) { + return osm_tag_value(ib, "name"); } #endif -osmid -boundary_relid(struct boundary *b) -{ - long long *id; - if (!b) - return 0; - if (!b->ib) - return 0; - id=item_bin_get_attr(b->ib, attr_osm_relationid, NULL); - if (id) - return *id; - return 0; +osmid boundary_relid(struct boundary *b) { + long long *id; + if (!b) + return 0; + if (!b->ib) + return 0; + id=item_bin_get_attr(b->ib, attr_osm_relationid, NULL); + if (id) + return *id; + return 0; } -static void -process_boundaries_member(void *func_priv, void *relation_priv, struct item_bin *member, void *member_priv) -{ - struct boundary *b=relation_priv; - enum geom_poly_segment_type role=(long)member_priv; - int *dup; - dup=item_bin_get_attr(member,attr_duplicate,NULL); - if(!dup || *dup==0) - b->segments=g_list_prepend(b->segments,item_bin_to_poly_segment(member, role)); +static void process_boundaries_member(void *func_priv, void *relation_priv, struct item_bin *member, + void *member_priv) { + struct boundary *b=relation_priv; + enum geom_poly_segment_type role=(long)member_priv; + int *dup; + dup=item_bin_get_attr(member,attr_duplicate,NULL); + if(!dup || *dup==0) + b->segments=g_list_prepend(b->segments,item_bin_to_poly_segment(member, role)); } -static GList * -process_boundaries_setup(FILE *boundaries, struct relations *relations) -{ - struct item_bin *ib; - GList *boundaries_list=NULL; - struct relations_func *relations_func; +static GList *process_boundaries_setup(FILE *boundaries, struct relations *relations) { + struct item_bin *ib; + GList *boundaries_list=NULL; + struct relations_func *relations_func; - relations_func=relations_func_new(process_boundaries_member, NULL); - 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"); - int has_subrelations=0; - int has_outer_ways=0; - - processed_relations++; - - if(!iso) - iso=osm_tag_value(ib, "iso3166-1:alpha2"); - - if (admin_level && !strcmp(admin_level, "2")) { - if(!iso) { - char *int_name=osm_tag_value(ib,"int_name"); - if(int_name && !strcmp(int_name,"France")) - iso="FR"; - } - 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); - else { - boundary->iso2=g_strdup(iso); - osm_info("relation",item_bin_get_relationid(ib),0,"Country Boundary for '%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 osm_id; - int read=0; - enum relation_member_type member_type; - int member_type_numeric; - char *rolestr; + relations_func=relations_func_new(process_boundaries_member, NULL); + 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"); + int has_subrelations=0; + int has_outer_ways=0; - if (sscanf(member,RELATION_MEMBER_PARSE_FORMAT,&member_type_numeric,&osm_id,&read) < 2) - continue; - - member_type=(enum relation_member_type)member_type_numeric; - rolestr=member+read; - - if(member_type==rel_member_node) { - if(!strcmp(rolestr,"admin_centre") || !strcmp(rolestr,"admin_center")) - boundary->admin_centre=osm_id; - } - if(member_type==rel_member_way) { - enum geom_poly_segment_type role; - if (!strcmp(rolestr,"outer") || !strcmp(rolestr,"exclave")) { - has_outer_ways=1; - role=geom_poly_segment_type_way_outer; - } - else if (!strcmp(rolestr,"inner") || !strcmp(rolestr,"enclave")) - role=geom_poly_segment_type_way_inner; - else if (!strcmp(rolestr,"")) - role=geom_poly_segment_type_way_unknown; - else { - osm_warning("relation",item_bin_get_relationid(ib),0,"Unknown role %s in member ",rolestr); - osm_warning("way",osm_id,1,"\n"); - role=geom_poly_segment_type_none; - } - relations_add_relation_member_entry(relations, relations_func, boundary, (gpointer)role, rel_member_way, osm_id); - } - if(member_type==rel_member_relation) { - if (!strcmp(rolestr,"outer") || !strcmp(rolestr,"exclave") || !strcmp(rolestr,"inner") || !strcmp(rolestr,"enclave")) - has_subrelations++; - } - } - if(boundary->iso2 && has_subrelations) - osm_warning("relation",item_bin_get_relationid(ib),0,"Country boundary '%s' has %d relations as boundary segments. These are not supported yet.\n", boundary->iso2, has_subrelations); - if(boundary->iso2 && !has_outer_ways) { - osm_warning("relation",item_bin_get_relationid(ib),0,"Skipping country boundary for '%s' because it has no outer ways.\n", boundary->iso2); - g_free(boundary->iso2); - boundary->iso2=NULL; - } + processed_relations++; - boundary->ib=item_bin_dup(ib); - boundaries_list=g_list_append(boundaries_list, boundary); - } - return boundaries_list; + if(!iso) + iso=osm_tag_value(ib, "iso3166-1:alpha2"); + + if (!g_strcmp0(admin_level, "2")) { + if(!iso) { + char *int_name=osm_tag_value(ib,"int_name"); + if(!g_strcmp0(int_name,"France")) + iso="FR"; + } + 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); + else { + boundary->iso2=g_strdup(iso); + osm_info("relation",item_bin_get_relationid(ib),0,"Country Boundary for '%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 osm_id; + int read=0; + enum relation_member_type member_type; + int member_type_numeric; + char *rolestr; + + if (sscanf(member,RELATION_MEMBER_PARSE_FORMAT,&member_type_numeric,&osm_id,&read) < 2) + continue; + + member_type=(enum relation_member_type)member_type_numeric; + rolestr=member+read; + + if(member_type==rel_member_node) { + if(!g_strcmp0(rolestr,"admin_centre") || !g_strcmp0(rolestr,"admin_center")) + boundary->admin_centre=osm_id; + } + if(member_type==rel_member_way) { + enum geom_poly_segment_type role; + if (!g_strcmp0(rolestr,"outer") || !g_strcmp0(rolestr,"exclave")) { + has_outer_ways=1; + role=geom_poly_segment_type_way_outer; + } else if (!g_strcmp0(rolestr,"inner") || !g_strcmp0(rolestr,"enclave")) + role=geom_poly_segment_type_way_inner; + else if (!g_strcmp0(rolestr,"")) + role=geom_poly_segment_type_way_unknown; + else { + osm_warning("relation",item_bin_get_relationid(ib),0,"Unknown role %s in member ",rolestr); + osm_warning("way",osm_id,1,"\n"); + role=geom_poly_segment_type_none; + } + relations_add_relation_member_entry(relations, relations_func, boundary, (gpointer)role, rel_member_way, osm_id); + } + if(member_type==rel_member_relation) { + if (!g_strcmp0(rolestr,"outer") || !g_strcmp0(rolestr,"exclave") || !g_strcmp0(rolestr,"inner") + || !g_strcmp0(rolestr,"enclave")) + has_subrelations++; + } + } + if(boundary->iso2 && has_subrelations) + osm_warning("relation",item_bin_get_relationid(ib),0, + "Country boundary '%s' has %d relations as boundary segments. These are not supported yet.\n", boundary->iso2, + has_subrelations); + if(boundary->iso2 && !has_outer_ways) { + osm_warning("relation",item_bin_get_relationid(ib),0, + "Skipping country boundary for '%s' because it has no outer ways.\n", boundary->iso2); + g_free(boundary->iso2); + boundary->iso2=NULL; + } + + boundary->ib=item_bin_dup(ib); + boundaries_list=g_list_append(boundaries_list, boundary); + } + return boundaries_list; } -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)) { - if (geom_poly_segments_point_inside(boundary->sorted_segments,c) > 0) - ret=g_list_prepend(ret, boundary); - ret=g_list_concat(ret,boundary_find_matches(boundary->children, c)); - } - l=g_list_next(l); - } - return ret; +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)) { + if (geom_poly_segments_point_inside(boundary->sorted_segments,c) > 0) + ret=g_list_prepend(ret, boundary); + ret=g_list_concat(ret,boundary_find_matches(boundary->children, c)); + } + l=g_list_next(l); + } + return ret; } #if 0 -static void -test(GList *boundaries_list) -{ - struct item_bin *ib; - FILE *f=fopen("country_276.bin.unsorted","r"); - printf("start\n"); - while ((ib=read_item(f))) { - struct coord *c=(struct coord *)(ib+1); - char *name=item_bin_get_attr(ib, attr_town_name, NULL); - printf("%s:",name); - boundary_find_matches(boundaries_list, c); - printf("\n"); - } - fclose(f); - printf("end\n"); +static void test(GList *boundaries_list) { + struct item_bin *ib; + FILE *f=fopen("country_276.bin.unsorted","r"); + printf("start\n"); + while ((ib=read_item(f))) { + struct coord *c=(struct coord *)(ib+1); + char *name=item_bin_get_attr(ib, attr_town_name, NULL); + printf("%s:",name); + boundary_find_matches(boundaries_list, c); + printf("\n"); + } + fclose(f); + printf("end\n"); } -static void -dump_hierarchy(GList *l, char *prefix) -{ - char *newprefix=g_alloca(sizeof(char)*(strlen(prefix)+2)); - strcpy(newprefix, prefix); - strcat(newprefix," "); - while (l) { - struct boundary *boundary=l->data; - fprintf(stderr,"%s:%s (0x%x,0x%x)-(0x%x,0x%x)\n",prefix,osm_tag_name(boundary->ib),boundary->r.l.x,boundary->r.l.y,boundary->r.h.x,boundary->r.h.y); - dump_hierarchy(boundary->children, newprefix); - l=g_list_next(l); - } +static void dump_hierarchy(GList *l, char *prefix) { + char *newprefix=g_alloca(sizeof(char)*(strlen(prefix)+2)); + strcpy(newprefix, prefix); + strcat(newprefix," "); + while (l) { + struct boundary *boundary=l->data; + fprintf(stderr,"%s:%s (0x%x,0x%x)-(0x%x,0x%x)\n",prefix,osm_tag_name(boundary->ib),boundary->r.l.x,boundary->r.l.y, + boundary->r.h.x,boundary->r.h.y); + dump_hierarchy(boundary->children, newprefix); + l=g_list_next(l); + } } -static gint -boundary_bbox_compare(gconstpointer a, gconstpointer b) -{ - const struct boundary *boundarya=a; - const struct boundary *boundaryb=b; - long long areaa=bbox_area(&boundarya->r); - long long areab=bbox_area(&boundaryb->r); - if (areaa > areab) - return 1; - if (areaa < areab) - return -1; - return 0; +static gint boundary_bbox_compare(gconstpointer a, gconstpointer b) { + const struct boundary *boundarya=a; + const struct boundary *boundaryb=b; + long long areaa=bbox_area(&boundarya->r); + long long areab=bbox_area(&boundaryb->r); + if (areaa > areab) + return 1; + if (areaa < areab) + return -1; + return 0; } #endif -static GList * -process_boundaries_insert(GList *list, struct boundary *boundary) -{ - GList *l=list; - while (l) { - struct boundary *b=l->data; - if (bbox_contains_bbox(&boundary->r, &b->r)) { - list=g_list_remove(list, b); - boundary->children=g_list_prepend(boundary->children, b); - l=list; - } else if (bbox_contains_bbox(&b->r, &boundary->r)) { - b->children=process_boundaries_insert(b->children, boundary); - return list; - } else - l=g_list_next(l); - } - return g_list_prepend(list, boundary); +static GList *process_boundaries_insert(GList *list, struct boundary *boundary) { + GList *l=list; + while (l) { + struct boundary *b=l->data; + if (bbox_contains_bbox(&boundary->r, &b->r)) { + list=g_list_remove(list, b); + boundary->children=g_list_prepend(boundary->children, b); + l=list; + } else if (bbox_contains_bbox(&b->r, &boundary->r)) { + b->children=process_boundaries_insert(b->children, boundary); + return list; + } else + l=g_list_next(l); + } + return g_list_prepend(list, boundary); } -static GList * -process_boundaries_finish(GList *boundaries_list) -{ - GList *l,*sl; - GList *ret=NULL; - l=boundaries_list; - while (l) { - struct boundary *boundary=l->data; - int first=1; - FILE *f=NULL,*fu=NULL; - if (boundary->country) { - char *name=g_strdup_printf("country_%s_poly",boundary->iso2); - f=tempfile("",name,1); - g_free(name); - } - boundary->sorted_segments=geom_poly_segments_sort(boundary->segments, geom_poly_segment_type_way_right_side); - sl=boundary->sorted_segments; - while (sl) { - struct geom_poly_segment *gs=sl->data; - struct coord *c=gs->first; - while (c <= gs->last) { - if (first) { - boundary->r.l=*c; - boundary->r.h=*c; - first=0; - } else - bbox_extend(c, &boundary->r); - c++; - } - if (f) { - struct item_bin *ib=tmp_item_bin; - item_bin_init(ib, type_selected_line); - /* FIXME check for overflow */ - item_bin_add_coord(ib, gs->first, gs->last-gs->first+1); - item_bin_write(ib, f); - } - if (boundary->country) { - if (!coord_is_equal(*gs->first,*gs->last)) { - struct item_bin *ib; - if (!fu) { - char *name=g_strdup_printf("country_%s_broken",boundary->iso2); - fu=tempfile("",name,1); - g_free(name); - } - ib=tmp_item_bin; - item_bin_init(ib, type_selected_point); - item_bin_add_coord(ib, gs->first, 1); - item_bin_write(ib, fu); - item_bin_init(ib, type_selected_point); - item_bin_add_coord(ib, gs->last, 1); - item_bin_write(ib, fu); - } - } - sl=g_list_next(sl); - } - ret=process_boundaries_insert(ret, boundary); - l=g_list_next(l); - if (f) - fclose(f); - if (fu) { - if (boundary->country) - osm_warning("relation",item_bin_get_relationid(boundary->ib),0,"Broken country polygon '%s'\n",boundary->iso2); - fclose(fu); - } - - } -#if 0 - printf("hierarchy\n"); -#endif -#if 0 - boundaries_list=g_list_sort(boundaries_list, boundary_bbox_compare); - l=boundaries_list; - while (l) { - struct boundary *boundary=l->data; - GList *l2,*ln; - ln=l2=g_list_next(l); - while (l2) { - struct boundary *boundary2=l2->data; - 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; - } - dump_hierarchy(boundaries_list,""); -#if 0 - printf("hierarchy done\n"); - printf("test\n"); - test(boundaries_list); -#endif -#endif - return ret; +static GList *process_boundaries_finish(GList *boundaries_list) { + GList *l,*sl; + GList *ret=NULL; + l=boundaries_list; + while (l) { + struct boundary *boundary=l->data; + int first=1; + FILE *f=NULL,*fu=NULL; + if (boundary->country) { + char *name=g_strdup_printf("country_%s_poly",boundary->iso2); + f=tempfile("",name,1); + g_free(name); + } + boundary->sorted_segments=geom_poly_segments_sort(boundary->segments, geom_poly_segment_type_way_right_side); + sl=boundary->sorted_segments; + while (sl) { + struct geom_poly_segment *gs=sl->data; + struct coord *c=gs->first; + while (c <= gs->last) { + if (first) { + boundary->r.l=*c; + boundary->r.h=*c; + first=0; + } else + bbox_extend(c, &boundary->r); + c++; + } + if (f) { + struct item_bin *ib=tmp_item_bin; + item_bin_init(ib, type_selected_line); + /* FIXME check for overflow */ + item_bin_add_coord(ib, gs->first, gs->last-gs->first+1); + item_bin_write(ib, f); + } + if (boundary->country) { + if (!coord_is_equal(*gs->first,*gs->last)) { + struct item_bin *ib; + if (!fu) { + char *name=g_strdup_printf("country_%s_broken",boundary->iso2); + fu=tempfile("",name,1); + g_free(name); + } + ib=tmp_item_bin; + item_bin_init(ib, type_selected_point); + item_bin_add_coord(ib, gs->first, 1); + item_bin_write(ib, fu); + item_bin_init(ib, type_selected_point); + item_bin_add_coord(ib, gs->last, 1); + item_bin_write(ib, fu); + } + } + sl=g_list_next(sl); + } + ret=process_boundaries_insert(ret, boundary); + l=g_list_next(l); + if (f) + fclose(f); + if (fu) { + if (boundary->country) + osm_warning("relation",item_bin_get_relationid(boundary->ib),0,"Broken country polygon '%s'\n",boundary->iso2); + fclose(fu); + } + + } + return ret; } -GList * -process_boundaries(FILE *boundaries, FILE *ways) -{ - GList *boundaries_list; - struct relations *relations=relations_new(); +GList *process_boundaries(FILE *boundaries, FILE *ways) { + GList *boundaries_list; + struct relations *relations=relations_new(); - boundaries_list=process_boundaries_setup(boundaries, relations); - relations_process(relations, NULL, ways); - relations_destroy(relations); - return process_boundaries_finish(boundaries_list); + boundaries_list=process_boundaries_setup(boundaries, relations); + relations_process(relations, NULL, ways); + relations_destroy(relations); + return process_boundaries_finish(boundaries_list); } -void -free_boundaries(GList *bl) -{ - GList *l=bl; - while (l) { - struct boundary *boundary=l->data; - GList *s=boundary->segments; - while (s) { - struct geom_poly_segment *seg=s->data; - g_free(seg->first); - g_free(seg); - s=g_list_next(s); - }; - s=boundary->sorted_segments; - while (s) { - struct geom_poly_segment *seg=s->data; - g_free(seg->first); - g_free(seg); - s=g_list_next(s); - }; - g_list_free(boundary->segments); - g_list_free(boundary->sorted_segments); - g_free(boundary->ib); - g_free(boundary->iso2); - free_boundaries(boundary->children); - g_free(boundary); - l=g_list_next(l); - } - g_list_free(bl); +void free_boundaries(GList *bl) { + GList *l=bl; + while (l) { + struct boundary *boundary=l->data; + GList *s=boundary->segments; + while (s) { + struct geom_poly_segment *seg=s->data; + g_free(seg->first); + g_free(seg); + s=g_list_next(s); + }; + s=boundary->sorted_segments; + while (s) { + struct geom_poly_segment *seg=s->data; + g_free(seg->first); + g_free(seg); + s=g_list_next(s); + }; + g_list_free(boundary->segments); + g_list_free(boundary->sorted_segments); + g_free(boundary->ib); + g_free(boundary->iso2); + free_boundaries(boundary->children); + g_free(boundary); + l=g_list_next(l); + } + g_list_free(bl); } |