⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tkcanvline.c

📁 MPICH是MPI的重要研究,提供了一系列的接口函数,为并行计算的实现提供了编程环境.
💻 C
📖 第 1 页 / 共 4 页
字号:
 *-------------------------------------------------------------- * * LineToArea -- * *	This procedure is called to determine whether an item *	lies entirely inside, entirely outside, or overlapping *	a given rectangular area. * * Results: *	-1 is returned if the item is entirely outside the *	area, 0 if it overlaps, and 1 if it is entirely *	inside the given area. * * Side effects: *	None. * *-------------------------------------------------------------- */	/* ARGSUSED */static intLineToArea(canvasPtr, itemPtr, rectPtr)    Tk_Canvas *canvasPtr;	/* Canvas containing item. */    Tk_Item *itemPtr;		/* Item to check against line. */    double *rectPtr;{    register LineItem *linePtr = (LineItem *) itemPtr;    register double *coordPtr;    double staticSpace[2*MAX_STATIC_POINTS];    double *linePoints, poly[10];    double radius;    int numPoints, count;    int changedMiterToBevel;	/* Non-zero means that a mitered corner				 * had to be treated as beveled after all				 * because the angle was < 11 degrees. */    int inside;			/* Tentative guess about what to return,				 * based on all points seen so far:  one				 * means everything seen so far was				 * inside the area;  -1 means everything				 * was outside the area.  0 means overlap				 * has been found. */     radius = linePtr->width/2.0;    inside = -1;    /*     * Handle smoothed lines by generating an expanded set of points     * against which to do the check.     */    if ((linePtr->smooth) && (linePtr->numPoints > 2)) {	numPoints = 1 + linePtr->numPoints*linePtr->splineSteps;	if (numPoints <= MAX_STATIC_POINTS) {	    linePoints = staticSpace;	} else {	    linePoints = (double *) ckalloc((unsigned)		    (2*numPoints*sizeof(double)));	}	numPoints = TkMakeBezierCurve(canvasPtr, linePtr->coordPtr,		linePtr->numPoints, linePtr->splineSteps, (XPoint *) NULL,		linePoints);    } else {	numPoints = linePtr->numPoints;	linePoints = linePtr->coordPtr;    }    coordPtr = linePoints;    if ((coordPtr[0] >= rectPtr[0]) && (coordPtr[0] <= rectPtr[2])	    && (coordPtr[1] >= rectPtr[1]) && (coordPtr[1] <= rectPtr[3])) {	inside = 1;    }    /*     * Iterate through all of the edges of the line, computing a polygon     * for each edge and testing the area against that polygon.  In     * addition, there are additional tests to deal with rounded joints     * and caps.     */    changedMiterToBevel = 0;    for (count = numPoints; count >= 2; count--, coordPtr += 2) {	/*	 * If rounding is done around the first point of the edge	 * then test a circular region around the point with the	 * area.	 */	if (((linePtr->capStyle == CapRound) && (count == numPoints))		|| ((linePtr->joinStyle == JoinRound)		&& (count != numPoints))) {	    poly[0] = coordPtr[0] - radius;	    poly[1] = coordPtr[1] - radius;	    poly[2] = coordPtr[0] + radius;	    poly[3] = coordPtr[1] + radius;	    if (TkOvalToArea(poly, rectPtr) != inside) {		inside = 0;		goto done;	    }	}	/*	 * Compute the polygonal shape corresponding to this edge,	 * consisting of two points for the first point of the edge	 * and two points for the last point of the edge.	 */	if (count == numPoints) {	    TkGetButtPoints(coordPtr+2, coordPtr, (double) linePtr->width,		    linePtr->capStyle == CapProjecting, poly, poly+2);	} else if ((linePtr->joinStyle == JoinMiter) && !changedMiterToBevel) {	    poly[0] = poly[6];	    poly[1] = poly[7];	    poly[2] = poly[4];	    poly[3] = poly[5];	} else {	    TkGetButtPoints(coordPtr+2, coordPtr, (double) linePtr->width, 0,		    poly, poly+2);	    /*	     * If the last joint was beveled, then also check a	     * polygon comprising the last two points of the previous	     * polygon and the first two from this polygon;  this checks	     * the wedges that fill the beveled joint.	     */	    if ((linePtr->joinStyle == JoinBevel) || changedMiterToBevel) {		poly[8] = poly[0];		poly[9] = poly[1];		if (TkPolygonToArea(poly, 5, rectPtr) != inside) {		    inside = 0;		    goto done;		}		changedMiterToBevel = 0;	    }	}	if (count == 2) {	    TkGetButtPoints(coordPtr, coordPtr+2, (double) linePtr->width,		    linePtr->capStyle == CapProjecting, poly+4, poly+6);	} else if (linePtr->joinStyle == JoinMiter) {	    if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4,		    (double) linePtr->width, poly+4, poly+6) == 0) {		changedMiterToBevel = 1;		TkGetButtPoints(coordPtr, coordPtr+2, (double) linePtr->width,			0, poly+4, poly+6);	    }	} else {	    TkGetButtPoints(coordPtr, coordPtr+2, (double) linePtr->width, 0,		    poly+4, poly+6);	}	poly[8] = poly[0];	poly[9] = poly[1];	if (TkPolygonToArea(poly, 5, rectPtr) != inside) {	    inside = 0;	    goto done;	}    }    /*     * If caps are rounded, check the cap around the final point     * of the line.     */    if (linePtr->capStyle == CapRound) {	poly[0] = coordPtr[0] - radius;	poly[1] = coordPtr[1] - radius;	poly[2] = coordPtr[0] + radius;	poly[3] = coordPtr[1] + radius;	if (TkOvalToArea(poly, rectPtr) != inside) {	    inside = 0;	    goto done;	}    }    /*     * Check arrowheads, if any.     */    if (linePtr->arrow != noneUid) {	if (linePtr->arrow != lastUid) {	    if (TkPolygonToArea(linePtr->firstArrowPtr, PTS_IN_ARROW,		    rectPtr) != inside) {		inside = 0;		goto done;	    }	}	if (linePtr->arrow != firstUid) {	    if (TkPolygonToArea(linePtr->lastArrowPtr, PTS_IN_ARROW,		    rectPtr) != inside) {		inside = 0;		goto done;	    }	}    }    done:    if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) {	ckfree((char *) linePoints);    }    return inside;}/* *-------------------------------------------------------------- * * ScaleLine -- * *	This procedure is invoked to rescale a line item. * * Results: *	None. * * Side effects: *	The line referred to by itemPtr is rescaled so that the *	following transformation is applied to all point *	coordinates: *		x' = originX + scaleX*(x-originX) *		y' = originY + scaleY*(y-originY) * *-------------------------------------------------------------- */static voidScaleLine(canvasPtr, itemPtr, originX, originY, scaleX, scaleY)    Tk_Canvas *canvasPtr;		/* Canvas containing line. */    Tk_Item *itemPtr;			/* Line to be scaled. */    double originX, originY;		/* Origin about which to scale rect. */    double scaleX;			/* Amount to scale in X direction. */    double scaleY;			/* Amount to scale in Y direction. */{    LineItem *linePtr = (LineItem *) itemPtr;    register double *coordPtr;    int i;    for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;	    i++, coordPtr += 2) {	coordPtr[0] = originX + scaleX*(*coordPtr - originX);	coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);    }    if (linePtr->firstArrowPtr != NULL) {	for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;		i++, coordPtr += 2) {	    coordPtr[0] = originX + scaleX*(coordPtr[0] - originX);	    coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);	}    }    if (linePtr->lastArrowPtr != NULL) {	for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;		i++, coordPtr += 2) {	    coordPtr[0] = originX + scaleX*(coordPtr[0] - originX);	    coordPtr[1] = originY + scaleY*(coordPtr[1] - originY);	}    }    ComputeLineBbox(canvasPtr, linePtr);}/* *-------------------------------------------------------------- * * TranslateLine -- * *	This procedure is called to move a line by a given amount. * * Results: *	None. * * Side effects: *	The position of the line is offset by (xDelta, yDelta), and *	the bounding box is updated in the generic part of the item *	structure. * *-------------------------------------------------------------- */static voidTranslateLine(canvasPtr, itemPtr, deltaX, deltaY)    Tk_Canvas *canvasPtr;		/* Canvas containing item. */    Tk_Item *itemPtr;			/* Item that is being moved. */    double deltaX, deltaY;		/* Amount by which item is to be					 * moved. */{    LineItem *linePtr = (LineItem *) itemPtr;    register double *coordPtr;    int i;    for (i = 0, coordPtr = linePtr->coordPtr; i < linePtr->numPoints;	    i++, coordPtr += 2) {	coordPtr[0] += deltaX;	coordPtr[1] += deltaY;    }    if (linePtr->firstArrowPtr != NULL) {	for (i = 0, coordPtr = linePtr->firstArrowPtr; i < PTS_IN_ARROW;		i++, coordPtr += 2) {	    coordPtr[0] += deltaX;	    coordPtr[1] += deltaY;	}    }    if (linePtr->lastArrowPtr != NULL) {	for (i = 0, coordPtr = linePtr->lastArrowPtr; i < PTS_IN_ARROW;		i++, coordPtr += 2) {	    coordPtr[0] += deltaX;	    coordPtr[1] += deltaY;	}    }    ComputeLineBbox(canvasPtr, linePtr);}/* *-------------------------------------------------------------- * * ParseArrowShape -- * *	This procedure is called back during option parsing to *	parse arrow shape information. * * Results: *	The return value is a standard Tcl result:  TCL_OK means *	that the arrow shape information was parsed ok, and *	TCL_ERROR means it couldn't be parsed. * * Side effects: *	Arrow information in recordPtr is updated. * *-------------------------------------------------------------- */	/* ARGSUSED */static intParseArrowShape(clientData, interp, tkwin, value, recordPtr, offset)    ClientData clientData;	/* Not used. */    Tcl_Interp *interp;		/* Used for error reporting. */    Tk_Window tkwin;		/* Not used. */    char *value;		/* Textual specification of arrow shape. */    char *recordPtr;		/* Pointer to item record in which to				 * store arrow information. */    int offset;			/* Offset of shape information in widget				 * record. */{    LineItem *linePtr = (LineItem *) recordPtr;    double a, b, c;    int argc;    char **argv = NULL;    if (offset != Tk_Offset(LineItem, arrowShapeA)) {	panic("ParseArrowShape received bogus offset");    }    if (Tcl_SplitList(interp, value, &argc, &argv) != TCL_OK) {	syntaxError:	Tcl_ResetResult(interp);	Tcl_AppendResult(interp, "bad arrow shape \"", value,		"\": must be list with three numbers", (char *) NULL);	if (argv != NULL) {	    ckfree((char *) argv);	}	return TCL_ERROR;    }    if (argc != 3) {	goto syntaxError;    }    if ((TkGetCanvasCoord(linePtr->canvasPtr, argv[0], &a) != TCL_OK)	    || (TkGetCanvasCoord(linePtr->canvasPtr, argv[1], &b) != TCL_OK)	    || (TkGetCanvasCoord(linePtr->canvasPtr, argv[2], &c) != TCL_OK)) {	goto syntaxError;    }    linePtr->arrowShapeA = a;    linePtr->arrowShapeB = b;    linePtr->arrowShapeC = c;    ckfree((char *) argv);    return TCL_OK;}/* *-------------------------------------------------------------- * * PrintArrowShape -- * *	This procedure is a callback invoked by the configuration *	code to return a printable value describing an arrow shape. * * Results: *	None. * * Side effects: *	None. * *-------------------------------------------------------------- */    /* ARGSUSED */static char *PrintArrowShape(clientData, tkwin, recordPtr, offset, freeProcPtr)    ClientData clientData;	/* Not used. */    Tk_Window tkwin;		/* Window associated with linePtr's widget. */    char *recordPtr;		/* Pointer to item record containing current				 * shape information. */    int offset;			/* Offset of arrow information in record. */    Tcl_FreeProc **freeProcPtr;	/* Store address of procedure to call to				 * free string here. */{    LineItem *linePtr = (LineItem *) recordPtr;    char *buffer;    buffer = ckalloc(120);    sprintf(buffer, "%.5g %.5g %.5g", linePtr->arrowShapeA,	    linePtr->arrowShapeB, linePtr->arrowShapeC);    *freeProcPtr = (Tcl_FreeProc *) free;    return buffer;}/* *-------------------------------------------------------------- * * ConfigureArrows -- * *	If arrowheads have been requested for a line, this *	procedure makes arrangements for the arrowheads. * * Results: *	A standard Tcl return value.  If an error occurs, then *	an error message is left in canvasPtr->interp->result. * * Side effects: *	Information in linePtr is set up for one or two arrowheads. *	the firstArrowPtr and lastArrowPtr polygons are allocated *	and initialized, if need be, and the end points of the line *	are adjusted so that a thick line doesn't stick out past *	the arrowheads. * *-------------------------------------------------------------- */	/* ARGSUSED */static intConfigureArrows(canvasPtr, linePtr)    Tk_Canvas *canvasPtr;		/* Canvas in which arrows will be					 * displayed (interp and tkwin					 * fields are needed). */    register LineItem *linePtr;		/* Item to configure for arrows. */{    double *poly, *coordPtr;    double dx, dy, length, sinTheta, cosTheta, temp, shapeC;    double fracHeight;			/* Line width as fraction of					 * arrowhead width. */    double backup;			/* Distance to backup end points					 * so the line ends in the middle					 * of the arrowhead. */    double vertX, vertY;		/* Position of arrowhead vertex. */    /*     * If there's an arrowhead on the first point of the line, compute     * its polygon and adjust the first point of the line so that the     * line doesn't stick out past the leading edge of the arrowhead.     */    shapeC = linePtr->arrowShapeC + linePtr->width/2.0;    fracHeight = (linePtr->width/2.0)/shapeC;    backup = fracHeight*linePtr->arrowShapeB	    + linePtr->arrowShapeA*(1.0 - fracHeight)/2.0;    if (linePtr->arrow != lastUid) {	poly = linePtr->firstArrowPtr;	if (poly == NULL) {	    poly = (double *) ckalloc((unsigned)		    (2*PTS_IN_ARROW*sizeof(double)));	    poly[0] = poly[10] = linePtr->coordPtr[0];	    poly[1] = poly[11] = linePtr->coordPtr[1];	    linePtr->firstArrowPtr = poly;	}	dx = poly[0] - linePtr->coordPtr[2];	dy = poly[1] - linePtr->coordPtr[3];	length = hypot(dx, dy);	if (length == 0) {	    sinTheta = cosTheta = 0.0;	} else {	    sinTheta = dy/length;	    cosTheta = dx/length;	}	vertX = poly[0] - linePtr->arrowShapeA*cosTheta;	vertY = poly[1] - linePtr->arrowShapeA*sinTheta;	temp = shapeC*sinTheta;	poly[2] = poly[0] - linePtr->arrowShapeB*cosTheta + temp;	poly[8] = poly[2] - 2*temp;	temp = shapeC*cosTheta;	poly[3] = poly[1] - linePtr->arrowShapeB*sinTheta - temp;	poly[9] = poly[3] + 2*temp;	poly[4] = poly[2]*fracHeight + vertX*(1.0-fracHeight);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -