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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 31 - (show annotations) (download)
Mon Feb 4 17:41:59 2013 UTC (11 years, 1 month ago) by zoff99
File MIME type: text/plain
File size: 15009 byte(s)
new map version, lots of fixes and experimental new features
1 /**
2 * ZANavi, Zoff Android Navigation system.
3 * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
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
20 /**
21 * Navit, a modular navigation system.
22 * Copyright (C) 2005-2011 Navit Team
23 *
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * version 2 as published by the Free Software Foundation.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the
35 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36 * Boston, MA 02110-1301, USA.
37 */
38 #include <stdio.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include "maptool.h"
42
43 char *
44 osm_tag_value(struct item_bin *ib, char *key)
45 {
46 char *tag = NULL;
47 int len = strlen(key);
48 while ((tag = item_bin_get_attr(ib, attr_osm_tag, tag)))
49 {
50 if (!strncmp(tag, key, len) && tag[len] == '=')
51 return tag + len + 1;
52 }
53 return NULL;
54 }
55
56 static char *
57 osm_tag_name(struct item_bin *ib)
58 {
59 return osm_tag_value(ib, "name");
60 }
61
62 long long *
63 boundary_relid(struct boundary *b)
64 {
65 long long *id;
66 if (!b)
67 return 0;
68 if (!b->ib)
69 return 0;
70 id = item_bin_get_attr(b->ib, attr_osm_relationid, NULL);
71 if (id)
72 return *id;
73 return 0;
74 }
75
76 static void process_boundaries_member(void *func_priv, void *relation_priv, struct item_bin *member, void *member_priv)
77 {
78 //fprintf(stderr,"process_boundaries_member:001\n");
79
80 struct boundary *b = relation_priv;
81 enum geom_poly_segment_type role = (long) member_priv;
82
83 int *dup;
84 dup=item_bin_get_attr(member,attr_duplicate_way,NULL);
85 // only add way to boundary if this way is not already added
86 if(!dup || *dup==0)
87 {
88 b->segments = g_list_prepend(b->segments, item_bin_to_poly_segment(member, role));
89 }
90 else
91 {
92 fprintf(stderr, "process_boundaries_member: dup=true wayid=%lld\n", item_bin_get_wayid(member));
93 }
94
95 //fprintf(stderr,"process_boundaries_member:099\n");
96 }
97
98 static GList *
99 process_boundaries_setup(FILE *boundaries, struct relations *relations)
100 {
101 struct item_bin *ib;
102 GList *boundaries_list = NULL;
103 struct relations_func *relations_func;
104 long long b_counter_1 = 0;
105 // long long b_counter_2 = 0;
106
107 //fprintf(stderr,"process_boundaries_setup:001\n");
108
109 relations_func = relations_func_new(process_boundaries_member, NULL);
110 while ((ib = read_item(boundaries, 0)))
111 {
112
113 //fprintf(stderr,"********DUMP b ***********\n");
114 //dump_itembin(ib);
115 //fprintf(stderr,"********DUMP b ***********\n");
116
117
118 char *member = NULL;
119 struct boundary *boundary=g_new0(struct boundary, 1);
120 char *admin_level = osm_tag_value(ib, "admin_level");
121 char *iso = osm_tag_value(ib, "ISO3166-1");
122
123 b_counter_1++;
124 if ((b_counter_1 % 500) == 0)
125 {
126 fprintf(stderr,"boundaries:B:%lld\n", b_counter_1);
127 }
128
129 //fprintf(stderr,"process_boundaries_setup:002\n");
130 //fprintf(stderr,"== b:%s %s ==\n", iso, admin_level);
131
132 /* disable spain for now since it creates a too large index */
133 if (admin_level && !strcmp(admin_level, "2") && (!iso || strcasecmp(iso, "es")))
134 {
135 if (iso)
136 {
137 struct country_table *country = country_from_iso2(iso);
138 if (!country)
139 {
140 osm_warning("relation", item_bin_get_relationid(ib), 0, "Country Boundary contains unknown ISO3166-1 value '%s'\n", iso);
141 }
142 else
143 {
144 boundary->iso2 = g_strdup(iso);
145 osm_info("relation", item_bin_get_relationid(ib), 0, "Country Boundary for '%s'\n", iso);
146 }
147 boundary->country = country;
148 }
149 else
150 {
151 osm_warning("relation", item_bin_get_relationid(ib), 0, "Country Boundary doesn't contain an ISO3166-1 tag\n");
152 }
153 }
154
155 //b_counter_2 = 0;
156 while ((member = item_bin_get_attr(ib, attr_osm_member, member)))
157 {
158 //fprintf(stderr,"process_boundaries_setup:005\n");
159 //fprintf(stderr,"********DUMP b ***********\n");
160 //dump_itembin(ib);
161 //fprintf(stderr,"********DUMP b ***********\n");
162
163 //b_counter_2++;
164 //fprintf(stderr,"boundaries:M:%lld\n", b_counter_2);
165
166 long long wayid;
167 int read = 0;
168 if (sscanf(member, "2:%Ld:%n", &wayid, &read) >= 1)
169 {
170 char *rolestr = member + read;
171 enum geom_poly_segment_type role;
172 if (!strcmp(rolestr, "outer") || !strcmp(rolestr, "exclave"))
173 role = geom_poly_segment_type_way_outer;
174 else if (!strcmp(rolestr, "inner") || !strcmp(rolestr, "enclave"))
175 role = geom_poly_segment_type_way_inner;
176 else if (!strcmp(rolestr, ""))
177 role = geom_poly_segment_type_way_unknown;
178 else
179 {
180 osm_warning("relation", item_bin_get_relationid(ib), 0, "Unknown role %s in member ", rolestr);
181 osm_warning("way", wayid, 1, "\n");
182 role = geom_poly_segment_type_none;
183 }
184
185 //fprintf(stderr,"process_boundaries_setup:006 %s %Ld\n", rolestr,wayid);
186
187 relations_add_func(relations, relations_func, boundary, (gpointer) role, 2, wayid);
188 }
189 }
190
191 boundary->ib = item_bin_dup(ib);
192 boundaries_list = g_list_append(boundaries_list, boundary);
193 }
194
195 return boundaries_list;
196 }
197
198 GList *
199 boundary_find_matches(GList *l, struct coord *c)
200 {
201 GList *ret = NULL;
202 //fprintf(stderr,"boundary_find_matches:001\n");
203 while (l)
204 {
205 //fprintf(stderr,"boundary_find_matches:002\n");
206
207 struct boundary *boundary = l->data;
208 if (bbox_contains_coord(&boundary->r, c))
209 {
210 //fprintf(stderr,"boundary_find_matches:003 id=%lld name=%s\n", item_bin_get_relationid(boundary->ib), osm_tag_name(boundary->ib));
211 if (geom_poly_segments_point_inside(boundary->sorted_segments, c) > 0)
212 {
213 //fprintf(stderr,"boundary_find_matches:004\n");
214 ret = g_list_prepend(ret, boundary);
215 }
216 // children stuff disabled!!
217 // ret = g_list_concat(ret, boundary_find_matches(boundary->children, c));
218 // children stuff disabled!!
219 }
220 l = g_list_next(l);
221 }
222
223 //fprintf(stderr,"boundary_find_matches:099\n");
224
225 return ret;
226 }
227
228 GList *
229 boundary_find_matches_level(GList *l, struct coord *c, int min_admin_level, int max_admin_level)
230 {
231 GList *ret = NULL;
232 char *al;
233 int admin_level;
234 struct boundary *boundary = NULL;
235
236 while (l)
237 {
238 boundary = l->data;
239 al = osm_tag_value(boundary->ib, "admin_level");
240 if (!al)
241 {
242 admin_level = 9999;
243 }
244 else
245 {
246 admin_level = atoi(al);
247 }
248
249 if (admin_level < 2)
250 {
251 admin_level = 9999;
252 }
253
254 //fprintf(stderr, "matches 001:this:%d min:%d max:%d\n", admin_level, min_admin_level, max_admin_level);
255
256 if ((admin_level >= min_admin_level) && (admin_level <= max_admin_level))
257 {
258 //fprintf(stderr, "matches 002:level\n");
259 if (bbox_contains_coord(&boundary->r, c))
260 {
261 //fprintf(stderr, "matches 003:bbox\n");
262 if (geom_poly_segments_point_inside(boundary->sorted_segments, c) > 0)
263 {
264 //fprintf(stderr, "matches 004:**found**\n");
265 ret = g_list_prepend(ret, boundary);
266 }
267 }
268 }
269 l = g_list_next(l);
270 }
271
272 return ret;
273 }
274
275
276 GList *
277 boundary_find_matches_single(GList *l, struct coord *c)
278 {
279 GList *ret = NULL;
280
281 if (l)
282 {
283 //fprintf(stderr, "bbox:001\n");
284 struct boundary *boundary = l->data;
285 //fprintf(stderr, "bbox:%d %d %d %d\n", boundary->r.l.x, boundary->r.l.y, boundary->r.h.x, boundary->r.h.y);
286 //fprintf(stderr, "c:%d %d\n", c->x, c->y);
287 if (bbox_contains_coord(&boundary->r, c))
288 {
289 //fprintf(stderr, "inside bbox\n");
290 if (geom_poly_segments_point_inside(boundary->sorted_segments, c) > 0)
291 {
292 //fprintf(stderr, "bbox:002\n");
293 ret = g_list_prepend(ret, boundary);
294 }
295 }
296 }
297
298 return ret;
299 }
300
301
302 static void dump_hierarchy(GList *l, char *prefix)
303 {
304 char *newprefix = g_alloca(sizeof(char) * (strlen(prefix) + 2));
305 strcpy(newprefix, prefix);
306 strcat(newprefix, " ");
307 while (l)
308 {
309 struct boundary *boundary = l->data;
310 fprintf(stderr, "%s:childs:%d:%lld:%s\n", prefix, g_list_length(boundary->children), item_bin_get_relationid(boundary->ib), osm_tag_name(boundary->ib));
311 dump_hierarchy(boundary->children, newprefix);
312 l = g_list_next(l);
313 }
314 }
315
316 static gint boundary_bbox_compare(gconstpointer a, gconstpointer b)
317 {
318 const struct boundary *boundarya = a;
319 const struct boundary *boundaryb = b;
320 long long areaa = bbox_area(&boundarya->r);
321 long long areab = bbox_area(&boundaryb->r);
322 if (areaa > areab)
323 return 1;
324 if (areaa < areab)
325 return -1;
326 return 0;
327 }
328
329 static GList *
330 process_boundaries_insert(GList *list, struct boundary *boundary)
331 {
332 // children stuff is totally broken, so it is disabled now!!
333 /*
334 GList *l = list;
335 while (l)
336 {
337 struct boundary *b = l->data;
338 if (bbox_contains_bbox(&boundary->r, &b->r))
339 {
340 list = g_list_remove(list, b);
341 boundary->children = g_list_prepend(boundary->children, b);
342 l = list;
343 }
344 else if (bbox_contains_bbox(&b->r, &boundary->r))
345 {
346 b->children = process_boundaries_insert(b->children, boundary);
347 return list;
348 }
349 else
350 {
351 l = g_list_next(l);
352 }
353 }
354 */
355 // children stuff is totally broken, so it is disabled now!!
356
357 return g_list_prepend(list, boundary);
358 }
359
360 static GList *
361 process_boundaries_finish(GList *boundaries_list)
362 {
363 //fprintf(stderr,"process_boundaries_finish:001\n");
364
365 GList *l, *sl, *l2, *ln;
366 GList *ret = NULL;
367 l = boundaries_list;
368 char *f1_name = NULL;
369 char *f2_name = NULL;
370 long long b_counter_1 = 0;
371 long long nodes_counter_ = 0;
372 long long ways_counter_ = 0;
373
374 while (l)
375 {
376 struct boundary *boundary = l->data;
377 int first = 1;
378 FILE *f = NULL, *fu = NULL;
379
380 b_counter_1++;
381 if ((b_counter_1 % 500) == 0)
382 {
383 fprintf(stderr,"boundaries_f1:B:%lld\n", b_counter_1);
384 }
385
386 //fprintf(stderr,"process_boundaries_finish:002\n");
387
388 // only lowercase country code
389 if (boundary->iso2)
390 {
391 int i99;
392 for (i99 = 0; boundary->iso2[i99]; i99++)
393 {
394 boundary->iso2[i99] = tolower(boundary->iso2[i99]);
395 }
396 }
397 // only lowercase country code
398
399 if (boundary->country)
400 {
401 //fprintf(stderr,"process_boundaries_finish:003\n");
402
403 char *name = g_strdup_printf("country_%s_poly", boundary->iso2);
404 f1_name = g_strdup_printf("country_%s_poly", boundary->iso2);
405 f = tempfile("", name, 1);
406 g_free(name);
407 }
408
409
410
411 // calc bounding box
412 first = 1;
413 nodes_counter_ = 0;
414 ways_counter_ = 0;
415 sl = boundary->segments;
416 while (sl)
417 {
418 struct geom_poly_segment *gs = sl->data;
419 struct coord *c = gs->first;
420 while (c <= gs->last)
421 {
422 if (first)
423 {
424 boundary->r.l = *c;
425 boundary->r.h = *c;
426 first = 0;
427 }
428 else
429 {
430 bbox_extend(c, &boundary->r);
431 }
432 c++;
433 nodes_counter_++;
434 }
435 sl = g_list_next(sl);
436 ways_counter_++;
437 }
438
439 //fprintf(stderr, "relid:%lld\n", item_bin_get_relationid(boundary->ib));
440 //fprintf(stderr, "ways:%lld nodes:%lld\n", ways_counter_, nodes_counter_);
441
442 boundary->sorted_segments = geom_poly_segments_sort(boundary->segments, geom_poly_segment_type_way_right_side);
443 sl = boundary->sorted_segments;
444
445 first = 1;
446 while (sl)
447 {
448 //fprintf(stderr,"process_boundaries_finish:004.1\n");
449
450 struct geom_poly_segment *gs = sl->data;
451 struct coord *c = gs->first;
452
453 /*
454 while (c <= gs->last)
455 {
456 if (first)
457 {
458 boundary->r.l = *c;
459 boundary->r.h = *c;
460 first = 0;
461 }
462 else
463 {
464 bbox_extend(c, &boundary->r);
465 }
466 c++;
467
468 //fprintf(stderr,"process_boundaries_finish:004.2 lx=%d ly=%d hx=%d hy=%d\n",boundary->r.l.x,boundary->r.l.y,boundary->r.h.x,boundary->r.h.y);
469
470 }
471 */
472
473 if (f)
474 {
475 struct item_bin *ib = item_bin_2;
476 item_bin_init(ib, type_selected_line);
477 item_bin_add_coord(ib, gs->first, gs->last - gs->first + 1);
478 item_bin_write(ib, f);
479 }
480
481 if (boundary->country)
482 {
483 if (!coord_is_equal(*gs->first, *gs->last))
484 {
485 if (!fu)
486 {
487 char *name = g_strdup_printf("country_%s_broken", boundary->iso2);
488 f2_name = g_strdup_printf("country_%s_broken", boundary->iso2);
489 fprintf(stderr, "*BROKEN* country_%s_broken\n", boundary->iso2);
490 fu = tempfile("", name, 1);
491 g_free(name);
492 }
493 struct item_bin *ib = item_bin_2;
494 item_bin_init(ib, type_selected_point);
495 item_bin_add_coord(ib, gs->first, 1);
496 item_bin_write(ib, fu);
497
498 item_bin_init(ib, type_selected_point);
499 item_bin_add_coord(ib, gs->last, 1);
500 item_bin_write(ib, fu);
501 }
502 }
503 sl = g_list_next(sl);
504
505 if (f2_name)
506 {
507 tempfile_unlink("", f2_name);
508 g_free(f2_name);
509 f2_name = NULL;
510 }
511 }
512
513 ret = process_boundaries_insert(ret, boundary);
514 l = g_list_next(l);
515
516 if (f)
517 {
518 fclose(f);
519 }
520
521 if (fu)
522 {
523 if (boundary->country)
524 {
525 //osm_warning("relation", item_bin_get_relationid(boundary->ib), 0, "Broken country polygon '%s'\n", boundary->iso2);
526 fprintf(stderr, "*BROKEN* country polygon '%s'\n", boundary->iso2);
527 }
528 fclose(fu);
529 }
530
531 if (f1_name)
532 {
533 tempfile_unlink("", f1_name);
534 g_free(f1_name);
535 f1_name = NULL;
536 }
537 }
538 #if 0
539 printf("hierarchy\n");
540 #endif
541
542 // boundaries_list = g_list_sort(boundaries_list, boundary_bbox_compare); // disable sorting, does not seem to do any good
543
544 // children stuff totally broken!!!
545 #if 0
546 b_counter_1 = 0;
547 l = boundaries_list;
548 while (l)
549 {
550 b_counter_1++;
551 if ((b_counter_1 % 500) == 0)
552 {
553 fprintf(stderr,"boundaries_f2:B:%lld\n", b_counter_1);
554 }
555
556 struct boundary *boundary = l->data;
557 ln = l2 = g_list_next(l);
558 while (l2)
559 {
560 struct boundary *boundary2 = l2->data;
561 if (bbox_contains_bbox(&boundary2->r, &boundary->r))
562 {
563 boundaries_list = g_list_remove(boundaries_list, boundary);
564 boundary2->children = g_list_append(boundary2->children, boundary);
565 break;
566 }
567 l2 = g_list_next(l2);
568 }
569 l = ln;
570 }
571 #endif
572 // children stuff totally broken!!!
573
574 // -- DEBUG --
575 // -- DEBUG --
576 // -- DEBUG --
577 // dump_hierarchy(boundaries_list,""); // --> prints huge amounts of data!! be careful
578 // -- DEBUG --
579 // -- DEBUG --
580 // -- DEBUG --
581
582 return boundaries_list;
583 }
584
585 GList *
586 process_boundaries(FILE *boundaries, FILE *coords, FILE *ways)
587 {
588 GList *boundaries_list;
589 struct relations *relations = relations_new();
590
591 //fprintf(stderr,"process_boundaries:001\n");
592 boundaries_list = process_boundaries_setup(boundaries, relations);
593 //fprintf(stderr,"process_boundaries:001.rp1\n");
594 relations_process(relations, NULL, ways, NULL);
595 //fprintf(stderr,"process_boundaries:001.rp2\n");
596 return process_boundaries_finish(boundaries_list);
597 }
598

   
Visit the ZANavi Wiki