📄 area.java
字号:
/* * @(#)Area.java 1.14 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */package java.awt.geom;import java.awt.Shape;import java.awt.Rectangle;import java.util.Vector;import java.util.Enumeration;import java.util.NoSuchElementException;import sun.awt.geom.Curve;import sun.awt.geom.Crossings;import sun.awt.geom.AreaOp;/** * The <code>Area</code> class is a device-independent specification of an * arbitrarily-shaped area. The <code>Area</code> object is defined as an * object that performs certain binary CAG (Constructive Area Geometry) * operations on other area-enclosing geometries, such as rectangles, * ellipses, and polygons. The CAG operations are Add(union), Subtract, * Intersect, and ExclusiveOR. For example, an <code>Area</code> can be * made up of the area of a rectangle minus the area of an ellipse. */public class Area implements Shape, Cloneable { private static Vector EmptyCurves = new Vector(); private Vector curves; /** * Default constructor which creates an empty area. */ public Area() { curves = EmptyCurves; } /** * The <code>Area</code> class creates an area geometry from the * specified {@link Shape} object. The geometry is explicitly * closed, if the <code>Shape</code> is not already closed. The * fill rule (even-odd or winding) specified by the geometry of the * <code>Shape</code> is used to determine the resulting enclosed area. * @param s the <code>Shape</code> from which the area is constructed */ public Area(Shape s) { if (s instanceof Area) { curves = ((Area) s).curves; return; } curves = new Vector(); PathIterator pi = s.getPathIterator(null); int windingRule = pi.getWindingRule(); // coords array is big enough for holding: // coordinates returned from currentSegment (6) // OR // two subdivided quadratic curves (2+4+4=10) // AND // 0-1 horizontal splitting parameters // OR // 2 parametric equation derivative coefficients // OR // three subdivided cubic curves (2+6+6+6=20) // AND // 0-2 horizontal splitting parameters // OR // 3 parametric equation derivative coefficients double coords[] = new double[23]; double movx = 0, movy = 0; double curx = 0, cury = 0; double newx, newy; while (!pi.isDone()) { switch (pi.currentSegment(coords)) { case PathIterator.SEG_MOVETO: Curve.insertLine(curves, curx, cury, movx, movy); curx = movx = coords[0]; cury = movy = coords[1]; Curve.insertMove(curves, movx, movy); break; case PathIterator.SEG_LINETO: newx = coords[0]; newy = coords[1]; Curve.insertLine(curves, curx, cury, newx, newy); curx = newx; cury = newy; break; case PathIterator.SEG_QUADTO: newx = coords[2]; newy = coords[3]; Curve.insertQuad(curves, curx, cury, coords); curx = newx; cury = newy; break; case PathIterator.SEG_CUBICTO: newx = coords[4]; newy = coords[5]; Curve.insertCubic(curves, curx, cury, coords); curx = newx; cury = newy; break; case PathIterator.SEG_CLOSE: Curve.insertLine(curves, curx, cury, movx, movy); curx = movx; cury = movy; break; } pi.next(); } Curve.insertLine(curves, curx, cury, movx, movy); AreaOp operator; if (windingRule == PathIterator.WIND_EVEN_ODD) { operator = new AreaOp.EOWindOp(); } else { operator = new AreaOp.NZWindOp(); } curves = operator.calculate(this.curves, EmptyCurves); } /** * Adds the shape of the specified <code>Area</code> to the * shape of this <code>Area</code>. * Addition is achieved through union. * @param rhs the <code>Area</code> to be added to the * current shape */ public void add(Area rhs) { curves = new AreaOp.AddOp().calculate(this.curves, rhs.curves); invalidateBounds(); } /** * Subtracts the shape of the specified <code>Area</code> from the * shape of this <code>Area</code>. * @param rhs the <code>Area</code> to be subtracted from the * current shape */ public void subtract(Area rhs) { curves = new AreaOp.SubOp().calculate(this.curves, rhs.curves); invalidateBounds(); } /** * Sets the shape of this <code>Area</code> to the intersection of * its current shape and the shape of the specified <code>Area</code>. * @param rhs the <code>Area</code> to be intersected with this * <code>Area</code> */ public void intersect(Area rhs) { curves = new AreaOp.IntOp().calculate(this.curves, rhs.curves); invalidateBounds(); } /** * Sets the shape of this <code>Area</code> to be the combined area * of its current shape and the shape of the specified <code>Area</code>, * minus their intersection. * @param rhs the <code>Area</code> to be exclusive ORed with this * <code>Area</code>. */ public void exclusiveOr(Area rhs) { curves = new AreaOp.XorOp().calculate(this.curves, rhs.curves); invalidateBounds(); } /** * Removes all of the geometry from this <code>Area</code> and * restores it to an empty area. */ public void reset() { curves = new Vector(); invalidateBounds(); } /** * Tests whether this <code>Area</code> object encloses any area. * @return <code>true</code> if this <code>Area</code> object * represents an empty area; <code>false</code> otherwise. */ public boolean isEmpty() { return (curves.size() == 0); } /** * Tests whether this <code>Area</code> consists entirely of * straight edged polygonal geometry. * @return <code>true</code> if the geometry of this * <code>Area</code> consists entirely of line segments; * <code>false</code> otherwise. */ public boolean isPolygonal() { Enumeration enum = curves.elements(); while (enum.hasMoreElements()) { if (((Curve) enum.nextElement()).getOrder() > 1) { return false; } } return true; } /** * Tests whether this <code>Area</code> is rectangular in shape. * @return <code>true</code> if the geometry of this * <code>Area</code> is rectangular in shape; <code>false</code> * otherwise. */ public boolean isRectangular() { int size = curves.size(); if (size == 0) { return true; } if (size > 3) { return false; } Curve c1 = (Curve) curves.get(1); Curve c2 = (Curve) curves.get(2); if (c1.getOrder() != 1 || c2.getOrder() != 1) { return false; } if (c1.getXTop() != c1.getXBot() || c2.getXTop() != c2.getXBot()) { return false; } if (c1.getYTop() != c2.getYTop() || c1.getYBot() != c2.getYBot()) { // One might be able to prove that this is impossible... return false; } return true; } /** * Tests whether this <code>Area</code> is comprised of a single * closed subpath. This method returns <code>true</code> if the * path contains 0 or 1 subpaths, or <code>false</code> if the path * contains more than 1 subpath. The subpaths are counted by the * number of {@link PathIterator#SEG_MOVETO SEG_MOVETO} segments * that appear in the path. * @return <code>true</code> if the <code>Area</code> is comprised * of a single basic geometry; <code>false</code> otherwise. */ public boolean isSingular() { if (curves.size() < 3) { return true; } Enumeration enum = curves.elements(); enum.nextElement(); // First Order0 "moveto" while (enum.hasMoreElements()) { if (((Curve) enum.nextElement()).getOrder() == 0) { return false; } } return true; } private Rectangle2D cachedBounds; private void invalidateBounds() { cachedBounds = null; } private Rectangle2D getCachedBounds() { if (cachedBounds != null) { return cachedBounds; } Rectangle2D r = new Rectangle2D.Double(); if (curves.size() > 0) { Curve c = (Curve) curves.get(0); // First point is always an order 0 curve (moveto) r.setRect(c.getX0(), c.getY0(), 0, 0); for (int i = 1; i < curves.size(); i++) { ((Curve) curves.get(i)).enlarge(r); } } return (cachedBounds = r); } /** * Returns a high precision bounding {@link Rectangle2D} that * completely encloses this <code>Area</code>. * <p> * The Area class will attempt to return the tightest bounding * box possible for the Shape. The bounding box will not be * padded to include the control points of curves in the outline * of the Shape, but should tightly fit the actual geometry of * the outline itself. * @return the bounding <code>Rectangle2D</code> for the * <code>Area</code>. */ public Rectangle2D getBounds2D() { return getCachedBounds().getBounds2D(); } /** * Returns a bounding {@link Rectangle} that completely encloses * this <code>Area</code>. * <p> * The Area class will attempt to return the tightest bounding * box possible for the Shape. The bounding box will not be * padded to include the control points of curves in the outline * of the Shape, but should tightly fit the actual geometry of
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -