下面列出了怎么用java.awt.geom.Area的API类实例代码及写法,或者点击链接到github查看源代码。
private Area generateSafeArea()
{
final Area area = new Area();
for (WorldPoint wp : safeCenters)
{
if (wp == null)
{
continue;
}
Polygon poly = new Polygon();
poly.addPoint(wp.getX() - SAFE_AREA_RADIUS, wp.getY() - SAFE_AREA_RADIUS);
poly.addPoint(wp.getX() - SAFE_AREA_RADIUS, wp.getY() + SAFE_AREA_RADIUS + 1);
poly.addPoint(wp.getX() + SAFE_AREA_RADIUS + 1, wp.getY() + SAFE_AREA_RADIUS + 1);
poly.addPoint(wp.getX() + SAFE_AREA_RADIUS + 1, wp.getY() - SAFE_AREA_RADIUS);
area.add(new Area(poly));
}
return area;
}
/**
* Draws the frame. This method is called by the {@link DialPlot} class,
* you shouldn't need to call it directly.
*
* @param g2 the graphics target (<code>null</code> not permitted).
* @param plot the plot (<code>null</code> not permitted).
* @param frame the frame (<code>null</code> not permitted).
* @param view the view (<code>null</code> not permitted).
*/
@Override
public void draw(Graphics2D g2, DialPlot plot, Rectangle2D frame,
Rectangle2D view) {
Shape window = getWindow(frame);
Rectangle2D f = DialPlot.rectangleByRadius(frame, this.radius + 0.02,
this.radius + 0.02);
Ellipse2D e = new Ellipse2D.Double(f.getX(), f.getY(), f.getWidth(),
f.getHeight());
Area area = new Area(e);
Area area2 = new Area(window);
area.subtract(area2);
g2.setPaint(this.backgroundPaint);
g2.fill(area);
g2.setStroke(this.stroke);
g2.setPaint(this.foregroundPaint);
g2.draw(window);
g2.draw(e);
}
public void drawArea(Area area) {
PathIterator iter = area.getPathIterator(null);
Path2D.Float poly = new Path2D.Float();
double[] firstPoint = null;
while (!iter.isDone()) {
double point[] = new double[2]; // x, y
int type = iter.currentSegment(point);
point[0] = t.xToScreen(point[0]);
point[1] = t.yToScreen(point[1]);
if (type == PathIterator.SEG_MOVETO) {
firstPoint = point;
poly.moveTo(point[0], point[1]);
} else if (type == PathIterator.SEG_CLOSE) {
poly.lineTo(firstPoint[0], firstPoint[1]);
g.draw(poly);
poly.reset();
} else {
poly.lineTo(point[0], point[1]);
}
iter.next();
}
}
/**
* Gets the icon.
*
* @param w width of the icon
* @param h height of the icon
* @return the icon
*/
public Icon getIcon(int w, int h) {
int scale = FontSizer.getIntegerFactor();
w *= scale;
h *= scale;
if (stroke==null || stroke.getLineWidth()!=scale*baseStroke.getLineWidth()) {
stroke = new BasicStroke(scale*baseStroke.getLineWidth());
}
transform.setToScale(scale, scale);
Shape target = stroke.createStrokedShape(transform.createTransformedShape(targetShape));
Area area = new Area(target);
double x0 = scale*(size+2)-w;
double y0 = h-scale*(size+2);
double d = Math.sqrt(x0*x0+y0*y0);
double x1 = x0*scale*size/d;
double y1 = y0*scale*size/d;
Line2D line = new Line2D.Double(x0, y0, x1, y1);
area.add(new Area(stroke.createStrokedShape(line)));
ShapeIcon icon = new ShapeIcon(area, w, h);
icon.setColor(color);
return icon;
}
/**
* Modify the current clipping path by intersecting it with the given path.
* @param area area to intersect with the clipping path
*/
public void intersectClippingPath(Area area)
{
// lazy cloning of clipping path for performance
if (!isClippingPathDirty)
{
// deep copy (can't use clone() as it performs only a shallow copy)
Area cloned = new Area();
cloned.add(clippingPath);
clippingPath = cloned;
isClippingPathDirty = true;
}
// intersection as usual
clippingPath.intersect(area);
}
/**
* This constructor supports polygon shapes Future shapes (and corresponding
* constructors) will be added later
*
* @param source
* @param loa
* @param clipping
*/
public ShapedAction( StructureSource oSource, Location[] loa, Shape clipping )
{
_oSource = oSource;
if ( clipping != null )
{
Area ar1 = new Area( clipping );
Area ar2 = new Area( G2dRendererBase.getPolygon2D( loa ) );
ar2.intersect( ar1 );
_sh = ar2;
}
else
{
_sh = G2dRendererBase.getPolygon2D( loa );
}
}
/**
* Draw pie
*
* @param aPoint Start point
* @param width Width
* @param height Height
* @param startAngle Start angle
* @param sweepAngle Sweep angle
* @param aPGB Polygon break
* @param wedgeWidth Wedge width
* @param g Graphics2D
*/
public static void drawPie(PointF aPoint, float width, float height, float startAngle,
float sweepAngle, PolygonBreak aPGB, float wedgeWidth, Graphics2D g) {
Color aColor = aPGB.getColor();
Arc2D.Float arc2D = new Arc2D.Float(aPoint.X, aPoint.Y, width, height, startAngle, sweepAngle, Arc2D.PIE);
Area area1 = new Area(arc2D);
Ellipse2D e2 = new Ellipse2D.Float(aPoint.X + wedgeWidth, aPoint.Y + wedgeWidth, width - wedgeWidth * 2,
height - wedgeWidth * 2);
Area area2 = new Area(e2);
area1.subtract(area2);
if (aPGB.isDrawFill()) {
g.setColor(aColor);
g.fill(area1);
}
if (aPGB.isDrawOutline()) {
g.setColor(aPGB.getOutlineColor());
g.setStroke(new BasicStroke(aPGB.getOutlineSize()));
g.draw(area1);
}
}
private Table.UnsignedByte computeRelevantPoints (Area area)
{
Table.UnsignedByte table = new Table.UnsignedByte(rect.width, rect.height);
Point loc = rect.getLocation();
table.fill(PixelFilter.BACKGROUND);
for (int y = 0; y < rect.height; y++) {
int ay = y + loc.y; // Absolute ordinate
for (int x = 0; x < rect.width; x++) {
int ax = x + loc.x; // Absolute abscissa
if (area.contains(ax, ay)) {
table.setValue(x, y, 0);
pointCount++;
}
}
}
return table;
}
private void buildFullShape() {
// Note: this method assumes all bounds have been set
Area parent = new Area();
Area v = new Area(vertexShape);
Area name = new Area(nameLabel.getBounds());
parent.add(v);
parent.add(name);
// for now, the buttons only appear on hover, but if we want to avoid clipping when
// painting, we need to account for them in the shape's overall bounds
Area in = new Area(toggleInsButton.getBounds());
Area out = new Area(toggleOutsButton.getBounds());
parent.add(in);
parent.add(out);
fullShape = parent;
}
/**
* Returns <code>true</code> if the rectangle (in device space) intersects
* with the shape (the interior, if <code>onStroke</code> is false,
* otherwise the stroked outline of the shape).
*
* @param rect a rectangle (in device space).
* @param s the shape.
* @param onStroke test the stroked outline only?
*
* @return A boolean.
*/
@Override
public boolean hit(Rectangle rect, Shape s, boolean onStroke) {
AffineTransform transform = getTransform();
Shape ts;
if (onStroke) {
Stroke stroke = getStroke();
ts = transform.createTransformedShape(stroke.createStrokedShape(s));
} else {
ts = transform.createTransformedShape(s);
}
if (!rect.getBounds2D().intersects(ts.getBounds2D())) {
return false;
}
Area a1 = new Area(rect);
Area a2 = new Area(ts);
a1.intersect(a2);
return !a1.isEmpty();
}
/**
* Draw the exploration limit rectangle borders.
* @param g2 the graphics context
*/
void renderExplorationLimits(Graphics2D g2) {
if (player().explorationOuterLimit != null) {
Area a = new Area(new Rectangle(0, 0, world().galaxyModel.map.getWidth(), world().galaxyModel.map.getHeight()));
a.subtract(new Area(player().explorationOuterLimit));
g2.setColor(new Color(0x80000000, true));
drawShape(g2, a, true);
g2.setColor(Color.RED);
drawRect(g2, player().explorationOuterLimit, false);
} else
if (player().explorationInnerLimit != null) {
g2.setColor(new Color(0x80000000, true));
drawRect(g2, player().explorationInnerLimit, true);
}
}
/** Returns the bounds of this object as it shows in the given layer. */
@Override
public Rectangle getBounds(final Rectangle r, final Layer layer) {
if (null == layer) return super.getBounds(r, null);
final Area area = (Area)ht_areas.get(layer.getId());
if (null == area) {
if (null == r) return new Rectangle();
r.x = 0;
r.y = 0;
r.width = 0;
r.height = 0;
return r;
}
final Rectangle b = area.createTransformedArea(this.at).getBounds();
if (null == r) return b;
r.setBounds(b.x, b.y, b.width, b.height);
return r;
}
/**
* Draws the frame.
*
* @param g2 the graphics target.
* @param plot the plot.
* @param frame the dial's reference frame.
* @param view the dial's view rectangle.
*/
public void draw(Graphics2D g2, DialPlot plot, Rectangle2D frame,
Rectangle2D view) {
Shape window = getWindow(frame);
Shape outerWindow = getOuterWindow(frame);
Area area1 = new Area(outerWindow);
Area area2 = new Area(window);
area1.subtract(area2);
g2.setPaint(Color.lightGray);
g2.fill(area1);
g2.setStroke(this.stroke);
g2.setPaint(this.foregroundPaint);
g2.draw(window);
g2.draw(outerWindow);
}
/**
* Retrieve the competitors intersected by the provided horizontal slice.
*
* @param area the horizontal slice
* @return the list of competitors, sorted by abscissa.
*/
private List<Inter> getCompetitorsSlice (Area area)
{
List<Inter> rawComps = Inters.intersectedInters(
systemCompetitors,
GeoOrder.BY_ORDINATE,
area);
// Keep only the "really good" competitors
List<Inter> kept = new ArrayList<>();
for (Inter inter : rawComps) {
if (inter.isGood()) {
kept.add(inter);
}
}
// Sort by abscissa for more efficient lookup
Collections.sort(kept, Inters.byAbscissa);
return kept;
}
/**
* This constructor supports shape definition via an ellipse
*
* @param oSource
* @param boEllipse
* @param clipping
*/
public ShapedAction( StructureSource oSource, Bounds boEllipse,
Shape clipping )
{
_oSource = oSource;
if ( clipping != null )
{
Area ar1 = new Area( clipping );
Area ar2 = new Area( new Ellipse2D.Double( boEllipse.getLeft( ),
boEllipse.getTop( ),
boEllipse.getWidth( ),
boEllipse.getHeight( ) ) );
ar2.intersect( ar1 );
_sh = ar2;
}
else
{
_sh = new Ellipse2D.Double( boEllipse.getLeft( ),
boEllipse.getTop( ),
boEllipse.getWidth( ),
boEllipse.getHeight( ) );
}
}
/**
* Draws the frame.
*
* @param g2 the graphics target.
* @param plot the plot.
* @param frame the dial's reference frame.
* @param view the dial's view rectangle.
*/
@Override
public void draw(Graphics2D g2, DialPlot plot, Rectangle2D frame,
Rectangle2D view) {
Shape window = getWindow(frame);
Shape outerWindow = getOuterWindow(frame);
Area area1 = new Area(outerWindow);
Area area2 = new Area(window);
area1.subtract(area2);
g2.setPaint(Color.lightGray);
g2.fill(area1);
g2.setStroke(this.stroke);
g2.setPaint(this.foregroundPaint);
g2.draw(window);
g2.draw(outerWindow);
}
public static Shape subtractClip ( final Graphics g, final Shape clip, final boolean shouldSetup )
{
if ( shouldSetup && clip != null )
{
final Shape oldClip = g.getClip ();
if ( oldClip != null )
{
// Area-based substraction
final Area finalClip = new Area ( oldClip );
finalClip.subtract ( new Area ( clip ) );
g.setClip ( finalClip );
}
return oldClip;
}
else
{
return null;
}
}
/** Find ZDisplayable objects of the given class that intersect the given area in the given layer.
* If @param instance_of is true, use c.isAssignableFrom instead of class equality. */
public Collection<Displayable> findZDisplayables(final Class<?> c, final Layer layer, final Area aroi, final boolean visible_only, final boolean instance_of) {
final LayerBucket lb;
synchronized (lbucks) {
lb = lbucks.get(layer);
}
if (null != lb) return lb.root.find(c, aroi, layer, visible_only, instance_of);
else nbmsg(layer);
final ArrayList<Displayable> al = new ArrayList<Displayable>();
for (final ZDisplayable zd : al_zdispl) {
if (visible_only && !zd.isVisible()) continue;
if (instance_of) {
if (!c.isAssignableFrom(zd.getClass())) continue;
} else if (zd.getClass() != c) continue;
if (zd.intersects(layer, aroi)) al.add(zd);
}
return al;
}
/**
* Check whether the gap between curve and candidate arc is acceptable, taking any
* hidden inter into account.
* To do so, we use a "line area" between curve and arc and fill it with hidden items.
* We then check the widest true gap against maximum acceptable value.
*
* @param curve curve to extend
* @param arcView candidate arc
* @param hiddenInters relevant hidden inters
* @return true for acceptable, false otherwise
*/
private boolean isGapAcceptable (Curve curve,
ArcView arcView)
{
Point ce = curve.getEnd(reverse);
if (ce == null) {
ce = curve.getJunction(reverse);
}
Point ae = arcView.getEnd(!reverse);
if (ae == null) {
ae = arcView.getJunction(!reverse);
}
// Check for adjacent points
if ((Math.abs(ae.x - ce.x) <= 1) && (Math.abs(ae.y - ce.y) <= 1)) {
logger.debug("Adjacent points {} {}", ce, ae);
return true;
}
CurveGap gap = CurveGap.create(ce, ae);
Area lArea = gap.getArea();
curve.addAttachment("G", lArea);
int[] vector = gap.computeVector(binaryBuf);
int hole = gap.getLargestGap();
logger.debug("{} {} rev:{} {} hole:{}", curve, arcView.getArc(), reverse, vector, hole);
return hole <= params.gapMaxLength;
}
/**
* Draws the needle.
*
* @param g2 the graphics device.
* @param plotArea the plot area.
* @param rotate the rotation point.
* @param angle the angle.
*/
@Override
protected void drawNeedle(Graphics2D g2, Rectangle2D plotArea,
Point2D rotate, double angle) {
Arc2D shape = new Arc2D.Double(Arc2D.PIE);
double radius = plotArea.getHeight();
double halfX = plotArea.getWidth() / 2;
double diameter = 2 * radius;
shape.setFrame(plotArea.getMinX() + halfX - radius ,
plotArea.getMinY() - radius,
diameter, diameter);
radius = Math.toDegrees(Math.asin(halfX / radius));
shape.setAngleStart(270 - radius);
shape.setAngleExtent(2 * radius);
Area s = new Area(shape);
if ((rotate != null) && (angle != 0)) {
/// we have rotation houston, please spin me
getTransform().setToRotation(angle, rotate.getX(), rotate.getY());
s.transform(getTransform());
}
defaultDisplay(g2, s);
}
/**
* Select the best slur in clump (within current system).
*
* @param areas the lookup areas for each candidate
* @return the entry for best slur and its best links
*/
public SlurEntry selectSlur (Map<Inter, Map<HorizontalSide, Area>> areas)
{
// Determine the pair of best links for every slur candidate
List<SlurEntry> entries = new ArrayList<>();
for (Inter inter : clump) {
SlurInter slur = (SlurInter) inter;
// Determine the pair of best links (left & right) for this slur candidate
Map<HorizontalSide, SlurHeadLink> linkPair = slurLinker.lookupLinkPair(
slur,
areas.get(slur),
system,
chords);
if (linkPair != null) {
entries.add(new SlurEntry(slur, linkPair));
}
}
// Make a selection among clump slurs
// Choose (among the longest ones) the slur with best links
// Accept orphan only if quorum slurs agree
// Retrieve non-orphans
List<SlurEntry> nonOrphans = getNonOrphans(entries);
SlurEntry bestEntry = selectAmong(nonOrphans);
if (bestEntry != null) {
return bestEntry;
}
entries.removeAll(nonOrphans);
return selectAmong(entries);
}
/**
* Draws the needle.
*
* @param g2 the graphics device.
* @param plotArea the plot area.
* @param rotate the rotation point.
* @param angle the angle.
*/
@Override
protected void drawNeedle(Graphics2D g2, Rectangle2D plotArea,
Point2D rotate, double angle) {
Arc2D shape = new Arc2D.Double(Arc2D.PIE);
double radius = plotArea.getHeight();
double halfX = plotArea.getWidth() / 2;
double diameter = 2 * radius;
shape.setFrame(plotArea.getMinX() + halfX - radius ,
plotArea.getMinY() - radius,
diameter, diameter);
radius = Math.toDegrees(Math.asin(halfX / radius));
shape.setAngleStart(270 - radius);
shape.setAngleExtent(2 * radius);
Area s = new Area(shape);
if ((rotate != null) && (angle != 0)) {
/// we have rotation houston, please spin me
getTransform().setToRotation(angle, rotate.getX(), rotate.getY());
s.transform(getTransform());
}
defaultDisplay(g2, s);
}
@Override
protected Shape createShape() {
Area route = new Area();
GeoPoint previousPoint = null;
for (int i = 0; i < points.size(); i++) {
GeoPoint point = points.get(i);
/*
if (i > 0 && i < points.size() - 1) {
GeoEllipse ellipse = new GeoEllipse(point, widthMeters, widthMeters, maxDistanceMeters,
flatnessDistanceMeters, limit);
route.add(new Area(ellipse));
}
* */
if (previousPoint != null) {
// Skip if points are the same -- doesn't take into account height difference
if(previousPoint.equals(point))
continue;
// Draw rectangle connection
GeoBlock2 block = new GeoBlock2(previousPoint, point, this.leftWidthMeters, this.rightWidthMeters, maxDistanceMeters,
flatnessDistanceMeters, limit);
Area area = new Area(block);
route.add(area);
}
previousPoint = point;
}
return route;
}
/**
* Paints complex component area.
*
* @param g2d graphics context
* @param insets area insets
* @param outer outer area bounds
* @param inner inner area bounds
* @param color area color
*/
private void paintComplexArea ( @NotNull final Graphics2D g2d, @NotNull final Insets insets, @NotNull final Rectangle outer,
@NotNull final Rectangle inner, @NotNull final Color color )
{
if ( !insets.equals ( emptyInsets ) )
{
g2d.setPaint ( color );
final Area ma = new Area ( outer );
ma.exclusiveOr ( new Area ( inner ) );
g2d.fill ( ma );
}
}
boolean intersects(final Area area, final double z_first, final double z_last) {
for (int i=0; i<n_points; i++) {
final Layer la = layer_set.getLayer(p_layer[i]);
if (la.getZ() >= z_first && la.getZ() <= z_last) {
for (int k=0; k<n_points; k++) {
if (area.contains(p[0][k], p[1][k])) return true;
}
}
}
return false;
}
/**
* Check whether the (beam) side designated by provided point and height values
* lies fully in the current system
*
* @param pt side point on median
* @param height beam height
* @return true if side is fully within current system, false otherwise
*/
boolean isSideInSystem (Point2D pt,
double height)
{
Area area = system.getArea();
// Check top and bottom points of the beam side
for (int dir : new int[]{-1, +1}) {
if (!area.contains(pt.getX(), pt.getY() + (dir * (height / 2)))) {
return false;
}
}
return true;
}
@Override public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) {
Graphics2D g2 = (Graphics2D) g.create();
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
double r = 12d;
double w = width - 1d;
double h = height - 1d;
Path2D p = new Path2D.Double();
p.moveTo(x, y + h);
p.lineTo(x, y + r);
p.quadTo(x, y, x + r, y);
p.lineTo(x + w - r, y);
p.quadTo(x + w, y, x + w, y + r);
p.lineTo(x + w, y + h);
p.closePath();
Area round = new Area(p);
// Area round = new Area(new RoundRectangle2D.Double(x, y, w, h, r, r));
// Rectangle b = round.getBounds();
// b.setBounds(b.x, b.y + r, b.width, b.height - r);
// round.add(new Area(b));
Container parent = c.getParent();
if (Objects.nonNull(parent)) {
g2.setPaint(parent.getBackground());
Area corner = new Area(new Rectangle2D.Double(x, y, width, height));
corner.subtract(round);
g2.fill(corner);
}
// g2.setPaint(tp);
// g2.fill(round);
g2.setPaint(c.getForeground());
g2.draw(round);
g2.dispose();
}
/** Add an area that needs to be transformed by tmp first to bring it to world coordinates;
* will MODIFY the to_world AffineTransform object. */
public void add(final Area a, final AffineTransform to_world) {
try {
to_world.preConcatenate(source.getAffineTransform().createInverse());
this.area.add(a.createTransformedArea(to_world));
} catch (NoninvertibleTransformException nite) { IJError.print(nite); }
}
/**
* Define the lookup area on given corner, knowing the reference point of the
* entity (head).
* Global slope is used (plus and minus slopeMargin).
*
* @return the lookup area
*/
private Area getLuArea ()
{
final double slope = skew.getSlope();
final double dSlope = -xDir * yDir * params.slopeMargin;
final Point2D outPt = getOutPoint();
final Point2D inPt = getInPoint();
// Look Up path, start by head horizontal segment
final Path2D lu = new Path2D.Double();
lu.moveTo(outPt.getX(), outPt.getY());
lu.lineTo(inPt.getX(), inPt.getY());
// Then segment away from head (system limit)
final Rectangle systemBox = system.getBounds();
final double yLimit = (yDir > 0) ? systemBox.getMaxY() : systemBox.getMinY();
final double dy = yLimit - outPt.getY();
lu.lineTo(inPt.getX() + ((slope + dSlope) * dy), yLimit);
lu.lineTo(outPt.getX() + ((slope - dSlope) * dy), yLimit);
lu.closePath();
// Attachment
StringBuilder sb = new StringBuilder();
sb.append((corner.vSide == TOP) ? "T" : "B");
sb.append((corner.hSide == LEFT) ? "L" : "R");
head.addAttachment(sb.toString(), lu);
return new Area(lu);
}
/**
* Look up for potential Beam-Stem links around this Beam instance.
* <p>
* This method used to check for stems only on beam left and right sides.
* Now, it check also for stems within the whole beam width.
*
* @param systemStems all stems in system, sorted by abscissa
* @param system containing system
* @return the potential links
*/
private Collection<Link> lookupLinks (List<Inter> systemStems,
SystemInfo system)
{
if (systemStems.isEmpty()) {
return Collections.emptySet();
}
if (isVip()) {
logger.info("VIP lookupLinks for {}", this);
}
final List<Link> links = new ArrayList<>();
final Scale scale = system.getSheet().getScale();
final Area luArea = getLookupArea(scale);
List<Inter> stems = Inters.intersectedInters(systemStems, GeoOrder.NONE, luArea);
for (Inter inter : stems) {
StemInter stem = (StemInter) inter;
Point2D stemMiddle = PointUtil.middle(stem.getMedian());
VerticalSide vSide = (median.relativeCCW(stemMiddle) > 0) ? TOP : BOTTOM;
Link link = checkLink(stem, vSide, scale);
if (link != null) {
links.add(link);
}
}
return links;
}