5 geom_coord_copy(struct coord *from, struct coord *to, int count, int reverse)
9 memcpy(to, from, count*sizeof(struct coord));
13 for (i = 0 ; i < count ; i++)
18 geom_coord_revert(struct coord *c, int count)
23 for (i = 0 ; i < count/2 ; i++) {
32 geom_poly_area(struct coord *c, int count)
37 fprintf(stderr,"count=%d\n",count);
39 for (i=0; i<count; i++) {
43 fprintf(stderr,"(%d+%d)*(%d-%d)=%d*%d=%Ld\n",c[i].x,c[j].x,c[i].y,c[j].y,c[i].x+c[j].x,c[i].y-c[j].y,(long long)(c[i].x+c[j].x)*(c[i].y-c[j].y));
45 area+=(long long)(c[i].x+c[j].x)*(c[i].y-c[j].y);
47 fprintf(stderr,"area=%Ld\n",area);
54 geom_poly_segments_insert(GList *list, struct geom_poly_segment *first, struct geom_poly_segment *second, struct geom_poly_segment *third)
57 struct geom_poly_segment *ret;
62 ret=g_new(struct geom_poly_segment, 1);
63 ret->type=second->type;
64 count=(second->last-second->first)+1;
66 count+=(first->last-first->first);
68 count+=(third->last-third->first);
70 fprintf(stderr,"count=%d first=%p second=%p third=%p\n",count,first,second,third);
72 fprintf(stderr,"first:0x%x,0x%x-0x%x,0x%x (%d)\n",first->first->x,first->first->y,first->last->x,first->last->y, first->last-first->first+1);
74 fprintf(stderr,"second:0x%x,0x%x-0x%x,0x%x (%d)\n",second->first->x,second->first->y,second->last->x,second->last->y, second->last-second->first+1);
76 fprintf(stderr,"third:0x%x,0x%x-0x%x,0x%x (%d)\n",third->first->x,third->first->y,third->last->x,third->last->y, third->last-third->first+1);
78 ret->first=g_new(struct coord, count);
81 count=(first->last-first->first)+1;
82 geom_coord_copy(first->first, pos, count, coord_is_equal(*first->first, *second->first));
85 count=(second->last-second->first)+1;
86 geom_coord_copy(second->first, pos, count, 0);
90 count=(third->last-third->first)+1;
91 geom_coord_copy(third->first, pos, count, coord_is_equal(*third->last, *second->last));
96 fprintf(stderr,"result:0x%x,0x%x-0x%x,0x%x (%d)\n",ret->first->x,ret->first->y,ret->last->x,ret->last->y, ret->last-ret->first+1);
98 list=g_list_prepend(list, ret);
100 fprintf(stderr,"List=%p\n",list);
106 geom_poly_segment_destroy(struct geom_poly_segment *seg)
113 geom_poly_segments_remove(GList *list, struct geom_poly_segment *seg)
116 list=g_list_remove(list, seg);
117 geom_poly_segment_destroy(seg);
123 geom_poly_segment_compatible(struct geom_poly_segment *s1, struct geom_poly_segment *s2, int dir)
125 int same=0,opposite=0;
126 if (s1->type == geom_poly_segment_type_none || s2->type == geom_poly_segment_type_none)
128 if (s1->type == s2->type)
130 if (s1->type == geom_poly_segment_type_way_inner && s2->type == geom_poly_segment_type_way_outer)
132 if (s1->type == geom_poly_segment_type_way_outer && s2->type == geom_poly_segment_type_way_inner)
134 if (s1->type == geom_poly_segment_type_way_left_side && s2->type == geom_poly_segment_type_way_right_side)
136 if (s1->type == geom_poly_segment_type_way_right_side && s2->type == geom_poly_segment_type_way_left_side)
138 if (s1->type == geom_poly_segment_type_way_unknown || s2->type == geom_poly_segment_type_way_unknown) {
143 if ((opposite && coord_is_equal(*s1->first, *s2->first)) || (same && coord_is_equal(*s1->first, *s2->last)))
146 if ((opposite && coord_is_equal(*s1->last, *s2->last)) || (same && coord_is_equal(*s1->last, *s2->first)))
154 geom_poly_segments_sort(GList *in, enum geom_poly_segment_type type)
158 struct geom_poly_segment *seg=in->data;
160 struct geom_poly_segment *merge_first=NULL,*merge_last=NULL;
162 struct geom_poly_segment *cseg=tmp->data;
163 if (geom_poly_segment_compatible(seg, cseg, -1))
165 if (geom_poly_segment_compatible(seg, cseg, 1))
167 tmp=g_list_next(tmp);
169 if (merge_first == merge_last)
171 ret=geom_poly_segments_insert(ret, merge_first, seg, merge_last);
172 ret=geom_poly_segments_remove(ret, merge_first);
173 ret=geom_poly_segments_remove(ret, merge_last);
178 struct geom_poly_segment *seg=in->data;
179 if (coord_is_equal(*seg->first, *seg->last)) {
180 long long area=geom_poly_area(seg->first,seg->last-seg->first+1);
181 if (type == geom_poly_segment_type_way_right_side && seg->type == geom_poly_segment_type_way_right_side) {
182 seg->type=area > 0 ? geom_poly_segment_type_way_outer : geom_poly_segment_type_way_inner;
190 struct geom_poly_segment *
191 item_bin_to_poly_segment(struct item_bin *ib, int type)
193 struct geom_poly_segment *ret=g_new(struct geom_poly_segment, 1);
194 int count=ib->clen*sizeof(int)/sizeof(struct coord);
196 ret->first=g_new(struct coord, count);
197 ret->last=ret->first+count-1;
198 geom_coord_copy((struct coord *)(ib+1), ret->first, count, 0);
204 clipcode(struct coord *p, struct rect *r)
220 clip_line_code(struct coord *p1, struct coord *p2, struct rect *r)
222 int code1,code2,ret=1;
224 code1=clipcode(p1, r);
227 code2=clipcode(p2, r);
232 while (code1 || code2) {
236 p1->y+=(r->l.x-p1->x)*dy/dx;
238 } else if (code1 & 2) {
239 p1->y+=(r->h.x-p1->x)*dy/dx;
241 } else if (code1 & 4) {
242 p1->x+=(r->l.y-p1->y)*dx/dy;
244 } else if (code1 & 8) {
245 p1->x+=(r->h.y-p1->y)*dx/dy;
248 code1=clipcode(p1, r);
252 p2->y+=(r->l.x-p2->x)*dy/dx;
254 } else if (code2 & 2) {
255 p2->y+=(r->h.x-p2->x)*dy/dx;
257 } else if (code2 & 4) {
258 p2->x+=(r->l.y-p2->y)*dx/dy;
260 } else if (code2 & 8) {
261 p2->x+=(r->h.y-p2->y)*dx/dy;
264 code2=clipcode(p2, r);
266 if (p1->x == p2->x && p1->y == p2->y)
272 clip_line(struct item_bin *ib, struct rect *r, struct tile_parameter *param, struct item_bin_sink *out)
274 char buffer[ib->len*4+32];
275 struct item_bin *ib_new=(struct item_bin *)buffer;
276 struct coord *pa=(struct coord *)(ib+1);
277 int count=ib->clen/2;
280 item_bin_init(ib_new, ib->type);
281 for (i = 0 ; i < count ; i++) {
287 /* 0 = invisible, 1 = completely visible, 3 = start point clipped, 5 = end point clipped, 7 both points clipped */
288 code=clip_line_code(&p1, &p2, r);
290 if (((code == 1 || code == 5) && ib_new->clen == 0) || (code & 2)) {
291 item_bin_add_coord(ib_new, &p1, 1);
294 item_bin_add_coord(ib_new, &p2, 1);
296 if (i == count-1 || (code & 4)) {
298 item_bin_write_clipped(ib_new, param, out);
299 item_bin_init(ib_new, ib->type);
303 item_bin_init(ib_new, ib->type);
304 item_bin_add_coord(ib_new, &p1, 1);
305 item_bin_add_coord(ib_new, &p2, 1);
306 item_bin_write_clipped(ib_new, param, out);
314 is_inside(struct coord *p, struct rect *r, int edge)
318 return p->x >= r->l.x;
320 return p->x <= r->h.x;
322 return p->y >= r->l.y;
324 return p->y <= r->h.y;
331 poly_intersection(struct coord *p1, struct coord *p2, struct rect *r, int edge, struct coord *ret)
337 ret->y=p1->y+(r->l.x-p1->x)*dy/dx;
341 ret->y=p1->y+(r->h.x-p1->x)*dy/dx;
345 ret->x=p1->x+(r->l.y-p1->y)*dx/dy;
349 ret->x=p1->x+(r->h.y-p1->y)*dx/dy;
356 clip_polygon(struct item_bin *ib, struct rect *r, struct tile_parameter *param, struct item_bin_sink *out)
358 int count_in=ib->clen/2;
359 struct coord *pin,*p,*s,pi;
360 char buffer1[ib->len*4+ib->clen*7+32];
361 struct item_bin *ib1=(struct item_bin *)buffer1;
362 char buffer2[ib->len*4+ib->clen*7+32];
363 struct item_bin *ib2=(struct item_bin *)buffer2;
364 struct item_bin *ib_in,*ib_out;
368 for (edge = 0 ; edge < 4 ; edge++) {
369 count_in=ib_in->clen/2;
370 pin=(struct coord *)(ib_in+1);
373 item_bin_init(ib_out, ib_in->type);
374 for (i = 0 ; i < count_in ; i++) {
375 if (is_inside(p, r, edge)) {
376 if (! is_inside(s, r, edge)) {
377 poly_intersection(s,p,r,edge,&pi);
378 item_bin_add_coord(ib_out, &pi, 1);
380 item_bin_add_coord(ib_out, p, 1);
382 if (is_inside(s, r, edge)) {
383 poly_intersection(p,s,r,edge,&pi);
384 item_bin_add_coord(ib_out, &pi, 1);
399 item_bin_write_clipped(ib_in, param, out);