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.
28 static int distance_from_ll(struct coord *c, struct rect *bbox)
31 if (c->x == bbox->l.x)
32 return dist+c->y-bbox->l.y;
33 dist+=bbox->h.y-bbox->l.y;
34 if (c->y == bbox->h.y)
35 return dist+c->x-bbox->l.x;
36 dist+=bbox->h.x-bbox->l.x;
37 if (c->x == bbox->h.x)
38 return dist+bbox->h.y-c->y;
39 dist+=bbox->h.y-bbox->l.y;
40 if (c->y == bbox->l.y)
41 return dist+bbox->h.x-c->x;
45 static struct geom_poly_segment *
46 find_next(struct rect *bbox, GList *segments, struct coord *c, int exclude, struct coord *ci)
48 int min=INT_MAX,search=distance_from_ll(c, bbox)+(exclude?1:0);
51 struct geom_poly_segment *ret=NULL;
54 for (i = 0 ; i < 2 ; i++) {
56 dbg(dbgl,"search distance %d\n",search);
58 struct geom_poly_segment *seg=curr->data;
59 int dist=distance_from_ll(seg->first, bbox);
60 dbg(dbgl,"0x%x 0x%x dist %d\n",seg->first->x,seg->first->y,dist);
61 if (dist != -1 && seg->first != seg->last && dist < min && (dist >= search)) {
67 curr=g_list_next(curr);
77 close_polygon(struct item_bin *ib, struct coord *from, struct coord *to, int dir, struct rect *bbox, int *edges)
79 int i,e,dist,fromdist,todist;
80 int full=(bbox->h.x-bbox->l.x+bbox->h.y-bbox->l.y)*2;
81 int corners=0,first_corner=0;
84 fromdist=distance_from_ll(from, bbox);
85 todist=distance_from_ll(to, bbox);
87 fromdist=distance_from_ll(to, bbox);
88 todist=distance_from_ll(from, bbox);
91 fprintf(stderr,"close_polygon fromdist %d todist %d full %d dir %d\n", fromdist, todist, full, dir);
93 if (fromdist > todist)
96 fprintf(stderr,"close_polygon corrected fromdist %d todist %d full %d dir %d\n", fromdist, todist, full, dir);
98 for (i = 0 ; i < 8 ; i++) {
119 dist=distance_from_ll(&c, bbox);
123 fprintf(stderr,"dist %d %d\n",e,dist);
125 if (dist > fromdist && dist < todist) {
126 item_bin_add_coord(ib, &c, 1);
128 fprintf(stderr,"add\n");
131 if (dist >= fromdist && dist <= todist) {
137 while (corners >= 2) {
138 *edges |= 1<<(first_corner%4);
144 struct coastline_tile_data {
145 struct item_bin_sink_func *sink;
146 GHashTable *tile_edges;
151 tile_data_to_segments(int *tile_data)
153 int *end=tile_data+tile_data[0];
154 int *curr=tile_data+1;
155 GList *segments=NULL;
159 struct item_bin *ib=(struct item_bin *)curr;
160 segments=g_list_prepend(segments,item_bin_to_poly_segment(ib, geom_poly_segment_type_way_right_side));
165 fprintf(stderr,"%d segments\n",count);
171 tile_collector_process_tile(char *tile, int *tile_data, struct coastline_tile_data *data)
173 int poly_start_valid,tile_start_valid,exclude,search=0;
175 struct coord cn[2],end,poly_start,tile_start;
176 struct geom_poly_segment *first;
177 struct item_bin *ib=NULL;
178 struct item_bin_sink *out=data->sink->priv_data[1];
181 GList *sorted_segments,*curr;
182 struct item_bin *ibt=(struct item_bin *)(tile_data+1);
183 struct coastline_tile *ct=g_new0(struct coastline_tile, 1);
184 ct->wayid=item_bin_get_wayid(ibt);
186 if (strncmp(tile,"bcdbdcabddddba",7))
190 if (strncmp(tile,"bcdbdcaaaaddba",14))
194 fprintf(stderr,"tile %s of size %d\n", tile, *tile_data);
196 tile_bbox(tile, &bbox, 0);
197 sorted_segments=geom_poly_segments_sort(tile_data_to_segments(tile_data), geom_poly_segment_type_way_right_side);
200 GList *sort_segments=sorted_segments;
202 while (sort_segments) {
203 struct geom_poly_segment *seg=sort_segments->data;
204 struct item_bin *ib=(struct item_bin *)buffer;
205 char *text=g_strdup_printf("segment %d type %d %p %s area "LONGLONG_FMT,count++,seg->type,sort_segments,coord_is_equal(*seg->first, *seg->last) ? "closed":"open",geom_poly_area(seg->first,seg->last-seg->first+1));
206 item_bin_init(ib, type_rg_segment);
207 item_bin_add_coord(ib, seg->first, seg->last-seg->first+1);
208 item_bin_add_attr_string(ib, attr_debug, text);
209 // fprintf(stderr,"%s\n",text);
211 // item_bin_dump(ib, stderr);
212 item_bin_write_to_sink(ib, out, NULL);
213 sort_segments=g_list_next(sort_segments);
218 curr=sorted_segments;
220 struct geom_poly_segment *seg=curr->data;
222 case geom_poly_segment_type_way_inner:
225 case geom_poly_segment_type_way_outer:
232 curr=g_list_next(curr);
236 ib=init_item(type_poly_water_tiled);
237 item_bin_bbox(ib, &bbox);
238 item_bin_add_attr_longlong(ib, attr_osm_wayid, ct->wayid);
239 item_bin_write_to_sink(ib, out, NULL);
240 g_hash_table_insert(data->tile_edges, g_strdup(tile), ct);
254 // item_bin_write_debug_point_to_sink(out, &end, "Search %d",search);
255 dbg(dbgl,"searching next polygon from 0x%x 0x%x\n",end.x,end.y);
256 first=find_next(&bbox, sorted_segments, &end, exclude, cn);
260 if (!tile_start_valid) {
264 if (cn[0].x == tile_start.x && cn[0].y == tile_start.y) {
265 dbg(dbgl,"end of tile reached\n");
269 if (first->type == geom_poly_segment_type_none) {
274 dbg(dbgl,"start of polygon 0x%x 0x%x\n",cn[0].x,cn[0].y);
276 if (!poly_start_valid) {
279 ib=init_item(type_poly_water_tiled);
281 close_polygon(ib, &end, &cn[0], 1, &bbox, &edges);
282 if (cn[0].x == poly_start.x && cn[0].y == poly_start.y) {
283 dbg(dbgl,"poly end reached\n");
284 item_bin_add_attr_longlong(ib, attr_osm_wayid, ct->wayid);
285 item_bin_write_to_sink(ib, out, NULL);
290 if (first->type == geom_poly_segment_type_none)
292 item_bin_add_coord(ib, first->first, first->last-first->first+1);
293 first->type=geom_poly_segment_type_none;
295 if (distance_from_ll(&end, &bbox) == -1) {
296 dbg(dbgl,"incomplete\n");
299 first=find_next(&bbox, sorted_segments, &end, 1, cn);
300 dbg(dbgl,"next segment of polygon 0x%x 0x%x\n",cn[0].x,cn[0].y);
309 int *end=tile_data+tile_data[0];
310 int *curr=tile_data+1;
312 struct item_bin *ib=(struct item_bin *)curr;
313 // item_bin_dump(ib);
314 ib->type=type_rg_segment;
315 item_bin_write_to_sink(ib, out, NULL);
322 c[0]=(struct coord *)(ib+1);
323 c[1]=c[0]+ib->clen/2-1;
324 for (i = 0 ; i < 2 ; i++) {
325 s=coord_to_str(c[i]);
326 item_bin_write_debug_point_to_sink(out, c[i], "%s",s);
336 g_hash_table_insert(data->tile_edges, g_strdup(tile), ct);
338 item_bin_init(ib, type_border_country);
339 item_bin_bbox(ib, &bbox);
340 item_bin_add_attr_string(ib, attr_debug, tile);
341 item_bin_write_to_sink(ib, out, NULL);
344 c.x=(bbox.l.x+bbox.h.x)/2;
345 c.y=(bbox.l.y+bbox.h.y)/2;
346 item_bin_write_debug_point_to_sink(out, &c, "%s %d",tile,edges);
351 ocean_tile(GHashTable *hash, char *tile, char c, osmid wayid, struct item_bin_sink *out)
353 int len=strlen(tile);
354 char *tile2=g_alloca(sizeof(char)*(len+1));
358 struct coastline_tile *ct=g_new0(struct coastline_tile, 1);
362 //fprintf(stderr,"Testing %s\n",tile2);
363 ct=g_hash_table_lookup(hash, tile2);
366 //fprintf(stderr,"%s ok\n",tile2);
367 tile_bbox(tile2, &bbox, 0);
368 ib=init_item(type_poly_water_tiled);
369 item_bin_bbox(ib, &bbox);
370 item_bin_add_attr_longlong(ib, attr_osm_wayid, wayid);
371 item_bin_write_to_sink(ib, out, NULL);
372 ct=g_new0(struct coastline_tile, 1);
375 g_hash_table_insert(hash, g_strdup(tile2), ct);
377 item_bin_init(ib, type_border_country);
378 item_bin_bbox(ib, &bbox);
379 item_bin_add_attr_string(ib, attr_debug, tile2);
380 item_bin_write_to_sink(ib, out, NULL);
382 co.x=(bbox.l.x+bbox.h.x)/2;
383 co.y=(bbox.l.y+bbox.h.y)/2;
384 //item_bin_write_debug_point_to_sink(out, &co, "%s 15",tile2);
392 tile_collector_add_siblings(char *tile, struct coastline_tile *ct, struct coastline_tile_data *data)
394 int len=strlen(tile);
396 struct item_bin_sink *out=data->sink->priv_data[1];
400 if (len != data->level)
403 if (!strncmp(tile,"bcacccaadbdcd",10))
407 fprintf(stderr,"%s (%c) has %d edges active\n",tile,t,edges);
408 if (t == 'a' && (edges & 1))
409 ocean_tile(data->tile_edges, tile, 'b', ct->wayid, out);
410 if (t == 'a' && (edges & 8))
411 ocean_tile(data->tile_edges, tile, 'c', ct->wayid, out);
412 if (t == 'b' && (edges & 4))
413 ocean_tile(data->tile_edges, tile, 'a', ct->wayid, out);
414 if (t == 'b' && (edges & 8))
415 ocean_tile(data->tile_edges, tile, 'd', ct->wayid, out);
416 if (t == 'c' && (edges & 1))
417 ocean_tile(data->tile_edges, tile, 'd', ct->wayid, out);
418 if (t == 'c' && (edges & 2))
419 ocean_tile(data->tile_edges, tile, 'a', ct->wayid, out);
420 if (t == 'd' && (edges & 4))
421 ocean_tile(data->tile_edges, tile, 'c', ct->wayid, out);
422 if (t == 'd' && (edges & 2))
423 ocean_tile(data->tile_edges, tile, 'b', ct->wayid, out);
427 tile_sibling_edges(GHashTable *hash, char *tile, char c)
429 int len=strlen(tile);
430 char *tile2=g_alloca(sizeof(char)*(len+1));
431 struct coastline_tile *ct;
434 ct=g_hash_table_lookup(hash, tile2);
441 ocean_tile2(struct rect *r, int dx, int dy, int wf, int hf, struct item_bin_sink *out)
449 bbox.l.x=r->l.x+dx*w;
450 bbox.l.y=r->l.y+dy*h;
451 bbox.h.x=bbox.l.x+w*wf;
452 bbox.h.y=bbox.l.y+h*hf;
453 //fprintf(stderr,"0x%x,0x%x-0x%x,0x%x -> 0x%x,0x%x-0x%x,0x%x\n",r->l.x,r->l.y,r->h.x,r->h.y,bbox.l.x,bbox.l.y,bbox.h.x,bbox.h.y);
454 ib=init_item(type_poly_water_tiled);
455 item_bin_bbox(ib, &bbox);
456 item_bin_write_to_sink(ib, out, NULL);
458 item_bin_init(ib, type_border_country);
459 item_bin_bbox(ib, &bbox);
460 item_bin_add_attr_string(ib, attr_debug, tile2);
461 item_bin_write_to_sink(ib, out, NULL);
463 tile(&bbox, NULL, tile2, 32, 0, NULL);
464 co.x=(bbox.l.x+bbox.h.x)/2;
465 co.y=(bbox.l.y+bbox.h.y)/2;
466 //item_bin_write_debug_point_to_sink(out, &co, "%s 15",tile2);
470 tile_collector_add_siblings2(char *tile, struct coastline_tile *ct, struct coastline_tile_data *data)
475 int len=strlen(tile);
476 char *tile2=g_alloca(sizeof(char)*(len+1));
480 struct coastline_tile *cn, *co;
482 if (!strncmp(tile,"bcacccaadbdcd",10))
486 fprintf(stderr,"len of %s %d vs %d\n",tile,len,data->level);
487 if (len != data->level)
492 fprintf(stderr,"checking siblings of '%s' with %d edges active\n",tile,edges);
493 if (t == 'b' && (edges & 1) && (tile_sibling_edges(data->tile_edges, tile, 'd') & 1))
495 if (t == 'd' && (edges & 2) && (tile_sibling_edges(data->tile_edges, tile, 'b') & 1))
497 if (t == 'a' && (edges & 2) && (tile_sibling_edges(data->tile_edges, tile, 'b') & 2))
499 if (t == 'b' && (edges & 2) && (tile_sibling_edges(data->tile_edges, tile, 'a') & 2))
501 if (t == 'a' && (edges & 4) && (tile_sibling_edges(data->tile_edges, tile, 'c') & 4))
503 if (t == 'c' && (edges & 4) && (tile_sibling_edges(data->tile_edges, tile, 'a') & 4))
505 if (t == 'd' && (edges & 8) && (tile_sibling_edges(data->tile_edges, tile, 'c') & 8))
507 if (t == 'c' && (edges & 8) && (tile_sibling_edges(data->tile_edges, tile, 'd') & 8))
509 co=g_hash_table_lookup(data->tile_edges, tile2);
511 fprintf(stderr,"result '%s' %d old %d\n",tile2,pedges,co?co->edges:0);
512 cn=g_new0(struct coastline_tile, 1);
515 cn->edges|=co->edges;
519 g_hash_table_insert(data->tile_edges, g_strdup(tile2), cn);
523 tile_collector_finish(struct item_bin_sink_func *tile_collector)
525 struct coastline_tile_data data;
528 data.sink=tile_collector;
529 data.tile_edges=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
530 hash=tile_collector->priv_data[0];
531 fprintf(stderr,"tile_collector_finish\n");
532 g_hash_table_foreach(hash, (GHFunc) tile_collector_process_tile, &data);
533 fprintf(stderr,"tile_collector_finish foreach done\n");
534 g_hash_table_destroy(hash);
535 fprintf(stderr,"tile_collector_finish destroy done\n");
536 for (i = 14 ; i > 0 ; i--) {
537 fprintf(stderr,"Level=%d\n",i);
539 g_hash_table_foreach(data.tile_edges, (GHFunc) tile_collector_add_siblings, &data);
541 g_hash_table_foreach(data.tile_edges, (GHFunc) tile_collector_add_siblings, &data);
543 g_hash_table_foreach(data.tile_edges, (GHFunc) tile_collector_add_siblings, &data);
545 g_hash_table_foreach(data.tile_edges, (GHFunc) tile_collector_add_siblings, &data);
547 g_hash_table_foreach(data.tile_edges, (GHFunc) tile_collector_add_siblings2, &data);
548 fprintf(stderr,"*\n");
549 g_hash_table_foreach(data.tile_edges, (GHFunc) tile_collector_add_siblings2, &data);
550 fprintf(stderr,"*\n");
551 g_hash_table_foreach(data.tile_edges, (GHFunc) tile_collector_add_siblings2, &data);
552 fprintf(stderr,"*\n");
553 g_hash_table_foreach(data.tile_edges, (GHFunc) tile_collector_add_siblings2, &data);
554 fprintf(stderr,"*\n");
558 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
559 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
560 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings2, &data);
562 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
563 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
565 item_bin_sink_func_destroy(tile_collector);
566 fprintf(stderr,"tile_collector_finish done\n");
572 coastline_processor_process(struct item_bin_sink_func *func, struct item_bin *ib, struct tile_data *tile_data)
576 struct coord *c=(struct coord *)(ib+1);
577 for (i = 0 ; i < 19 ; i++) {
582 item_bin_write_clipped(ib, func->priv_data[0], func->priv_data[1]);
586 static struct item_bin_sink_func *
587 coastline_processor_new(struct item_bin_sink *out)
589 struct item_bin_sink_func *coastline_processor=item_bin_sink_func_new(coastline_processor_process);
590 struct item_bin_sink *tiles=item_bin_sink_new();
591 struct item_bin_sink_func *tile_collector=tile_collector_new(out);
592 struct tile_parameter *param=g_new0(struct tile_parameter, 1);
597 param->attr_to_copy=attr_osm_wayid;
599 item_bin_sink_add_func(tiles, tile_collector);
600 coastline_processor->priv_data[0]=param;
601 coastline_processor->priv_data[1]=tiles;
602 coastline_processor->priv_data[2]=tile_collector;
603 return coastline_processor;
607 coastline_processor_finish(struct item_bin_sink_func *coastline_processor)
609 struct tile_parameter *param=coastline_processor->priv_data[0];
610 struct item_bin_sink *tiles=coastline_processor->priv_data[1];
611 struct item_bin_sink_func *tile_collector=coastline_processor->priv_data[2];
613 tile_collector_finish(tile_collector);
614 item_bin_sink_destroy(tiles);
615 item_bin_sink_func_destroy(coastline_processor);
619 process_coastlines(FILE *in, FILE *out)
621 struct item_bin_sink *reader=file_reader_new(in,1000000,0);
622 struct item_bin_sink_func *file_writer=file_writer_new(out);
623 struct item_bin_sink *result=item_bin_sink_new();
624 struct item_bin_sink_func *coastline_processor=coastline_processor_new(result);
625 item_bin_sink_add_func(reader, coastline_processor);
626 item_bin_sink_add_func(result, file_writer);
627 file_reader_finish(reader);
628 coastline_processor_finish(coastline_processor);
629 file_writer_finish(file_writer);
630 item_bin_sink_destroy(result);