summaryrefslogtreecommitdiff
path: root/navit/maptool/boundaries.c
diff options
context:
space:
mode:
Diffstat (limited to 'navit/maptool/boundaries.c')
-rw-r--r--navit/maptool/boundaries.c604
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);
}