aboutsummaryrefslogtreecommitdiff
path: root/generic/Geo.c
diff options
context:
space:
mode:
authorlecoanet2002-11-05 09:26:09 +0000
committerlecoanet2002-11-05 09:26:09 +0000
commit82d8c4f1b6b26bdf6ff2ea1cef4349856274404a (patch)
tree928ccd7bee821f70f71ecc9836398856bae400ba /generic/Geo.c
parent5e0ed72ae64be877c89bf8a73c9788866f76d3b8 (diff)
downloadtkzinc-82d8c4f1b6b26bdf6ff2ea1cef4349856274404a.zip
tkzinc-82d8c4f1b6b26bdf6ff2ea1cef4349856274404a.tar.gz
tkzinc-82d8c4f1b6b26bdf6ff2ea1cef4349856274404a.tar.bz2
tkzinc-82d8c4f1b6b26bdf6ff2ea1cef4349856274404a.tar.xz
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.
Diffstat (limited to 'generic/Geo.c')
-rw-r--r--generic/Geo.c129
1 files changed, 76 insertions, 53 deletions
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);
}
}
}