0001 /*
0002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
0003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0004 *
0005 * This code is free software; you can redistribute it and/or modify it
0006 * under the terms of the GNU General Public License version 2 only, as
0007 * published by the Free Software Foundation. Sun designates this
0008 * particular file as subject to the "Classpath" exception as provided
0009 * by Sun in the LICENSE file that accompanied this code.
0010 *
0011 * This code is distributed in the hope that it will be useful, but WITHOUT
0012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0014 * version 2 for more details (a copy is included in the LICENSE file that
0015 * accompanied this code).
0016 *
0017 * You should have received a copy of the GNU General Public License version
0018 * 2 along with this work; if not, write to the Free Software Foundation,
0019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0020 *
0021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
0022 * CA 95054 USA or visit www.sun.com if you need additional information or
0023 * have any questions.
0024 */
0025
0026 package java.awt.geom;
0027
0028 import java.awt.Shape;
0029 import java.awt.Rectangle;
0030 import java.io.Serializable;
0031 import sun.awt.geom.Curve;
0032
0033 /**
0034 * The <code>QuadCurve2D</code> class defines a quadratic parametric curve
0035 * segment in {@code (x,y)} coordinate space.
0036 * <p>
0037 * This class is only the abstract superclass for all objects that
0038 * store a 2D quadratic curve segment.
0039 * The actual storage representation of the coordinates is left to
0040 * the subclass.
0041 *
0042 * @version 1.40, 05/05/07
0043 * @author Jim Graham
0044 * @since 1.2
0045 */
0046 public abstract class QuadCurve2D implements Shape, Cloneable {
0047
0048 /**
0049 * A quadratic parametric curve segment specified with
0050 * {@code float} coordinates.
0051 *
0052 * @since 1.2
0053 */
0054 public static class Float extends QuadCurve2D implements
0055 Serializable {
0056 /**
0057 * The X coordinate of the start point of the quadratic curve
0058 * segment.
0059 * @since 1.2
0060 * @serial
0061 */
0062 public float x1;
0063
0064 /**
0065 * The Y coordinate of the start point of the quadratic curve
0066 * segment.
0067 * @since 1.2
0068 * @serial
0069 */
0070 public float y1;
0071
0072 /**
0073 * The X coordinate of the control point of the quadratic curve
0074 * segment.
0075 * @since 1.2
0076 * @serial
0077 */
0078 public float ctrlx;
0079
0080 /**
0081 * The Y coordinate of the control point of the quadratic curve
0082 * segment.
0083 * @since 1.2
0084 * @serial
0085 */
0086 public float ctrly;
0087
0088 /**
0089 * The X coordinate of the end point of the quadratic curve
0090 * segment.
0091 * @since 1.2
0092 * @serial
0093 */
0094 public float x2;
0095
0096 /**
0097 * The Y coordinate of the end point of the quadratic curve
0098 * segment.
0099 * @since 1.2
0100 * @serial
0101 */
0102 public float y2;
0103
0104 /**
0105 * Constructs and initializes a <code>QuadCurve2D</code> with
0106 * coordinates (0, 0, 0, 0, 0, 0).
0107 * @since 1.2
0108 */
0109 public Float() {
0110 }
0111
0112 /**
0113 * Constructs and initializes a <code>QuadCurve2D</code> from the
0114 * specified {@code float} coordinates.
0115 *
0116 * @param x1 the X coordinate of the start point
0117 * @param y1 the Y coordinate of the start point
0118 * @param ctrlx the X coordinate of the control point
0119 * @param ctrly the Y coordinate of the control point
0120 * @param x2 the X coordinate of the end point
0121 * @param y2 the Y coordinate of the end point
0122 * @since 1.2
0123 */
0124 public Float(float x1, float y1, float ctrlx, float ctrly,
0125 float x2, float y2) {
0126 setCurve(x1, y1, ctrlx, ctrly, x2, y2);
0127 }
0128
0129 /**
0130 * {@inheritDoc}
0131 * @since 1.2
0132 */
0133 public double getX1() {
0134 return (double) x1;
0135 }
0136
0137 /**
0138 * {@inheritDoc}
0139 * @since 1.2
0140 */
0141 public double getY1() {
0142 return (double) y1;
0143 }
0144
0145 /**
0146 * {@inheritDoc}
0147 * @since 1.2
0148 */
0149 public Point2D getP1() {
0150 return new Point2D.Float(x1, y1);
0151 }
0152
0153 /**
0154 * {@inheritDoc}
0155 * @since 1.2
0156 */
0157 public double getCtrlX() {
0158 return (double) ctrlx;
0159 }
0160
0161 /**
0162 * {@inheritDoc}
0163 * @since 1.2
0164 */
0165 public double getCtrlY() {
0166 return (double) ctrly;
0167 }
0168
0169 /**
0170 * {@inheritDoc}
0171 * @since 1.2
0172 */
0173 public Point2D getCtrlPt() {
0174 return new Point2D.Float(ctrlx, ctrly);
0175 }
0176
0177 /**
0178 * {@inheritDoc}
0179 * @since 1.2
0180 */
0181 public double getX2() {
0182 return (double) x2;
0183 }
0184
0185 /**
0186 * {@inheritDoc}
0187 * @since 1.2
0188 */
0189 public double getY2() {
0190 return (double) y2;
0191 }
0192
0193 /**
0194 * {@inheritDoc}
0195 * @since 1.2
0196 */
0197 public Point2D getP2() {
0198 return new Point2D.Float(x2, y2);
0199 }
0200
0201 /**
0202 * {@inheritDoc}
0203 * @since 1.2
0204 */
0205 public void setCurve(double x1, double y1, double ctrlx,
0206 double ctrly, double x2, double y2) {
0207 this .x1 = (float) x1;
0208 this .y1 = (float) y1;
0209 this .ctrlx = (float) ctrlx;
0210 this .ctrly = (float) ctrly;
0211 this .x2 = (float) x2;
0212 this .y2 = (float) y2;
0213 }
0214
0215 /**
0216 * Sets the location of the end points and control point of this curve
0217 * to the specified {@code float} coordinates.
0218 *
0219 * @param x1 the X coordinate of the start point
0220 * @param y1 the Y coordinate of the start point
0221 * @param ctrlx the X coordinate of the control point
0222 * @param ctrly the Y coordinate of the control point
0223 * @param x2 the X coordinate of the end point
0224 * @param y2 the Y coordinate of the end point
0225 * @since 1.2
0226 */
0227 public void setCurve(float x1, float y1, float ctrlx,
0228 float ctrly, float x2, float y2) {
0229 this .x1 = x1;
0230 this .y1 = y1;
0231 this .ctrlx = ctrlx;
0232 this .ctrly = ctrly;
0233 this .x2 = x2;
0234 this .y2 = y2;
0235 }
0236
0237 /**
0238 * {@inheritDoc}
0239 * @since 1.2
0240 */
0241 public Rectangle2D getBounds2D() {
0242 float left = Math.min(Math.min(x1, x2), ctrlx);
0243 float top = Math.min(Math.min(y1, y2), ctrly);
0244 float right = Math.max(Math.max(x1, x2), ctrlx);
0245 float bottom = Math.max(Math.max(y1, y2), ctrly);
0246 return new Rectangle2D.Float(left, top, right - left,
0247 bottom - top);
0248 }
0249
0250 /*
0251 * JDK 1.6 serialVersionUID
0252 */
0253 private static final long serialVersionUID = -8511188402130719609L;
0254 }
0255
0256 /**
0257 * A quadratic parametric curve segment specified with
0258 * {@code double} coordinates.
0259 *
0260 * @since 1.2
0261 */
0262 public static class Double extends QuadCurve2D implements
0263 Serializable {
0264 /**
0265 * The X coordinate of the start point of the quadratic curve
0266 * segment.
0267 * @since 1.2
0268 * @serial
0269 */
0270 public double x1;
0271
0272 /**
0273 * The Y coordinate of the start point of the quadratic curve
0274 * segment.
0275 * @since 1.2
0276 * @serial
0277 */
0278 public double y1;
0279
0280 /**
0281 * The X coordinate of the control point of the quadratic curve
0282 * segment.
0283 * @since 1.2
0284 * @serial
0285 */
0286 public double ctrlx;
0287
0288 /**
0289 * The Y coordinate of the control point of the quadratic curve
0290 * segment.
0291 * @since 1.2
0292 * @serial
0293 */
0294 public double ctrly;
0295
0296 /**
0297 * The X coordinate of the end point of the quadratic curve
0298 * segment.
0299 * @since 1.2
0300 * @serial
0301 */
0302 public double x2;
0303
0304 /**
0305 * The Y coordinate of the end point of the quadratic curve
0306 * segment.
0307 * @since 1.2
0308 * @serial
0309 */
0310 public double y2;
0311
0312 /**
0313 * Constructs and initializes a <code>QuadCurve2D</code> with
0314 * coordinates (0, 0, 0, 0, 0, 0).
0315 * @since 1.2
0316 */
0317 public Double() {
0318 }
0319
0320 /**
0321 * Constructs and initializes a <code>QuadCurve2D</code> from the
0322 * specified {@code double} coordinates.
0323 *
0324 * @param x1 the X coordinate of the start point
0325 * @param y1 the Y coordinate of the start point
0326 * @param ctrlx the X coordinate of the control point
0327 * @param ctrly the Y coordinate of the control point
0328 * @param x2 the X coordinate of the end point
0329 * @param y2 the Y coordinate of the end point
0330 * @since 1.2
0331 */
0332 public Double(double x1, double y1, double ctrlx, double ctrly,
0333 double x2, double y2) {
0334 setCurve(x1, y1, ctrlx, ctrly, x2, y2);
0335 }
0336
0337 /**
0338 * {@inheritDoc}
0339 * @since 1.2
0340 */
0341 public double getX1() {
0342 return x1;
0343 }
0344
0345 /**
0346 * {@inheritDoc}
0347 * @since 1.2
0348 */
0349 public double getY1() {
0350 return y1;
0351 }
0352
0353 /**
0354 * {@inheritDoc}
0355 * @since 1.2
0356 */
0357 public Point2D getP1() {
0358 return new Point2D.Double(x1, y1);
0359 }
0360
0361 /**
0362 * {@inheritDoc}
0363 * @since 1.2
0364 */
0365 public double getCtrlX() {
0366 return ctrlx;
0367 }
0368
0369 /**
0370 * {@inheritDoc}
0371 * @since 1.2
0372 */
0373 public double getCtrlY() {
0374 return ctrly;
0375 }
0376
0377 /**
0378 * {@inheritDoc}
0379 * @since 1.2
0380 */
0381 public Point2D getCtrlPt() {
0382 return new Point2D.Double(ctrlx, ctrly);
0383 }
0384
0385 /**
0386 * {@inheritDoc}
0387 * @since 1.2
0388 */
0389 public double getX2() {
0390 return x2;
0391 }
0392
0393 /**
0394 * {@inheritDoc}
0395 * @since 1.2
0396 */
0397 public double getY2() {
0398 return y2;
0399 }
0400
0401 /**
0402 * {@inheritDoc}
0403 * @since 1.2
0404 */
0405 public Point2D getP2() {
0406 return new Point2D.Double(x2, y2);
0407 }
0408
0409 /**
0410 * {@inheritDoc}
0411 * @since 1.2
0412 */
0413 public void setCurve(double x1, double y1, double ctrlx,
0414 double ctrly, double x2, double y2) {
0415 this .x1 = x1;
0416 this .y1 = y1;
0417 this .ctrlx = ctrlx;
0418 this .ctrly = ctrly;
0419 this .x2 = x2;
0420 this .y2 = y2;
0421 }
0422
0423 /**
0424 * {@inheritDoc}
0425 * @since 1.2
0426 */
0427 public Rectangle2D getBounds2D() {
0428 double left = Math.min(Math.min(x1, x2), ctrlx);
0429 double top = Math.min(Math.min(y1, y2), ctrly);
0430 double right = Math.max(Math.max(x1, x2), ctrlx);
0431 double bottom = Math.max(Math.max(y1, y2), ctrly);
0432 return new Rectangle2D.Double(left, top, right - left,
0433 bottom - top);
0434 }
0435
0436 /*
0437 * JDK 1.6 serialVersionUID
0438 */
0439 private static final long serialVersionUID = 4217149928428559721L;
0440 }
0441
0442 /**
0443 * This is an abstract class that cannot be instantiated directly.
0444 * Type-specific implementation subclasses are available for
0445 * instantiation and provide a number of formats for storing
0446 * the information necessary to satisfy the various accessor
0447 * methods below.
0448 *
0449 * @see java.awt.geom.QuadCurve2D.Float
0450 * @see java.awt.geom.QuadCurve2D.Double
0451 * @since 1.2
0452 */
0453 protected QuadCurve2D() {
0454 }
0455
0456 /**
0457 * Returns the X coordinate of the start point in
0458 * <code>double</code> in precision.
0459 * @return the X coordinate of the start point.
0460 * @since 1.2
0461 */
0462 public abstract double getX1();
0463
0464 /**
0465 * Returns the Y coordinate of the start point in
0466 * <code>double</code> precision.
0467 * @return the Y coordinate of the start point.
0468 * @since 1.2
0469 */
0470 public abstract double getY1();
0471
0472 /**
0473 * Returns the start point.
0474 * @return a <code>Point2D</code> that is the start point of this
0475 * <code>QuadCurve2D</code>.
0476 * @since 1.2
0477 */
0478 public abstract Point2D getP1();
0479
0480 /**
0481 * Returns the X coordinate of the control point in
0482 * <code>double</code> precision.
0483 * @return X coordinate the control point
0484 * @since 1.2
0485 */
0486 public abstract double getCtrlX();
0487
0488 /**
0489 * Returns the Y coordinate of the control point in
0490 * <code>double</code> precision.
0491 * @return the Y coordinate of the control point.
0492 * @since 1.2
0493 */
0494 public abstract double getCtrlY();
0495
0496 /**
0497 * Returns the control point.
0498 * @return a <code>Point2D</code> that is the control point of this
0499 * <code>Point2D</code>.
0500 * @since 1.2
0501 */
0502 public abstract Point2D getCtrlPt();
0503
0504 /**
0505 * Returns the X coordinate of the end point in
0506 * <code>double</code> precision.
0507 * @return the x coordiante of the end point.
0508 * @since 1.2
0509 */
0510 public abstract double getX2();
0511
0512 /**
0513 * Returns the Y coordinate of the end point in
0514 * <code>double</code> precision.
0515 * @return the Y coordinate of the end point.
0516 * @since 1.2
0517 */
0518 public abstract double getY2();
0519
0520 /**
0521 * Returns the end point.
0522 * @return a <code>Point</code> object that is the end point
0523 * of this <code>Point2D</code>.
0524 * @since 1.2
0525 */
0526 public abstract Point2D getP2();
0527
0528 /**
0529 * Sets the location of the end points and control point of this curve
0530 * to the specified <code>double</code> coordinates.
0531 *
0532 * @param x1 the X coordinate of the start point
0533 * @param y1 the Y coordinate of the start point
0534 * @param ctrlx the X coordinate of the control point
0535 * @param ctrly the Y coordinate of the control point
0536 * @param x2 the X coordinate of the end point
0537 * @param y2 the Y coordinate of the end point
0538 * @since 1.2
0539 */
0540 public abstract void setCurve(double x1, double y1, double ctrlx,
0541 double ctrly, double x2, double y2);
0542
0543 /**
0544 * Sets the location of the end points and control points of this
0545 * <code>QuadCurve2D</code> to the <code>double</code> coordinates at
0546 * the specified offset in the specified array.
0547 * @param coords the array containing coordinate values
0548 * @param offset the index into the array from which to start
0549 * getting the coordinate values and assigning them to this
0550 * <code>QuadCurve2D</code>
0551 * @since 1.2
0552 */
0553 public void setCurve(double[] coords, int offset) {
0554 setCurve(coords[offset + 0], coords[offset + 1],
0555 coords[offset + 2], coords[offset + 3],
0556 coords[offset + 4], coords[offset + 5]);
0557 }
0558
0559 /**
0560 * Sets the location of the end points and control point of this
0561 * <code>QuadCurve2D</code> to the specified <code>Point2D</code>
0562 * coordinates.
0563 * @param p1 the start point
0564 * @param cp the control point
0565 * @param p2 the end point
0566 * @since 1.2
0567 */
0568 public void setCurve(Point2D p1, Point2D cp, Point2D p2) {
0569 setCurve(p1.getX(), p1.getY(), cp.getX(), cp.getY(), p2.getX(),
0570 p2.getY());
0571 }
0572
0573 /**
0574 * Sets the location of the end points and control points of this
0575 * <code>QuadCurve2D</code> to the coordinates of the
0576 * <code>Point2D</code> objects at the specified offset in
0577 * the specified array.
0578 * @param pts an array containing <code>Point2D</code> that define
0579 * coordinate values
0580 * @param offset the index into <code>pts</code> from which to start
0581 * getting the coordinate values and assigning them to this
0582 * <code>QuadCurve2D</code>
0583 * @since 1.2
0584 */
0585 public void setCurve(Point2D[] pts, int offset) {
0586 setCurve(pts[offset + 0].getX(), pts[offset + 0].getY(),
0587 pts[offset + 1].getX(), pts[offset + 1].getY(),
0588 pts[offset + 2].getX(), pts[offset + 2].getY());
0589 }
0590
0591 /**
0592 * Sets the location of the end points and control point of this
0593 * <code>QuadCurve2D</code> to the same as those in the specified
0594 * <code>QuadCurve2D</code>.
0595 * @param c the specified <code>QuadCurve2D</code>
0596 * @since 1.2
0597 */
0598 public void setCurve(QuadCurve2D c) {
0599 setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(), c
0600 .getX2(), c.getY2());
0601 }
0602
0603 /**
0604 * Returns the square of the flatness, or maximum distance of a
0605 * control point from the line connecting the end points, of the
0606 * quadratic curve specified by the indicated control points.
0607 *
0608 * @param x1 the X coordinate of the start point
0609 * @param y1 the Y coordinate of the start point
0610 * @param ctrlx the X coordinate of the control point
0611 * @param ctrly the Y coordinate of the control point
0612 * @param x2 the X coordinate of the end point
0613 * @param y2 the Y coordinate of the end point
0614 * @return the square of the flatness of the quadratic curve
0615 * defined by the specified coordinates.
0616 * @since 1.2
0617 */
0618 public static double getFlatnessSq(double x1, double y1,
0619 double ctrlx, double ctrly, double x2, double y2) {
0620 return Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx, ctrly);
0621 }
0622
0623 /**
0624 * Returns the flatness, or maximum distance of a
0625 * control point from the line connecting the end points, of the
0626 * quadratic curve specified by the indicated control points.
0627 *
0628 * @param x1 the X coordinate of the start point
0629 * @param y1 the Y coordinate of the start point
0630 * @param ctrlx the X coordinate of the control point
0631 * @param ctrly the Y coordinate of the control point
0632 * @param x2 the X coordinate of the end point
0633 * @param y2 the Y coordinate of the end point
0634 * @return the flatness of the quadratic curve defined by the
0635 * specified coordinates.
0636 * @since 1.2
0637 */
0638 public static double getFlatness(double x1, double y1,
0639 double ctrlx, double ctrly, double x2, double y2) {
0640 return Line2D.ptSegDist(x1, y1, x2, y2, ctrlx, ctrly);
0641 }
0642
0643 /**
0644 * Returns the square of the flatness, or maximum distance of a
0645 * control point from the line connecting the end points, of the
0646 * quadratic curve specified by the control points stored in the
0647 * indicated array at the indicated index.
0648 * @param coords an array containing coordinate values
0649 * @param offset the index into <code>coords</code> from which to
0650 * to start getting the values from the array
0651 * @return the flatness of the quadratic curve that is defined by the
0652 * values in the specified array at the specified index.
0653 * @since 1.2
0654 */
0655 public static double getFlatnessSq(double coords[], int offset) {
0656 return Line2D.ptSegDistSq(coords[offset + 0],
0657 coords[offset + 1], coords[offset + 4],
0658 coords[offset + 5], coords[offset + 2],
0659 coords[offset + 3]);
0660 }
0661
0662 /**
0663 * Returns the flatness, or maximum distance of a
0664 * control point from the line connecting the end points, of the
0665 * quadratic curve specified by the control points stored in the
0666 * indicated array at the indicated index.
0667 * @param coords an array containing coordinate values
0668 * @param offset the index into <code>coords</code> from which to
0669 * start getting the coordinate values
0670 * @return the flatness of a quadratic curve defined by the
0671 * specified array at the specified offset.
0672 * @since 1.2
0673 */
0674 public static double getFlatness(double coords[], int offset) {
0675 return Line2D.ptSegDist(coords[offset + 0], coords[offset + 1],
0676 coords[offset + 4], coords[offset + 5],
0677 coords[offset + 2], coords[offset + 3]);
0678 }
0679
0680 /**
0681 * Returns the square of the flatness, or maximum distance of a
0682 * control point from the line connecting the end points, of this
0683 * <code>QuadCurve2D</code>.
0684 * @return the square of the flatness of this
0685 * <code>QuadCurve2D</code>.
0686 * @since 1.2
0687 */
0688 public double getFlatnessSq() {
0689 return Line2D.ptSegDistSq(getX1(), getY1(), getX2(), getY2(),
0690 getCtrlX(), getCtrlY());
0691 }
0692
0693 /**
0694 * Returns the flatness, or maximum distance of a
0695 * control point from the line connecting the end points, of this
0696 * <code>QuadCurve2D</code>.
0697 * @return the flatness of this <code>QuadCurve2D</code>.
0698 * @since 1.2
0699 */
0700 public double getFlatness() {
0701 return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(),
0702 getCtrlX(), getCtrlY());
0703 }
0704
0705 /**
0706 * Subdivides this <code>QuadCurve2D</code> and stores the resulting
0707 * two subdivided curves into the <code>left</code> and
0708 * <code>right</code> curve parameters.
0709 * Either or both of the <code>left</code> and <code>right</code>
0710 * objects can be the same as this <code>QuadCurve2D</code> or
0711 * <code>null</code>.
0712 * @param left the <code>QuadCurve2D</code> object for storing the
0713 * left or first half of the subdivided curve
0714 * @param right the <code>QuadCurve2D</code> object for storing the
0715 * right or second half of the subdivided curve
0716 * @since 1.2
0717 */
0718 public void subdivide(QuadCurve2D left, QuadCurve2D right) {
0719 subdivide(this , left, right);
0720 }
0721
0722 /**
0723 * Subdivides the quadratic curve specified by the <code>src</code>
0724 * parameter and stores the resulting two subdivided curves into the
0725 * <code>left</code> and <code>right</code> curve parameters.
0726 * Either or both of the <code>left</code> and <code>right</code>
0727 * objects can be the same as the <code>src</code> object or
0728 * <code>null</code>.
0729 * @param src the quadratic curve to be subdivided
0730 * @param left the <code>QuadCurve2D</code> object for storing the
0731 * left or first half of the subdivided curve
0732 * @param right the <code>QuadCurve2D</code> object for storing the
0733 * right or second half of the subdivided curve
0734 * @since 1.2
0735 */
0736 public static void subdivide(QuadCurve2D src, QuadCurve2D left,
0737 QuadCurve2D right) {
0738 double x1 = src.getX1();
0739 double y1 = src.getY1();
0740 double ctrlx = src.getCtrlX();
0741 double ctrly = src.getCtrlY();
0742 double x2 = src.getX2();
0743 double y2 = src.getY2();
0744 double ctrlx1 = (x1 + ctrlx) / 2.0;
0745 double ctrly1 = (y1 + ctrly) / 2.0;
0746 double ctrlx2 = (x2 + ctrlx) / 2.0;
0747 double ctrly2 = (y2 + ctrly) / 2.0;
0748 ctrlx = (ctrlx1 + ctrlx2) / 2.0;
0749 ctrly = (ctrly1 + ctrly2) / 2.0;
0750 if (left != null) {
0751 left.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx, ctrly);
0752 }
0753 if (right != null) {
0754 right.setCurve(ctrlx, ctrly, ctrlx2, ctrly2, x2, y2);
0755 }
0756 }
0757
0758 /**
0759 * Subdivides the quadratic curve specified by the coordinates
0760 * stored in the <code>src</code> array at indices
0761 * <code>srcoff</code> through <code>srcoff</code> + 5
0762 * and stores the resulting two subdivided curves into the two
0763 * result arrays at the corresponding indices.
0764 * Either or both of the <code>left</code> and <code>right</code>
0765 * arrays can be <code>null</code> or a reference to the same array
0766 * and offset as the <code>src</code> array.
0767 * Note that the last point in the first subdivided curve is the
0768 * same as the first point in the second subdivided curve. Thus,
0769 * it is possible to pass the same array for <code>left</code> and
0770 * <code>right</code> and to use offsets such that
0771 * <code>rightoff</code> equals <code>leftoff</code> + 4 in order
0772 * to avoid allocating extra storage for this common point.
0773 * @param src the array holding the coordinates for the source curve
0774 * @param srcoff the offset into the array of the beginning of the
0775 * the 6 source coordinates
0776 * @param left the array for storing the coordinates for the first
0777 * half of the subdivided curve
0778 * @param leftoff the offset into the array of the beginning of the
0779 * the 6 left coordinates
0780 * @param right the array for storing the coordinates for the second
0781 * half of the subdivided curve
0782 * @param rightoff the offset into the array of the beginning of the
0783 * the 6 right coordinates
0784 * @since 1.2
0785 */
0786 public static void subdivide(double src[], int srcoff,
0787 double left[], int leftoff, double right[], int rightoff) {
0788 double x1 = src[srcoff + 0];
0789 double y1 = src[srcoff + 1];
0790 double ctrlx = src[srcoff + 2];
0791 double ctrly = src[srcoff + 3];
0792 double x2 = src[srcoff + 4];
0793 double y2 = src[srcoff + 5];
0794 if (left != null) {
0795 left[leftoff + 0] = x1;
0796 left[leftoff + 1] = y1;
0797 }
0798 if (right != null) {
0799 right[rightoff + 4] = x2;
0800 right[rightoff + 5] = y2;
0801 }
0802 x1 = (x1 + ctrlx) / 2.0;
0803 y1 = (y1 + ctrly) / 2.0;
0804 x2 = (x2 + ctrlx) / 2.0;
0805 y2 = (y2 + ctrly) / 2.0;
0806 ctrlx = (x1 + x2) / 2.0;
0807 ctrly = (y1 + y2) / 2.0;
0808 if (left != null) {
0809 left[leftoff + 2] = x1;
0810 left[leftoff + 3] = y1;
0811 left[leftoff + 4] = ctrlx;
0812 left[leftoff + 5] = ctrly;
0813 }
0814 if (right != null) {
0815 right[rightoff + 0] = ctrlx;
0816 right[rightoff + 1] = ctrly;
0817 right[rightoff + 2] = x2;
0818 right[rightoff + 3] = y2;
0819 }
0820 }
0821
0822 /**
0823 * Solves the quadratic whose coefficients are in the <code>eqn</code>
0824 * array and places the non-complex roots back into the same array,
0825 * returning the number of roots. The quadratic solved is represented
0826 * by the equation:
0827 * <pre>
0828 * eqn = {C, B, A};
0829 * ax^2 + bx + c = 0
0830 * </pre>
0831 * A return value of <code>-1</code> is used to distinguish a constant
0832 * equation, which might be always 0 or never 0, from an equation that
0833 * has no zeroes.
0834 * @param eqn the array that contains the quadratic coefficients
0835 * @return the number of roots, or <code>-1</code> if the equation is
0836 * a constant
0837 * @since 1.2
0838 */
0839 public static int solveQuadratic(double eqn[]) {
0840 return solveQuadratic(eqn, eqn);
0841 }
0842
0843 /**
0844 * Solves the quadratic whose coefficients are in the <code>eqn</code>
0845 * array and places the non-complex roots into the <code>res</code>
0846 * array, returning the number of roots.
0847 * The quadratic solved is represented by the equation:
0848 * <pre>
0849 * eqn = {C, B, A};
0850 * ax^2 + bx + c = 0
0851 * </pre>
0852 * A return value of <code>-1</code> is used to distinguish a constant
0853 * equation, which might be always 0 or never 0, from an equation that
0854 * has no zeroes.
0855 * @param eqn the specified array of coefficients to use to solve
0856 * the quadratic equation
0857 * @param res the array that contains the non-complex roots
0858 * resulting from the solution of the quadratic equation
0859 * @return the number of roots, or <code>-1</code> if the equation is
0860 * a constant.
0861 * @since 1.3
0862 */
0863 public static int solveQuadratic(double eqn[], double res[]) {
0864 double a = eqn[2];
0865 double b = eqn[1];
0866 double c = eqn[0];
0867 int roots = 0;
0868 if (a == 0.0) {
0869 // The quadratic parabola has degenerated to a line.
0870 if (b == 0.0) {
0871 // The line has degenerated to a constant.
0872 return -1;
0873 }
0874 res[roots++] = -c / b;
0875 } else {
0876 // From Numerical Recipes, 5.6, Quadratic and Cubic Equations
0877 double d = b * b - 4.0 * a * c;
0878 if (d < 0.0) {
0879 // If d < 0.0, then there are no roots
0880 return 0;
0881 }
0882 d = Math.sqrt(d);
0883 // For accuracy, calculate one root using:
0884 // (-b +/- d) / 2a
0885 // and the other using:
0886 // 2c / (-b +/- d)
0887 // Choose the sign of the +/- so that b+d gets larger in magnitude
0888 if (b < 0.0) {
0889 d = -d;
0890 }
0891 double q = (b + d) / -2.0;
0892 // We already tested a for being 0 above
0893 res[roots++] = q / a;
0894 if (q != 0.0) {
0895 res[roots++] = c / q;
0896 }
0897 }
0898 return roots;
0899 }
0900
0901 /**
0902 * {@inheritDoc}
0903 * @since 1.2
0904 */
0905 public boolean contains(double x, double y) {
0906
0907 double x1 = getX1();
0908 double y1 = getY1();
0909 double xc = getCtrlX();
0910 double yc = getCtrlY();
0911 double x2 = getX2();
0912 double y2 = getY2();
0913
0914 /*
0915 * We have a convex shape bounded by quad curve Pc(t)
0916 * and ine Pl(t).
0917 *
0918 * P1 = (x1, y1) - start point of curve
0919 * P2 = (x2, y2) - end point of curve
0920 * Pc = (xc, yc) - control point
0921 *
0922 * Pq(t) = P1*(1 - t)^2 + 2*Pc*t*(1 - t) + P2*t^2 =
0923 * = (P1 - 2*Pc + P2)*t^2 + 2*(Pc - P1)*t + P1
0924 * Pl(t) = P1*(1 - t) + P2*t
0925 * t = [0:1]
0926 *
0927 * P = (x, y) - point of interest
0928 *
0929 * Let's look at second derivative of quad curve equation:
0930 *
0931 * Pq''(t) = 2 * (P1 - 2 * Pc + P2) = Pq''
0932 * It's constant vector.
0933 *
0934 * Let's draw a line through P to be parallel to this
0935 * vector and find the intersection of the quad curve
0936 * and the line.
0937 *
0938 * Pq(t) is point of intersection if system of equations
0939 * below has the solution.
0940 *
0941 * L(s) = P + Pq''*s == Pq(t)
0942 * Pq''*s + (P - Pq(t)) == 0
0943 *
0944 * | xq''*s + (x - xq(t)) == 0
0945 * | yq''*s + (y - yq(t)) == 0
0946 *
0947 * This system has the solution if rank of its matrix equals to 1.
0948 * That is, determinant of the matrix should be zero.
0949 *
0950 * (y - yq(t))*xq'' == (x - xq(t))*yq''
0951 *
0952 * Let's solve this equation with 't' variable.
0953 * Also let kx = x1 - 2*xc + x2
0954 * ky = y1 - 2*yc + y2
0955 *
0956 * t0q = (1/2)*((x - x1)*ky - (y - y1)*kx) /
0957 * ((xc - x1)*ky - (yc - y1)*kx)
0958 *
0959 * Let's do the same for our line Pl(t):
0960 *
0961 * t0l = ((x - x1)*ky - (y - y1)*kx) /
0962 * ((x2 - x1)*ky - (y2 - y1)*kx)
0963 *
0964 * It's easy to check that t0q == t0l. This fact means
0965 * we can compute t0 only one time.
0966 *
0967 * In case t0 < 0 or t0 > 1, we have an intersections outside
0968 * of shape bounds. So, P is definitely out of shape.
0969 *
0970 * In case t0 is inside [0:1], we should calculate Pq(t0)
0971 * and Pl(t0). We have three points for now, and all of them
0972 * lie on one line. So, we just need to detect, is our point
0973 * of interest between points of intersections or not.
0974 *
0975 * If the denominator in the t0q and t0l equations is
0976 * zero, then the points must be collinear and so the
0977 * curve is degenerate and encloses no area. Thus the
0978 * result is false.
0979 */
0980 double kx = x1 - 2 * xc + x2;
0981 double ky = y1 - 2 * yc + y2;
0982 double dx = x - x1;
0983 double dy = y - y1;
0984 double dxl = x2 - x1;
0985 double dyl = y2 - y1;
0986
0987 double t0 = (dx * ky - dy * kx) / (dxl * ky - dyl * kx);
0988 if (t0 < 0 || t0 > 1 || t0 != t0) {
0989 return false;
0990 }
0991
0992 double xb = kx * t0 * t0 + 2 * (xc - x1) * t0 + x1;
0993 double yb = ky * t0 * t0 + 2 * (yc - y1) * t0 + y1;
0994 double xl = dxl * t0 + x1;
0995 double yl = dyl * t0 + y1;
0996
0997 return (x >= xb && x < xl) || (x >= xl && x < xb)
0998 || (y >= yb && y < yl) || (y >= yl && y < yb);
0999 }
1000
1001 /**
1002 * {@inheritDoc}
1003 * @since 1.2
1004 */
1005 public boolean contains(Point2D p) {
1006 return contains(p.getX(), p.getY());
1007 }
1008
1009 /**
1010 * Fill an array with the coefficients of the parametric equation
1011 * in t, ready for solving against val with solveQuadratic.
1012 * We currently have:
1013 * val = Py(t) = C1*(1-t)^2 + 2*CP*t*(1-t) + C2*t^2
1014 * = C1 - 2*C1*t + C1*t^2 + 2*CP*t - 2*CP*t^2 + C2*t^2
1015 * = C1 + (2*CP - 2*C1)*t + (C1 - 2*CP + C2)*t^2
1016 * 0 = (C1 - val) + (2*CP - 2*C1)*t + (C1 - 2*CP + C2)*t^2
1017 * 0 = C + Bt + At^2
1018 * C = C1 - val
1019 * B = 2*CP - 2*C1
1020 * A = C1 - 2*CP + C2
1021 */
1022 private static void fillEqn(double eqn[], double val, double c1,
1023 double cp, double c2) {
1024 eqn[0] = c1 - val;
1025 eqn[1] = cp + cp - c1 - c1;
1026 eqn[2] = c1 - cp - cp + c2;
1027 return;
1028 }
1029
1030 /**
1031 * Evaluate the t values in the first num slots of the vals[] array
1032 * and place the evaluated values back into the same array. Only
1033 * evaluate t values that are within the range <0, 1>, including
1034 * the 0 and 1 ends of the range iff the include0 or include1
1035 * booleans are true. If an "inflection" equation is handed in,
1036 * then any points which represent a point of inflection for that
1037 * quadratic equation are also ignored.
1038 */
1039 private static int evalQuadratic(double vals[], int num,
1040 boolean include0, boolean include1, double inflect[],
1041 double c1, double ctrl, double c2) {
1042 int j = 0;
1043 for (int i = 0; i < num; i++) {
1044 double t = vals[i];
1045 if ((include0 ? t >= 0 : t > 0)
1046 && (include1 ? t <= 1 : t < 1)
1047 && (inflect == null || inflect[1] + 2 * inflect[2]
1048 * t != 0)) {
1049 double u = 1 - t;
1050 vals[j++] = c1 * u * u + 2 * ctrl * t * u + c2 * t * t;
1051 }
1052 }
1053 return j;
1054 }
1055
1056 private static final int BELOW = -2;
1057 private static final int LOWEDGE = -1;
1058 private static final int INSIDE = 0;
1059 private static final int HIGHEDGE = 1;
1060 private static final int ABOVE = 2;
1061
1062 /**
1063 * Determine where coord lies with respect to the range from
1064 * low to high. It is assumed that low <= high. The return
1065 * value is one of the 5 values BELOW, LOWEDGE, INSIDE, HIGHEDGE,
1066 * or ABOVE.
1067 */
1068 private static int getTag(double coord, double low, double high) {
1069 if (coord <= low) {
1070 return (coord < low ? BELOW : LOWEDGE);
1071 }
1072 if (coord >= high) {
1073 return (coord > high ? ABOVE : HIGHEDGE);
1074 }
1075 return INSIDE;
1076 }
1077
1078 /**
1079 * Determine if the pttag represents a coordinate that is already
1080 * in its test range, or is on the border with either of the two
1081 * opttags representing another coordinate that is "towards the
1082 * inside" of that test range. In other words, are either of the
1083 * two "opt" points "drawing the pt inward"?
1084 */
1085 private static boolean inwards(int pttag, int opt1tag, int opt2tag) {
1086 switch (pttag) {
1087 case BELOW:
1088 case ABOVE:
1089 default:
1090 return false;
1091 case LOWEDGE:
1092 return (opt1tag >= INSIDE || opt2tag >= INSIDE);
1093 case INSIDE:
1094 return true;
1095 case HIGHEDGE:
1096 return (opt1tag <= INSIDE || opt2tag <= INSIDE);
1097 }
1098 }
1099
1100 /**
1101 * {@inheritDoc}
1102 * @since 1.2
1103 */
1104 public boolean intersects(double x, double y, double w, double h) {
1105 // Trivially reject non-existant rectangles
1106 if (w <= 0 || h <= 0) {
1107 return false;
1108 }
1109
1110 // Trivially accept if either endpoint is inside the rectangle
1111 // (not on its border since it may end there and not go inside)
1112 // Record where they lie with respect to the rectangle.
1113 // -1 => left, 0 => inside, 1 => right
1114 double x1 = getX1();
1115 double y1 = getY1();
1116 int x1tag = getTag(x1, x, x + w);
1117 int y1tag = getTag(y1, y, y + h);
1118 if (x1tag == INSIDE && y1tag == INSIDE) {
1119 return true;
1120 }
1121 double x2 = getX2();
1122 double y2 = getY2();
1123 int x2tag = getTag(x2, x, x + w);
1124 int y2tag = getTag(y2, y, y + h);
1125 if (x2tag == INSIDE && y2tag == INSIDE) {
1126 return true;
1127 }
1128 double ctrlx = getCtrlX();
1129 double ctrly = getCtrlY();
1130 int ctrlxtag = getTag(ctrlx, x, x + w);
1131 int ctrlytag = getTag(ctrly, y, y + h);
1132
1133 // Trivially reject if all points are entirely to one side of
1134 // the rectangle.
1135 if (x1tag < INSIDE && x2tag < INSIDE && ctrlxtag < INSIDE) {
1136 return false; // All points left
1137 }
1138 if (y1tag < INSIDE && y2tag < INSIDE && ctrlytag < INSIDE) {
1139 return false; // All points above
1140 }
1141 if (x1tag > INSIDE && x2tag > INSIDE && ctrlxtag > INSIDE) {
1142 return false; // All points right
1143 }
1144 if (y1tag > INSIDE && y2tag > INSIDE && ctrlytag > INSIDE) {
1145 return false; // All points below
1146 }
1147
1148 // Test for endpoints on the edge where either the segment
1149 // or the curve is headed "inwards" from them
1150 // Note: These tests are a superset of the fast endpoint tests
1151 // above and thus repeat those tests, but take more time
1152 // and cover more cases
1153 if (inwards(x1tag, x2tag, ctrlxtag)
1154 && inwards(y1tag, y2tag, ctrlytag)) {
1155 // First endpoint on border with either edge moving inside
1156 return true;
1157 }
1158 if (inwards(x2tag, x1tag, ctrlxtag)
1159 && inwards(y2tag, y1tag, ctrlytag)) {
1160 // Second endpoint on border with either edge moving inside
1161 return true;
1162 }
1163
1164 // Trivially accept if endpoints span directly across the rectangle
1165 boolean xoverlap = (x1tag * x2tag <= 0);
1166 boolean yoverlap = (y1tag * y2tag <= 0);
1167 if (x1tag == INSIDE && x2tag == INSIDE && yoverlap) {
1168 return true;
1169 }
1170 if (y1tag == INSIDE && y2tag == INSIDE && xoverlap) {
1171 return true;
1172 }
1173
1174 // We now know that both endpoints are outside the rectangle
1175 // but the 3 points are not all on one side of the rectangle.
1176 // Therefore the curve cannot be contained inside the rectangle,
1177 // but the rectangle might be contained inside the curve, or
1178 // the curve might intersect the boundary of the rectangle.
1179
1180 double[] eqn = new double[3];
1181 double[] res = new double[3];
1182 if (!yoverlap) {
1183 // Both Y coordinates for the closing segment are above or
1184 // below the rectangle which means that we can only intersect
1185 // if the curve crosses the top (or bottom) of the rectangle
1186 // in more than one place and if those crossing locations
1187 // span the horizontal range of the rectangle.
1188 fillEqn(eqn, (y1tag < INSIDE ? y : y + h), y1, ctrly, y2);
1189 return (solveQuadratic(eqn, res) == 2
1190 && evalQuadratic(res, 2, true, true, null, x1,
1191 ctrlx, x2) == 2 && getTag(res[0], x, x + w)
1192 * getTag(res[1], x, x + w) <= 0);
1193 }
1194
1195 // Y ranges overlap. Now we examine the X ranges
1196 if (!xoverlap) {
1197 // Both X coordinates for the closing segment are left of
1198 // or right of the rectangle which means that we can only
1199 // intersect if the curve crosses the left (or right) edge
1200 // of the rectangle in more than one place and if those
1201 // crossing locations span the vertical range of the rectangle.
1202 fillEqn(eqn, (x1tag < INSIDE ? x : x + w), x1, ctrlx, x2);
1203 return (solveQuadratic(eqn, res) == 2
1204 && evalQuadratic(res, 2, true, true, null, y1,
1205 ctrly, y2) == 2 && getTag(res[0], y, y + h)
1206 * getTag(res[1], y, y + h) <= 0);
1207 }
1208
1209 // The X and Y ranges of the endpoints overlap the X and Y
1210 // ranges of the rectangle, now find out how the endpoint
1211 // line segment intersects the Y range of the rectangle
1212 double dx = x2 - x1;
1213 double dy = y2 - y1;
1214 double k = y2 * x1 - x2 * y1;
1215 int c1tag, c2tag;
1216 if (y1tag == INSIDE) {
1217 c1tag = x1tag;
1218 } else {
1219 c1tag = getTag(
1220 (k + dx * (y1tag < INSIDE ? y : y + h)) / dy, x, x
1221 + w);
1222 }
1223 if (y2tag == INSIDE) {
1224 c2tag = x2tag;
1225 } else {
1226 c2tag = getTag(
1227 (k + dx * (y2tag < INSIDE ? y : y + h)) / dy, x, x
1228 + w);
1229 }
1230 // If the part of the line segment that intersects the Y range
1231 // of the rectangle crosses it horizontally - trivially accept
1232 if (c1tag * c2tag <= 0) {
1233 return true;
1234 }
1235
1236 // Now we know that both the X and Y ranges intersect and that
1237 // the endpoint line segment does not directly cross the rectangle.
1238 //
1239 // We can almost treat this case like one of the cases above
1240 // where both endpoints are to one side, except that we will
1241 // only get one intersection of the curve with the vertical
1242 // side of the rectangle. This is because the endpoint segment
1243 // accounts for the other intersection.
1244 //
1245 // (Remember there is overlap in both the X and Y ranges which
1246 // means that the segment must cross at least one vertical edge
1247 // of the rectangle - in particular, the "near vertical side" -
1248 // leaving only one intersection for the curve.)
1249 //
1250 // Now we calculate the y tags of the two intersections on the
1251 // "near vertical side" of the rectangle. We will have one with
1252 // the endpoint segment, and one with the curve. If those two
1253 // vertical intersections overlap the Y range of the rectangle,
1254 // we have an intersection. Otherwise, we don't.
1255
1256 // c1tag = vertical intersection class of the endpoint segment
1257 //
1258 // Choose the y tag of the endpoint that was not on the same
1259 // side of the rectangle as the subsegment calculated above.
1260 // Note that we can "steal" the existing Y tag of that endpoint
1261 // since it will be provably the same as the vertical intersection.
1262 c1tag = ((c1tag * x1tag <= 0) ? y1tag : y2tag);
1263
1264 // c2tag = vertical intersection class of the curve
1265 //
1266 // We have to calculate this one the straightforward way.
1267 // Note that the c2tag can still tell us which vertical edge
1268 // to test against.
1269 fillEqn(eqn, (c2tag < INSIDE ? x : x + w), x1, ctrlx, x2);
1270 int num = solveQuadratic(eqn, res);
1271
1272 // Note: We should be able to assert(num == 2); since the
1273 // X range "crosses" (not touches) the vertical boundary,
1274 // but we pass num to evalQuadratic for completeness.
1275 evalQuadratic(res, num, true, true, null, y1, ctrly, y2);
1276
1277 // Note: We can assert(num evals == 1); since one of the
1278 // 2 crossings will be out of the [0,1] range.
1279 c2tag = getTag(res[0], y, y + h);
1280
1281 // Finally, we have an intersection if the two crossings
1282 // overlap the Y range of the rectangle.
1283 return (c1tag * c2tag <= 0);
1284 }
1285
1286 /**
1287 * {@inheritDoc}
1288 * @since 1.2
1289 */
1290 public boolean intersects(Rectangle2D r) {
1291 return intersects(r.getX(), r.getY(), r.getWidth(), r
1292 .getHeight());
1293 }
1294
1295 /**
1296 * {@inheritDoc}
1297 * @since 1.2
1298 */
1299 public boolean contains(double x, double y, double w, double h) {
1300 if (w <= 0 || h <= 0) {
1301 return false;
1302 }
1303 // Assertion: Quadratic curves closed by connecting their
1304 // endpoints are always convex.
1305 return (contains(x, y) && contains(x + w, y)
1306 && contains(x + w, y + h) && contains(x, y + h));
1307 }
1308
1309 /**
1310 * {@inheritDoc}
1311 * @since 1.2
1312 */
1313 public boolean contains(Rectangle2D r) {
1314 return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
1315 }
1316
1317 /**
1318 * {@inheritDoc}
1319 * @since 1.2
1320 */
1321 public Rectangle getBounds() {
1322 return getBounds2D().getBounds();
1323 }
1324
1325 /**
1326 * Returns an iteration object that defines the boundary of the
1327 * shape of this <code>QuadCurve2D</code>.
1328 * The iterator for this class is not multi-threaded safe,
1329 * which means that this <code>QuadCurve2D</code> class does not
1330 * guarantee that modifications to the geometry of this
1331 * <code>QuadCurve2D</code> object do not affect any iterations of
1332 * that geometry that are already in process.
1333 * @param at an optional {@link AffineTransform} to apply to the
1334 * shape boundary
1335 * @return a {@link PathIterator} object that defines the boundary
1336 * of the shape.
1337 * @since 1.2
1338 */
1339 public PathIterator getPathIterator(AffineTransform at) {
1340 return new QuadIterator(this , at);
1341 }
1342
1343 /**
1344 * Returns an iteration object that defines the boundary of the
1345 * flattened shape of this <code>QuadCurve2D</code>.
1346 * The iterator for this class is not multi-threaded safe,
1347 * which means that this <code>QuadCurve2D</code> class does not
1348 * guarantee that modifications to the geometry of this
1349 * <code>QuadCurve2D</code> object do not affect any iterations of
1350 * that geometry that are already in process.
1351 * @param at an optional <code>AffineTransform</code> to apply
1352 * to the boundary of the shape
1353 * @param flatness the maximum distance that the control points for a
1354 * subdivided curve can be with respect to a line connecting
1355 * the end points of this curve before this curve is
1356 * replaced by a straight line connecting the end points.
1357 * @return a <code>PathIterator</code> object that defines the
1358 * flattened boundary of the shape.
1359 * @since 1.2
1360 */
1361 public PathIterator getPathIterator(AffineTransform at,
1362 double flatness) {
1363 return new FlatteningPathIterator(getPathIterator(at), flatness);
1364 }
1365
1366 /**
1367 * Creates a new object of the same class and with the same contents
1368 * as this object.
1369 *
1370 * @return a clone of this instance.
1371 * @exception OutOfMemoryError if there is not enough memory.
1372 * @see java.lang.Cloneable
1373 * @since 1.2
1374 */
1375 public Object clone() {
1376 try {
1377 return super .clone();
1378 } catch (CloneNotSupportedException e) {
1379 // this shouldn't happen, since we are Cloneable
1380 throw new InternalError();
1381 }
1382 }
1383 }
|