int TkPolygonToArea( double *polyPtr, /* Points to an array coordinates for closed * polygon: x0, y0, x1, y1, ... The polygon * may be self-intersecting. */ int numPoints, /* Total number of points at *polyPtr. */ register double *rectPtr) /* Points to coords for rectangle, in the * order x1, y1, x2, y2. X1 and y1 must be * lower-left corner. */ { int state; /* State of all edges seen so far (-1 means * outside, 1 means inside, won't ever be * 0). */ int count; register double *pPtr; /* * Iterate over all of the edges of the polygon and test them against the * rectangle. Can quit as soon as the state becomes "intersecting". */ state = TkLineToArea(polyPtr, polyPtr+2, rectPtr); if (state == 0) { return 0; } for (pPtr = polyPtr+2, count = numPoints-1; count >= 2; pPtr += 2, count--) { if (TkLineToArea(pPtr, pPtr+2, rectPtr) != state) { return 0; } } /* * If all of the edges were inside the rectangle we're done. If all of the * edges were outside, then the rectangle could still intersect the * polygon (if it's entirely enclosed). Call TkPolygonToPoint to figure * this out. */ if (state == 1) { return 1; } if (TkPolygonToPoint(polyPtr, numPoints, rectPtr) == 0.0) { return 0; } return -1; }
/* ARGSUSED */ static double BLineToPoint(Tk_Canvas canvas, Tk_Item *itemPtr, double *pointPtr) { register BLineItem *linePtr = (BLineItem *) itemPtr; register double *coordPtr, *linePoints; double staticSpace[2*MAX_STATIC_POINTS]; double poly[10]; double bestDist, dist; 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. */ bestDist = 1.0e40; /* * Handle smoothed lines by generating an expanded set of points * against which to do the check. */ numPoints = linePtr->numPoints; linePoints = linePtr->coordPtr; /* * The overall idea is to iterate through all of the edges of * the line, computing a polygon for each edge and testing the * point against that polygon. In addition, there are additional * tests to deal with rounded joints and caps. */ changedMiterToBevel = 0; for (count = numPoints, coordPtr = linePoints; count >= 2; count--, coordPtr += 2) { /* * If rounding is done around the first point then compute * the distance between the point and the point. */ if (((linePtr->capStyle == CapRound) && (count == numPoints)) || ((linePtr->joinStyle == JoinRound) && (count != numPoints))) { dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1]) - linePtr->width/2.0; if (dist <= 0.0) { bestDist = 0.0; goto done; } else if (dist < bestDist) { bestDist = dist; } } /* * 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 this line uses beveled joints, then check the distance * to 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 mitered joint. */ if ((linePtr->joinStyle == JoinBevel) || changedMiterToBevel) { poly[8] = poly[0]; poly[9] = poly[1]; dist = TkPolygonToPoint(poly, 5, pointPtr); if (dist <= 0.0) { bestDist = 0.0; goto done; } else if (dist < bestDist) { bestDist = dist; } 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]; dist = TkPolygonToPoint(poly, 5, pointPtr); if (dist <= 0.0) { bestDist = 0.0; goto done; } else if (dist < bestDist) { bestDist = dist; } } /* * If caps are rounded, check the distance to the cap around the * final end point of the line. */ if (linePtr->capStyle == CapRound) { dist = hypot(coordPtr[0] - pointPtr[0], coordPtr[1] - pointPtr[1]) - linePtr->width/2.0; if (dist <= 0.0) { bestDist = 0.0; goto done; } else if (dist < bestDist) { bestDist = dist; } } done: if ((linePoints != staticSpace) && (linePoints != linePtr->coordPtr)) { ckfree((char *) linePoints); } return bestDist; }