/** * Returns the distance, that a Rectangle needs to grow (or shrink) to make hit detections on a * shape as specified by the FILL_UNDER_STROKE and STROKE_POSITION attributes of a figure. The * value returned is the number of units that need to be grown (or shrunk) perpendicular to a * stroke on an outline of the shape. */ public static double getPerpendicularHitGrowth(Figure f) { double grow; if (STROKE_COLOR.get(f) == null && STROKE_GRADIENT.get(f) == null) { grow = getPerpendicularFillGrowth(f); } else { double strokeWidth = AttributeKeys.getStrokeTotalWidth(f); grow = getPerpendicularDrawGrowth(f) + strokeWidth / 2d; } return grow; }
@Override public boolean contains(Point2D.Double p) { double tolerance = Math.max(2f, AttributeKeys.getStrokeTotalWidth(this) / 2d); if (isClosed() || get(FILL_COLOR) != null && get(UNCLOSED_PATH_FILLED)) { if (path.contains(p)) { return true; } double grow = AttributeKeys.getPerpendicularHitGrowth(this) * 2d; GrowStroke gs = new GrowStroke(grow, AttributeKeys.getStrokeTotalWidth(this) * get(STROKE_MITER_LIMIT)); if (gs.createStrokedShape(path).contains(p)) { return true; } else { if (isClosed()) { return false; } } } if (!isClosed()) { if (getCappedPath().outlineContains(p, tolerance)) { return true; } if (get(START_DECORATION) != null) { BezierPath cp = getCappedPath(); Point2D.Double p1 = path.get(0, 0); Point2D.Double p2 = cp.get(0, 0); // FIXME - Check here, if caps path contains the point if (Geom.lineContainsPoint(p1.x, p1.y, p2.x, p2.y, p.x, p.y, tolerance)) { return true; } } if (get(END_DECORATION) != null) { BezierPath cp = getCappedPath(); Point2D.Double p1 = path.get(path.size() - 1, 0); Point2D.Double p2 = cp.get(path.size() - 1, 0); // FIXME - Check here, if caps path contains the point if (Geom.lineContainsPoint(p1.x, p1.y, p2.x, p2.y, p.x, p.y, tolerance)) { return true; } } } return false; }
protected Point2D.Double chop(Figure target, Point2D.Double from) { target = getConnectorTarget(target); Rectangle2D.Double r = target.getBounds(); if (STROKE_COLOR.get(target) != null) { double grow; switch (STROKE_PLACEMENT.get(target)) { case CENTER: default: grow = AttributeKeys.getStrokeTotalWidth(target) / 2d; break; case OUTSIDE: grow = AttributeKeys.getStrokeTotalWidth(target); break; case INSIDE: grow = 0d; break; } Geom.grow(r, grow, grow); } return Geom.angleToPoint(r, Geom.pointToAngle(r, from)); }
@Override protected void drawFill(Graphics2D g) { if (isClosed() || get(UNCLOSED_PATH_FILLED)) { double grow = AttributeKeys.getPerpendicularFillGrowth(this); if (grow == 0d) { g.fill(path); } else { GrowStroke gs = new GrowStroke(grow, AttributeKeys.getStrokeTotalWidth(this) * get(STROKE_MITER_LIMIT)); g.fill(gs.createStrokedShape(path)); } } }
public Rectangle2D.Double getDrawingArea() { double strokeTotalWidth = AttributeKeys.getStrokeTotalWidth(this); double width = strokeTotalWidth / 2d; if (STROKE_JOIN.get(this) == BasicStroke.JOIN_MITER) { width *= STROKE_MITER_LIMIT.get(this); } else if (STROKE_CAP.get(this) != BasicStroke.CAP_BUTT) { width += strokeTotalWidth * 2; } width++; Rectangle2D.Double r = getBounds(); Geom.grow(r, width, width); return r; }
public Point2D.Double chop(Point2D.Double p) { if (isClosed()) { double grow = AttributeKeys.getPerpendicularHitGrowth(this); if (grow == 0d) { return path.chop(p); } else { GrowStroke gs = new GrowStroke(grow, AttributeKeys.getStrokeTotalWidth(this) * get(STROKE_MITER_LIMIT)); return Geom.chop(gs.createStrokedShape(path), p); } } else { return path.chop(p); } }
@Override protected void drawStroke(Graphics2D g) { if (isClosed()) { double grow = AttributeKeys.getPerpendicularDrawGrowth(this); if (grow == 0d) { g.draw(path); } else { GrowStroke gs = new GrowStroke(grow, AttributeKeys.getStrokeTotalWidth(this) * get(STROKE_MITER_LIMIT)); g.draw(gs.createStrokedShape(path)); } } else { g.draw(getCappedPath()); } drawCaps(g); }
@Override public Rectangle2D.Double getDrawingArea() { if (cachedDrawingArea == null) { if (get(TRANSFORM) == null) { cachedDrawingArea = path.getBounds2D(); } else { BezierPath p2 = (BezierPath) path.clone(); p2.transform(get(TRANSFORM)); cachedDrawingArea = p2.getBounds2D(); } double strokeTotalWidth = AttributeKeys.getStrokeTotalWidth(this); double width = strokeTotalWidth / 2d; if (get(STROKE_JOIN) == BasicStroke.JOIN_MITER) { width *= get(STROKE_MITER_LIMIT); } else if (get(STROKE_CAP) != BasicStroke.CAP_BUTT) { width += strokeTotalWidth * 2; } Geom.grow(cachedDrawingArea, width, width); } return (Rectangle2D.Double) cachedDrawingArea.clone(); }