📄 cubiccurve2d.java
字号:
* Determines whether any part of a Rectangle2D is inside the area bounded * by the curve and the straight line connecting its end points. * @see #intersects(double, double, double, double) */ public boolean intersects(Rectangle2D r) { return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } /** * Determine whether a rectangle is entirely inside the area that is bounded * by the curve and the straight line connecting its end points. * * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" * alt="A drawing of the area spanned by the curve" /> * * <p>The above drawing illustrates in which area points are * considered “inside” a CubicCurve2D. * @see #contains(double, double) */ public boolean contains(double x, double y, double w, double h) { if (! getBounds2D().intersects(x, y, w, h)) return false; /* Does any edge intersect? */ if (getAxisIntersections(x, y, true, w) != 0 /* top */ || getAxisIntersections(x, y + h, true, w) != 0 /* bottom */ || getAxisIntersections(x + w, y, false, h) != 0 /* right */ || getAxisIntersections(x, y, false, h) != 0) /* left */ return false; /* No intersections, is any point inside? */ if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0) return true; return false; } /** * Determine whether a Rectangle2D is entirely inside the area that is * bounded by the curve and the straight line connecting its end points. * * <p><img src="doc-files/CubicCurve2D-5.png" width="350" height="180" * alt="A drawing of the area spanned by the curve" /> * * <p>The above drawing illustrates in which area points are * considered “inside” a CubicCurve2D. * @see #contains(double, double) */ public boolean contains(Rectangle2D r) { return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); } /** * Determines the smallest rectangle that encloses the * curve’s start, end and control points. */ public Rectangle getBounds() { return getBounds2D().getBounds(); } public PathIterator getPathIterator(final AffineTransform at) { return new PathIterator() { /** Current coordinate. */ private int current = 0; public int getWindingRule() { return WIND_NON_ZERO; } public boolean isDone() { return current >= 2; } public void next() { current++; } public int currentSegment(float[] coords) { int result; switch (current) { case 0: coords[0] = (float) getX1(); coords[1] = (float) getY1(); result = SEG_MOVETO; break; case 1: coords[0] = (float) getCtrlX1(); coords[1] = (float) getCtrlY1(); coords[2] = (float) getCtrlX2(); coords[3] = (float) getCtrlY2(); coords[4] = (float) getX2(); coords[5] = (float) getY2(); result = SEG_CUBICTO; break; default: throw new NoSuchElementException("cubic iterator out of bounds"); } if (at != null) at.transform(coords, 0, coords, 0, 3); return result; } public int currentSegment(double[] coords) { int result; switch (current) { case 0: coords[0] = getX1(); coords[1] = getY1(); result = SEG_MOVETO; break; case 1: coords[0] = getCtrlX1(); coords[1] = getCtrlY1(); coords[2] = getCtrlX2(); coords[3] = getCtrlY2(); coords[4] = getX2(); coords[5] = getY2(); result = SEG_CUBICTO; break; default: throw new NoSuchElementException("cubic iterator out of bounds"); } if (at != null) at.transform(coords, 0, coords, 0, 3); return result; } }; } public PathIterator getPathIterator(AffineTransform at, double flatness) { return new FlatteningPathIterator(getPathIterator(at), flatness); } /** * Create a new curve with the same contents as this one. * * @return the clone. */ public Object clone() { try { return super.clone(); } catch (CloneNotSupportedException e) { throw (Error) new InternalError().initCause(e); // Impossible } } /** * Helper method used by contains() and intersects() methods, that * returns the number of curve/line intersections on a given axis * extending from a certain point. * * @param x x coordinate of the origin point * @param y y coordinate of the origin point * @param useYaxis axis used, if true the positive Y axis is used, * false uses the positive X axis. * * This is an implementation of the line-crossings algorithm, * Detailed in an article on Eric Haines' page: * http://www.acm.org/tog/editors/erich/ptinpoly/ * * A special-case not adressed in this code is self-intersections * of the curve, e.g. if the axis intersects the self-itersection, * the degenerate roots of the polynomial will erroneously count as * a single intersection of the curve, and not two. */ private int getAxisIntersections(double x, double y, boolean useYaxis, double distance) { int nCrossings = 0; double a0; double a1; double a2; double a3; double b0; double b1; double b2; double b3; double[] r = new double[4]; int nRoots; a0 = a3 = 0.0; if (useYaxis) { a0 = getY1() - y; a1 = getCtrlY1() - y; a2 = getCtrlY2() - y; a3 = getY2() - y; b0 = getX1() - x; b1 = getCtrlX1() - x; b2 = getCtrlX2() - x; b3 = getX2() - x; } else { a0 = getX1() - x; a1 = getCtrlX1() - x; a2 = getCtrlX2() - x; a3 = getX2() - x; b0 = getY1() - y; b1 = getCtrlY1() - y; b2 = getCtrlY2() - y; b3 = getY2() - y; } /* If the axis intersects a start/endpoint, shift it up by some small amount to guarantee the line is 'inside' If this is not done, bad behaviour may result for points on that axis.*/ if (a0 == 0.0 || a3 == 0.0) { double small = getFlatness() * EPSILON; if (a0 == 0.0) a0 -= small; if (a3 == 0.0) a3 -= small; } if (useYaxis) { if (Line2D.linesIntersect(b0, a0, b3, a3, EPSILON, 0.0, distance, 0.0)) nCrossings++; } else { if (Line2D.linesIntersect(a0, b0, a3, b3, 0.0, EPSILON, 0.0, distance)) nCrossings++; } r[0] = a0; r[1] = 3 * (a1 - a0); r[2] = 3 * (a2 + a0 - 2 * a1); r[3] = a3 - 3 * a2 + 3 * a1 - a0; if ((nRoots = solveCubic(r)) != 0) for (int i = 0; i < nRoots; i++) { double t = r[i]; if (t >= 0.0 && t <= 1.0) { double crossing = -(t * t * t) * (b0 - 3 * b1 + 3 * b2 - b3) + 3 * t * t * (b0 - 2 * b1 + b2) + 3 * t * (b1 - b0) + b0; if (crossing > 0.0 && crossing <= distance) nCrossings++; } } return (nCrossings); } /** * A two-dimensional curve that is parameterized with a cubic * function and stores coordinate values in double-precision * floating-point format. * * @see CubicCurve2D.Float * * @author Eric Blake (ebb9@email.byu.edu) * @author Sascha Brawer (brawer@dandelis.ch) */ public static class Double extends CubicCurve2D { /** * The <i>x</i> coordinate of the curve’s start point. */ public double x1; /** * The <i>y</i> coordinate of the curve’s start point. */ public double y1; /** * The <i>x</i> coordinate of the curve’s first control point. */ public double ctrlx1; /** * The <i>y</i> coordinate of the curve’s first control point. */ public double ctrly1; /** * The <i>x</i> coordinate of the curve’s second control point. */ public double ctrlx2; /** * The <i>y</i> coordinate of the curve’s second control point. */ public double ctrly2; /** * The <i>x</i> coordinate of the curve’s end point. */ public double x2; /** * The <i>y</i> coordinate of the curve’s end point. */ public double y2; /** * Constructs a new CubicCurve2D that stores its coordinate values * in double-precision floating-point format. All points are * initially at position (0, 0). */ public Double() { } /** * Constructs a new CubicCurve2D that stores its coordinate values * in double-precision floating-point format, specifying the * initial position of each point. * * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" * alt="A drawing of a CubicCurve2D" /> * * @param x1 the <i>x</i> coordinate of the curve’s start * point. * * @param y1 the <i>y</i> coordinate of the curve’s start * point. * * @param cx1 the <i>x</i> coordinate of the curve’s first * control point. * * @param cy1 the <i>y</i> coordinate of the curve’s first * control point. * * @param cx2 the <i>x</i> coordinate of the curve’s second * control point. * * @param cy2 the <i>y</i> coordinate of the curve’s second * control point. * * @param x2 the <i>x</i> coordinate of the curve’s end * point. * * @param y2 the <i>y</i> coordinate of the curve’s end * point. */ public Double(double x1, double y1, double cx1, double cy1, double cx2, double cy2, double x2, double y2) { this.x1 = x1; this.y1 = y1; ctrlx1 = cx1; ctrly1 = cy1; ctrlx2 = cx2; ctrly2 = cy2; this.x2 = x2; this.y2 = y2; } /** * Returns the <i>x</i> coordinate of the curve’s start * point. */ public double getX1() { return x1; } /** * Returns the <i>y</i> coordinate of the curve’s start * point. */ public double getY1() { return y1; } /** * Returns the curve’s start point. */ public Point2D getP1() { return new Point2D.Double(x1, y1); } /** * Returns the <i>x</i> coordinate of the curve’s first * control point. */ public double getCtrlX1() { return ctrlx1; } /** * Returns the <i>y</i> coordinate of the curve’s first * control point. */ public double getCtrlY1() { return ctrly1; } /** * Returns the curve’s first control point. */ public Point2D getCtrlP1() { return new Point2D.Double(ctrlx1, ctrly1); } /** * Returns the <i>x</i> coordinate of the curve’s second * control point. */ public double getCtrlX2() {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -