2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2011 Navit Team
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
23 struct boundary_member {
25 enum geom_poly_segment_type role;
26 struct boundary *boundary;
30 boundary_member_hash(gconstpointer key)
32 const struct boundary_member *memb=key;
33 return (memb->wayid >> 32)^(memb->wayid & 0xffffffff);
37 boundary_member_equal(gconstpointer a, gconstpointer b)
39 const struct boundary_member *memba=a;
40 const struct boundary_member *membb=b;
41 return (memba->wayid == membb->wayid);
44 GHashTable *member_hash;
47 osm_tag_value(struct item_bin *ib, char *key)
51 while ((tag=item_bin_get_attr(ib, attr_osm_tag, tag))) {
52 if (!strncmp(tag,key,len) && tag[len] == '=')
59 osm_tag_name(struct item_bin *ib)
61 return osm_tag_value(ib, "name");
65 build_boundaries(FILE *boundaries)
68 GList *boundaries_list=NULL;
70 while ((ib=read_item(boundaries))) {
72 struct boundary *boundary=g_new0(struct boundary, 1);
73 char *admin_level=osm_tag_value(ib, "admin_level");
74 char *iso=osm_tag_value(ib, "ISO3166-1");
75 if (admin_level && !strcmp(admin_level, "2")) {
77 struct country_table *country=country_from_iso2(iso);
79 osm_warning("relation",item_bin_get_relationid(ib),0,"Country Boundary contains unknown ISO3166-1 value '%s'\n",iso);
80 boundary->country=country;
82 osm_warning("relation",item_bin_get_relationid(ib),0,"Country Boundary doesn't contain an ISO3166-1 tag\n");
84 while ((member=item_bin_get_attr(ib, attr_osm_member, member))) {
87 if (sscanf(member,"2:%Ld:%n",&wayid,&read) >= 1) {
88 struct boundary_member *memb=g_new(struct boundary_member, 1);
89 char *role=member+read;
91 memb->boundary=boundary;
92 if (!strcmp(role,"outer"))
93 memb->role=geom_poly_segment_type_way_outer;
94 else if (!strcmp(role,"inner"))
95 memb->role=geom_poly_segment_type_way_inner;
96 else if (!strcmp(role,""))
97 memb->role=geom_poly_segment_type_way_unknown;
99 printf("Unknown role %s\n",role);
100 memb->role=geom_poly_segment_type_none;
102 g_hash_table_insert(member_hash, memb, g_list_append(g_hash_table_lookup(member_hash, memb), memb));
106 boundary->ib=item_bin_dup(ib);
107 boundaries_list=g_list_append(boundaries_list, boundary);
109 return boundaries_list;
113 boundary_find_matches(GList *l, struct coord *c)
117 struct boundary *boundary=l->data;
118 if (bbox_contains_coord(&boundary->r, c)) {
119 if (geom_poly_segments_point_inside(boundary->sorted_segments,c))
120 ret=g_list_prepend(ret, boundary);
121 ret=g_list_concat(ret,boundary_find_matches(boundary->children, c));
129 test(GList *boundaries_list)
132 FILE *f=fopen("country_276.bin.unsorted","r");
134 while ((ib=read_item(f))) {
135 struct coord *c=(struct coord *)(ib+1);
136 char *name=item_bin_get_attr(ib, attr_town_name, NULL);
138 boundary_find_matches(boundaries_list, c);
146 dump_hierarchy(GList *l, char *prefix)
148 char *newprefix=g_alloca(sizeof(char)*(strlen(prefix)+2));
149 strcpy(newprefix, prefix);
150 strcat(newprefix," ");
152 struct boundary *boundary=l->data;
153 printf("%s:%s\n",prefix,osm_tag_name(boundary->ib));
154 dump_hierarchy(boundary->children, newprefix);
160 boundary_bbox_compare(gconstpointer a, gconstpointer b)
162 const struct boundary *boundarya=a;
163 const struct boundary *boundaryb=b;
164 long long areaa=bbox_area(&boundarya->r);
165 long long areab=bbox_area(&boundaryb->r);
174 process_boundaries(FILE *boundaries, FILE *ways)
177 GList *boundaries_list,*l,*sl,*l2,*ln;
179 member_hash=g_hash_table_new_full(boundary_member_hash, boundary_member_equal, NULL, NULL);
180 boundaries_list=build_boundaries(boundaries);
181 while ((ib=read_item(ways))) {
182 long long *wayid=item_bin_get_attr(ib, attr_osm_wayid, NULL);
184 GList *l=g_hash_table_lookup(member_hash, wayid);
186 struct boundary_member *memb=l->data;
187 memb->boundary->segments=g_list_prepend(memb->boundary->segments,item_bin_to_poly_segment(ib, memb->role));
195 struct boundary *boundary=l->data;
197 boundary->sorted_segments=geom_poly_segments_sort(boundary->segments, geom_poly_segment_type_way_right_side);
198 sl=boundary->sorted_segments;
200 struct geom_poly_segment *gs=sl->data;
201 struct coord *c=gs->first;
202 while (c <= gs->last) {
208 bbox_extend(c, &boundary->r);
217 printf("hierarchy\n");
219 boundaries_list=g_list_sort(boundaries_list, boundary_bbox_compare);
222 struct boundary *boundary=l->data;
223 ln=l2=g_list_next(l);
225 struct boundary *boundary2=l2->data;
226 if (bbox_contains_bbox(&boundary2->r, &boundary->r)) {
227 boundaries_list=g_list_remove(boundaries_list, boundary);
228 boundary2->children=g_list_append(boundary2->children, boundary);
239 printf("hierarchy done\n");
240 dump_hierarchy(boundaries_list,"");
242 test(boundaries_list);
244 return boundaries_list;