/[zanavi_public1]/navit/navit/maptool/boundaries.c
ZANavi

Contents of /navit/navit/maptool/boundaries.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 36 - (show annotations) (download)
Sat Mar 8 17:10:49 2014 UTC (10 years ago) by zoff99
File MIME type: text/plain
File size: 9103 byte(s)
new market version, lots of new features
1 /**
2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2011 Navit Team
4 *
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.
8 *
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.
13 *
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.
18 */
19 #include <stdio.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include "maptool.h"
23
24
25 char *
26 osm_tag_value(struct item_bin *ib, char *key)
27 {
28 char *tag=NULL;
29 int len=strlen(key);
30 while ((tag=item_bin_get_attr(ib, attr_osm_tag, tag))) {
31 if (!strncmp(tag,key,len) && tag[len] == '=')
32 return tag+len+1;
33 }
34 return NULL;
35 }
36
37 static char *
38 osm_tag_name(struct item_bin *ib)
39 {
40 return osm_tag_value(ib, "name");
41 }
42
43 long long *
44 boundary_relid(struct boundary *b)
45 {
46 long long *id;
47 if (!b)
48 return 0;
49 if (!b->ib)
50 return 0;
51 id=item_bin_get_attr(b->ib, attr_osm_relationid, NULL);
52 if (id)
53 return *id;
54 return 0;
55 }
56
57 static void
58 process_boundaries_member(void *func_priv, void *relation_priv, struct item_bin *member, void *member_priv)
59 {
60 struct boundary *b=relation_priv;
61 enum geom_poly_segment_type role=(long)member_priv;
62 b->segments=g_list_prepend(b->segments,item_bin_to_poly_segment(member, role));
63 }
64
65 static GList *
66 process_boundaries_setup(FILE *boundaries, struct relations *relations)
67 {
68 struct item_bin *ib;
69 GList *boundaries_list=NULL;
70 struct relations_func *relations_func;
71
72 relations_func=relations_func_new(process_boundaries_member, NULL);
73 while ((ib=read_item(boundaries))) {
74 char *member=NULL;
75 struct boundary *boundary=g_new0(struct boundary, 1);
76 char *admin_level=osm_tag_value(ib, "admin_level");
77 char *iso=osm_tag_value(ib, "ISO3166-1");
78 /* disable spain for now since it creates a too large index */
79 if (admin_level && !strcmp(admin_level, "2") && (!iso || strcasecmp(iso,"es"))) {
80 if (iso) {
81 struct country_table *country=country_from_iso2(iso);
82 if (!country)
83 osm_warning("relation",item_bin_get_relationid(ib),0,"Country Boundary contains unknown ISO3166-1 value '%s'\n",iso);
84 else {
85 boundary->iso2=g_strdup(iso);
86 osm_info("relation",item_bin_get_relationid(ib),0,"Country Boundary for '%s'\n",iso);
87 }
88 boundary->country=country;
89 } else
90 osm_warning("relation",item_bin_get_relationid(ib),0,"Country Boundary doesn't contain an ISO3166-1 tag\n");
91 }
92 while ((member=item_bin_get_attr(ib, attr_osm_member, member))) {
93 long long wayid;
94 int read=0;
95 if (sscanf(member,"2:%Ld:%n",&wayid,&read) >= 1) {
96 char *rolestr=member+read;
97 enum geom_poly_segment_type role;
98 if (!strcmp(rolestr,"outer") || !strcmp(rolestr,"exclave"))
99 role=geom_poly_segment_type_way_outer;
100 else if (!strcmp(rolestr,"inner") || !strcmp(rolestr,"enclave"))
101 role=geom_poly_segment_type_way_inner;
102 else if (!strcmp(rolestr,""))
103 role=geom_poly_segment_type_way_unknown;
104 else {
105 osm_warning("relation",item_bin_get_relationid(ib),0,"Unknown role %s in member ",rolestr);
106 osm_warning("way",wayid,1,"\n");
107 role=geom_poly_segment_type_none;
108 }
109 relations_add_func(relations, relations_func, boundary, (gpointer)role, 2, wayid);
110 }
111 }
112 boundary->ib=item_bin_dup(ib);
113 boundaries_list=g_list_append(boundaries_list, boundary);
114 }
115 return boundaries_list;
116 }
117
118 GList *
119 boundary_find_matches(GList *l, struct coord *c)
120 {
121 GList *ret=NULL;
122 while (l) {
123 struct boundary *boundary=l->data;
124 if (bbox_contains_coord(&boundary->r, c)) {
125 if (geom_poly_segments_point_inside(boundary->sorted_segments,c) > 0)
126 ret=g_list_prepend(ret, boundary);
127 ret=g_list_concat(ret,boundary_find_matches(boundary->children, c));
128 }
129 l=g_list_next(l);
130 }
131 return ret;
132 }
133
134 static void
135 test(GList *boundaries_list)
136 {
137 struct item_bin *ib;
138 FILE *f=fopen("country_276.bin.unsorted","r");
139 printf("start\n");
140 while ((ib=read_item(f))) {
141 struct coord *c=(struct coord *)(ib+1);
142 char *name=item_bin_get_attr(ib, attr_town_name, NULL);
143 printf("%s:",name);
144 boundary_find_matches(boundaries_list, c);
145 printf("\n");
146 }
147 fclose(f);
148 printf("end\n");
149 }
150
151 static void
152 dump_hierarchy(GList *l, char *prefix)
153 {
154 char *newprefix=g_alloca(sizeof(char)*(strlen(prefix)+2));
155 strcpy(newprefix, prefix);
156 strcat(newprefix," ");
157 while (l) {
158 struct boundary *boundary=l->data;
159 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);
160 dump_hierarchy(boundary->children, newprefix);
161 l=g_list_next(l);
162 }
163 }
164
165 static gint
166 boundary_bbox_compare(gconstpointer a, gconstpointer b)
167 {
168 const struct boundary *boundarya=a;
169 const struct boundary *boundaryb=b;
170 long long areaa=bbox_area(&boundarya->r);
171 long long areab=bbox_area(&boundaryb->r);
172 if (areaa > areab)
173 return 1;
174 if (areaa < areab)
175 return -1;
176 return 0;
177 }
178
179 static GList *
180 process_boundaries_insert(GList *list, struct boundary *boundary)
181 {
182 GList *l=list;
183 while (l) {
184 struct boundary *b=l->data;
185 if (bbox_contains_bbox(&boundary->r, &b->r)) {
186 list=g_list_remove(list, b);
187 boundary->children=g_list_prepend(boundary->children, b);
188 l=list;
189 } else if (bbox_contains_bbox(&b->r, &boundary->r)) {
190 b->children=process_boundaries_insert(b->children, boundary);
191 return list;
192 } else
193 l=g_list_next(l);
194 }
195 return g_list_prepend(list, boundary);
196 }
197
198
199 static GList *
200 process_boundaries_finish(GList *boundaries_list)
201 {
202 GList *l,*sl,*l2,*ln;
203 GList *ret=NULL;
204 l=boundaries_list;
205 char *f1_name=NULL;
206 char *f2_name=NULL;
207 while (l)
208 {
209 struct boundary *boundary=l->data;
210 int first=1;
211 FILE *f=NULL,*fu=NULL;
212
213 // only lowercase country code
214 if (boundary->iso2)
215 {
216 int i99;
217 for (i99 = 0; boundary->iso2[i99]; i99++)
218 {
219 boundary->iso2[i99] = tolower(boundary->iso2[i99]);
220 }
221 }
222 // only lowercase country code
223
224 if (boundary->country) {
225 char *name=g_strdup_printf("country_%s_poly",boundary->iso2);
226 f1_name=g_strdup_printf("country_%s_poly",boundary->iso2);
227 f=tempfile("",name,1);
228 g_free(name);
229 }
230 boundary->sorted_segments=geom_poly_segments_sort(boundary->segments, geom_poly_segment_type_way_right_side);
231 sl=boundary->sorted_segments;
232 while (sl)
233 {
234 struct geom_poly_segment *gs=sl->data;
235 struct coord *c=gs->first;
236 while (c <= gs->last) {
237 if (first) {
238 boundary->r.l=*c;
239 boundary->r.h=*c;
240 first=0;
241 } else
242 bbox_extend(c, &boundary->r);
243 c++;
244 }
245 if (f) {
246 struct item_bin *ib=item_bin;
247 item_bin_init(ib, type_selected_line);
248 item_bin_add_coord(ib, gs->first, gs->last-gs->first+1);
249 item_bin_write(ib, f);
250 }
251 if (boundary->country) {
252 if (!coord_is_equal(*gs->first,*gs->last)) {
253 if (!fu) {
254 char *name=g_strdup_printf("country_%s_broken",boundary->iso2);
255 f2_name=g_strdup_printf("country_%s_broken",boundary->iso2);
256 fu=tempfile("",name,1);
257 g_free(name);
258 }
259 struct item_bin *ib=item_bin;
260 item_bin_init(ib, type_selected_point);
261 item_bin_add_coord(ib, gs->first, 1);
262 item_bin_write(ib, fu);
263
264 item_bin_init(ib, type_selected_point);
265 item_bin_add_coord(ib, gs->last, 1);
266 item_bin_write(ib, fu);
267 }
268 }
269 sl=g_list_next(sl);
270
271 if (f2_name)
272 {
273 tempfile_unlink("",f2_name);
274 g_free(f2_name);
275 f2_name=NULL;
276 }
277 }
278 ret=process_boundaries_insert(ret, boundary);
279 l=g_list_next(l);
280 if (f)
281 fclose(f);
282 if (fu) {
283 if (boundary->country)
284 osm_warning("relation",item_bin_get_relationid(boundary->ib),0,"Broken country polygon '%s'\n",boundary->iso2);
285 fclose(fu);
286 }
287
288 if (f1_name)
289 {
290 tempfile_unlink("",f1_name);
291 g_free(f1_name);
292 f1_name=NULL;
293 }
294 }
295 #if 0
296 printf("hierarchy\n");
297 #endif
298 boundaries_list=g_list_sort(boundaries_list, boundary_bbox_compare);
299 l=boundaries_list;
300 while (l) {
301 struct boundary *boundary=l->data;
302 ln=l2=g_list_next(l);
303 while (l2) {
304 struct boundary *boundary2=l2->data;
305 if (bbox_contains_bbox(&boundary2->r, &boundary->r)) {
306 boundaries_list=g_list_remove(boundaries_list, boundary);
307 boundary2->children=g_list_append(boundary2->children, boundary);
308 #if 0
309 printf("found\n");
310 #endif
311 break;
312 }
313 l2=g_list_next(l2);
314 }
315 l=ln;
316 }
317 // dump_hierarchy(boundaries_list,""); --> make much data!! be careful
318 #if 0
319 printf("hierarchy done\n");
320 printf("test\n");
321 test(boundaries_list);
322 #endif
323 return boundaries_list;
324 }
325
326 GList *
327 process_boundaries(FILE *boundaries, FILE *ways)
328 {
329 GList *boundaries_list;
330 struct relations *relations=relations_new();
331
332 boundaries_list=process_boundaries_setup(boundaries, relations);
333 relations_process(relations, NULL, ways, NULL);
334 return process_boundaries_finish(boundaries_list);
335 }
336
337

   
Visit the ZANavi Wiki