Esempio n. 1
0
	/* 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;
}
Esempio n. 2
0
	/* ARGSUSED */
static int
OvalToArea(
    Tk_Canvas canvas,		/* Canvas containing item. */
    Tk_Item *itemPtr,		/* Item to check against oval. */
    double *areaPtr)		/* Pointer to array of four coordinates (x1,
				 * y1, x2, y2) describing rectangular area. */
{
    RectOvalItem *ovalPtr = (RectOvalItem *) itemPtr;
    double oval[4], halfWidth, width;
    int result;
    Tk_State state = itemPtr->state;

    if (state == TK_STATE_NULL) {
	state = Canvas(canvas)->canvas_state;
    }

    width = ovalPtr->outline.width;
    if (Canvas(canvas)->currentItemPtr == itemPtr) {
	if (ovalPtr->outline.activeWidth > width) {
	    width = ovalPtr->outline.activeWidth;
	}
    } else if (state == TK_STATE_DISABLED) {
	if (ovalPtr->outline.disabledWidth > 0) {
	    width = ovalPtr->outline.disabledWidth;
	}
    }

    /*
     * Expand the oval to include the width of the outline, if any.
     */

    halfWidth = width/2.0;
    if (ovalPtr->outline.gc == None) {
	halfWidth = 0.0;
    }
    oval[0] = ovalPtr->bbox[0] - halfWidth;
    oval[1] = ovalPtr->bbox[1] - halfWidth;
    oval[2] = ovalPtr->bbox[2] + halfWidth;
    oval[3] = ovalPtr->bbox[3] + halfWidth;

    result = TkOvalToArea(oval, areaPtr);

    /*
     * If the rectangle appears to overlap the oval and the oval isn't filled,
     * do one more check to see if perhaps all four of the rectangle's corners
     * are totally inside the oval's unfilled center, in which case we should
     * return "outside".
     */

    if ((result == 0) && (ovalPtr->outline.gc != None)
	    && (ovalPtr->fillGC == None)) {
	double centerX, centerY, height;
	double xDelta1, yDelta1, xDelta2, yDelta2;

	centerX = (ovalPtr->bbox[0] + ovalPtr->bbox[2])/2.0;
	centerY = (ovalPtr->bbox[1] + ovalPtr->bbox[3])/2.0;
	width = (ovalPtr->bbox[2] - ovalPtr->bbox[0])/2.0 - halfWidth;
	height = (ovalPtr->bbox[3] - ovalPtr->bbox[1])/2.0 - halfWidth;
	xDelta1 = (areaPtr[0] - centerX)/width;
	xDelta1 *= xDelta1;
	yDelta1 = (areaPtr[1] - centerY)/height;
	yDelta1 *= yDelta1;
	xDelta2 = (areaPtr[2] - centerX)/width;
	xDelta2 *= xDelta2;
	yDelta2 = (areaPtr[3] - centerY)/height;
	yDelta2 *= yDelta2;
	if (((xDelta1 + yDelta1) < 1.0)
		&& ((xDelta1 + yDelta2) < 1.0)
		&& ((xDelta2 + yDelta1) < 1.0)
		&& ((xDelta2 + yDelta2) < 1.0)) {
	    return -1;
	}
    }
    return result;
}
Esempio n. 3
0
	/* 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;
}