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

Diff of /navit/navit/maptool/boundaries.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 35 Revision 36
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA. 17 * Boston, MA 02110-1301, USA.
18 */ 18 */
19#include <stdio.h> 19#include <stdio.h>
20#include <string.h> 20#include <string.h>
21#include <ctype.h>
21#include "maptool.h" 22#include "maptool.h"
22 23
23struct boundary {
24 struct item_bin *ib;
25 GList *segments,*sorted_segments;
26 GList *children;
27 struct rect r;
28};
29 24
30struct boundary_member { 25char *
31 long long wayid; 26osm_tag_value(struct item_bin *ib, char *key)
32 enum geom_poly_segment_type role;
33 struct boundary *boundary;
34};
35
36static guint
37boundary_member_hash(gconstpointer key)
38{ 27{
39 const struct boundary_member *memb=key; 28 char *tag=NULL;
40 return (memb->wayid >> 32)^(memb->wayid & 0xffffffff); 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;
41} 35}
42
43static gboolean
44boundary_member_equal(gconstpointer a, gconstpointer b)
45{
46 const struct boundary_member *memba=a;
47 const struct boundary_member *membb=b;
48 return (memba->wayid == membb->wayid);
49}
50
51GHashTable *member_hash;
52 36
53static char * 37static char *
54osm_tag_name(struct item_bin *ib) 38osm_tag_name(struct item_bin *ib)
55{ 39{
56 char *tag=NULL; 40 return osm_tag_value(ib, "name");
57 while ((tag=item_bin_get_attr(ib, attr_osm_tag, tag))) { 41}
58 if (!strncmp(tag,"name=",5)) 42
59 return tag+5; 43long long *
60 } 44boundary_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;
61 return NULL; 54 return 0;
55}
56
57static void
58process_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));
62} 63}
63 64
64static GList * 65static GList *
65build_boundaries(FILE *boundaries) 66process_boundaries_setup(FILE *boundaries, struct relations *relations)
66{ 67{
67 struct item_bin *ib; 68 struct item_bin *ib;
68 GList *boundaries_list=NULL; 69 GList *boundaries_list=NULL;
70 struct relations_func *relations_func;
69 71
72 relations_func=relations_func_new(process_boundaries_member, NULL);
70 while ((ib=read_item(boundaries))) { 73 while ((ib=read_item(boundaries))) {
71 char *member=NULL; 74 char *member=NULL;
72 struct boundary *boundary=g_new0(struct boundary, 1); 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 }
73 while ((member=item_bin_get_attr(ib, attr_osm_member, member))) { 92 while ((member=item_bin_get_attr(ib, attr_osm_member, member))) {
74 long long wayid; 93 long long wayid;
75 int read=0; 94 int read=0;
76 if (sscanf(member,"2:%Ld:%n",&wayid,&read) >= 1) { 95 if (sscanf(member,"2:%Ld:%n",&wayid,&read) >= 1) {
77 struct boundary_member *memb=g_new(struct boundary_member, 1);
78 char *role=member+read; 96 char *rolestr=member+read;
79 memb->wayid=wayid; 97 enum geom_poly_segment_type role;
80 memb->boundary=boundary; 98 if (!strcmp(rolestr,"outer") || !strcmp(rolestr,"exclave"))
81 if (!strcmp(role,"outer"))
82 memb->role=geom_poly_segment_type_way_outer; 99 role=geom_poly_segment_type_way_outer;
83 else if (!strcmp(role,"inner")) 100 else if (!strcmp(rolestr,"inner") || !strcmp(rolestr,"enclave"))
84 memb->role=geom_poly_segment_type_way_inner; 101 role=geom_poly_segment_type_way_inner;
85 else if (!strcmp(role,"")) 102 else if (!strcmp(rolestr,""))
86 memb->role=geom_poly_segment_type_way_unknown; 103 role=geom_poly_segment_type_way_unknown;
87 else { 104 else {
88 printf("Unknown role %s\n",role); 105 osm_warning("relation",item_bin_get_relationid(ib),0,"Unknown role %s in member ",rolestr);
106 osm_warning("way",wayid,1,"\n");
89 memb->role=geom_poly_segment_type_none; 107 role=geom_poly_segment_type_none;
90 } 108 }
91 g_hash_table_insert(member_hash, memb, g_list_append(g_hash_table_lookup(member_hash, memb), memb)); 109 relations_add_func(relations, relations_func, boundary, (gpointer)role, 2, wayid);
92
93 } 110 }
94 } 111 }
95 boundary->ib=item_bin_dup(ib); 112 boundary->ib=item_bin_dup(ib);
96 boundaries_list=g_list_append(boundaries_list, boundary); 113 boundaries_list=g_list_append(boundaries_list, boundary);
97 } 114 }
98 return boundaries_list; 115 return boundaries_list;
99} 116}
100 117
101static void 118GList *
102find_matches(GList *l, struct coord *c) 119boundary_find_matches(GList *l, struct coord *c)
103{ 120{
121 GList *ret=NULL;
104 while (l) { 122 while (l) {
105 struct boundary *boundary=l->data; 123 struct boundary *boundary=l->data;
106 if (bbox_contains_coord(&boundary->r, c)) { 124 if (bbox_contains_coord(&boundary->r, c)) {
107 struct item_bin *ib=boundary->ib;
108 if (geom_poly_segments_point_inside(boundary->sorted_segments,c)) 125 if (geom_poly_segments_point_inside(boundary->sorted_segments,c) > 0)
109 printf("%s,",osm_tag_name(ib)); 126 ret=g_list_prepend(ret, boundary);
110 find_matches(boundary->children, c); 127 ret=g_list_concat(ret,boundary_find_matches(boundary->children, c));
111 } 128 }
112 l=g_list_next(l); 129 l=g_list_next(l);
113 } 130 }
131 return ret;
114} 132}
115 133
116static void 134static void
117test(GList *boundaries_list) 135test(GList *boundaries_list)
118{ 136{
121 printf("start\n"); 139 printf("start\n");
122 while ((ib=read_item(f))) { 140 while ((ib=read_item(f))) {
123 struct coord *c=(struct coord *)(ib+1); 141 struct coord *c=(struct coord *)(ib+1);
124 char *name=item_bin_get_attr(ib, attr_town_name, NULL); 142 char *name=item_bin_get_attr(ib, attr_town_name, NULL);
125 printf("%s:",name); 143 printf("%s:",name);
126 find_matches(boundaries_list, c); 144 boundary_find_matches(boundaries_list, c);
127 printf("\n"); 145 printf("\n");
128 } 146 }
129 fclose(f); 147 fclose(f);
130 printf("end\n"); 148 printf("end\n");
131} 149}
136 char *newprefix=g_alloca(sizeof(char)*(strlen(prefix)+2)); 154 char *newprefix=g_alloca(sizeof(char)*(strlen(prefix)+2));
137 strcpy(newprefix, prefix); 155 strcpy(newprefix, prefix);
138 strcat(newprefix," "); 156 strcat(newprefix," ");
139 while (l) { 157 while (l) {
140 struct boundary *boundary=l->data; 158 struct boundary *boundary=l->data;
141 printf("%s:%s\n",prefix,osm_tag_name(boundary->ib)); 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);
142 dump_hierarchy(boundary->children, newprefix); 160 dump_hierarchy(boundary->children, newprefix);
143 l=g_list_next(l); 161 l=g_list_next(l);
144 } 162 }
145} 163}
146 164
156 if (areaa < areab) 174 if (areaa < areab)
157 return -1; 175 return -1;
158 return 0; 176 return 0;
159} 177}
160 178
161int 179static GList *
162process_boundaries(FILE *boundaries, FILE *ways) 180process_boundaries_insert(GList *list, struct boundary *boundary)
163{ 181{
164 struct item_bin *ib; 182 GList *l=list;
165 GList *boundaries_list,*l,*sl,*l2,*ln;
166
167 member_hash=g_hash_table_new_full(boundary_member_hash, boundary_member_equal, NULL, NULL);
168 boundaries_list=build_boundaries(boundaries);
169 while ((ib=read_item(ways))) {
170 long long *wayid=item_bin_get_attr(ib, attr_osm_wayid, NULL);
171 if (wayid) {
172 GList *l=g_hash_table_lookup(member_hash, wayid);
173 while (l) { 183 while (l) {
174 struct boundary_member *memb=l->data; 184 struct boundary *b=l->data;
175 memb->boundary->segments=g_list_prepend(memb->boundary->segments,item_bin_to_poly_segment(ib, memb->role)); 185 if (bbox_contains_bbox(&boundary->r, &b->r)) {
176 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
177 l=g_list_next(l); 193 l=g_list_next(l);
178 }
179 } 194 }
180 } 195 return g_list_prepend(list, boundary);
196}
197
198
199static GList *
200process_boundaries_finish(GList *boundaries_list)
201{
202 GList *l,*sl,*l2,*ln;
203 GList *ret=NULL;
181 l=boundaries_list; 204 l=boundaries_list;
205 char *f1_name=NULL;
206 char *f2_name=NULL;
182 while (l) { 207 while (l)
208 {
183 struct boundary *boundary=l->data; 209 struct boundary *boundary=l->data;
184 int first=1; 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 }
185 boundary->sorted_segments=geom_poly_segments_sort(boundary->segments, geom_poly_segment_type_way_right_side); 230 boundary->sorted_segments=geom_poly_segments_sort(boundary->segments, geom_poly_segment_type_way_right_side);
186 sl=boundary->sorted_segments; 231 sl=boundary->sorted_segments;
187 while (sl) { 232 while (sl)
233 {
188 struct geom_poly_segment *gs=sl->data; 234 struct geom_poly_segment *gs=sl->data;
189 struct coord *c=gs->first; 235 struct coord *c=gs->first;
190 while (c <= gs->last) { 236 while (c <= gs->last) {
191 if (first) { 237 if (first) {
192 boundary->r.l=*c; 238 boundary->r.l=*c;
194 first=0; 240 first=0;
195 } else 241 } else
196 bbox_extend(c, &boundary->r); 242 bbox_extend(c, &boundary->r);
197 c++; 243 c++;
198 } 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 }
199 sl=g_list_next(sl); 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 }
200 } 277 }
278 ret=process_boundaries_insert(ret, boundary);
201 l=g_list_next(l); 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);
202 286 }
287
288 if (f1_name)
289 {
290 tempfile_unlink("",f1_name);
291 g_free(f1_name);
292 f1_name=NULL;
203 } 293 }
294 }
295#if 0
204 printf("hierarchy\n"); 296 printf("hierarchy\n");
297#endif
205 boundaries_list=g_list_sort(boundaries_list, boundary_bbox_compare); 298 boundaries_list=g_list_sort(boundaries_list, boundary_bbox_compare);
206 l=boundaries_list; 299 l=boundaries_list;
207 while (l) { 300 while (l) {
208 struct boundary *boundary=l->data; 301 struct boundary *boundary=l->data;
209 ln=l2=g_list_next(l); 302 ln=l2=g_list_next(l);
210 while (l2) { 303 while (l2) {
211 struct boundary *boundary2=l2->data; 304 struct boundary *boundary2=l2->data;
212 if (bbox_contains_bbox(&boundary2->r, &boundary->r)) { 305 if (bbox_contains_bbox(&boundary2->r, &boundary->r)) {
213 boundaries_list=g_list_remove(boundaries_list, boundary); 306 boundaries_list=g_list_remove(boundaries_list, boundary);
214 boundary2->children=g_list_append(boundary2->children, boundary); 307 boundary2->children=g_list_append(boundary2->children, boundary);
308#if 0
215 printf("found\n"); 309 printf("found\n");
310#endif
216 break; 311 break;
217 } 312 }
218 l2=g_list_next(l2); 313 l2=g_list_next(l2);
219 } 314 }
220 l=ln; 315 l=ln;
221 } 316 }
317 // dump_hierarchy(boundaries_list,""); --> make much data!! be careful
318#if 0
222 printf("hierarchy done\n"); 319 printf("hierarchy done\n");
223 dump_hierarchy(boundaries_list,"");
224 printf("test\n"); 320 printf("test\n");
225 test(boundaries_list); 321 test(boundaries_list);
226 return 1; 322#endif
323 return boundaries_list;
227} 324}
325
326GList *
327process_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

Legend:
Removed from v.35  
changed lines
  Added in v.36

   
Visit the ZANavi Wiki