/* ARGSUSED */ int TkThickPolyLineToArea( double *coordPtr, /* Points to an array of coordinates for the * polyline: x0, y0, x1, y1, ... */ int numPoints, /* Total number of points at *coordPtr. */ double width, /* Width of each line segment. */ int capStyle, /* How are end-points of polyline drawn? * CapRound, CapButt, or CapProjecting. */ int joinStyle, /* How are joints in polyline drawn? * JoinMiter, JoinRound, or JoinBevel. */ double *rectPtr) /* Rectangular area to check against. */ { double radius, poly[10]; int 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 = width/2.0; inside = -1; 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 (((capStyle == CapRound) && (count == numPoints)) || ((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) { return 0; } } /* * 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, width, capStyle == CapProjecting, poly, poly+2); } else if ((joinStyle == JoinMiter) && !changedMiterToBevel) { poly[0] = poly[6]; poly[1] = poly[7]; poly[2] = poly[4]; poly[3] = poly[5]; } else { TkGetButtPoints(coordPtr+2, coordPtr, 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 ((joinStyle == JoinBevel) || changedMiterToBevel) { poly[8] = poly[0]; poly[9] = poly[1]; if (TkPolygonToArea(poly, 5, rectPtr) != inside) { return 0; } changedMiterToBevel = 0; } } if (count == 2) { TkGetButtPoints(coordPtr, coordPtr+2, width, capStyle == CapProjecting, poly+4, poly+6); } else if (joinStyle == JoinMiter) { if (TkGetMiterPoints(coordPtr, coordPtr+2, coordPtr+4, (double) width, poly+4, poly+6) == 0) { changedMiterToBevel = 1; TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4, poly+6); } } else { TkGetButtPoints(coordPtr, coordPtr+2, width, 0, poly+4, poly+6); } poly[8] = poly[0]; poly[9] = poly[1]; if (TkPolygonToArea(poly, 5, rectPtr) != inside) { return 0; } } /* * If caps are rounded, check the cap around the final point of the line. */ if (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) { return 0; } } return inside; }
/* ARGSUSED */ static int BLineToArea(Tk_Canvas canvas, Tk_Item *itemPtr, double *rectPtr) { register BLineItem *linePtr = (BLineItem *) 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; 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; } } done: if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) { ckfree((char *) linePoints); } return inside; }