/[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 - (hide 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 zoff99 8 /**
2 zoff99 31 * 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 zoff99 8 * 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 zoff99 31 #include <ctype.h>
41 zoff99 8 #include "maptool.h"
42    
43 zoff99 31 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 zoff99 8
56 zoff99 31 static char *
57     osm_tag_name(struct item_bin *ib)
58 zoff99 8 {
59 zoff99 31 return osm_tag_value(ib, "name");
60 zoff99 8 }
61    
62 zoff99 31 long long *
63     boundary_relid(struct boundary *b)
64 zoff99 8 {
65 zoff99 31 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 zoff99 8 }
75    
76 zoff99 31 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 zoff99 8
80 zoff99 31 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 zoff99 8 }
90 zoff99 31 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 zoff99 8 }
97    
98     static GList *
99 zoff99 31 process_boundaries_setup(FILE *boundaries, struct relations *relations)
100 zoff99 8 {
101     struct item_bin *ib;
102 zoff99 31 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 zoff99 8
107 zoff99 31 //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 zoff99 8 struct boundary *boundary=g_new0(struct boundary, 1);
120 zoff99 31 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 zoff99 8 long long wayid;
167 zoff99 31 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 zoff99 8 }
184    
185 zoff99 31 //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 zoff99 8 }
189     }
190 zoff99 31
191     boundary->ib = item_bin_dup(ib);
192     boundaries_list = g_list_append(boundaries_list, boundary);
193 zoff99 8 }
194 zoff99 31
195 zoff99 8 return boundaries_list;
196     }
197    
198 zoff99 31 GList *
199     boundary_find_matches(GList *l, struct coord *c)
200 zoff99 8 {
201 zoff99 31 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 zoff99 8 }
220 zoff99 31 l = g_list_next(l);
221 zoff99 8 }
222 zoff99 31
223     //fprintf(stderr,"boundary_find_matches:099\n");
224    
225     return ret;
226 zoff99 8 }
227    
228 zoff99 31 GList *
229     boundary_find_matches_level(GList *l, struct coord *c, int min_admin_level, int max_admin_level)
230 zoff99 8 {
231 zoff99 31 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 zoff99 8 }
271 zoff99 31
272     return ret;
273 zoff99 8 }
274    
275 zoff99 31
276     GList *
277     boundary_find_matches_single(GList *l, struct coord *c)
278 zoff99 8 {
279 zoff99 31 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 zoff99 8 strcpy(newprefix, prefix);
306 zoff99 31 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 zoff99 8 dump_hierarchy(boundary->children, newprefix);
312 zoff99 31 l = g_list_next(l);
313 zoff99 8 }
314     }
315    
316 zoff99 31 static gint boundary_bbox_compare(gconstpointer a, gconstpointer b)
317 zoff99 8 {
318 zoff99 31 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 zoff99 8 if (areaa > areab)
323     return 1;
324     if (areaa < areab)
325     return -1;
326     return 0;
327     }
328    
329 zoff99 31 static GList *
330     process_boundaries_insert(GList *list, struct boundary *boundary)
331 zoff99 8 {
332 zoff99 31 // 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 zoff99 8
357 zoff99 31 return g_list_prepend(list, boundary);
358     }
359 zoff99 8
360 zoff99 31 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 zoff99 8 }
396     }
397 zoff99 31 // 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 zoff99 8 bbox_extend(c, &boundary->r);
431 zoff99 31 }
432 zoff99 8 c++;
433 zoff99 31 nodes_counter_++;
434 zoff99 8 }
435 zoff99 31 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 zoff99 8 }
538 zoff99 31 #if 0
539 zoff99 8 printf("hierarchy\n");
540 zoff99 31 #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 zoff99 8 break;
566     }
567 zoff99 31 l2 = g_list_next(l2);
568 zoff99 8 }
569 zoff99 31 l = ln;
570 zoff99 8 }
571 zoff99 31 #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 zoff99 8 }
584 zoff99 31
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