📄 generalpath.java
字号:
* within the path, <code>false</code> otherwise */ public boolean contains(Rectangle2D r) { return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } /** * Evaluates if a rectangle intersects the path. * @param x x coordinate of the rectangle * @param y y coordinate of the rectangle * @param w width of the rectangle * @param h height of the rectangle * @return <code>true</code> if the rectangle intersects the path, * <code>false</code> otherwise */ public boolean intersects(double x, double y, double w, double h) { /* Does any edge intersect? */ if (getAxisIntersections(x, y, false, w) != 0 /* top */ || getAxisIntersections(x, y + h, false, w) != 0 /* bottom */ || getAxisIntersections(x + w, y, true, h) != 0 /* right */ || getAxisIntersections(x, y, true, h) != 0) /* left */ return true; /* No intersections, is any point inside? */ if (getWindingNumber(x, y) != 0) return true; return false; } /** * Evaluates if a Rectangle2D intersects the path. * @param r The rectangle * @return <code>true</code> if the rectangle intersects the path, * <code>false</code> otherwise */ public boolean intersects(Rectangle2D r) { return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } /** * A PathIterator that iterates over the segments of a GeneralPath. * * @author Sascha Brawer (brawer@dandelis.ch) */ private static class GeneralPathIterator implements PathIterator { /** * The number of coordinate values for each segment type. */ private static final int[] NUM_COORDS = { /* 0: SEG_MOVETO */ 1, /* 1: SEG_LINETO */ 1, /* 2: SEG_QUADTO */ 2, /* 3: SEG_CUBICTO */ 3, /* 4: SEG_CLOSE */ 0}; /** * The GeneralPath whose segments are being iterated. * This is package-private to avoid an accessor method. */ final GeneralPath path; /** * The affine transformation used to transform coordinates. */ private final AffineTransform transform; /** * The current position of the iterator. */ private int pos; /** * Constructs a new iterator for enumerating the segments of a * GeneralPath. * * @param path the path to enumerate * @param transform an affine transformation for projecting the returned * points, or <code>null</code> to return the original points * without any mapping. */ GeneralPathIterator(GeneralPath path, AffineTransform transform) { this.path = path; this.transform = transform; } /** * Returns the current winding rule of the GeneralPath. */ public int getWindingRule() { return path.rule; } /** * Determines whether the iterator has reached the last segment in * the path. */ public boolean isDone() { return pos >= path.index; } /** * Advances the iterator position by one segment. */ public void next() { int seg; /* * Increment pos by the number of coordinate pairs. */ seg = path.types[pos]; if (seg == SEG_CLOSE) pos++; else pos += NUM_COORDS[seg]; } /** * Returns the current segment in float coordinates. */ public int currentSegment(float[] coords) { int seg; int numCoords; seg = path.types[pos]; numCoords = NUM_COORDS[seg]; if (numCoords > 0) { for (int i = 0; i < numCoords; i++) { coords[i << 1] = path.xpoints[pos + i]; coords[(i << 1) + 1] = path.ypoints[pos + i]; } if (transform != null) transform.transform( /* src */ coords, /* srcOffset */ 0, /* dest */ coords, /* destOffset */ 0, /* numPoints */ numCoords); } return seg; } /** * Returns the current segment in double coordinates. */ public int currentSegment(double[] coords) { int seg; int numCoords; seg = path.types[pos]; numCoords = NUM_COORDS[seg]; if (numCoords > 0) { for (int i = 0; i < numCoords; i++) { coords[i << 1] = (double) path.xpoints[pos + i]; coords[(i << 1) + 1] = (double) path.ypoints[pos + i]; } if (transform != null) transform.transform( /* src */ coords, /* srcOffset */ 0, /* dest */ coords, /* destOffset */ 0, /* numPoints */ numCoords); } return seg; } } /** * Creates a PathIterator for iterating along the segments of the path. * * @param at an affine transformation for projecting the returned * points, or <code>null</code> to let the created iterator return * the original points without any mapping. */ public PathIterator getPathIterator(AffineTransform at) { return new GeneralPathIterator(this, at); } /** * Creates a new FlatteningPathIterator for the path */ public PathIterator getPathIterator(AffineTransform at, double flatness) { return new FlatteningPathIterator(getPathIterator(at), flatness); } /** * Creates a new shape of the same run-time type with the same contents * as this one. * * @return the clone * * @exception OutOfMemoryError If there is not enough memory available. * * @since 1.2 */ public Object clone() { // This class is final; no need to use super.clone(). return new GeneralPath(this); } /** * Helper method - ensure the size of the data arrays, * otherwise, reallocate new ones twice the size */ private void ensureSize(int size) { if (subpath < 0) throw new IllegalPathStateException("need initial moveto"); if (size <= xpoints.length) return; byte[] b = new byte[types.length << 1]; System.arraycopy(types, 0, b, 0, index); types = b; float[] f = new float[xpoints.length << 1]; System.arraycopy(xpoints, 0, f, 0, index); xpoints = f; f = new float[ypoints.length << 1]; System.arraycopy(ypoints, 0, f, 0, index); ypoints = f; } /** * Helper method - Get the total number of intersections from (x,y) along * a given axis, within a given distance. */ private int getAxisIntersections(double x, double y, boolean useYaxis, double distance) { return (evaluateCrossings(x, y, false, useYaxis, distance)); } /** * Helper method - returns the winding number of a point. */ private int getWindingNumber(double x, double y) { /* Evaluate the crossings from x,y to infinity on the y axis (arbitrary choice). Note that we don't actually use Double.INFINITY, since that's slower, and may cause problems. */ return (evaluateCrossings(x, y, true, true, BIG_VALUE)); } /** * Helper method - evaluates the number of intersections on an axis from * the point (x,y) to the point (x,y+distance) or (x+distance,y). * @param x x coordinate. * @param y y coordinate. * @param neg True if opposite-directed intersections should cancel, * false to sum all intersections. * @param useYaxis Use the Y axis, false uses the X axis. * @param distance Interval from (x,y) on the selected axis to find * intersections. */ private int evaluateCrossings(double x, double y, boolean neg, boolean useYaxis, double distance) { float cx = 0.0f; float cy = 0.0f; float firstx = 0.0f; float firsty = 0.0f; int negative = (neg) ? -1 : 1; double x0; double x1; double x2; double x3; double y0; double y1; double y2; double y3; double[] r = new double[4]; int nRoots; double epsilon = 0.0; int pos = 0; int windingNumber = 0; boolean pathStarted = false; if (index == 0) return (0); if (useYaxis) { float[] swap1; swap1 = ypoints; ypoints = xpoints; xpoints = swap1; double swap2; swap2 = y; y = x; x = swap2; } /* Get a value which is hopefully small but not insignificant relative the path. */ epsilon = ypoints[0] * 1E-7; if(epsilon == 0) epsilon = 1E-7; pos = 0; while (pos < index) { switch (types[pos]) { case PathIterator.SEG_MOVETO: if (pathStarted) // close old path { x0 = cx; y0 = cy; x1 = firstx; y1 = firsty; if (y0 == 0.0) y0 -= epsilon; if (y1 == 0.0) y1 -= epsilon; if (Line2D.linesIntersect(x0, y0, x1, y1, epsilon, 0.0, distance, 0.0)) windingNumber += (y1 < y0) ? 1 : negative; cx = firstx; cy = firsty; } cx = firstx = xpoints[pos] - (float) x; cy = firsty = ypoints[pos++] - (float) y; pathStarted = true; break; case PathIterator.SEG_CLOSE: x0 = cx; y0 = cy; x1 = firstx; y1 = firsty; if (y0 == 0.0) y0 -= epsilon; if (y1 == 0.0) y1 -= epsilon; if (Line2D.linesIntersect(x0, y0, x1, y1, epsilon, 0.0, distance, 0.0)) windingNumber += (y1 < y0) ? 1 : negative; cx = firstx; cy = firsty; pos++; pathStarted = false; break; case PathIterator.SEG_LINETO: x0 = cx; y0 = cy; x1 = xpoints[pos] - (float) x; y1 = ypoints[pos++] - (float) y; if (y0 == 0.0) y0 -= epsilon; if (y1 == 0.0) y1 -= epsilon; if (Line2D.linesIntersect(x0, y0, x1, y1, epsilon, 0.0, distance, 0.0)) windingNumber += (y1 < y0) ? 1 : negative; cx = xpoints[pos - 1] - (float) x; cy = ypoints[pos - 1] - (float) y; break; case PathIterator.SEG_QUADTO: x0 = cx; y0 = cy; x1 = xpoints[pos] - x; y1 = ypoints[pos++] - y; x2 = xpoints[pos] - x; y2 = ypoints[pos++] - y; /* check if curve may intersect X+ axis. */ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0) && (y0 * y1 <= 0 || y1 * y2 <= 0)) { if (y0 == 0.0) y0 -= epsilon; if (y2 == 0.0) y2 -= epsilon; r[0] = y0; r[1] = 2 * (y1 - y0); r[2] = (y2 - 2 * y1 + y0); /* degenerate roots (=tangent points) do not contribute to the winding number. */ if ((nRoots = QuadCurve2D.solveQuadratic(r)) == 2) for (int i = 0; i < nRoots; i++) { float t = (float) r[i]; if (t > 0.0f && t < 1.0f) { double crossing = t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0) + x0; if (crossing >= 0.0 && crossing <= distance) windingNumber += (2 * t * (y2 - 2 * y1 + y0) + 2 * (y1 - y0) < 0) ? 1 : negative; } } } cx = xpoints[pos - 1] - (float) x; cy = ypoints[pos - 1] - (float) y; break; case PathIterator.SEG_CUBICTO: x0 = cx; y0 = cy; x1 = xpoints[pos] - x; y1 = ypoints[pos++] - y; x2 = xpoints[pos] - x; y2 = ypoints[pos++] - y; x3 = xpoints[pos] - x; y3 = ypoints[pos++] - y; /* check if curve may intersect X+ axis. */ if ((x0 > 0.0 || x1 > 0.0 || x2 > 0.0 || x3 > 0.0) && (y0 * y1 <= 0 || y1 * y2 <= 0 || y2 * y3 <= 0)) { if (y0 == 0.0) y0 -= epsilon; if (y3 == 0.0) y3 -= epsilon; r[0] = y0; r[1] = 3 * (y1 - y0); r[2] = 3 * (y2 + y0 - 2 * y1); r[3] = y3 - 3 * y2 + 3 * y1 - y0; if ((nRoots = CubicCurve2D.solveCubic(r)) != 0) for (int i = 0; i < nRoots; i++) { float t = (float) r[i]; if (t > 0.0 && t < 1.0) { double crossing = -(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3) + 3 * t * t * (x0 - 2 * x1 + x2) + 3 * t * (x1 - x0) + x0; if (crossing >= 0 && crossing <= distance) windingNumber += (3 * t * t * (y3 + 3 * y1 - 3 * y2 - y0) + 6 * t * (y0 - 2 * y1 + y2) + 3 * (y1 - y0) < 0) ? 1 : negative; } } } cx = xpoints[pos - 1] - (float) x; cy = ypoints[pos - 1] - (float) y; break; } } // swap coordinates back if (useYaxis) { float[] swap; swap = ypoints; ypoints = xpoints; xpoints = swap; } return (windingNumber); }} // class GeneralPath
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -