From 82d8c4f1b6b26bdf6ff2ea1cef4349856274404a Mon Sep 17 00:00:00 2001 From: lecoanet Date: Tue, 5 Nov 2002 09:26:09 +0000 Subject: Ajout de TestCCW et exportation de GetBezierPoints, BezierSubdivide devient priv�e. Le param�tre fan est ajout� � TRI_STRIP1. Suppression de holes et changement de gestion de cw qui est int�gr� au contour. --- generic/Geo.c | 129 ++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 76 insertions(+), 53 deletions(-) (limited to 'generic/Geo.c') diff --git a/generic/Geo.c b/generic/Geo.c index f91e7d2..2039e77 100644 --- a/generic/Geo.c +++ b/generic/Geo.c @@ -46,9 +46,6 @@ void POLY_INIT(ZnPoly *poly) { poly->num_contours = 0; - poly->contours = NULL; - poly->holes = NULL; - poly->cw = NULL; } void @@ -57,9 +54,6 @@ POLY_CONTOUR1(ZnPoly *poly, int num_pts) { poly->num_contours = 1; - poly->holes = &poly->hole1; - poly->hole1 = False; - poly->cw = &poly->cw1; poly->contours = &poly->contour1; poly->contour1.num_points = num_pts; poly->contour1.points = pts; @@ -79,8 +73,6 @@ POLY_SET(ZnPoly *poly1, else { poly1->num_contours = poly2->num_contours; poly1->contours = poly2->contours; - poly1->holes = poly2->holes; - poly1->cw = poly2->cw; } } @@ -95,29 +87,23 @@ POLY_FREE(ZnPoly *poly) if ((poly->contours != &poly->contour1) && (poly->num_contours > 1)) { ZnFree(poly->contours); - if (poly->holes) { - ZnFree(poly->holes); - } - if (poly->cw) { - ZnFree(poly->cw); - } } poly->num_contours = 0; poly->contours = NULL; - poly->holes = NULL; - poly->cw = NULL; } } void TRI_STRIP1(ZnTriStrip *tristrip, ZnPoint *pts, - int num_pts) + int num_pts, + ZnBool fan) { tristrip->num_strips = 1; tristrip->strips = &tristrip->strip1; tristrip->strip1.points = pts; tristrip->strip1.num_points = num_pts; + tristrip->strip1.fan = fan; } void @@ -544,6 +530,48 @@ LineInBBox(ZnPoint *p1, } +ZnBool +TestCCW(ZnPoint *points, + int num_points) +{ + ZnPoint *p, *p_p, *p_n, min; + ZnReal xprod; + int i, min_index; + + if (num_points < 3) { + return True; + } + + /* + * First find the lowest rightmost vertex. In X11 this is the + * topmost one. + */ + p = points; + min = *p; + min_index = 0; + for (i = 1, p++; i < num_points; i++, p++) { + if ((p->y < min.y) || + ((p->y == min.y) && (p->x > min.x))) { + min_index = i; + min = *p; + } + } + /* + * Then find the indices of the previous and next + * vertices. + */ + p = &points[min_index]; + /*printf("min index %d, prev %d, next %d\n", min_index, + (min_index+(num_points-1))%num_points, (min_index+1)%num_points);*/ + p_p = &points[(min_index+(num_points-1))%num_points]; /* min_index-1 */ + p_n = &points[(min_index+1)%num_points]; + xprod = ((p_p->x*p->y - p_p->y*p->x) + + (p_p->y*p_n->x - p_p->x*p_n->y) + + (p->x*p_n->y - p->y*p_n->x)); + return (xprod <= 0.0); /* Should be >= 0 but X11 has Y axis reverted. */ +} + + /* * ShiftLine -- * Given two points describing a line and a distance, return @@ -595,7 +623,7 @@ ShiftLine(ZnPoint *p1, dy_neg = False; } if ((dy < PRECISION_LIMIT) && (dx < PRECISION_LIMIT)) { - printf("ShiftLine: segment is a point\n"); + fprintf(stderr, "ShiftLine: segment is a point\n"); return; } @@ -1894,7 +1922,7 @@ Arc2Param(ZnPoint *controls, * ********************************************************************************** */ -void +static void BezierSubdivide(ZnPoint *controls, ZnReal t, ZnBool first) @@ -1938,8 +1966,11 @@ BezierSubdivide(ZnPoint *controls, * ********************************************************************************** */ -static void -GetBezierPoints(ZnPoint *controls, +void +GetBezierPoints(ZnPoint *p1, + ZnPoint *c1, + ZnPoint *c2, + ZnPoint *p2, ZnList to_points, double eps) { @@ -1947,44 +1978,40 @@ GetBezierPoints(ZnPoint *controls, ZnPoint mid_segm, mid_cord, delta; /* - * Compute distance between cord center and curve at t = 0.5 + * Compute distance between coord center and curve at t = 0.5 */ - mid_segm.x = (controls[0].x + 3*controls[1].x + 3*controls[2].x + controls[3].x) / 8.0; - mid_segm.y = (controls[0].y + 3*controls[1].y + 3*controls[2].y + controls[3].y) / 8.0; - mid_cord.x = (controls[0].x + controls[3].x) / 2.0; - mid_cord.y = (controls[0].y + controls[3].y) / 2.0; + mid_segm.x = (p1->x + 3*c1->x + 3*c2->x + p2->x) / 8.0; + mid_segm.y = (p1->y + 3*c1->y + 3*c2->y + p2->y) / 8.0; + mid_cord.x = (p1->x + p2->x) / 2.0; + mid_cord.y = (p1->y + p2->y) / 2.0; delta.x = mid_segm.x - mid_cord.x; delta.y = mid_segm.y - mid_cord.y; dist2 = delta.x*delta.x + delta.y*delta.y; if (dist2 > eps) { - ZnPoint new_controls[4]; + ZnPoint new_c1, new_c2; /* * Subdivide the curve at t = 0.5 * and compute each new curve. */ - new_controls[0] = controls[0]; - new_controls[1].x = (controls[0].x + controls[1].x) / 2.0; - new_controls[1].y = (controls[0].y + controls[1].y) / 2.0; - new_controls[2].x = (controls[0].x + 2*controls[1].x + controls[2].x) / 4.0; - new_controls[2].y = (controls[0].y + 2*controls[1].y + controls[2].y) / 4.0; - new_controls[3] = mid_segm; - GetBezierPoints(new_controls, to_points, eps); + new_c1.x = (p1->x + c1->x) / 2.0; + new_c1.y = (p1->y + c1->y) / 2.0; + new_c2.x = (p1->x + 2*c1->x + c2->x) / 4.0; + new_c2.y = (p1->y + 2*c1->y + c2->y) / 4.0; + GetBezierPoints(p1, &new_c1, &new_c2, &mid_segm, to_points, eps); - new_controls[0] = mid_segm; - new_controls[1].x = (controls[1].x + 2*controls[2].x + controls[3].x) / 4.0; - new_controls[1].y = (controls[1].y + 2*controls[2].y + controls[3].y) / 4.0; - new_controls[2].x = (controls[2].x + (controls[3].x)) / 2.0; - new_controls[2].y = (controls[2].y + (controls[3].y)) / 2.0; - new_controls[3] = controls[3]; - GetBezierPoints(new_controls, to_points, eps); + new_c1.x = (c1->x + 2*c2->x + p2->x) / 4.0; + new_c1.y = (c1->y + 2*c2->y + p2->y) / 4.0; + new_c2.x = (c2->x + (p2->x)) / 2.0; + new_c2.y = (c2->y + (p2->y)) / 2.0; + GetBezierPoints(&mid_segm, &new_c1, &new_c2, p2, to_points, eps); } else { /* * Flat enough add the end to the current path. * The start should already be there. */ - ZnListAdd(to_points, &controls[3], ZnListTail); + ZnListAdd(to_points, p2, ZnListTail); } } @@ -2009,20 +2036,19 @@ GetBezierPath(ZnList from_points, { ZnPoint *fp; int num_fp, i; - ZnPoint s[4]; - fp = (ZnPoint *) ZnListArray(from_points); + fp = ZnListArray(from_points); num_fp = ZnListSize(from_points); /* * make sure the output vector is empty, then add the first point. */ ZnListEmpty(to_points); - ZnListAdd(to_points, &fp[0], ZnListTail); + ZnListAdd(to_points, fp, ZnListTail); for (i = 0; i < num_fp; ) { if (i < (num_fp-3)) { - GetBezierPoints(fp, to_points, 1.0); + GetBezierPoints(fp, fp+1, fp+2, fp+3, to_points, 1.0); if (i < (num_fp-4)) { fp += 3; i += 3; @@ -2032,14 +2058,11 @@ GetBezierPath(ZnList from_points, } } else if (i == (num_fp-3)) { - s[0] = fp[0]; - s[1] = s[2] = fp[1]; - s[3] = fp[2]; - GetBezierPoints(s, to_points, 1.0); + GetBezierPoints(fp, fp+1, fp+1, fp+2, to_points, 1.0); break; } else if (i == (num_fp-2)) { - ZnListAdd(to_points, &fp[1], ZnListTail); + ZnListAdd(to_points, fp+1, ZnListTail); break; } } @@ -2466,7 +2489,7 @@ SmoothPathWithBezier(ZnPoint *fp, s[3].x = 0.5*fp[0].x + 0.5*fp[1].x; s[3].y = 0.5*fp[0].y + 0.5*fp[1].y; ZnListAdd(to_points, s, ZnListTail); - GetBezierPoints(s, to_points, 1.0); + GetBezierPoints(s, s+1, s+2, s+3, to_points, 1.0); } else { closed = False; @@ -2516,7 +2539,7 @@ SmoothPathWithBezier(ZnPoint *fp, ZnListAdd(to_points, &s[3], ZnListTail); } else { - GetBezierPoints(s, to_points, 1.0); + GetBezierPoints(s, s+1, s+2, s+3, to_points, 1.0); } } } -- cgit v1.1