📄 arc2d.java
字号:
return result; } /** * Construct a bounding box in a precision appropriate for the subclass. * * @param x the x coordinate * @param y the y coordinate * @param w the width * @param h the height * @return the rectangle for use in getBounds2D */ protected abstract Rectangle2D makeBounds(double x, double y, double w, double h); /** * Tests if the given angle, in degrees, is included in the arc. * All angles are normalized to be between 0 and 360 degrees. * * @param a the angle to test * @return true if it is contained */ public boolean containsAngle(double a) { double start = getAngleStart(); double end = start + getAngleExtent(); start %= 360; if (start < 0) start += 360; end %= 360; if (end < 0) end += 360; a %= 360; if (a < 0) a += 360; return a >= start && a <= end; } /** * Determines if the arc contains the given point. If the bounding box * is empty, then this will return false. * * @param x the x coordinate to test * @param y the y coordinate to test * @return true if the point is inside the arc */ public boolean contains(double x, double y) { double w = getWidth(); double h = getHeight(); if (w <= 0 || h <= 0) return false; // XXX Finish implementing. throw new Error("not implemented"); } /** * Tests if a given rectangle intersects the area of the arc. * * @param x the x coordinate of the rectangle * @param y the y coordinate of the rectangle * @param w the width of the rectangle * @param h the height of the rectangle * @return true if the two shapes share common points */ public boolean intersects(double x, double y, double w, double h) { double mw = getWidth(); double mh = getHeight(); if (mw <= 0 || mh <= 0 || w <= 0 || h <= 0) return false; // XXX Finish implementing. throw new Error("not implemented"); } /** * Tests if a given rectangle is contained in the area of the arc. * * @param x the x coordinate of the rectangle * @param y the y coordinate of the rectangle * @param w the width of the rectangle * @param h the height of the rectangle * @return true if the arc contains the rectangle */ public boolean contains(double x, double y, double w, double h) { double mw = getWidth(); double mh = getHeight(); if (mw <= 0 || mh <= 0 || w <= 0 || h <= 0) return false; // XXX Finish implementing. throw new Error("not implemented"); } /** * Tests if a given rectangle is contained in the area of the arc. * * @param r the rectangle * @return true if the arc contains the rectangle */ public boolean contains(Rectangle2D r) { return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } /** * Returns an iterator over this arc, with an optional transformation. * This iterator is threadsafe, so future modifications to the arc do not * affect the iteration. * * @param at the transformation, or null * @return a path iterator */ public PathIterator getPathIterator(AffineTransform at) { return new ArcIterator(this, at); } /** * This class is used to iterate over an arc. Since ellipses are a subclass * of arcs, this is used by Ellipse2D as well. * * @author Eric Blake <ebb9@email.byu.edu> */ static final class ArcIterator implements PathIterator { /** The current iteration. */ private int current; /** The last iteration. */ private final int limit; /** The optional transformation. */ private final AffineTransform xform; /** The x coordinate of the bounding box. */ private final double x; /** The y coordinate of the bounding box. */ private final double y; /** The width of the bounding box. */ private final double w; /** The height of the bounding box. */ private final double h; /** The start angle, in radians (not degrees). */ private final double start; /** The extent angle, in radians (not degrees). */ private final double extent; /** The arc closure type. */ private final int type; /** * Construct a new iterator over an arc. * * @param a the arc * @param xform the transform */ ArcIterator(Arc2D a, AffineTransform xform) { this.xform = xform; x = a.getX(); y = a.getY(); w = a.getWidth(); h = a.getHeight(); start = a.getAngleStart() * (Math.PI / 180); extent = a.getAngleExtent() * (Math.PI / 180); type = a.type; double e = extent < 0 ? -extent : extent; if (w < 0 || h < 0) limit = -1; else if (e == 0) limit = type; else if (e <= Math.PI / 2.0) limit = type + 1; else if (e <= Math.PI) limit = type + 2; else if (e <= 3.0 * (Math.PI / 2.0)) limit = type + 3; else limit = type + 4; } /** * Construct a new iterator over an ellipse. * * @param e the ellipse * @param xform the transform */ ArcIterator(Ellipse2D e, AffineTransform xform) { this.xform = xform; x = e.getX(); y = e.getY(); w = e.getWidth(); h = e.getHeight(); start = 0; extent = -2 * Math.PI; type = CHORD; limit = (w < 0 || h < 0) ? -1 : 5; } /** * Return the winding rule. * * @return {@link PathIterator#WIND_NON_ZERO} */ public int getWindingRule() { return WIND_NON_ZERO; } /** * Test if the iteration is complete. * * @return true if more segments exist */ public boolean isDone() { return current > limit; } /** * Advance the iterator. */ public void next() { current++; } /** * Put the current segment into the array, and return the segment type. * * @param coords an array of 6 elements * @return the segment type * @throws NullPointerException if coords is null * @throws ArrayIndexOutOfBoundsException if coords is too small */ public int currentSegment(float[] coords) { double[] double_coords = new double[6]; int code = currentSegment (double_coords); for (int i = 0; i < 6; ++i) coords[i] = (float) double_coords[i]; return code; } /** * Put the current segment into the array, and return the segment type. * * @param coords an array of 6 elements * @return the segment type * @throws NullPointerException if coords is null * @throws ArrayIndexOutOfBoundsException if coords is too small */ public int currentSegment(double[] coords) { double rx = w/2; double ry = h/2; double xmid = x + rx; double ymid = y + ry; if (current > limit) throw new NoSuchElementException("arc iterator out of bounds"); if (current == 0) { coords[0] = xmid + rx * Math.cos(start); coords[1] = ymid - ry * Math.sin(start); if (xform != null) xform.transform(coords, 0, coords, 0, 1); return SEG_MOVETO; } if (type != OPEN && current == limit) return SEG_CLOSE; if ((current == limit - 1) && (type == PIE) || (type == CHORD)) { if (type == PIE) { coords[0] = xmid; coords[1] = ymid; } else if (type == CHORD) { coords[0] = xmid + rx * Math.cos(start); coords[1] = ymid - ry * Math.sin(start); } if (xform != null) xform.transform(coords, 0, coords, 0, 1); return SEG_LINETO; } // note that this produces a cubic approximation of the arc segment, // not a true ellipsoid. there's no ellipsoid path segment code, // unfortunately. the cubic approximation looks about right, though. double kappa = (Math.sqrt(2.0) - 1.0) * (4.0 / 3.0); double quad = (Math.PI / 2.0); double curr_begin = start + (current - 1) * quad; double curr_extent = Math.min((start + extent) - curr_begin, quad); double portion_of_a_quadrant = curr_extent / quad; double x0 = xmid + rx * Math.cos(curr_begin); double y0 = ymid - ry * Math.sin(curr_begin); double x1 = xmid + rx * Math.cos(curr_begin + curr_extent); double y1 = ymid - ry * Math.sin(curr_begin + curr_extent); AffineTransform trans = new AffineTransform (); double [] cvec = new double[2]; double len = kappa * portion_of_a_quadrant; double angle = curr_begin; // in a hypothetical "first quadrant" setting, our first control // vector would be sticking up, from [1,0] to [1,kappa]. // // let us recall however that in java2d, y coords are upside down // from what one would consider "normal" first quadrant rules, so we // will *subtract* the y value of this control vector from our first // point. cvec[0] = 0; cvec[1] = len; trans.scale (rx, ry); trans.rotate (angle); trans.transform(cvec, 0, cvec, 0, 1); coords[0] = x0 + cvec[0]; coords[1] = y0 - cvec[1]; // control vector #2 would, ideally, be sticking out and to the // right, in a first quadrant arc segment. again, subtraction of y. cvec[0] = 0; cvec[1] = -len; trans.rotate (curr_extent); trans.transform(cvec, 0, cvec, 0, 1); coords[2] = x1 + cvec[0]; coords[3] = y1 - cvec[1]; // end point coords[4] = x1; coords[5] = y1; if (xform != null) xform.transform(coords, 0, coords, 0, 3); return SEG_CUBICTO; } } // class ArcIterator /** * This class implements an arc in double precision. * * @author Eric Blake <ebb9@email.byu.edu * @since 1.2 */ public static class Double extends Arc2D { /** The x coordinate of the box bounding the ellipse of this arc. */ public double x; /** The y coordinate of the box bounding the ellipse of this arc. */ public double y; /** The width of the box bounding the ellipse of this arc. */ public double width; /** The height of the box bounding the ellipse of this arc. */ public double height; /** The start angle of this arc, in degrees. */ public double start; /** The extent angle of this arc, in degrees. */ public double extent; /** * Create a new, open arc at (0,0) with 0 extent. */ public Double() { super(OPEN); } /** * Create a new arc of the given type at (0,0) with 0 extent. * * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} * @throws IllegalArgumentException if type is invalid
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -