4 static int distance_from_ll(struct coord *c, struct rect *bbox)
8 return dist+c->y-bbox->l.y;
9 dist+=bbox->h.y-bbox->l.y;
10 if (c->y == bbox->h.y)
11 return dist+c->x-bbox->l.x;
12 dist+=bbox->h.x-bbox->l.x;
13 if (c->x == bbox->h.x)
14 return dist+bbox->h.y-c->y;
15 dist+=bbox->h.y-bbox->l.y;
16 if (c->y == bbox->l.y)
17 return dist+bbox->h.x-c->x;
21 static struct geom_poly_segment *
22 find_next(struct rect *bbox, GList *segments, struct coord *c, int exclude, struct coord *ci)
24 int min=INT_MAX,search=distance_from_ll(c, bbox)+(exclude?1:0);
27 struct geom_poly_segment *ret=NULL;
30 for (i = 0 ; i < 2 ; i++) {
32 dbg(dbgl,"search distance %d\n",search);
34 struct geom_poly_segment *seg=curr->data;
35 int dist=distance_from_ll(seg->first, bbox);
36 dbg(dbgl,"0x%x 0x%x dist %d\n",seg->first->x,seg->first->y,dist);
37 if (dist != -1 && seg->first != seg->last && dist < min && (dist >= search)) {
43 curr=g_list_next(curr);
53 close_polygon(struct item_bin *ib, struct coord *from, struct coord *to, int dir, struct rect *bbox, int *edges)
55 int i,e,dist,fromdist,todist;
56 int full=(bbox->h.x-bbox->l.x+bbox->h.y-bbox->l.y)*2;
57 int corners=0,first_corner=0;
60 fromdist=distance_from_ll(from, bbox);
61 todist=distance_from_ll(to, bbox);
63 fromdist=distance_from_ll(to, bbox);
64 todist=distance_from_ll(from, bbox);
67 fprintf(stderr,"close_polygon fromdist %d todist %d full %d dir %d\n", fromdist, todist, full, dir);
69 if (fromdist > todist)
72 fprintf(stderr,"close_polygon corrected fromdist %d todist %d full %d dir %d\n", fromdist, todist, full, dir);
74 for (i = 0 ; i < 8 ; i++) {
95 dist=distance_from_ll(&c, bbox);
99 fprintf(stderr,"dist %d %d\n",e,dist);
101 if (dist > fromdist && dist < todist) {
102 item_bin_add_coord(ib, &c, 1);
104 fprintf(stderr,"add\n");
107 if (dist >= fromdist && dist <= todist) {
113 while (corners >= 2) {
114 *edges |= 1<<(first_corner%4);
120 struct coastline_tile_data {
121 struct item_bin_sink_func *sink;
122 GHashTable *tile_edges;
127 tile_data_to_segments(int *tile_data)
129 int *end=tile_data+tile_data[0];
130 int *curr=tile_data+1;
131 GList *segments=NULL;
135 struct item_bin *ib=(struct item_bin *)curr;
136 segments=g_list_prepend(segments,item_bin_to_poly_segment(ib, geom_poly_segment_type_way_right_side));
141 fprintf(stderr,"%d segments\n",count);
147 tile_collector_process_tile(char *tile, int *tile_data, struct coastline_tile_data *data)
149 int poly_start_valid,tile_start_valid,exclude,search=0,workload=0;
151 struct coord c,cn[2],end,poly_start,tile_start;
152 struct geom_poly_segment *first;
153 struct item_bin *ib=(struct item_bin *)buffer;
154 struct item_bin_sink *out=data->sink->priv_data[1];
157 GList *sorted_segments,*curr;
159 if (strncmp(tile,"bcdbdcabddddba",7))
163 if (strncmp(tile,"bcdbdcaaaaddba",14))
167 fprintf(stderr,"tile %s of size %d\n", tile, *tile_data);
169 tile_bbox(tile, &bbox, 0);
170 sorted_segments=geom_poly_segments_sort(tile_data_to_segments(tile_data), geom_poly_segment_type_way_right_side);
173 GList *sort_segments=sorted_segments;
175 while (sort_segments) {
176 struct geom_poly_segment *seg=sort_segments->data;
177 struct item_bin *ib=(struct item_bin *)buffer;
178 char *text=g_strdup_printf("segment %d type %d %p %s area %Ld",count++,seg->type,sort_segments,coord_is_equal(*seg->first, *seg->last) ? "closed":"open",geom_poly_area(seg->first,seg->last-seg->first+1));
179 item_bin_init(ib, type_rg_segment);
180 item_bin_add_coord(ib, seg->first, seg->last-seg->first+1);
181 item_bin_add_attr_string(ib, attr_debug, text);
182 // fprintf(stderr,"%s\n",text);
184 // item_bin_dump(ib, stderr);
185 item_bin_write_to_sink(ib, out, NULL);
186 sort_segments=g_list_next(sort_segments);
191 curr=sorted_segments;
193 struct geom_poly_segment *seg=curr->data;
195 case geom_poly_segment_type_way_inner:
198 case geom_poly_segment_type_way_outer:
205 curr=g_list_next(curr);
208 item_bin_init(ib, type_poly_water_tiled);
209 item_bin_bbox(ib, &bbox);
210 item_bin_write_to_sink(ib, out, NULL);
211 g_hash_table_insert(data->tile_edges, g_strdup(tile), (void *)15);
225 // item_bin_write_debug_point_to_sink(out, &end, "Search %d",search);
226 dbg(dbgl,"searching next polygon from 0x%x 0x%x\n",end.x,end.y);
227 first=find_next(&bbox, sorted_segments, &end, exclude, cn);
231 if (!tile_start_valid) {
235 if (cn[0].x == tile_start.x && cn[0].y == tile_start.y) {
236 dbg(dbgl,"end of tile reached\n");
240 if (first->type == geom_poly_segment_type_none) {
245 dbg(dbgl,"start of polygon 0x%x 0x%x\n",cn[0].x,cn[0].y);
247 if (!poly_start_valid) {
250 item_bin_init(ib,type_poly_water_tiled);
252 close_polygon(ib, &end, &cn[0], 1, &bbox, &edges);
253 if (cn[0].x == poly_start.x && cn[0].y == poly_start.y) {
254 dbg(dbgl,"poly end reached\n");
255 item_bin_write_to_sink(ib, out, NULL);
260 if (first->type == geom_poly_segment_type_none)
262 item_bin_add_coord(ib, first->first, first->last-first->first+1);
263 first->type=geom_poly_segment_type_none;
265 if (distance_from_ll(&end, &bbox) == -1) {
266 dbg(dbgl,"incomplete\n");
269 first=find_next(&bbox, sorted_segments, &end, 1, cn);
270 dbg(dbgl,"next segment of polygon 0x%x 0x%x\n",cn[0].x,cn[0].y);
279 int *end=tile_data+tile_data[0];
280 int *curr=tile_data+1;
282 struct item_bin *ib=(struct item_bin *)curr;
283 // item_bin_dump(ib);
284 ib->type=type_rg_segment;
285 item_bin_write_to_sink(ib, out, NULL);
292 c[0]=(struct coord *)(ib+1);
293 c[1]=c[0]+ib->clen/2-1;
294 for (i = 0 ; i < 2 ; i++) {
295 s=coord_to_str(c[i]);
296 item_bin_write_debug_point_to_sink(out, c[i], "%s",s);
305 g_hash_table_insert(data->tile_edges, g_strdup(tile), (void *)edges);
307 item_bin_init(ib, type_border_country);
308 item_bin_bbox(ib, &bbox);
309 item_bin_add_attr_string(ib, attr_debug, tile);
310 item_bin_write_to_sink(ib, out, NULL);
313 c.x=(bbox.l.x+bbox.h.x)/2;
314 c.y=(bbox.l.y+bbox.h.y)/2;
315 item_bin_write_debug_point_to_sink(out, &c, "%s %d",tile,edges);
320 ocean_tile(GHashTable *hash, char *tile, char c, struct item_bin_sink *out)
322 int len=strlen(tile);
325 struct item_bin *ib=(struct item_bin *)buffer;
330 //fprintf(stderr,"Testing %s\n",tile2);
331 if (g_hash_table_lookup_extended(hash, tile2, NULL, NULL))
333 //fprintf(stderr,"%s ok\n",tile2);
334 tile_bbox(tile2, &bbox, 0);
335 item_bin_init(ib,type_poly_water_tiled);
336 item_bin_bbox(ib, &bbox);
337 item_bin_write_to_sink(ib, out, NULL);
338 g_hash_table_insert(hash, g_strdup(tile2), (void *)15);
340 item_bin_init(ib, type_border_country);
341 item_bin_bbox(ib, &bbox);
342 item_bin_add_attr_string(ib, attr_debug, tile2);
343 item_bin_write_to_sink(ib, out, NULL);
345 co.x=(bbox.l.x+bbox.h.x)/2;
346 co.y=(bbox.l.y+bbox.h.y)/2;
347 //item_bin_write_debug_point_to_sink(out, &co, "%s 15",tile2);
355 tile_collector_add_siblings(char *tile, void *edgesp, struct coastline_tile_data *data)
357 int len=strlen(tile);
359 struct item_bin_sink *out=data->sink->priv_data[1];
360 int edges=(int)edgesp;
363 if (len != data->level)
366 if (!strncmp(tile,"bcacccaadbdcd",10))
370 fprintf(stderr,"%s (%c) has %d edges active\n",tile,t,edges);
371 if (t == 'a' && (edges & 1))
372 ocean_tile(data->tile_edges, tile, 'b', out);
373 if (t == 'a' && (edges & 8))
374 ocean_tile(data->tile_edges, tile, 'c', out);
375 if (t == 'b' && (edges & 4))
376 ocean_tile(data->tile_edges, tile, 'a', out);
377 if (t == 'b' && (edges & 8))
378 ocean_tile(data->tile_edges, tile, 'd', out);
379 if (t == 'c' && (edges & 1))
380 ocean_tile(data->tile_edges, tile, 'd', out);
381 if (t == 'c' && (edges & 2))
382 ocean_tile(data->tile_edges, tile, 'a', out);
383 if (t == 'd' && (edges & 4))
384 ocean_tile(data->tile_edges, tile, 'c', out);
385 if (t == 'd' && (edges & 2))
386 ocean_tile(data->tile_edges, tile, 'b', out);
390 tile_sibling_edges(GHashTable *hash, char *tile, char c)
392 int len=strlen(tile);
398 if (!g_hash_table_lookup_extended(hash, tile2, NULL, &data))
402 //fprintf(stderr,"checking '%s' with %d edges active\n",tile2,ret);
408 ocean_tile2(struct rect *r, int dx, int dy, int wf, int hf, struct item_bin_sink *out)
410 struct item_bin *ib=(struct item_bin *)buffer;
416 bbox.l.x=r->l.x+dx*w;
417 bbox.l.y=r->l.y+dy*h;
418 bbox.h.x=bbox.l.x+w*wf;
419 bbox.h.y=bbox.l.y+h*hf;
420 //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);
421 item_bin_init(ib,type_poly_water_tiled);
422 item_bin_bbox(ib, &bbox);
423 item_bin_write_to_sink(ib, out, NULL);
425 item_bin_init(ib, type_border_country);
426 item_bin_bbox(ib, &bbox);
427 item_bin_add_attr_string(ib, attr_debug, tile2);
428 item_bin_write_to_sink(ib, out, NULL);
430 tile(&bbox, NULL, tile2, 32, 0, NULL);
431 co.x=(bbox.l.x+bbox.h.x)/2;
432 co.y=(bbox.l.y+bbox.h.y)/2;
433 //item_bin_write_debug_point_to_sink(out, &co, "%s 15",tile2);
437 tile_collector_add_siblings2(char *tile, void *edgesp, struct coastline_tile_data *data)
439 int len=strlen(tile);
444 struct item_bin_sink *out=data->sink->priv_data[1];
446 int edges=(int)edgesp;
450 if (!strncmp(tile,"bcacccaadbdcd",10))
454 fprintf(stderr,"len of %s %d vs %d\n",tile,len,data->level);
455 if (len != data->level)
460 fprintf(stderr,"checking siblings of '%s' with %d edges active\n",tile,edges);
461 if (t == 'b' && (edges & 1) && (tile_sibling_edges(data->tile_edges, tile, 'd') & 1))
463 if (t == 'd' && (edges & 2) && (tile_sibling_edges(data->tile_edges, tile, 'b') & 1))
465 if (t == 'a' && (edges & 2) && (tile_sibling_edges(data->tile_edges, tile, 'b') & 2))
467 if (t == 'b' && (edges & 2) && (tile_sibling_edges(data->tile_edges, tile, 'a') & 2))
469 if (t == 'a' && (edges & 4) && (tile_sibling_edges(data->tile_edges, tile, 'c') & 4))
471 if (t == 'c' && (edges & 4) && (tile_sibling_edges(data->tile_edges, tile, 'a') & 4))
473 if (t == 'd' && (edges & 8) && (tile_sibling_edges(data->tile_edges, tile, 'c') & 8))
475 if (t == 'c' && (edges & 8) && (tile_sibling_edges(data->tile_edges, tile, 'd') & 8))
478 fprintf(stderr,"result '%s' %d old %d\n",tile2,pedges,(int)g_hash_table_lookup(data->tile_edges, tile2));
479 g_hash_table_insert(data->tile_edges, g_strdup(tile2), (void *)((int)g_hash_table_lookup(data->tile_edges, tile2)|pedges));
483 tile_collector_finish(struct item_bin_sink_func *tile_collector)
485 struct coastline_tile_data data;
487 data.sink=tile_collector;
488 data.tile_edges=g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
489 GHashTable *hash=tile_collector->priv_data[0];
490 fprintf(stderr,"tile_collector_finish\n");
491 g_hash_table_foreach(hash, tile_collector_process_tile, &data);
492 fprintf(stderr,"tile_collector_finish foreach done\n");
493 g_hash_table_destroy(hash);
494 fprintf(stderr,"tile_collector_finish destroy done\n");
495 for (i = 14 ; i > 0 ; i--) {
496 fprintf(stderr,"Level=%d\n",i);
498 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
500 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
502 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
504 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
506 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings2, &data);
507 fprintf(stderr,"*\n");
508 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings2, &data);
509 fprintf(stderr,"*\n");
510 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings2, &data);
511 fprintf(stderr,"*\n");
512 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings2, &data);
513 fprintf(stderr,"*\n");
517 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
518 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
519 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings2, &data);
521 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
522 g_hash_table_foreach(data.tile_edges, tile_collector_add_siblings, &data);
524 item_bin_sink_func_destroy(tile_collector);
525 fprintf(stderr,"tile_collector_finish done\n");
531 coastline_processor_process(struct item_bin_sink_func *func, struct item_bin *ib, struct tile_data *tile_data)
534 struct coord *c=(struct coord *)(ib+1);
536 for (i = 0 ; i < 19 ; i++) {
541 item_bin_write_clipped(ib, func->priv_data[0], func->priv_data[1]);
545 static struct item_bin_sink_func *
546 coastline_processor_new(struct item_bin_sink *out)
548 struct item_bin_sink_func *coastline_processor=item_bin_sink_func_new(coastline_processor_process);
549 struct item_bin_sink *tiles=item_bin_sink_new();
550 struct item_bin_sink_func *tile_collector=tile_collector_new(out);
551 struct tile_parameter *param=g_new0(struct tile_parameter, 1);
553 fprintf(stderr,"new:out=%p\n",out);
558 item_bin_sink_add_func(tiles, tile_collector);
559 coastline_processor->priv_data[0]=param;
560 coastline_processor->priv_data[1]=tiles;
561 coastline_processor->priv_data[2]=tile_collector;
562 return coastline_processor;
566 coastline_processor_finish(struct item_bin_sink_func *coastline_processor)
568 struct tile_parameter *param=coastline_processor->priv_data[0];
569 struct item_bin_sink *tiles=coastline_processor->priv_data[1];
570 struct item_bin_sink_func *tile_collector=coastline_processor->priv_data[2];
572 tile_collector_finish(tile_collector);
573 item_bin_sink_destroy(tiles);
574 item_bin_sink_func_destroy(coastline_processor);
578 process_coastlines(FILE *in, FILE *out)
580 struct item_bin_sink *reader=file_reader_new(in,1000000,0);
581 struct item_bin_sink_func *file_writer=file_writer_new(out);
582 struct item_bin_sink *result=item_bin_sink_new();
583 struct item_bin_sink_func *coastline_processor=coastline_processor_new(result);
584 item_bin_sink_add_func(reader, coastline_processor);
585 item_bin_sink_add_func(result, file_writer);
586 file_reader_finish(reader);
587 coastline_processor_finish(coastline_processor);
588 file_writer_finish(file_writer);
589 item_bin_sink_destroy(result);