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.
24 osm_tag_value(struct item_bin *ib, char *key)
28 while ((tag=item_bin_get_attr(ib, attr_osm_tag, tag))) {
29 if (!strncmp(tag,key,len) && tag[len] == '=')
36 osm_tag_name(struct item_bin *ib)
38 return osm_tag_value(ib, "name");
42 boundary_relid(struct boundary *b)
49 id=item_bin_get_attr(b->ib, attr_osm_relationid, NULL);
55 process_boundaries_member(void *func_priv, void *relation_priv, struct item_bin *member, void *member_priv)
57 struct boundary *b=relation_priv;
58 enum geom_poly_segment_type role=(long)member_priv;
59 b->segments=g_list_prepend(b->segments,item_bin_to_poly_segment(member, role));
63 process_boundaries_setup(FILE *boundaries, struct relations *relations)
66 GList *boundaries_list=NULL;
67 struct relations_func *relations_func;
69 relations_func=relations_func_new(process_boundaries_member, 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 /* disable spain for now since it creates a too large index */
76 if (admin_level && !strcmp(admin_level, "2") && (!iso || strcasecmp(iso,"es"))) {
78 struct country_table *country=country_from_iso2(iso);
80 osm_warning("relation",item_bin_get_relationid(ib),0,"Country Boundary contains unknown ISO3166-1 value '%s'\n",iso);
82 boundary->iso2=g_strdup(iso);
83 osm_info("relation",item_bin_get_relationid(ib),0,"Country Boundary for '%s'\n",iso);
85 boundary->country=country;
87 osm_warning("relation",item_bin_get_relationid(ib),0,"Country Boundary doesn't contain an ISO3166-1 tag\n");
89 while ((member=item_bin_get_attr(ib, attr_osm_member, member))) {
92 if (sscanf(member,"2:%Ld:%n",&wayid,&read) >= 1) {
93 char *rolestr=member+read;
94 enum geom_poly_segment_type role;
95 if (!strcmp(rolestr,"outer") || !strcmp(rolestr,"exclave"))
96 role=geom_poly_segment_type_way_outer;
97 else if (!strcmp(rolestr,"inner") || !strcmp(rolestr,"enclave"))
98 role=geom_poly_segment_type_way_inner;
99 else if (!strcmp(rolestr,""))
100 role=geom_poly_segment_type_way_unknown;
102 osm_warning("relation",item_bin_get_relationid(ib),0,"Unknown role %s in member ",rolestr);
103 osm_warning("way",wayid,1,"\n");
104 role=geom_poly_segment_type_none;
106 relations_add_func(relations, relations_func, boundary, (gpointer)role, 2, wayid);
109 boundary->ib=item_bin_dup(ib);
110 boundaries_list=g_list_append(boundaries_list, boundary);
112 return boundaries_list;
116 boundary_find_matches(GList *l, struct coord *c)
120 struct boundary *boundary=l->data;
121 if (bbox_contains_coord(&boundary->r, c)) {
122 if (geom_poly_segments_point_inside(boundary->sorted_segments,c) > 0)
123 ret=g_list_prepend(ret, boundary);
124 ret=g_list_concat(ret,boundary_find_matches(boundary->children, c));
132 test(GList *boundaries_list)
135 FILE *f=fopen("country_276.bin.unsorted","r");
137 while ((ib=read_item(f))) {
138 struct coord *c=(struct coord *)(ib+1);
139 char *name=item_bin_get_attr(ib, attr_town_name, NULL);
141 boundary_find_matches(boundaries_list, c);
149 dump_hierarchy(GList *l, char *prefix)
151 char *newprefix=g_alloca(sizeof(char)*(strlen(prefix)+2));
152 strcpy(newprefix, prefix);
153 strcat(newprefix," ");
155 struct boundary *boundary=l->data;
156 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);
157 dump_hierarchy(boundary->children, newprefix);
163 boundary_bbox_compare(gconstpointer a, gconstpointer b)
165 const struct boundary *boundarya=a;
166 const struct boundary *boundaryb=b;
167 long long areaa=bbox_area(&boundarya->r);
168 long long areab=bbox_area(&boundaryb->r);
177 process_boundaries_insert(GList *list, struct boundary *boundary)
181 struct boundary *b=l->data;
182 if (bbox_contains_bbox(&boundary->r, &b->r)) {
183 list=g_list_remove(list, b);
184 boundary->children=g_list_prepend(boundary->children, b);
186 } else if (bbox_contains_bbox(&b->r, &boundary->r)) {
187 b->children=process_boundaries_insert(b->children, boundary);
192 return g_list_prepend(list, boundary);
197 process_boundaries_finish(GList *boundaries_list)
199 GList *l,*sl,*l2,*ln;
203 struct boundary *boundary=l->data;
205 FILE *f=NULL,*fu=NULL;
206 if (boundary->country) {
207 char *name=g_strdup_printf("country_%s_poly",boundary->iso2);
208 f=tempfile("",name,1);
211 boundary->sorted_segments=geom_poly_segments_sort(boundary->segments, geom_poly_segment_type_way_right_side);
212 sl=boundary->sorted_segments;
214 struct geom_poly_segment *gs=sl->data;
215 struct coord *c=gs->first;
216 while (c <= gs->last) {
222 bbox_extend(c, &boundary->r);
226 struct item_bin *ib=item_bin;
227 item_bin_init(ib, type_selected_line);
228 item_bin_add_coord(ib, gs->first, gs->last-gs->first+1);
229 item_bin_write(ib, f);
231 if (boundary->country) {
232 if (!coord_is_equal(*gs->first,*gs->last)) {
234 char *name=g_strdup_printf("country_%s_broken",boundary->iso2);
235 fu=tempfile("",name,1);
238 struct item_bin *ib=item_bin;
239 item_bin_init(ib, type_selected_point);
240 item_bin_add_coord(ib, gs->first, 1);
241 item_bin_write(ib, fu);
242 item_bin_init(ib, type_selected_point);
243 item_bin_add_coord(ib, gs->last, 1);
244 item_bin_write(ib, fu);
249 ret=process_boundaries_insert(ret, boundary);
254 if (boundary->country)
255 osm_warning("relation",item_bin_get_relationid(boundary->ib),0,"Broken country polygon '%s'\n",boundary->iso2);
261 printf("hierarchy\n");
264 boundaries_list=g_list_sort(boundaries_list, boundary_bbox_compare);
267 struct boundary *boundary=l->data;
268 ln=l2=g_list_next(l);
270 struct boundary *boundary2=l2->data;
271 if (bbox_contains_bbox(&boundary2->r, &boundary->r)) {
272 boundaries_list=g_list_remove(boundaries_list, boundary);
273 boundary2->children=g_list_append(boundary2->children, boundary);
283 dump_hierarchy(boundaries_list,"");
285 printf("hierarchy done\n");
287 test(boundaries_list);
294 process_boundaries(FILE *boundaries, FILE *ways)
296 GList *boundaries_list;
297 struct relations *relations=relations_new();
299 boundaries_list=process_boundaries_setup(boundaries, relations);
300 relations_process(relations, NULL, ways, NULL);
301 return process_boundaries_finish(boundaries_list);