📄 tkcanvarc.c
字号:
angle = atan2(boxWidth*sin1, boxHeight*cos1); } corner1[0] = arcPtr->center1[0] + cos(angle)*halfWidth; corner1[1] = arcPtr->center1[1] + sin(angle)*halfWidth; if (((boxWidth*sin2) == 0.0) && ((boxHeight*cos2) == 0.0)) { angle = 0.0; } else { angle = atan2(boxWidth*sin2, boxHeight*cos2); } corner2[0] = arcPtr->center2[0] + cos(angle)*halfWidth; corner2[1] = arcPtr->center2[1] + sin(angle)*halfWidth; /* * For a chord outline, generate a six-sided polygon with three * points for each end of the chord. The first and third points * for each end are butt points generated on either side of the * center point. The second point is the corner point. */ if (arcPtr->style == chordUid) { outlinePtr[0] = outlinePtr[12] = corner1[0]; outlinePtr[1] = outlinePtr[13] = corner1[1]; TkGetButtPoints(arcPtr->center2, arcPtr->center1, (double) arcPtr->width, 0, outlinePtr+10, outlinePtr+2); outlinePtr[4] = arcPtr->center2[0] + outlinePtr[2] - arcPtr->center1[0]; outlinePtr[5] = arcPtr->center2[1] + outlinePtr[3] - arcPtr->center1[1]; outlinePtr[6] = corner2[0]; outlinePtr[7] = corner2[1]; outlinePtr[8] = arcPtr->center2[0] + outlinePtr[10] - arcPtr->center1[0]; outlinePtr[9] = arcPtr->center2[1] + outlinePtr[11] - arcPtr->center1[1]; } else if (arcPtr->style == pieSliceUid) { /* * For pie slices, generate two polygons, one for each side * of the pie slice. The first arm has a shape like this, * where the center of the oval is X, arcPtr->center1 is at Y, and * corner1 is at Z: * * _____________________ * | \ * | \ * X Y Z * | / * |_____________________/ * */ TkGetButtPoints(arcPtr->center1, vertex, (double) arcPtr->width, 0, outlinePtr, outlinePtr+2); outlinePtr[4] = arcPtr->center1[0] + outlinePtr[2] - vertex[0]; outlinePtr[5] = arcPtr->center1[1] + outlinePtr[3] - vertex[1]; outlinePtr[6] = corner1[0]; outlinePtr[7] = corner1[1]; outlinePtr[8] = arcPtr->center1[0] + outlinePtr[0] - vertex[0]; outlinePtr[9] = arcPtr->center1[1] + outlinePtr[1] - vertex[1]; outlinePtr[10] = outlinePtr[0]; outlinePtr[11] = outlinePtr[1]; /* * The second arm has a shape like this: * * * ______________________ * / \ * / \ * Z Y X / * \ / * \______________________/ * * Similar to above X is the center of the oval/circle, Y is * arcPtr->center2, and Z is corner2. The extra jog out to the left * of X is needed in or to produce a butted joint with the * first arm; the corner to the right of X is one of the * first two points of the first arm, depending on extent. */ TkGetButtPoints(arcPtr->center2, vertex, (double) arcPtr->width, 0, outlinePtr+12, outlinePtr+16); if ((arcPtr->extent > 180) || ((arcPtr->extent < 0) && (arcPtr->extent > -180))) { outlinePtr[14] = outlinePtr[0]; outlinePtr[15] = outlinePtr[1]; } else { outlinePtr[14] = outlinePtr[2]; outlinePtr[15] = outlinePtr[3]; } outlinePtr[18] = arcPtr->center2[0] + outlinePtr[16] - vertex[0]; outlinePtr[19] = arcPtr->center2[1] + outlinePtr[17] - vertex[1]; outlinePtr[20] = corner2[0]; outlinePtr[21] = corner2[1]; outlinePtr[22] = arcPtr->center2[0] + outlinePtr[12] - vertex[0]; outlinePtr[23] = arcPtr->center2[1] + outlinePtr[13] - vertex[1]; outlinePtr[24] = outlinePtr[12]; outlinePtr[25] = outlinePtr[13]; }}/* *-------------------------------------------------------------- * * HorizLineToArc -- * * Determines whether a horizontal line segment intersects * a given arc. * * Results: * The return value is 1 if the given line intersects the * infinitely-thin arc section defined by rx, ry, start, * and extent, and 0 otherwise. Only the perimeter of the * arc is checked: interior areas (e.g. pie-slice or chord) * are not checked. * * Side effects: * None. * *-------------------------------------------------------------- */static intHorizLineToArc(x1, x2, y, rx, ry, start, extent) double x1, x2; /* X-coords of endpoints of line segment. * X1 must be <= x2. */ double y; /* Y-coordinate of line segment. */ double rx, ry; /* These x- and y-radii define an oval * centered at the origin. */ double start, extent; /* Angles that define extent of arc, in * the standard fashion for this module. */{ double tmp; double tx, ty; /* Coordinates of intersection point in * transformed coordinate system. */ double x; /* * Compute the x-coordinate of one possible intersection point * between the arc and the line. Use a transformed coordinate * system where the oval is a unit circle centered at the origin. * Then scale back to get actual x-coordinate. */ ty = y/ry; tmp = 1 - ty*ty; if (tmp < 0) { return 0; } tx = sqrt(tmp); x = tx*rx; /* * Test both intersection points. */ if ((x >= x1) && (x <= x2) && AngleInRange(tx, ty, start, extent)) { return 1; } if ((-x >= x1) && (-x <= x2) && AngleInRange(-tx, ty, start, extent)) { return 1; } return 0;}/* *-------------------------------------------------------------- * * VertLineToArc -- * * Determines whether a vertical line segment intersects * a given arc. * * Results: * The return value is 1 if the given line intersects the * infinitely-thin arc section defined by rx, ry, start, * and extent, and 0 otherwise. Only the perimeter of the * arc is checked: interior areas (e.g. pie-slice or chord) * are not checked. * * Side effects: * None. * *-------------------------------------------------------------- */static intVertLineToArc(x, y1, y2, rx, ry, start, extent) double x; /* X-coordinate of line segment. */ double y1, y2; /* Y-coords of endpoints of line segment. * Y1 must be <= y2. */ double rx, ry; /* These x- and y-radii define an oval * centered at the origin. */ double start, extent; /* Angles that define extent of arc, in * the standard fashion for this module. */{ double tmp; double tx, ty; /* Coordinates of intersection point in * transformed coordinate system. */ double y; /* * Compute the y-coordinate of one possible intersection point * between the arc and the line. Use a transformed coordinate * system where the oval is a unit circle centered at the origin. * Then scale back to get actual y-coordinate. */ tx = x/rx; tmp = 1 - tx*tx; if (tmp < 0) { return 0; } ty = sqrt(tmp); y = ty*ry; /* * Test both intersection points. */ if ((y > y1) && (y < y2) && AngleInRange(tx, ty, start, extent)) { return 1; } if ((-y > y1) && (-y < y2) && AngleInRange(tx, -ty, start, extent)) { return 1; } return 0;}/* *-------------------------------------------------------------- * * AngleInRange -- * * Determine whether the angle from the origin to a given * point is within a given range. * * Results: * The return value is 1 if the angle from (0,0) to (x,y) * is in the range given by start and extent, where angles * are interpreted in the standard way for ovals (meaning * backwards from normal interpretation). Otherwise the * return value is 0. * * Side effects: * None. * *-------------------------------------------------------------- */static intAngleInRange(x, y, start, extent) double x, y; /* Coordinate of point; angle measured * from origin to here, relative to x-axis. */ double start; /* First angle, degrees, >=0, <=360. */ double extent; /* Size of arc in degrees >=-360, <=360. */{ double diff; if ((x == 0.0) && (y == 0.0)) { return 1; } diff = -atan2(y, x); diff = diff*(180.0/PI) - start; while (diff > 360.0) { diff -= 360.0; } while (diff < 0.0) { diff += 360.0; } if (extent >= 0) { return diff <= extent; } return (diff-360.0) >= extent;}/* *-------------------------------------------------------------- * * ArcToPostscript -- * * This procedure is called to generate Postscript for * arc items. * * Results: * The return value is a standard Tcl result. If an error * occurs in generating Postscript then an error message is * left in interp->result, replacing whatever used * to be there. If no error occurs, then Postscript for the * item is appended to the result. * * Side effects: * None. * *-------------------------------------------------------------- */static intArcToPostscript(interp, canvas, itemPtr, prepass) Tcl_Interp *interp; /* Leave Postscript or error message * here. */ Tk_Canvas canvas; /* Information about overall canvas. */ Tk_Item *itemPtr; /* Item for which Postscript is * wanted. */ int prepass; /* 1 means this is a prepass to * collect font information; 0 means * final Postscript is being created. */{ ArcItem *arcPtr = (ArcItem *) itemPtr; char buffer[400]; double y1, y2, ang1, ang2; y1 = Tk_CanvasPsY(canvas, arcPtr->bbox[1]); y2 = Tk_CanvasPsY(canvas, arcPtr->bbox[3]); ang1 = arcPtr->start; ang2 = ang1 + arcPtr->extent; if (ang2 < ang1) { ang1 = ang2; ang2 = arcPtr->start; } /* * If the arc is filled, output Postscript for the interior region * of the arc. */ if (arcPtr->fillGC != None) { sprintf(buffer, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale\n", (arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2, (arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2); Tcl_AppendResult(interp, buffer, (char *) NULL); if (arcPtr->style == chordUid) { sprintf(buffer, "0 0 1 %.15g %.15g arc closepath\nsetmatrix\n", ang1, ang2); } else { sprintf(buffer, "0 0 moveto 0 0 1 %.15g %.15g arc closepath\nsetmatrix\n", ang1, ang2); } Tcl_AppendResult(interp, buffer, (char *) NULL); if (Tk_CanvasPsColor(interp, canvas, arcPtr->fillColor) != TCL_OK) { return TCL_ERROR; }; if (arcPtr->fillStipple != None) { Tcl_AppendResult(interp, "clip ", (char *) NULL); if (Tk_CanvasPsStipple(interp, canvas, arcPtr->fillStipple) != TCL_OK) { return TCL_ERROR; } if (arcPtr->outlineGC != None) { Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL); } } else { Tcl_AppendResult(interp, "fill\n", (char *) NULL); } } /* * If there's an outline for the arc, draw it. */ if (arcPtr->outlineGC != None) { sprintf(buffer, "matrix currentmatrix\n%.15g %.15g translate %.15g %.15g scale\n", (arcPtr->bbox[0] + arcPtr->bbox[2])/2, (y1 + y2)/2, (arcPtr->bbox[2] - arcPtr->bbox[0])/2, (y1 - y2)/2); Tcl_AppendResult(interp, buffer, (char *) NULL); sprintf(buffer, "0 0 1 %.15g %.15g arc\nsetmatrix\n", ang1, ang2); Tcl_AppendResult(interp, buffer, (char *) NULL); sprintf(buffer, "%d setlinewidth\n0 setlinecap\n", arcPtr->width); Tcl_AppendResult(interp, buffer, (char *) NULL); if (Tk_CanvasPsColor(interp, canvas, arcPtr->outlineColor) != TCL_OK) { return TCL_ERROR; } if (arcPtr->outlineStipple != None) { Tcl_AppendResult(interp, "StrokeClip ", (char *) NULL); if (Tk_CanvasPsStipple(interp, canvas, arcPtr->outlineStipple) != TCL_OK) { return TCL_ERROR; } } else { Tcl_AppendResult(interp, "stroke\n", (char *) NULL); } if (arcPtr->style != arcUid) { Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL); if (arcPtr->style == chordUid) { Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr, CHORD_OUTLINE_PTS); } else { Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr, PIE_OUTLINE1_PTS); if (Tk_CanvasPsColor(interp, canvas, arcPtr->outlineColor) != TCL_OK) { return TCL_ERROR; } if (arcPtr->outlineStipple != None) { Tcl_AppendResult(interp, "clip ", (char *) NULL); if (Tk_CanvasPsStipple(interp, canvas, arcPtr->outlineStipple) != TCL_OK) { return TCL_ERROR; } } else { Tcl_AppendResult(interp, "fill\n", (char *) NULL); } Tcl_AppendResult(interp, "grestore gsave\n", (char *) NULL); Tk_CanvasPsPath(interp, canvas, arcPtr->outlinePtr + 2*PIE_OUTLINE1_PTS, PIE_OUTLINE2_PTS); } if (Tk_CanvasPsColor(interp, canvas, arcPtr->outlineColor) != TCL_OK) { return TCL_ERROR; } if (arcPtr->outlineStipple != None) { Tcl_AppendResult(interp, "clip ", (char *) NULL); if (Tk_CanvasPsStipple(interp, canvas, arcPtr->outlineStipple) != TCL_OK) { return TCL_ERROR; } } else { Tcl_AppendResult(interp, "fill\n", (char *) NULL); } } } return TCL_OK;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -