Beispiel #1
0
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;
}
Beispiel #2
0
	/* 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;
}