?? tktrig.c
字號:
* Side effects: * None. * *-------------------------------------------------------------- */voidTkBezierPoints(control, numSteps, coordPtr) double control[]; /* Array of coordinates for four * control points: x0, y0, x1, y1, * ... x3 y3. */ int numSteps; /* Number of curve points to * generate. */ register double *coordPtr; /* Where to put new points. */{ int i; double u, u2, u3, t, t2, t3; for (i = 1; i <= numSteps; i++, coordPtr += 2) { t = ((double) i)/((double) numSteps); t2 = t*t; t3 = t2*t; u = 1.0 - t; u2 = u*u; u3 = u2*u; coordPtr[0] = control[0]*u3 + 3.0 * (control[2]*t*u2 + control[4]*t2*u) + control[6]*t3; coordPtr[1] = control[1]*u3 + 3.0 * (control[3]*t*u2 + control[5]*t2*u) + control[7]*t3; }}/* *-------------------------------------------------------------- * * TkMakeBezierCurve -- * * Given a set of points, create a new set of points that fit * parabolic splines to the line segments connecting the original * points. Produces output points in either of two forms. * * Note: in spite of this procedure's name, it does *not* generate * Bezier curves. Since only three control points are used for * each curve segment, not four, the curves are actually just * parabolic. * * Results: * Either or both of the xPoints or dblPoints arrays are filled * in. The return value is the number of points placed in the * arrays. Note: if the first and last points are the same, then * a closed curve is generated. * * Side effects: * None. * *-------------------------------------------------------------- */intTkMakeBezierCurve(canvas, pointPtr, numPoints, numSteps, xPoints, dblPoints) Tk_Canvas canvas; /* Canvas in which curve is to be * drawn. */ double *pointPtr; /* Array of input coordinates: x0, * y0, x1, y1, etc.. */ int numPoints; /* Number of points at pointPtr. */ int numSteps; /* Number of steps to use for each * spline segments (determines * smoothness of curve). */ XPoint xPoints[]; /* Array of XPoints to fill in (e.g. * for display. NULL means don't * fill in any XPoints. */ double dblPoints[]; /* Array of points to fill in as * doubles, in the form x0, y0, * x1, y1, .... NULL means don't * fill in anything in this form. * Caller must make sure that this * array has enough space. */{ int closed, outputPoints, i; int numCoords = numPoints*2; double control[8]; /* * If the curve is a closed one then generate a special spline * that spans the last points and the first ones. Otherwise * just put the first point into the output. */ outputPoints = 0; if ((pointPtr[0] == pointPtr[numCoords-2]) && (pointPtr[1] == pointPtr[numCoords-1])) { closed = 1; control[0] = 0.5*pointPtr[numCoords-4] + 0.5*pointPtr[0]; control[1] = 0.5*pointPtr[numCoords-3] + 0.5*pointPtr[1]; control[2] = 0.167*pointPtr[numCoords-4] + 0.833*pointPtr[0]; control[3] = 0.167*pointPtr[numCoords-3] + 0.833*pointPtr[1]; control[4] = 0.833*pointPtr[0] + 0.167*pointPtr[2]; control[5] = 0.833*pointPtr[1] + 0.167*pointPtr[3]; control[6] = 0.5*pointPtr[0] + 0.5*pointPtr[2]; control[7] = 0.5*pointPtr[1] + 0.5*pointPtr[3]; if (xPoints != NULL) { Tk_CanvasDrawableCoords(canvas, control[0], control[1], &xPoints->x, &xPoints->y); TkBezierScreenPoints(canvas, control, numSteps, xPoints+1); xPoints += numSteps+1; } if (dblPoints != NULL) { dblPoints[0] = control[0]; dblPoints[1] = control[1]; TkBezierPoints(control, numSteps, dblPoints+2); dblPoints += 2*(numSteps+1); } outputPoints += numSteps+1; } else { closed = 0; if (xPoints != NULL) { Tk_CanvasDrawableCoords(canvas, pointPtr[0], pointPtr[1], &xPoints->x, &xPoints->y); xPoints += 1; } if (dblPoints != NULL) { dblPoints[0] = pointPtr[0]; dblPoints[1] = pointPtr[1]; dblPoints += 2; } outputPoints += 1; } for (i = 2; i < numPoints; i++, pointPtr += 2) { /* * Set up the first two control points. This is done * differently for the first spline of an open curve * than for other cases. */ if ((i == 2) && !closed) { control[0] = pointPtr[0]; control[1] = pointPtr[1]; control[2] = 0.333*pointPtr[0] + 0.667*pointPtr[2]; control[3] = 0.333*pointPtr[1] + 0.667*pointPtr[3]; } else { control[0] = 0.5*pointPtr[0] + 0.5*pointPtr[2]; control[1] = 0.5*pointPtr[1] + 0.5*pointPtr[3]; control[2] = 0.167*pointPtr[0] + 0.833*pointPtr[2]; control[3] = 0.167*pointPtr[1] + 0.833*pointPtr[3]; } /* * Set up the last two control points. This is done * differently for the last spline of an open curve * than for other cases. */ if ((i == (numPoints-1)) && !closed) { control[4] = .667*pointPtr[2] + .333*pointPtr[4]; control[5] = .667*pointPtr[3] + .333*pointPtr[5]; control[6] = pointPtr[4]; control[7] = pointPtr[5]; } else { control[4] = .833*pointPtr[2] + .167*pointPtr[4]; control[5] = .833*pointPtr[3] + .167*pointPtr[5]; control[6] = 0.5*pointPtr[2] + 0.5*pointPtr[4]; control[7] = 0.5*pointPtr[3] + 0.5*pointPtr[5]; } /* * If the first two points coincide, or if the last * two points coincide, then generate a single * straight-line segment by outputting the last control * point. */ if (((pointPtr[0] == pointPtr[2]) && (pointPtr[1] == pointPtr[3])) || ((pointPtr[2] == pointPtr[4]) && (pointPtr[3] == pointPtr[5]))) { if (xPoints != NULL) { Tk_CanvasDrawableCoords(canvas, control[6], control[7], &xPoints[0].x, &xPoints[0].y); xPoints++; } if (dblPoints != NULL) { dblPoints[0] = control[6]; dblPoints[1] = control[7]; dblPoints += 2; } outputPoints += 1; continue; } /* * Generate a Bezier spline using the control points. */ if (xPoints != NULL) { TkBezierScreenPoints(canvas, control, numSteps, xPoints); xPoints += numSteps; } if (dblPoints != NULL) { TkBezierPoints(control, numSteps, dblPoints); dblPoints += 2*numSteps; } outputPoints += numSteps; } return outputPoints;}/* *-------------------------------------------------------------- * * TkMakeBezierPostscript -- * * This procedure generates Postscript commands that create * a path corresponding to a given Bezier curve. * * Results: * None. Postscript commands to generate the path are appended * to interp->result. * * Side effects: * None. * *-------------------------------------------------------------- */voidTkMakeBezierPostscript(interp, canvas, pointPtr, numPoints) Tcl_Interp *interp; /* Interpreter in whose result the * Postscript is to be stored. */ Tk_Canvas canvas; /* Canvas widget for which the * Postscript is being generated. */ double *pointPtr; /* Array of input coordinates: x0, * y0, x1, y1, etc.. */ int numPoints; /* Number of points at pointPtr. */{ int closed, i; int numCoords = numPoints*2; double control[8]; char buffer[200]; /* * If the curve is a closed one then generate a special spline * that spans the last points and the first ones. Otherwise * just put the first point into the path. */ if ((pointPtr[0] == pointPtr[numCoords-2]) && (pointPtr[1] == pointPtr[numCoords-1])) { closed = 1; control[0] = 0.5*pointPtr[numCoords-4] + 0.5*pointPtr[0]; control[1] = 0.5*pointPtr[numCoords-3] + 0.5*pointPtr[1]; control[2] = 0.167*pointPtr[numCoords-4] + 0.833*pointPtr[0]; control[3] = 0.167*pointPtr[numCoords-3] + 0.833*pointPtr[1]; control[4] = 0.833*pointPtr[0] + 0.167*pointPtr[2]; control[5] = 0.833*pointPtr[1] + 0.167*pointPtr[3]; control[6] = 0.5*pointPtr[0] + 0.5*pointPtr[2]; control[7] = 0.5*pointPtr[1] + 0.5*pointPtr[3]; sprintf(buffer, "%.15g %.15g moveto\n%.15g %.15g %.15g %.15g %.15g %.15g curveto\n", control[0], Tk_CanvasPsY(canvas, control[1]), control[2], Tk_CanvasPsY(canvas, control[3]), control[4], Tk_CanvasPsY(canvas, control[5]), control[6], Tk_CanvasPsY(canvas, control[7])); } else { closed = 0; control[6] = pointPtr[0]; control[7] = pointPtr[1]; sprintf(buffer, "%.15g %.15g moveto\n", control[6], Tk_CanvasPsY(canvas, control[7])); } Tcl_AppendResult(interp, buffer, (char *) NULL); /* * Cycle through all the remaining points in the curve, generating * a curve section for each vertex in the linear path. */ for (i = numPoints-2, pointPtr += 2; i > 0; i--, pointPtr += 2) { control[2] = 0.333*control[6] + 0.667*pointPtr[0]; control[3] = 0.333*control[7] + 0.667*pointPtr[1]; /* * Set up the last two control points. This is done * differently for the last spline of an open curve * than for other cases. */ if ((i == 1) && !closed) { control[6] = pointPtr[2]; control[7] = pointPtr[3]; } else { control[6] = 0.5*pointPtr[0] + 0.5*pointPtr[2]; control[7] = 0.5*pointPtr[1] + 0.5*pointPtr[3]; } control[4] = 0.333*control[6] + 0.667*pointPtr[0]; control[5] = 0.333*control[7] + 0.667*pointPtr[1]; sprintf(buffer, "%.15g %.15g %.15g %.15g %.15g %.15g curveto\n", control[2], Tk_CanvasPsY(canvas, control[3]), control[4], Tk_CanvasPsY(canvas, control[5]), control[6], Tk_CanvasPsY(canvas, control[7])); Tcl_AppendResult(interp, buffer, (char *) NULL); }}/* *-------------------------------------------------------------- * * TkGetMiterPoints -- * * Given three points forming an angle, compute the * coordinates of the inside and outside points of * the mitered corner formed by a line of a given * width at that angle. * * Results: * If the angle formed by the three points is less than * 11 degrees then 0 is returned and m1 and m2 aren't * modified. Otherwise 1 is returned and the points at * m1 and m2 are filled in with the positions of the points * of the mitered corner. * * Side effects: * None. * *-------------------------------------------------------------- */intTkGetMiterPoints(p1, p2, p3, width, m1, m2) double p1[]; /* Points to x- and y-coordinates of point * before vertex. */ double p2[]; /* Points to x- and y-coordinates of vertex * for mitered joint. */ double p3[]; /* Points to x- and y-coordinates of point * after vertex. */ double width; /* Width of line. */ double m1[]; /* Points to place to put "left" vertex * point (see as you face from p1 to p2). */ double m2[]; /* Points to place to put "right" vertex * point. */{ double theta1; /* Angle of segment p2-p1. */ double theta2; /* Angle of segment p2-p3. */ double theta; /* Angle between line segments (angle * of joint). */ double theta3; /* Angle that bisects theta1 and * theta2 and points to m1. */ double dist; /* Distance of miter points from p2. */ double deltaX, deltaY; /* X and y offsets cooresponding to * dist (fudge factors for bounding * box). */ double p1x, p1y, p2x, p2y, p3x, p3y; static double elevenDegrees = (11.0*2.0*PI)/360.0; /* * Round the coordinates to integers to mimic what happens when the * line segments are displayed; without this code, the bounding box * of a mitered line can be miscomputed greatly. */ p1x = floor(p1[0]+0.5); p1y = floor(p1[1]+0.5); p2x = floor(p2[0]+0.5); p2y = floor(p2[1]+0.5); p3x = floor(p3[0]+0.5); p3y = floor(p3[1]+0.5); if (p2y == p1y) { theta1 = (p2x < p1x) ? 0 : PI; } else if (p2x == p1x) { theta1 = (p2y < p1y) ? PI/2.0 : -PI/2.0; } else { theta1 = atan2(p1y - p2y, p1x - p2x); } if (p3y == p2y) { theta2 = (p3x > p2x) ? 0 : PI; } else if (p3x == p2x) { theta2 = (p3y > p2y) ? PI/2.0 : -PI/2.0; } else { theta2 = atan2(p3y - p2y, p3x - p2x); } theta = theta1 - theta2; if (theta > PI) { theta -= 2*PI; } else if (theta < -PI) { theta += 2*PI; } if ((theta < elevenDegrees) && (theta > -elevenDegrees)) { return 0; } dist = 0.5*width/sin(0.5*theta); if (dist < 0.0) { dist = -dist; } /* * Compute theta3 (make sure that it points to the left when * looking from p1 to p2). */ theta3 = (theta1 + theta2)/2.0; if (sin(theta3 - (theta1 + PI)) < 0.0) { theta3 += PI; } deltaX = dist*cos(theta3); m1[0] = p2x + deltaX; m2[0] = p2x - deltaX; deltaY = dist*sin(theta3); m1[1] = p2y + deltaY; m2[1] = p2y - deltaY; return 1;}/* *-------------------------------------------------------------- * * TkGetButtPoints -- * * Given two points forming a line segment, compute the * coordinates of two endpoints of a rectangle formed by * bloating the line segment until it is width units wide. * * Results: * There is no return value. M1 and m2 are filled in to * correspond to m1 and m2 in the diagram below: * * ----------------* m1 * | * p1 *---------------* p2 * | * ----------------* m2 * * M1 and m2 will be W units apart, with p2 centered between * them and m1-m2 perpendicular to p1-p2. However, if * "project" is true then m1 and m2 will be as follows: * * -------------------* m1 * p2 | * p1 *---------------* | * | * -------------------* m2 * * In this case p2 will be width/2 units from the segment m1-m2. * * Side effects: * None. * *-------------------------------------------------------------- */voidTkGetButtPoints(p1, p2, width, project, m1, m2) double p1[]; /* Points to x- and y-coordinates of point * before vertex. */ double p2[]; /* Points to x- and y-coordinates of vertex * for mitered joint. */ double width; /* Width of line. */ int project; /* Non-zero means project p2 by an additional * width/2 before computing m1 and m2. */ double m1[]; /* Points to place to put "left" result * point, as you face from p1 to p2. */ double m2[]; /* Points to place to put "right" result * point. */{ double length; /* Length of p1-p2 segment. */ double deltaX, deltaY; /* Increments in coords. */ width *= 0.5; length = hypot(p2[0] - p1[0], p2[1] - p1[1]); if (length == 0.0) { m1[0] = m2[0] = p2[0]; m1[1] = m2[1] = p2[1]; } else { deltaX = -width * (p2[1] - p1[1]) / length; deltaY = width * (p2[0] - p1[0]) / length; m1[0] = p2[0] + deltaX; m2[0] = p2[0] - deltaX; m1[1] = p2[1] + deltaY; m2[1] = p2[1] - deltaY; if (project) { m1[0] += deltaY; m2[0] += deltaY; m1[1] -= deltaX; m2[1] -= deltaX; } }}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -