diff options
author | Andrew Haley <aph@redhat.com> | 2016-09-30 16:24:48 +0000 |
---|---|---|
committer | Andrew Haley <aph@gcc.gnu.org> | 2016-09-30 16:24:48 +0000 |
commit | 07b78716af6a9d7c9fd1e94d9baf94a52c873947 (patch) | |
tree | 3f22b3241c513ad168c8353805614ae1249410f4 /libjava/classpath/java/awt/geom | |
parent | eae993948bae8b788c53772bcb9217c063716f93 (diff) | |
download | gcc-07b78716af6a9d7c9fd1e94d9baf94a52c873947.zip gcc-07b78716af6a9d7c9fd1e94d9baf94a52c873947.tar.gz gcc-07b78716af6a9d7c9fd1e94d9baf94a52c873947.tar.bz2 |
Makefile.def: Remove libjava.
2016-09-30 Andrew Haley <aph@redhat.com>
* Makefile.def: Remove libjava.
* Makefile.tpl: Likewise.
* Makefile.in: Regenerate.
* configure.ac: Likewise.
* configure: Likewise.
* gcc/java: Remove.
* libjava: Likewise.
From-SVN: r240662
Diffstat (limited to 'libjava/classpath/java/awt/geom')
32 files changed, 0 insertions, 15881 deletions
diff --git a/libjava/classpath/java/awt/geom/AffineTransform.java b/libjava/classpath/java/awt/geom/AffineTransform.java deleted file mode 100644 index 42590ef..0000000 --- a/libjava/classpath/java/awt/geom/AffineTransform.java +++ /dev/null @@ -1,1489 +0,0 @@ -/* AffineTransform.java -- transform coordinates between two 2-D spaces - Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.awt.geom; - -import java.awt.Shape; -import java.io.IOException; -import java.io.ObjectInputStream; -import java.io.Serializable; - -/** - * This class represents an affine transformation between two coordinate - * spaces in 2 dimensions. Such a transform preserves the "straightness" - * and "parallelness" of lines. The transform is built from a sequence of - * translations, scales, flips, rotations, and shears. - * - * <p>The transformation can be represented using matrix math on a 3x3 array. - * Given (x,y), the transformation (x',y') can be found by: - * <pre> - * [ x'] [ m00 m01 m02 ] [ x ] [ m00*x + m01*y + m02 ] - * [ y'] = [ m10 m11 m12 ] [ y ] = [ m10*x + m11*y + m12 ] - * [ 1 ] [ 0 0 1 ] [ 1 ] [ 1 ] - * </pre> - * The bottom row of the matrix is constant, so a transform can be uniquely - * represented (as in {@link #toString()}) by - * "[[m00, m01, m02], [m10, m11, m12]]". - * - * @author Tom Tromey (tromey@cygnus.com) - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @status partially updated to 1.4, still has some problems - */ -public class AffineTransform implements Cloneable, Serializable -{ - /** - * Compatible with JDK 1.2+. - */ - private static final long serialVersionUID = 1330973210523860834L; - - /** - * The transformation is the identity (x' = x, y' = y). All other transforms - * have either a combination of the appropriate transform flag bits for - * their type, or the type GENERAL_TRANSFORM. - * - * @see #TYPE_TRANSLATION - * @see #TYPE_UNIFORM_SCALE - * @see #TYPE_GENERAL_SCALE - * @see #TYPE_FLIP - * @see #TYPE_QUADRANT_ROTATION - * @see #TYPE_GENERAL_ROTATION - * @see #TYPE_GENERAL_TRANSFORM - * @see #getType() - */ - public static final int TYPE_IDENTITY = 0; - - /** - * The transformation includes a translation - shifting in the x or y - * direction without changing length or angles. - * - * @see #TYPE_IDENTITY - * @see #TYPE_UNIFORM_SCALE - * @see #TYPE_GENERAL_SCALE - * @see #TYPE_FLIP - * @see #TYPE_QUADRANT_ROTATION - * @see #TYPE_GENERAL_ROTATION - * @see #TYPE_GENERAL_TRANSFORM - * @see #getType() - */ - public static final int TYPE_TRANSLATION = 1; - - /** - * The transformation includes a uniform scale - length is scaled in both - * the x and y directions by the same amount, without affecting angles. - * This is mutually exclusive with TYPE_GENERAL_SCALE. - * - * @see #TYPE_IDENTITY - * @see #TYPE_TRANSLATION - * @see #TYPE_GENERAL_SCALE - * @see #TYPE_FLIP - * @see #TYPE_QUADRANT_ROTATION - * @see #TYPE_GENERAL_ROTATION - * @see #TYPE_GENERAL_TRANSFORM - * @see #TYPE_MASK_SCALE - * @see #getType() - */ - public static final int TYPE_UNIFORM_SCALE = 2; - - /** - * The transformation includes a general scale - length is scaled in either - * or both the x and y directions, but by different amounts; without - * affecting angles. This is mutually exclusive with TYPE_UNIFORM_SCALE. - * - * @see #TYPE_IDENTITY - * @see #TYPE_TRANSLATION - * @see #TYPE_UNIFORM_SCALE - * @see #TYPE_FLIP - * @see #TYPE_QUADRANT_ROTATION - * @see #TYPE_GENERAL_ROTATION - * @see #TYPE_GENERAL_TRANSFORM - * @see #TYPE_MASK_SCALE - * @see #getType() - */ - public static final int TYPE_GENERAL_SCALE = 4; - - /** - * This constant checks if either variety of scale transform is performed. - * - * @see #TYPE_UNIFORM_SCALE - * @see #TYPE_GENERAL_SCALE - */ - public static final int TYPE_MASK_SCALE = 6; - - /** - * The transformation includes a flip about an axis, swapping between - * right-handed and left-handed coordinate systems. In a right-handed - * system, the positive x-axis rotates counter-clockwise to the positive - * y-axis; in a left-handed system it rotates clockwise. - * - * @see #TYPE_IDENTITY - * @see #TYPE_TRANSLATION - * @see #TYPE_UNIFORM_SCALE - * @see #TYPE_GENERAL_SCALE - * @see #TYPE_QUADRANT_ROTATION - * @see #TYPE_GENERAL_ROTATION - * @see #TYPE_GENERAL_TRANSFORM - * @see #getType() - */ - public static final int TYPE_FLIP = 64; - - /** - * The transformation includes a rotation of a multiple of 90 degrees (PI/2 - * radians). Angles are rotated, but length is preserved. This is mutually - * exclusive with TYPE_GENERAL_ROTATION. - * - * @see #TYPE_IDENTITY - * @see #TYPE_TRANSLATION - * @see #TYPE_UNIFORM_SCALE - * @see #TYPE_GENERAL_SCALE - * @see #TYPE_FLIP - * @see #TYPE_GENERAL_ROTATION - * @see #TYPE_GENERAL_TRANSFORM - * @see #TYPE_MASK_ROTATION - * @see #getType() - */ - public static final int TYPE_QUADRANT_ROTATION = 8; - - /** - * The transformation includes a rotation by an arbitrary angle. Angles are - * rotated, but length is preserved. This is mutually exclusive with - * TYPE_QUADRANT_ROTATION. - * - * @see #TYPE_IDENTITY - * @see #TYPE_TRANSLATION - * @see #TYPE_UNIFORM_SCALE - * @see #TYPE_GENERAL_SCALE - * @see #TYPE_FLIP - * @see #TYPE_QUADRANT_ROTATION - * @see #TYPE_GENERAL_TRANSFORM - * @see #TYPE_MASK_ROTATION - * @see #getType() - */ - public static final int TYPE_GENERAL_ROTATION = 16; - - /** - * This constant checks if either variety of rotation is performed. - * - * @see #TYPE_QUADRANT_ROTATION - * @see #TYPE_GENERAL_ROTATION - */ - public static final int TYPE_MASK_ROTATION = 24; - - /** - * The transformation is an arbitrary conversion of coordinates which - * could not be decomposed into the other TYPEs. - * - * @see #TYPE_IDENTITY - * @see #TYPE_TRANSLATION - * @see #TYPE_UNIFORM_SCALE - * @see #TYPE_GENERAL_SCALE - * @see #TYPE_FLIP - * @see #TYPE_QUADRANT_ROTATION - * @see #TYPE_GENERAL_ROTATION - * @see #getType() - */ - public static final int TYPE_GENERAL_TRANSFORM = 32; - - /** - * The X coordinate scaling element of the transform matrix. - * - * @serial matrix[0,0] - */ - private double m00; - - /** - * The Y coordinate shearing element of the transform matrix. - * - * @serial matrix[1,0] - */ - private double m10; - - /** - * The X coordinate shearing element of the transform matrix. - * - * @serial matrix[0,1] - */ - private double m01; - - /** - * The Y coordinate scaling element of the transform matrix. - * - * @serial matrix[1,1] - */ - private double m11; - - /** - * The X coordinate translation element of the transform matrix. - * - * @serial matrix[0,2] - */ - private double m02; - - /** - * The Y coordinate translation element of the transform matrix. - * - * @serial matrix[1,2] - */ - private double m12; - - /** The type of this transform. */ - private transient int type; - - /** - * Construct a new identity transform: - * <pre> - * [ 1 0 0 ] - * [ 0 1 0 ] - * [ 0 0 1 ] - * </pre> - */ - public AffineTransform() - { - m00 = m11 = 1; - } - - /** - * Create a new transform which copies the given one. - * - * @param tx the transform to copy - * @throws NullPointerException if tx is null - */ - public AffineTransform(AffineTransform tx) - { - setTransform(tx); - } - - /** - * Construct a transform with the given matrix entries: - * <pre> - * [ m00 m01 m02 ] - * [ m10 m11 m12 ] - * [ 0 0 1 ] - * </pre> - * - * @param m00 the x scaling component - * @param m10 the y shearing component - * @param m01 the x shearing component - * @param m11 the y scaling component - * @param m02 the x translation component - * @param m12 the y translation component - */ - public AffineTransform(float m00, float m10, - float m01, float m11, - float m02, float m12) - { - this.m00 = m00; - this.m10 = m10; - this.m01 = m01; - this.m11 = m11; - this.m02 = m02; - this.m12 = m12; - updateType(); - } - - /** - * Construct a transform from a sequence of float entries. The array must - * have at least 4 entries, which has a translation factor of 0; or 6 - * entries, for specifying all parameters: - * <pre> - * [ f[0] f[2] (f[4]) ] - * [ f[1] f[3] (f[5]) ] - * [ 0 0 1 ] - * </pre> - * - * @param f the matrix to copy from, with at least 4 (6) entries - * @throws NullPointerException if f is null - * @throws ArrayIndexOutOfBoundsException if f is too small - */ - public AffineTransform(float[] f) - { - m00 = f[0]; - m10 = f[1]; - m01 = f[2]; - m11 = f[3]; - if (f.length >= 6) - { - m02 = f[4]; - m12 = f[5]; - } - updateType(); - } - - /** - * Construct a transform with the given matrix entries: - * <pre> - * [ m00 m01 m02 ] - * [ m10 m11 m12 ] - * [ 0 0 1 ] - * </pre> - * - * @param m00 the x scaling component - * @param m10 the y shearing component - * @param m01 the x shearing component - * @param m11 the y scaling component - * @param m02 the x translation component - * @param m12 the y translation component - */ - public AffineTransform(double m00, double m10, double m01, - double m11, double m02, double m12) - { - this.m00 = m00; - this.m10 = m10; - this.m01 = m01; - this.m11 = m11; - this.m02 = m02; - this.m12 = m12; - updateType(); - } - - /** - * Construct a transform from a sequence of double entries. The array must - * have at least 4 entries, which has a translation factor of 0; or 6 - * entries, for specifying all parameters: - * <pre> - * [ d[0] d[2] (d[4]) ] - * [ d[1] d[3] (d[5]) ] - * [ 0 0 1 ] - * </pre> - * - * @param d the matrix to copy from, with at least 4 (6) entries - * @throws NullPointerException if d is null - * @throws ArrayIndexOutOfBoundsException if d is too small - */ - public AffineTransform(double[] d) - { - m00 = d[0]; - m10 = d[1]; - m01 = d[2]; - m11 = d[3]; - if (d.length >= 6) - { - m02 = d[4]; - m12 = d[5]; - } - updateType(); - } - - /** - * Returns a translation transform: - * <pre> - * [ 1 0 tx ] - * [ 0 1 ty ] - * [ 0 0 1 ] - * </pre> - * - * @param tx the x translation distance - * @param ty the y translation distance - * @return the translating transform - */ - public static AffineTransform getTranslateInstance(double tx, double ty) - { - AffineTransform t = new AffineTransform(); - t.m02 = tx; - t.m12 = ty; - t.type = (tx == 0 && ty == 0) ? TYPE_UNIFORM_SCALE : TYPE_TRANSLATION; - return t; - } - - /** - * Returns a rotation transform. A positive angle (in radians) rotates - * the positive x-axis to the positive y-axis: - * <pre> - * [ cos(theta) -sin(theta) 0 ] - * [ sin(theta) cos(theta) 0 ] - * [ 0 0 1 ] - * </pre> - * - * @param theta the rotation angle - * @return the rotating transform - */ - public static AffineTransform getRotateInstance(double theta) - { - AffineTransform t = new AffineTransform(); - t.setToRotation(theta); - return t; - } - - /** - * Returns a rotation transform about a point. A positive angle (in radians) - * rotates the positive x-axis to the positive y-axis. This is the same - * as calling: - * <pre> - * AffineTransform tx = new AffineTransform(); - * tx.setToTranslation(x, y); - * tx.rotate(theta); - * tx.translate(-x, -y); - * </pre> - * - * <p>The resulting matrix is: - * <pre> - * [ cos(theta) -sin(theta) x-x*cos+y*sin ] - * [ sin(theta) cos(theta) y-x*sin-y*cos ] - * [ 0 0 1 ] - * </pre> - * - * @param theta the rotation angle - * @param x the x coordinate of the pivot point - * @param y the y coordinate of the pivot point - * @return the rotating transform - */ - public static AffineTransform getRotateInstance(double theta, - double x, double y) - { - AffineTransform t = new AffineTransform(); - t.setToTranslation(x, y); - t.rotate(theta); - t.translate(-x, -y); - return t; - } - - /** - * Returns a scaling transform: - * <pre> - * [ sx 0 0 ] - * [ 0 sy 0 ] - * [ 0 0 1 ] - * </pre> - * - * @param sx the x scaling factor - * @param sy the y scaling factor - * @return the scaling transform - */ - public static AffineTransform getScaleInstance(double sx, double sy) - { - AffineTransform t = new AffineTransform(); - t.setToScale(sx, sy); - return t; - } - - /** - * Returns a shearing transform (points are shifted in the x direction based - * on a factor of their y coordinate, and in the y direction as a factor of - * their x coordinate): - * <pre> - * [ 1 shx 0 ] - * [ shy 1 0 ] - * [ 0 0 1 ] - * </pre> - * - * @param shx the x shearing factor - * @param shy the y shearing factor - * @return the shearing transform - */ - public static AffineTransform getShearInstance(double shx, double shy) - { - AffineTransform t = new AffineTransform(); - t.setToShear(shx, shy); - return t; - } - - /** - * Returns the type of this transform. The result is always valid, although - * it may not be the simplest interpretation (in other words, there are - * sequences of transforms which reduce to something simpler, which this - * does not always detect). The result is either TYPE_GENERAL_TRANSFORM, - * or a bit-wise combination of TYPE_TRANSLATION, the mutually exclusive - * TYPE_*_ROTATIONs, and the mutually exclusive TYPE_*_SCALEs. - * - * @return The type. - * - * @see #TYPE_IDENTITY - * @see #TYPE_TRANSLATION - * @see #TYPE_UNIFORM_SCALE - * @see #TYPE_GENERAL_SCALE - * @see #TYPE_QUADRANT_ROTATION - * @see #TYPE_GENERAL_ROTATION - * @see #TYPE_GENERAL_TRANSFORM - */ - public int getType() - { - return type; - } - - /** - * Return the determinant of this transform matrix. If the determinant is - * non-zero, the transform is invertible; otherwise operations which require - * an inverse throw a NoninvertibleTransformException. A result very near - * zero, due to rounding errors, may indicate that inversion results do not - * carry enough precision to be meaningful. - * - * <p>If this is a uniform scale transformation, the determinant also - * represents the squared value of the scale. Otherwise, it carries little - * additional meaning. The determinant is calculated as: - * <pre> - * | m00 m01 m02 | - * | m10 m11 m12 | = m00 * m11 - m01 * m10 - * | 0 0 1 | - * </pre> - * - * @return the determinant - * @see #createInverse() - */ - public double getDeterminant() - { - return m00 * m11 - m01 * m10; - } - - /** - * Return the matrix of values used in this transform. If the matrix has - * fewer than 6 entries, only the scale and shear factors are returned; - * otherwise the translation factors are copied as well. The resulting - * values are: - * <pre> - * [ d[0] d[2] (d[4]) ] - * [ d[1] d[3] (d[5]) ] - * [ 0 0 1 ] - * </pre> - * - * @param d the matrix to store the results into; with 4 (6) entries - * @throws NullPointerException if d is null - * @throws ArrayIndexOutOfBoundsException if d is too small - */ - public void getMatrix(double[] d) - { - d[0] = m00; - d[1] = m10; - d[2] = m01; - d[3] = m11; - if (d.length >= 6) - { - d[4] = m02; - d[5] = m12; - } - } - - /** - * Returns the X coordinate scaling factor of the matrix. - * - * @return m00 - * @see #getMatrix(double[]) - */ - public double getScaleX() - { - return m00; - } - - /** - * Returns the Y coordinate scaling factor of the matrix. - * - * @return m11 - * @see #getMatrix(double[]) - */ - public double getScaleY() - { - return m11; - } - - /** - * Returns the X coordinate shearing factor of the matrix. - * - * @return m01 - * @see #getMatrix(double[]) - */ - public double getShearX() - { - return m01; - } - - /** - * Returns the Y coordinate shearing factor of the matrix. - * - * @return m10 - * @see #getMatrix(double[]) - */ - public double getShearY() - { - return m10; - } - - /** - * Returns the X coordinate translation factor of the matrix. - * - * @return m02 - * @see #getMatrix(double[]) - */ - public double getTranslateX() - { - return m02; - } - - /** - * Returns the Y coordinate translation factor of the matrix. - * - * @return m12 - * @see #getMatrix(double[]) - */ - public double getTranslateY() - { - return m12; - } - - /** - * Concatenate a translation onto this transform. This is equivalent, but - * more efficient than - * <code>concatenate(AffineTransform.getTranslateInstance(tx, ty))</code>. - * - * @param tx the x translation distance - * @param ty the y translation distance - * @see #getTranslateInstance(double, double) - * @see #concatenate(AffineTransform) - */ - public void translate(double tx, double ty) - { - m02 += tx * m00 + ty * m01; - m12 += tx * m10 + ty * m11; - updateType(); - } - - /** - * Concatenate a rotation onto this transform. This is equivalent, but - * more efficient than - * <code>concatenate(AffineTransform.getRotateInstance(theta))</code>. - * - * @param theta the rotation angle - * @see #getRotateInstance(double) - * @see #concatenate(AffineTransform) - */ - public void rotate(double theta) - { - double c = Math.cos(theta); - double s = Math.sin(theta); - double n00 = m00 * c + m01 * s; - double n01 = m00 * -s + m01 * c; - double n10 = m10 * c + m11 * s; - double n11 = m10 * -s + m11 * c; - m00 = n00; - m01 = n01; - m10 = n10; - m11 = n11; - updateType(); - } - - /** - * Concatenate a rotation about a point onto this transform. This is - * equivalent, but more efficient than - * <code>concatenate(AffineTransform.getRotateInstance(theta, x, y))</code>. - * - * @param theta the rotation angle - * @param x the x coordinate of the pivot point - * @param y the y coordinate of the pivot point - * @see #getRotateInstance(double, double, double) - * @see #concatenate(AffineTransform) - */ - public void rotate(double theta, double x, double y) - { - translate(x, y); - rotate(theta); - translate(-x, -y); - } - - /** - * Concatenate a scale onto this transform. This is equivalent, but more - * efficient than - * <code>concatenate(AffineTransform.getScaleInstance(sx, sy))</code>. - * - * @param sx the x scaling factor - * @param sy the y scaling factor - * @see #getScaleInstance(double, double) - * @see #concatenate(AffineTransform) - */ - public void scale(double sx, double sy) - { - m00 *= sx; - m01 *= sy; - m10 *= sx; - m11 *= sy; - updateType(); - } - - /** - * Concatenate a shearing onto this transform. This is equivalent, but more - * efficient than - * <code>concatenate(AffineTransform.getShearInstance(sx, sy))</code>. - * - * @param shx the x shearing factor - * @param shy the y shearing factor - * @see #getShearInstance(double, double) - * @see #concatenate(AffineTransform) - */ - public void shear(double shx, double shy) - { - double n00 = m00 + (shy * m01); - double n01 = m01 + (shx * m00); - double n10 = m10 + (shy * m11); - double n11 = m11 + (shx * m10); - m00 = n00; - m01 = n01; - m10 = n10; - m11 = n11; - updateType(); - } - - /** - * Reset this transform to the identity (no transformation): - * <pre> - * [ 1 0 0 ] - * [ 0 1 0 ] - * [ 0 0 1 ] - * </pre> - */ - public void setToIdentity() - { - m00 = m11 = 1; - m01 = m02 = m10 = m12 = 0; - type = TYPE_IDENTITY; - } - - /** - * Set this transform to a translation: - * <pre> - * [ 1 0 tx ] - * [ 0 1 ty ] - * [ 0 0 1 ] - * </pre> - * - * @param tx the x translation distance - * @param ty the y translation distance - */ - public void setToTranslation(double tx, double ty) - { - m00 = m11 = 1; - m01 = m10 = 0; - m02 = tx; - m12 = ty; - type = (tx == 0 && ty == 0) ? TYPE_UNIFORM_SCALE : TYPE_TRANSLATION; - } - - /** - * Set this transform to a rotation. A positive angle (in radians) rotates - * the positive x-axis to the positive y-axis: - * <pre> - * [ cos(theta) -sin(theta) 0 ] - * [ sin(theta) cos(theta) 0 ] - * [ 0 0 1 ] - * </pre> - * - * @param theta the rotation angle - */ - public void setToRotation(double theta) - { - double c = Math.cos(theta); - double s = Math.sin(theta); - m00 = c; - m01 = -s; - m02 = 0; - m10 = s; - m11 = c; - m12 = 0; - type = (c == 1 ? TYPE_IDENTITY - : c == 0 || c == -1 ? TYPE_QUADRANT_ROTATION - : TYPE_GENERAL_ROTATION); - } - - /** - * Set this transform to a rotation about a point. A positive angle (in - * radians) rotates the positive x-axis to the positive y-axis. This is the - * same as calling: - * <pre> - * tx.setToTranslation(x, y); - * tx.rotate(theta); - * tx.translate(-x, -y); - * </pre> - * - * <p>The resulting matrix is: - * <pre> - * [ cos(theta) -sin(theta) x-x*cos+y*sin ] - * [ sin(theta) cos(theta) y-x*sin-y*cos ] - * [ 0 0 1 ] - * </pre> - * - * @param theta the rotation angle - * @param x the x coordinate of the pivot point - * @param y the y coordinate of the pivot point - */ - public void setToRotation(double theta, double x, double y) - { - double c = Math.cos(theta); - double s = Math.sin(theta); - m00 = c; - m01 = -s; - m02 = x - x * c + y * s; - m10 = s; - m11 = c; - m12 = y - x * s - y * c; - updateType(); - } - - /** - * Set this transform to a scale: - * <pre> - * [ sx 0 0 ] - * [ 0 sy 0 ] - * [ 0 0 1 ] - * </pre> - * - * @param sx the x scaling factor - * @param sy the y scaling factor - */ - public void setToScale(double sx, double sy) - { - m00 = sx; - m01 = m02 = m10 = m12 = 0; - m11 = sy; - type = (sx != sy ? TYPE_GENERAL_SCALE - : sx == 1 ? TYPE_IDENTITY : TYPE_UNIFORM_SCALE); - } - - /** - * Set this transform to a shear (points are shifted in the x direction based - * on a factor of their y coordinate, and in the y direction as a factor of - * their x coordinate): - * <pre> - * [ 1 shx 0 ] - * [ shy 1 0 ] - * [ 0 0 1 ] - * </pre> - * - * @param shx the x shearing factor - * @param shy the y shearing factor - */ - public void setToShear(double shx, double shy) - { - m00 = m11 = 1; - m01 = shx; - m10 = shy; - m02 = m12 = 0; - updateType(); - } - - /** - * Set this transform to a copy of the given one. - * - * @param tx the transform to copy - * @throws NullPointerException if tx is null - */ - public void setTransform(AffineTransform tx) - { - m00 = tx.m00; - m01 = tx.m01; - m02 = tx.m02; - m10 = tx.m10; - m11 = tx.m11; - m12 = tx.m12; - type = tx.type; - } - - /** - * Set this transform to the given values: - * <pre> - * [ m00 m01 m02 ] - * [ m10 m11 m12 ] - * [ 0 0 1 ] - * </pre> - * - * @param m00 the x scaling component - * @param m10 the y shearing component - * @param m01 the x shearing component - * @param m11 the y scaling component - * @param m02 the x translation component - * @param m12 the y translation component - */ - public void setTransform(double m00, double m10, double m01, - double m11, double m02, double m12) - { - this.m00 = m00; - this.m10 = m10; - this.m01 = m01; - this.m11 = m11; - this.m02 = m02; - this.m12 = m12; - updateType(); - } - - /** - * Set this transform to the result of performing the original version of - * this followed by tx. This is commonly used when chaining transformations - * from one space to another. In matrix form: - * <pre> - * [ this ] = [ this ] x [ tx ] - * </pre> - * - * @param tx the transform to concatenate - * @throws NullPointerException if tx is null - * @see #preConcatenate(AffineTransform) - */ - public void concatenate(AffineTransform tx) - { - double n00 = m00 * tx.m00 + m01 * tx.m10; - double n01 = m00 * tx.m01 + m01 * tx.m11; - double n02 = m00 * tx.m02 + m01 * tx.m12 + m02; - double n10 = m10 * tx.m00 + m11 * tx.m10; - double n11 = m10 * tx.m01 + m11 * tx.m11; - double n12 = m10 * tx.m02 + m11 * tx.m12 + m12; - m00 = n00; - m01 = n01; - m02 = n02; - m10 = n10; - m11 = n11; - m12 = n12; - updateType(); - } - - /** - * Set this transform to the result of performing tx followed by the - * original version of this. This is less common than normal concatenation, - * but can still be used to chain transformations from one space to another. - * In matrix form: - * <pre> - * [ this ] = [ tx ] x [ this ] - * </pre> - * - * @param tx the transform to concatenate - * @throws NullPointerException if tx is null - * @see #concatenate(AffineTransform) - */ - public void preConcatenate(AffineTransform tx) - { - double n00 = tx.m00 * m00 + tx.m01 * m10; - double n01 = tx.m00 * m01 + tx.m01 * m11; - double n02 = tx.m00 * m02 + tx.m01 * m12 + tx.m02; - double n10 = tx.m10 * m00 + tx.m11 * m10; - double n11 = tx.m10 * m01 + tx.m11 * m11; - double n12 = tx.m10 * m02 + tx.m11 * m12 + tx.m12; - m00 = n00; - m01 = n01; - m02 = n02; - m10 = n10; - m11 = n11; - m12 = n12; - updateType(); - } - - /** - * Returns a transform, which if concatenated to this one, will result in - * the identity transform. This is useful for undoing transformations, but - * is only possible if the original transform has an inverse (ie. does not - * map multiple points to the same line or point). A transform exists only - * if getDeterminant() has a non-zero value. - * - * The inverse is calculated as: - * - * <pre> - * - * Let A be the matrix for which we want to find the inverse: - * - * A = [ m00 m01 m02 ] - * [ m10 m11 m12 ] - * [ 0 0 1 ] - * - * - * 1 - * inverse (A) = --- x adjoint(A) - * det - * - * - * - * = 1 [ m11 -m01 m01*m12-m02*m11 ] - * --- x [ -m10 m00 -m00*m12+m10*m02 ] - * det [ 0 0 m00*m11-m10*m01 ] - * - * - * - * = [ m11/det -m01/det m01*m12-m02*m11/det ] - * [ -m10/det m00/det -m00*m12+m10*m02/det ] - * [ 0 0 1 ] - * - * - * </pre> - * - * - * - * @return a new inverse transform - * @throws NoninvertibleTransformException if inversion is not possible - * @see #getDeterminant() - */ - public AffineTransform createInverse() - throws NoninvertibleTransformException - { - double det = getDeterminant(); - if (det == 0) - throw new NoninvertibleTransformException("can't invert transform"); - - double im00 = m11 / det; - double im10 = -m10 / det; - double im01 = -m01 / det; - double im11 = m00 / det; - double im02 = (m01 * m12 - m02 * m11) / det; - double im12 = (-m00 * m12 + m10 * m02) / det; - - return new AffineTransform (im00, im10, im01, im11, im02, im12); - } - - /** - * Perform this transformation on the given source point, and store the - * result in the destination (creating it if necessary). It is safe for - * src and dst to be the same. - * - * @param src the source point - * @param dst the destination, or null - * @return the transformation of src, in dst if it was non-null - * @throws NullPointerException if src is null - */ - public Point2D transform(Point2D src, Point2D dst) - { - if (dst == null) - dst = new Point2D.Double(); - double x = src.getX(); - double y = src.getY(); - double nx = m00 * x + m01 * y + m02; - double ny = m10 * x + m11 * y + m12; - dst.setLocation(nx, ny); - return dst; - } - - /** - * Perform this transformation on an array of points, storing the results - * in another (possibly same) array. This will not create a destination - * array, but will create points for the null entries of the destination. - * The transformation is done sequentially. While having a single source - * and destination point be the same is safe, you should be aware that - * duplicate references to the same point in the source, and having the - * source overlap the destination, may result in your source points changing - * from a previous transform before it is their turn to be evaluated. - * - * @param src the array of source points - * @param srcOff the starting offset into src - * @param dst the array of destination points (may have null entries) - * @param dstOff the starting offset into dst - * @param num the number of points to transform - * @throws NullPointerException if src or dst is null, or src has null - * entries - * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded - * @throws ArrayStoreException if new points are incompatible with dst - */ - public void transform(Point2D[] src, int srcOff, - Point2D[] dst, int dstOff, int num) - { - while (--num >= 0) - dst[dstOff] = transform(src[srcOff++], dst[dstOff++]); - } - - /** - * Perform this transformation on an array of points, in (x,y) pairs, - * storing the results in another (possibly same) array. This will not - * create a destination array. All sources are copied before the - * transformation, so that no result will overwrite a point that has not yet - * been evaluated. - * - * @param srcPts the array of source points - * @param srcOff the starting offset into src - * @param dstPts the array of destination points - * @param dstOff the starting offset into dst - * @param num the number of points to transform - * @throws NullPointerException if src or dst is null - * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded - */ - public void transform(float[] srcPts, int srcOff, - float[] dstPts, int dstOff, int num) - { - if (srcPts == dstPts && dstOff > srcOff - && num > 1 && srcOff + 2 * num > dstOff) - { - float[] f = new float[2 * num]; - System.arraycopy(srcPts, srcOff, f, 0, 2 * num); - srcPts = f; - } - while (--num >= 0) - { - float x = srcPts[srcOff++]; - float y = srcPts[srcOff++]; - dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02); - dstPts[dstOff++] = (float) (m10 * x + m11 * y + m12); - } - } - - /** - * Perform this transformation on an array of points, in (x,y) pairs, - * storing the results in another (possibly same) array. This will not - * create a destination array. All sources are copied before the - * transformation, so that no result will overwrite a point that has not yet - * been evaluated. - * - * @param srcPts the array of source points - * @param srcOff the starting offset into src - * @param dstPts the array of destination points - * @param dstOff the starting offset into dst - * @param num the number of points to transform - * @throws NullPointerException if src or dst is null - * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded - */ - public void transform(double[] srcPts, int srcOff, - double[] dstPts, int dstOff, int num) - { - if (srcPts == dstPts && dstOff > srcOff - && num > 1 && srcOff + 2 * num > dstOff) - { - double[] d = new double[2 * num]; - System.arraycopy(srcPts, srcOff, d, 0, 2 * num); - srcPts = d; - } - while (--num >= 0) - { - double x = srcPts[srcOff++]; - double y = srcPts[srcOff++]; - dstPts[dstOff++] = m00 * x + m01 * y + m02; - dstPts[dstOff++] = m10 * x + m11 * y + m12; - } - } - - /** - * Perform this transformation on an array of points, in (x,y) pairs, - * storing the results in another array. This will not create a destination - * array. - * - * @param srcPts the array of source points - * @param srcOff the starting offset into src - * @param dstPts the array of destination points - * @param dstOff the starting offset into dst - * @param num the number of points to transform - * @throws NullPointerException if src or dst is null - * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded - */ - public void transform(float[] srcPts, int srcOff, - double[] dstPts, int dstOff, int num) - { - while (--num >= 0) - { - float x = srcPts[srcOff++]; - float y = srcPts[srcOff++]; - dstPts[dstOff++] = m00 * x + m01 * y + m02; - dstPts[dstOff++] = m10 * x + m11 * y + m12; - } - } - - /** - * Perform this transformation on an array of points, in (x,y) pairs, - * storing the results in another array. This will not create a destination - * array. - * - * @param srcPts the array of source points - * @param srcOff the starting offset into src - * @param dstPts the array of destination points - * @param dstOff the starting offset into dst - * @param num the number of points to transform - * @throws NullPointerException if src or dst is null - * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded - */ - public void transform(double[] srcPts, int srcOff, - float[] dstPts, int dstOff, int num) - { - while (--num >= 0) - { - double x = srcPts[srcOff++]; - double y = srcPts[srcOff++]; - dstPts[dstOff++] = (float) (m00 * x + m01 * y + m02); - dstPts[dstOff++] = (float) (m10 * x + m11 * y + m12); - } - } - - /** - * Perform the inverse of this transformation on the given source point, - * and store the result in the destination (creating it if necessary). It - * is safe for src and dst to be the same. - * - * @param src the source point - * @param dst the destination, or null - * @return the inverse transformation of src, in dst if it was non-null - * @throws NullPointerException if src is null - * @throws NoninvertibleTransformException if the inverse does not exist - * @see #getDeterminant() - */ - public Point2D inverseTransform(Point2D src, Point2D dst) - throws NoninvertibleTransformException - { - return createInverse().transform(src, dst); - } - - /** - * Perform the inverse of this transformation on an array of points, in - * (x,y) pairs, storing the results in another (possibly same) array. This - * will not create a destination array. All sources are copied before the - * transformation, so that no result will overwrite a point that has not yet - * been evaluated. - * - * @param srcPts the array of source points - * @param srcOff the starting offset into src - * @param dstPts the array of destination points - * @param dstOff the starting offset into dst - * @param num the number of points to transform - * @throws NullPointerException if src or dst is null - * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded - * @throws NoninvertibleTransformException if the inverse does not exist - * @see #getDeterminant() - */ - public void inverseTransform(double[] srcPts, int srcOff, - double[] dstPts, int dstOff, int num) - throws NoninvertibleTransformException - { - createInverse().transform(srcPts, srcOff, dstPts, dstOff, num); - } - - /** - * Perform this transformation, less any translation, on the given source - * point, and store the result in the destination (creating it if - * necessary). It is safe for src and dst to be the same. The reduced - * transform is equivalent to: - * <pre> - * [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ] - * [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ] - * </pre> - * - * @param src the source point - * @param dst the destination, or null - * @return the delta transformation of src, in dst if it was non-null - * @throws NullPointerException if src is null - */ - public Point2D deltaTransform(Point2D src, Point2D dst) - { - if (dst == null) - dst = new Point2D.Double(); - double x = src.getX(); - double y = src.getY(); - double nx = m00 * x + m01 * y; - double ny = m10 * x + m11 * y; - dst.setLocation(nx, ny); - return dst; - } - - /** - * Perform this transformation, less any translation, on an array of points, - * in (x,y) pairs, storing the results in another (possibly same) array. - * This will not create a destination array. All sources are copied before - * the transformation, so that no result will overwrite a point that has - * not yet been evaluated. The reduced transform is equivalent to: - * <pre> - * [ x' ] = [ m00 m01 ] [ x ] = [ m00 * x + m01 * y ] - * [ y' ] [ m10 m11 ] [ y ] = [ m10 * x + m11 * y ] - * </pre> - * - * @param srcPts the array of source points - * @param srcOff the starting offset into src - * @param dstPts the array of destination points - * @param dstOff the starting offset into dst - * @param num the number of points to transform - * @throws NullPointerException if src or dst is null - * @throws ArrayIndexOutOfBoundsException if array bounds are exceeded - */ - public void deltaTransform(double[] srcPts, int srcOff, - double[] dstPts, int dstOff, - int num) - { - if (srcPts == dstPts && dstOff > srcOff - && num > 1 && srcOff + 2 * num > dstOff) - { - double[] d = new double[2 * num]; - System.arraycopy(srcPts, srcOff, d, 0, 2 * num); - srcPts = d; - } - while (--num >= 0) - { - double x = srcPts[srcOff++]; - double y = srcPts[srcOff++]; - dstPts[dstOff++] = m00 * x + m01 * y; - dstPts[dstOff++] = m10 * x + m11 * y; - } - } - - /** - * Return a new Shape, based on the given one, where the path of the shape - * has been transformed by this transform. Notice that this uses GeneralPath, - * which only stores points in float precision. - * - * @param src the shape source to transform - * @return the shape, transformed by this, <code>null</code> if src is - * <code>null</code>. - * @see GeneralPath#transform(AffineTransform) - */ - public Shape createTransformedShape(Shape src) - { - if(src == null) - return null; - GeneralPath p = new GeneralPath(src); - p.transform(this); - return p; - } - - /** - * Returns a string representation of the transform, in the format: - * <code>"AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], [" - * + m10 + ", " + m11 + ", " + m12 + "]]"</code>. - * - * @return the string representation - */ - public String toString() - { - return "AffineTransform[[" + m00 + ", " + m01 + ", " + m02 + "], [" - + m10 + ", " + m11 + ", " + m12 + "]]"; - } - - /** - * Tests if this transformation is the identity: - * <pre> - * [ 1 0 0 ] - * [ 0 1 0 ] - * [ 0 0 1 ] - * </pre> - * - * @return true if this is the identity transform - */ - public boolean isIdentity() - { - // Rather than rely on type, check explicitly. - return (m00 == 1 && m01 == 0 && m02 == 0 - && m10 == 0 && m11 == 1 && m12 == 0); - } - - /** - * Create a new transform of the same run-time type, with the same - * transforming properties as this one. - * - * @return the clone - */ - public Object clone() - { - try - { - return super.clone(); - } - catch (CloneNotSupportedException e) - { - throw (Error) new InternalError().initCause(e); // Impossible - } - } - - /** - * Return the hashcode for this transformation. The formula is not - * documented, but appears to be the same as: - * <pre> - * long l = Double.doubleToLongBits(getScaleX()); - * l = l * 31 + Double.doubleToLongBits(getShearX()); - * l = l * 31 + Double.doubleToLongBits(getTranslateX()); - * l = l * 31 + Double.doubleToLongBits(getShearY()); - * l = l * 31 + Double.doubleToLongBits(getScaleY()); - * l = l * 31 + Double.doubleToLongBits(getTranslateY()); - * return (int) ((l >> 32) ^ l); - * </pre> - * - * @return the hashcode - */ - public int hashCode() - { - long l = Double.doubleToLongBits(m00); - l = l * 31 + Double.doubleToLongBits(m01); - l = l * 31 + Double.doubleToLongBits(m02); - l = l * 31 + Double.doubleToLongBits(m10); - l = l * 31 + Double.doubleToLongBits(m11); - l = l * 31 + Double.doubleToLongBits(m12); - return (int) ((l >> 32) ^ l); - } - - /** - * Compares two transforms for equality. This returns true if they have the - * same matrix values. - * - * @param obj the transform to compare - * @return true if it is equal - */ - public boolean equals(Object obj) - { - if (! (obj instanceof AffineTransform)) - return false; - AffineTransform t = (AffineTransform) obj; - return (m00 == t.m00 && m01 == t.m01 && m02 == t.m02 - && m10 == t.m10 && m11 == t.m11 && m12 == t.m12); - } - - /** - * Helper to decode the type from the matrix. This is not guaranteed - * to find the optimal type, but at least it will be valid. - */ - private void updateType() - { - double det = getDeterminant(); - if (det == 0) - { - type = TYPE_GENERAL_TRANSFORM; - return; - } - // Scale (includes rotation by PI) or translation. - if (m01 == 0 && m10 == 0) - { - if (m00 == m11) - type = m00 == 1 ? TYPE_IDENTITY : TYPE_UNIFORM_SCALE; - else - type = TYPE_GENERAL_SCALE; - if (m02 != 0 || m12 != 0) - type |= TYPE_TRANSLATION; - } - // Rotation. - else if (m00 == m11 && m01 == -m10) - { - type = m00 == 0 ? TYPE_QUADRANT_ROTATION : TYPE_GENERAL_ROTATION; - if (det != 1) - type |= TYPE_UNIFORM_SCALE; - if (m02 != 0 || m12 != 0) - type |= TYPE_TRANSLATION; - } - else - type = TYPE_GENERAL_TRANSFORM; - } - - /** - * Reads a transform from an object stream. - * - * @param s the stream to read from - * @throws ClassNotFoundException if there is a problem deserializing - * @throws IOException if there is a problem deserializing - */ - private void readObject(ObjectInputStream s) - throws ClassNotFoundException, IOException - { - s.defaultReadObject(); - updateType(); - } -} // class AffineTransform diff --git a/libjava/classpath/java/awt/geom/Arc2D.java b/libjava/classpath/java/awt/geom/Arc2D.java deleted file mode 100644 index 928c5cf..0000000 --- a/libjava/classpath/java/awt/geom/Arc2D.java +++ /dev/null @@ -1,1413 +0,0 @@ -/* Arc2D.java -- represents an arc in 2-D space - Copyright (C) 2002, 2003, 2004 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.awt.geom; - -import java.util.NoSuchElementException; - - -/** - * This class represents all arcs (segments of an ellipse in 2-D space). The - * arcs are defined by starting angle and extent (arc length) in degrees, as - * opposed to radians (like the rest of Java), and can be open, chorded, or - * wedge shaped. The angles are skewed according to the ellipse, so that 45 - * degrees always points to the upper right corner (positive x, negative y) - * of the bounding rectangle. A positive extent draws a counterclockwise arc, - * and while the angle can be any value, the path iterator only traverses the - * first 360 degrees. Storage is up to the subclasses. - * - * @author Eric Blake (ebb9@email.byu.edu) - * @author Sven de Marothy (sven@physto.se) - * @since 1.2 - */ -public abstract class Arc2D extends RectangularShape -{ - /** - * An open arc, with no segment connecting the endpoints. This type of - * arc still contains the same points as a chorded version. - */ - public static final int OPEN = 0; - - /** - * A closed arc with a single segment connecting the endpoints (a chord). - */ - public static final int CHORD = 1; - - /** - * A closed arc with two segments, one from each endpoint, meeting at the - * center of the ellipse. - */ - public static final int PIE = 2; - - /** The closure type of this arc. This is package-private to avoid an - * accessor method. */ - int type; - - /** - * Create a new arc, with the specified closure type. - * - * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE}. - * @throws IllegalArgumentException if type is invalid - */ - protected Arc2D(int type) - { - if (type < OPEN || type > PIE) - throw new IllegalArgumentException(); - this.type = type; - } - - /** - * Get the starting angle of the arc in degrees. - * - * @return the starting angle - * @see #setAngleStart(double) - */ - public abstract double getAngleStart(); - - /** - * Get the extent angle of the arc in degrees. - * - * @return the extent angle - * @see #setAngleExtent(double) - */ - public abstract double getAngleExtent(); - - /** - * Return the closure type of the arc. - * - * @return the closure type - * @see #OPEN - * @see #CHORD - * @see #PIE - * @see #setArcType(int) - */ - public int getArcType() - { - return type; - } - - /** - * Returns the starting point of the arc. - * - * @return the start point - */ - public Point2D getStartPoint() - { - double angle = Math.toRadians(getAngleStart()); - double rx = getWidth() / 2; - double ry = getHeight() / 2; - double x = getX() + rx + rx * Math.cos(angle); - double y = getY() + ry - ry * Math.sin(angle); - return new Point2D.Double(x, y); - } - - /** - * Returns the ending point of the arc. - * - * @return the end point - */ - public Point2D getEndPoint() - { - double angle = Math.toRadians(getAngleStart() + getAngleExtent()); - double rx = getWidth() / 2; - double ry = getHeight() / 2; - double x = getX() + rx + rx * Math.cos(angle); - double y = getY() + ry - ry * Math.sin(angle); - return new Point2D.Double(x, y); - } - - /** - * Set the parameters of the arc. The angles are in degrees, and a positive - * extent sweeps counterclockwise (from the positive x-axis to the negative - * y-axis). - * - * @param x the new x coordinate of the upper left of the bounding box - * @param y the new y coordinate of the upper left of the bounding box - * @param w the new width of the bounding box - * @param h the new height of the bounding box - * @param start the start angle, in degrees - * @param extent the arc extent, in degrees - * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - */ - public abstract void setArc(double x, double y, double w, double h, - double start, double extent, int type); - - /** - * Set the parameters of the arc. The angles are in degrees, and a positive - * extent sweeps counterclockwise (from the positive x-axis to the negative - * y-axis). - * - * @param p the upper left point of the bounding box - * @param d the dimensions of the bounding box - * @param start the start angle, in degrees - * @param extent the arc extent, in degrees - * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - * @throws NullPointerException if p or d is null - */ - public void setArc(Point2D p, Dimension2D d, double start, double extent, - int type) - { - setArc(p.getX(), p.getY(), d.getWidth(), d.getHeight(), start, extent, type); - } - - /** - * Set the parameters of the arc. The angles are in degrees, and a positive - * extent sweeps counterclockwise (from the positive x-axis to the negative - * y-axis). - * - * @param r the new bounding box - * @param start the start angle, in degrees - * @param extent the arc extent, in degrees - * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - * @throws NullPointerException if r is null - */ - public void setArc(Rectangle2D r, double start, double extent, int type) - { - setArc(r.getX(), r.getY(), r.getWidth(), r.getHeight(), start, extent, type); - } - - /** - * Set the parameters of the arc from the given one. - * - * @param a the arc to copy - * @throws NullPointerException if a is null - */ - public void setArc(Arc2D a) - { - setArc(a.getX(), a.getY(), a.getWidth(), a.getHeight(), a.getAngleStart(), - a.getAngleExtent(), a.getArcType()); - } - - /** - * Set the parameters of the arc. The angles are in degrees, and a positive - * extent sweeps counterclockwise (from the positive x-axis to the negative - * y-axis). This controls the center point and radius, so the arc will be - * circular. - * - * @param x the x coordinate of the center of the circle - * @param y the y coordinate of the center of the circle - * @param r the radius of the circle - * @param start the start angle, in degrees - * @param extent the arc extent, in degrees - * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - */ - public void setArcByCenter(double x, double y, double r, double start, - double extent, int type) - { - setArc(x - r, y - r, r + r, r + r, start, extent, type); - } - - /** - * Sets the parameters of the arc by finding the tangents of two lines, and - * using the specified radius. The arc will be circular, will begin on the - * tangent point of the line extending from p1 to p2, and will end on the - * tangent point of the line extending from p2 to p3. - * - * XXX What happens if the points are colinear, or the radius negative? - * - * @param p1 the first point - * @param p2 the tangent line intersection point - * @param p3 the third point - * @param r the radius of the arc - * @throws NullPointerException if any point is null - */ - public void setArcByTangent(Point2D p1, Point2D p2, Point2D p3, double r) - { - if ((p2.getX() - p1.getX()) * (p3.getY() - p1.getY()) - - (p3.getX() - p1.getX()) * (p2.getY() - p1.getY()) > 0) - { - Point2D p = p3; - p3 = p1; - p1 = p; - } - - // normalized tangent vectors - double dx1 = (p1.getX() - p2.getX()) / p1.distance(p2); - double dy1 = (p1.getY() - p2.getY()) / p1.distance(p2); - double dx2 = (p2.getX() - p3.getX()) / p3.distance(p2); - double dy2 = (p2.getY() - p3.getY()) / p3.distance(p2); - double theta1 = Math.atan2(dx1, dy1); - double theta2 = Math.atan2(dx2, dy2); - - double dx = r * Math.cos(theta2) - r * Math.cos(theta1); - double dy = -r * Math.sin(theta2) + r * Math.sin(theta1); - - if (theta1 < 0) - theta1 += 2 * Math.PI; - if (theta2 < 0) - theta2 += 2 * Math.PI; - if (theta2 < theta1) - theta2 += 2 * Math.PI; - - // Vectors of the lines, not normalized, note we change - // the direction of line 2. - dx1 = p1.getX() - p2.getX(); - dy1 = p1.getY() - p2.getY(); - dx2 = p3.getX() - p2.getX(); - dy2 = p3.getY() - p2.getY(); - - // Calculate the tangent point to the second line - double t2 = -(dx1 * dy - dy1 * dx) / (dx2 * dy1 - dx1 * dy2); - double x2 = t2 * (p3.getX() - p2.getX()) + p2.getX(); - double y2 = t2 * (p3.getY() - p2.getY()) + p2.getY(); - - // calculate the center point - double x = x2 - r * Math.cos(theta2); - double y = y2 + r * Math.sin(theta2); - - setArc(x - r, y - r, 2 * r, 2 * r, Math.toDegrees(theta1), - Math.toDegrees(theta2 - theta1), getArcType()); - } - - /** - * Set the start, in degrees. - * - * @param start the new start angle - * @see #getAngleStart() - */ - public abstract void setAngleStart(double start); - - /** - * Set the extent, in degrees. - * - * @param extent the new extent angle - * @see #getAngleExtent() - */ - public abstract void setAngleExtent(double extent); - - /** - * Sets the starting angle to the angle of the given point relative to - * the center of the arc. The extent remains constant; in other words, - * this rotates the arc. - * - * @param p the new start point - * @throws NullPointerException if p is null - * @see #getStartPoint() - * @see #getAngleStart() - */ - public void setAngleStart(Point2D p) - { - // Normalize. - double x = p.getX() - (getX() + getWidth() / 2); - double y = p.getY() - (getY() + getHeight() / 2); - setAngleStart(Math.toDegrees(Math.atan2(-y, x))); - } - - /** - * Sets the starting and extent angles to those of the given points - * relative to the center of the arc. The arc will be non-empty, and will - * extend counterclockwise. - * - * @param x1 the first x coordinate - * @param y1 the first y coordinate - * @param x2 the second x coordinate - * @param y2 the second y coordinate - * @see #setAngleStart(Point2D) - */ - public void setAngles(double x1, double y1, double x2, double y2) - { - // Normalize the points. - double mx = getX(); - double my = getY(); - double mw = getWidth(); - double mh = getHeight(); - x1 = x1 - (mx + mw / 2); - y1 = y1 - (my + mh / 2); - x2 = x2 - (mx + mw / 2); - y2 = y2 - (my + mh / 2); - double start = Math.toDegrees(Math.atan2(-y1, x1)); - double extent = Math.toDegrees(Math.atan2(-y2, x2)) - start; - if (extent < 0) - extent += 360; - setAngleStart(start); - setAngleExtent(extent); - } - - /** - * Sets the starting and extent angles to those of the given points - * relative to the center of the arc. The arc will be non-empty, and will - * extend counterclockwise. - * - * @param p1 the first point - * @param p2 the second point - * @throws NullPointerException if either point is null - * @see #setAngleStart(Point2D) - */ - public void setAngles(Point2D p1, Point2D p2) - { - setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY()); - } - - /** - * Set the closure type of this arc. - * - * @param type one of {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - * @see #getArcType() - */ - public void setArcType(int type) - { - if (type < OPEN || type > PIE) - throw new IllegalArgumentException(); - this.type = type; - } - - /** - * Sets the location and bounds of the ellipse of which this arc is a part. - * - * @param x the new x coordinate - * @param y the new y coordinate - * @param w the new width - * @param h the new height - * @see #getFrame() - */ - public void setFrame(double x, double y, double w, double h) - { - setArc(x, y, w, h, getAngleStart(), getAngleExtent(), type); - } - - /** - * Gets the bounds of the arc. This is much tighter than - * <code>getBounds</code>, as it takes into consideration the start and - * end angles, and the center point of a pie wedge, rather than just the - * overall ellipse. - * - * @return the bounds of the arc - * @see #getBounds() - */ - public Rectangle2D getBounds2D() - { - double extent = getAngleExtent(); - if (Math.abs(extent) >= 360) - return makeBounds(getX(), getY(), getWidth(), getHeight()); - - // Find the minimal bounding box. This determined by its extrema, - // which are the center, the endpoints of the arc, and any local - // maximum contained by the arc. - double rX = getWidth() / 2; - double rY = getHeight() / 2; - double centerX = getX() + rX; - double centerY = getY() + rY; - - Point2D p1 = getStartPoint(); - Rectangle2D result = makeBounds(p1.getX(), p1.getY(), 0, 0); - result.add(getEndPoint()); - - if (type == PIE) - result.add(centerX, centerY); - if (containsAngle(0)) - result.add(centerX + rX, centerY); - if (containsAngle(90)) - result.add(centerX, centerY - rY); - if (containsAngle(180)) - result.add(centerX - rX, centerY); - if (containsAngle(270)) - result.add(centerX, centerY + rY); - - 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 extent = getAngleExtent(); - double end = start + extent; - - if (extent == 0) - return false; - - if (extent >= 360 || extent <= -360) - return true; - - if (extent < 0) - { - end = start; - start += extent; - } - - start %= 360; - while (start < 0) - start += 360; - - end %= 360; - while (end < start) - end += 360; - - a %= 360; - while (a < start) - a += 360; - - return a >= start && a < end; // starting angle included, ending angle not - } - - /** - * Determines if the arc contains the given point. If the bounding box - * is empty, then this will return false. - * - * The area considered 'inside' an arc of type OPEN is the same as the - * area inside an equivalent filled CHORD-type arc. The area considered - * 'inside' a CHORD-type arc is the same as the filled area. - * - * @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(); - double extent = getAngleExtent(); - if (w <= 0 || h <= 0 || extent == 0) - return false; - - double mx = getX() + w / 2; - double my = getY() + h / 2; - double dx = (x - mx) * 2 / w; - double dy = (y - my) * 2 / h; - if ((dx * dx + dy * dy) >= 1.0) - return false; - - double angle = Math.toDegrees(Math.atan2(-dy, dx)); - if (getArcType() == PIE) - return containsAngle(angle); - - double a1 = Math.toRadians(getAngleStart()); - double a2 = Math.toRadians(getAngleStart() + extent); - double x1 = mx + getWidth() * Math.cos(a1) / 2; - double y1 = my - getHeight() * Math.sin(a1) / 2; - double x2 = mx + getWidth() * Math.cos(a2) / 2; - double y2 = my - getHeight() * Math.sin(a2) / 2; - double sgn = ((x2 - x1) * (my - y1) - (mx - x1) * (y2 - y1)) * ((x2 - x1) * (y - - y1) - (x - x1) * (y2 - y1)); - - if (Math.abs(extent) > 180) - { - if (containsAngle(angle)) - return true; - return sgn > 0; - } - else - { - if (! containsAngle(angle)) - return false; - return sgn < 0; - } - } - - /** - * Tests if a given rectangle intersects the area of the arc. - * - * For a definition of the 'inside' area, see the contains() method. - * @see #contains(double, double) - * - * @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 extent = getAngleExtent(); - if (extent == 0) - return false; - - if (contains(x, y) || contains(x, y + h) || contains(x + w, y) - || contains(x + w, y + h)) - return true; - - Rectangle2D rect = new Rectangle2D.Double(x, y, w, h); - - double a = getWidth() / 2.0; - double b = getHeight() / 2.0; - - double mx = getX() + a; - double my = getY() + b; - double x1 = mx + a * Math.cos(Math.toRadians(getAngleStart())); - double y1 = my - b * Math.sin(Math.toRadians(getAngleStart())); - double x2 = mx + a * Math.cos(Math.toRadians(getAngleStart() + extent)); - double y2 = my - b * Math.sin(Math.toRadians(getAngleStart() + extent)); - - if (getArcType() != CHORD) - { - // check intersections against the pie radii - if (rect.intersectsLine(mx, my, x1, y1)) - return true; - if (rect.intersectsLine(mx, my, x2, y2)) - return true; - } - else// check the chord - if (rect.intersectsLine(x1, y1, x2, y2)) - return true; - - // Check the Arc segment against the four edges - double dx; - - // Check the Arc segment against the four edges - double dy; - dy = y - my; - dx = a * Math.sqrt(1 - ((dy * dy) / (b * b))); - if (! java.lang.Double.isNaN(dx)) - { - if (mx + dx >= x && mx + dx <= x + w - && containsAngle(Math.toDegrees(Math.atan2(-dy, dx)))) - return true; - if (mx - dx >= x && mx - dx <= x + w - && containsAngle(Math.toDegrees(Math.atan2(-dy, -dx)))) - return true; - } - dy = (y + h) - my; - dx = a * Math.sqrt(1 - ((dy * dy) / (b * b))); - if (! java.lang.Double.isNaN(dx)) - { - if (mx + dx >= x && mx + dx <= x + w - && containsAngle(Math.toDegrees(Math.atan2(-dy, dx)))) - return true; - if (mx - dx >= x && mx - dx <= x + w - && containsAngle(Math.toDegrees(Math.atan2(-dy, -dx)))) - return true; - } - dx = x - mx; - dy = b * Math.sqrt(1 - ((dx * dx) / (a * a))); - if (! java.lang.Double.isNaN(dy)) - { - if (my + dy >= y && my + dy <= y + h - && containsAngle(Math.toDegrees(Math.atan2(-dy, dx)))) - return true; - if (my - dy >= y && my - dy <= y + h - && containsAngle(Math.toDegrees(Math.atan2(dy, dx)))) - return true; - } - - dx = (x + w) - mx; - dy = b * Math.sqrt(1 - ((dx * dx) / (a * a))); - if (! java.lang.Double.isNaN(dy)) - { - if (my + dy >= y && my + dy <= y + h - && containsAngle(Math.toDegrees(Math.atan2(-dy, dx)))) - return true; - if (my - dy >= y && my - dy <= y + h - && containsAngle(Math.toDegrees(Math.atan2(dy, dx)))) - return true; - } - - // Check whether the arc is contained within the box - if (rect.contains(mx, my)) - return true; - - return false; - } - - /** - * 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 extent = getAngleExtent(); - if (extent == 0) - return false; - - if (! (contains(x, y) && contains(x, y + h) && contains(x + w, y) - && contains(x + w, y + h))) - return false; - - Rectangle2D rect = new Rectangle2D.Double(x, y, w, h); - - double a = getWidth() / 2.0; - double b = getHeight() / 2.0; - - double mx = getX() + a; - double my = getY() + b; - double x1 = mx + a * Math.cos(Math.toRadians(getAngleStart())); - double y1 = my - b * Math.sin(Math.toRadians(getAngleStart())); - double x2 = mx + a * Math.cos(Math.toRadians(getAngleStart() + extent)); - double y2 = my - b * Math.sin(Math.toRadians(getAngleStart() + extent)); - if (getArcType() != CHORD) - { - // check intersections against the pie radii - if (rect.intersectsLine(mx, my, x1, y1)) - return false; - - if (rect.intersectsLine(mx, my, x2, y2)) - return false; - } - else if (rect.intersectsLine(x1, y1, x2, y2)) - return false; - return true; - } - - /** - * 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 - */ - public ArcIterator(Arc2D a, AffineTransform xform) - { - this.xform = xform; - x = a.getX(); - y = a.getY(); - w = a.getWidth(); - h = a.getHeight(); - double start = Math.toRadians(a.getAngleStart()); - double extent = Math.toRadians(a.getAngleExtent()); - - this.start = start; - this.extent = extent; - - type = a.type; - if (w < 0 || h < 0) - limit = -1; - else if (extent == 0) - limit = type; - else if (Math.abs(extent) <= Math.PI / 2.0) - limit = type + 1; - else if (Math.abs(extent) <= Math.PI) - limit = type + 2; - else if (Math.abs(extent) <= 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 - */ - public 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)) - { - coords[0] = xmid; - coords[1] = ymid; - 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; - double curr_extent; - if (extent > 0) - { - curr_begin = start + (current - 1) * quad; - curr_extent = Math.min((start + extent) - curr_begin, quad); - } - else - { - curr_begin = start - (current - 1) * quad; - curr_extent = Math.max((start + extent) - curr_begin, -quad); - } - - double portion_of_a_quadrant = Math.abs(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; - if (extent > 0) - cvec[1] = len; - else - 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; - if (extent > 0) - cvec[1] = -len; - else - 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 - */ - public Double(int type) - { - super(type); - } - - /** - * Create a new arc with the given dimensions. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - * @param start the start angle, in degrees - * @param extent the extent, in degrees - * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - */ - public Double(double x, double y, double w, double h, double start, - double extent, int type) - { - super(type); - this.x = x; - this.y = y; - width = w; - height = h; - this.start = start; - this.extent = extent; - } - - /** - * Create a new arc with the given dimensions. - * - * @param r the bounding box - * @param start the start angle, in degrees - * @param extent the extent, in degrees - * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - * @throws NullPointerException if r is null - */ - public Double(Rectangle2D r, double start, double extent, int type) - { - super(type); - x = r.getX(); - y = r.getY(); - width = r.getWidth(); - height = r.getHeight(); - this.start = start; - this.extent = extent; - } - - /** - * Return the x coordinate of the bounding box. - * - * @return the value of x - */ - public double getX() - { - return x; - } - - /** - * Return the y coordinate of the bounding box. - * - * @return the value of y - */ - public double getY() - { - return y; - } - - /** - * Return the width of the bounding box. - * - * @return the value of width - */ - public double getWidth() - { - return width; - } - - /** - * Return the height of the bounding box. - * - * @return the value of height - */ - public double getHeight() - { - return height; - } - - /** - * Return the start angle of the arc, in degrees. - * - * @return the value of start - */ - public double getAngleStart() - { - return start; - } - - /** - * Return the extent of the arc, in degrees. - * - * @return the value of extent - */ - public double getAngleExtent() - { - return extent; - } - - /** - * Tests if the arc contains points. - * - * @return true if the arc has no interior - */ - public boolean isEmpty() - { - return width <= 0 || height <= 0; - } - - /** - * Sets the arc to the given dimensions. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - * @param start the start angle, in degrees - * @param extent the extent, in degrees - * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - */ - public void setArc(double x, double y, double w, double h, double start, - double extent, int type) - { - this.x = x; - this.y = y; - width = w; - height = h; - this.start = start; - this.extent = extent; - setArcType(type); - } - - /** - * Sets the start angle of the arc. - * - * @param start the new start angle - */ - public void setAngleStart(double start) - { - this.start = start; - } - - /** - * Sets the extent angle of the arc. - * - * @param extent the new extent angle - */ - public void setAngleExtent(double extent) - { - this.extent = extent; - } - - /** - * Creates a tight bounding box given dimensions that more precise than - * the bounding box of the ellipse. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - */ - protected Rectangle2D makeBounds(double x, double y, double w, double h) - { - return new Rectangle2D.Double(x, y, w, h); - } - } // class Double - - /** - * This class implements an arc in float precision. - * - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - */ - public static class Float extends Arc2D - { - /** The x coordinate of the box bounding the ellipse of this arc. */ - public float x; - - /** The y coordinate of the box bounding the ellipse of this arc. */ - public float y; - - /** The width of the box bounding the ellipse of this arc. */ - public float width; - - /** The height of the box bounding the ellipse of this arc. */ - public float height; - - /** The start angle of this arc, in degrees. */ - public float start; - - /** The extent angle of this arc, in degrees. */ - public float extent; - - /** - * Create a new, open arc at (0,0) with 0 extent. - */ - public Float() - { - 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 - */ - public Float(int type) - { - super(type); - } - - /** - * Create a new arc with the given dimensions. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - * @param start the start angle, in degrees - * @param extent the extent, in degrees - * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - */ - public Float(float x, float y, float w, float h, float start, - float extent, int type) - { - super(type); - this.x = x; - this.y = y; - width = w; - height = h; - this.start = start; - this.extent = extent; - } - - /** - * Create a new arc with the given dimensions. - * - * @param r the bounding box - * @param start the start angle, in degrees - * @param extent the extent, in degrees - * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - * @throws NullPointerException if r is null - */ - public Float(Rectangle2D r, float start, float extent, int type) - { - super(type); - x = (float) r.getX(); - y = (float) r.getY(); - width = (float) r.getWidth(); - height = (float) r.getHeight(); - this.start = start; - this.extent = extent; - } - - /** - * Return the x coordinate of the bounding box. - * - * @return the value of x - */ - public double getX() - { - return x; - } - - /** - * Return the y coordinate of the bounding box. - * - * @return the value of y - */ - public double getY() - { - return y; - } - - /** - * Return the width of the bounding box. - * - * @return the value of width - */ - public double getWidth() - { - return width; - } - - /** - * Return the height of the bounding box. - * - * @return the value of height - */ - public double getHeight() - { - return height; - } - - /** - * Return the start angle of the arc, in degrees. - * - * @return the value of start - */ - public double getAngleStart() - { - return start; - } - - /** - * Return the extent of the arc, in degrees. - * - * @return the value of extent - */ - public double getAngleExtent() - { - return extent; - } - - /** - * Tests if the arc contains points. - * - * @return true if the arc has no interior - */ - public boolean isEmpty() - { - return width <= 0 || height <= 0; - } - - /** - * Sets the arc to the given dimensions. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - * @param start the start angle, in degrees - * @param extent the extent, in degrees - * @param type the arc type: {@link #OPEN}, {@link #CHORD}, or {@link #PIE} - * @throws IllegalArgumentException if type is invalid - */ - public void setArc(double x, double y, double w, double h, double start, - double extent, int type) - { - this.x = (float) x; - this.y = (float) y; - width = (float) w; - height = (float) h; - this.start = (float) start; - this.extent = (float) extent; - setArcType(type); - } - - /** - * Sets the start angle of the arc. - * - * @param start the new start angle - */ - public void setAngleStart(double start) - { - this.start = (float) start; - } - - /** - * Sets the extent angle of the arc. - * - * @param extent the new extent angle - */ - public void setAngleExtent(double extent) - { - this.extent = (float) extent; - } - - /** - * Creates a tight bounding box given dimensions that more precise than - * the bounding box of the ellipse. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - */ - protected Rectangle2D makeBounds(double x, double y, double w, double h) - { - return new Rectangle2D.Float((float) x, (float) y, (float) w, (float) h); - } - } // class Float -} // class Arc2D diff --git a/libjava/classpath/java/awt/geom/Area.java b/libjava/classpath/java/awt/geom/Area.java deleted file mode 100644 index 51f914f..0000000 --- a/libjava/classpath/java/awt/geom/Area.java +++ /dev/null @@ -1,3298 +0,0 @@ -/* Area.java -- represents a shape built by constructive area geometry - Copyright (C) 2002, 2004 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.awt.geom; - -import java.awt.Rectangle; -import java.awt.Shape; -import java.util.Vector; - - -/** - * The Area class represents any area for the purpose of - * Constructive Area Geometry (CAG) manipulations. CAG manipulations - * work as an area-wise form of boolean logic, where the basic operations are: - * <P><li>Add (in boolean algebra: A <B>or</B> B)<BR> - * <li>Subtract (in boolean algebra: A <B>and</B> (<B>not</B> B) )<BR> - * <li>Intersect (in boolean algebra: A <B>and</B> B)<BR> - * <li>Exclusive Or <BR> - * <img src="doc-files/Area-1.png" width="342" height="302" - * alt="Illustration of CAG operations" /><BR> - * Above is an illustration of the CAG operations on two ring shapes.<P> - * - * The contains and intersects() methods are also more accurate than the - * specification of #Shape requires.<P> - * - * Please note that constructing an Area can be slow - * (Self-intersection resolving is proportional to the square of - * the number of segments).<P> - * @see #add(Area) - * @see #subtract(Area) - * @see #intersect(Area) - * @see #exclusiveOr(Area) - * - * @author Sven de Marothy (sven@physto.se) - * - * @since 1.2 - * @status Works, but could be faster and more reliable. - */ -public class Area implements Shape, Cloneable -{ - /** - * General numerical precision - */ - private static final double EPSILON = 1E-11; - - /** - * recursive subdivision epsilon - (see getRecursionDepth) - */ - private static final double RS_EPSILON = 1E-13; - - /** - * Snap distance - points within this distance are considered equal - */ - private static final double PE_EPSILON = 1E-11; - - /** - * Segment vectors containing solid areas and holes - * This is package-private to avoid an accessor method. - */ - Vector<Segment> solids; - - /** - * Segment vectors containing solid areas and holes - * This is package-private to avoid an accessor method. - */ - Vector<Segment> holes; - - /** - * Vector (temporary) storing curve-curve intersections - */ - private Vector<double[]> ccIntersections; - - /** - * Winding rule WIND_NON_ZERO used, after construction, - * this is irrelevant. - */ - private int windingRule; - - /** - * Constructs an empty Area - */ - public Area() - { - solids = new Vector<Segment>(); - holes = new Vector<Segment>(); - } - - /** - * Constructs an Area from any given Shape. <P> - * - * If the Shape is self-intersecting, the created Area will consist - * of non-self-intersecting subpaths, and any inner paths which - * are found redundant in accordance with the Shape's winding rule - * will not be included. - * - * @param s the shape (<code>null</code> not permitted). - * - * @throws NullPointerException if <code>s</code> is <code>null</code>. - */ - public Area(Shape s) - { - this(); - - Vector<Segment> p = makeSegment(s); - - // empty path - if (p == null) - return; - - // delete empty paths - for (int i = 0; i < p.size(); i++) - if (p.elementAt(i).getSignedArea() == 0.0) - p.remove(i--); - - /* - * Resolve self intersecting paths into non-intersecting - * solids and holes. - * Algorithm is as follows: - * 1: Create nodes at all self intersections - * 2: Put all segments into a list - * 3: Grab a segment, follow it, change direction at each node, - * removing segments from the list in the process - * 4: Repeat (3) until no segments remain in the list - * 5: Remove redundant paths and sort into solids and holes - */ - Segment v; - - for (int i = 0; i < p.size(); i++) - { - Segment path = p.elementAt(i); - createNodesSelf(path); - } - - if (p.size() > 1) - { - for (int i = 0; i < p.size() - 1; i++) - for (int j = i + 1; j < p.size(); j++) - { - Segment path1 = p.elementAt(i); - Segment path2 = p.elementAt(j); - createNodes(path1, path2); - } - } - - // we have intersecting points. - Vector<Segment> segments = new Vector<Segment>(); - - for (int i = 0; i < p.size(); i++) - { - Segment path = v = p.elementAt(i); - do - { - segments.add(v); - v = v.next; - } - while (v != path); - } - - Vector<Segment> paths = weilerAtherton(segments); - deleteRedundantPaths(paths); - } - - /** - * Performs an add (union) operation on this area with another Area.<BR> - * @param area - the area to be unioned with this one - */ - public void add(Area area) - { - if (equals(area)) - return; - if (area.isEmpty()) - return; - - Area B = (Area) area.clone(); - - Vector<Segment> pathA = new Vector<Segment>(); - Vector<Segment> pathB = new Vector<Segment>(); - pathA.addAll(solids); - pathA.addAll(holes); - pathB.addAll(B.solids); - pathB.addAll(B.holes); - - for (int i = 0; i < pathA.size(); i++) - { - Segment a = pathA.elementAt(i); - for (int j = 0; j < pathB.size(); j++) - { - Segment b = pathB.elementAt(j); - createNodes(a, b); - } - } - - Vector<Segment> paths = new Vector<Segment>(); - Segment v; - - // we have intersecting points. - Vector<Segment> segments = new Vector<Segment>(); - - // In a union operation, we keep all - // segments of A oustide B and all B outside A - for (int i = 0; i < pathA.size(); i++) - { - v = pathA.elementAt(i); - Segment path = v; - do - { - if (v.isSegmentOutside(area)) - segments.add(v); - v = v.next; - } - while (v != path); - } - - for (int i = 0; i < pathB.size(); i++) - { - v = pathB.elementAt(i); - Segment path = v; - do - { - if (v.isSegmentOutside(this)) - segments.add(v); - v = v.next; - } - while (v != path); - } - - paths = weilerAtherton(segments); - deleteRedundantPaths(paths); - } - - /** - * Performs a subtraction operation on this Area.<BR> - * @param area the area to be subtracted from this area. - * @throws NullPointerException if <code>area</code> is <code>null</code>. - */ - public void subtract(Area area) - { - if (isEmpty() || area.isEmpty()) - return; - - if (equals(area)) - { - reset(); - return; - } - - Vector<Segment> pathA = new Vector<Segment>(); - Area B = (Area) area.clone(); - pathA.addAll(solids); - pathA.addAll(holes); - - // reverse the directions of B paths. - setDirection(B.holes, true); - setDirection(B.solids, false); - - Vector<Segment> pathB = new Vector<Segment>(); - pathB.addAll(B.solids); - pathB.addAll(B.holes); - - // create nodes - for (int i = 0; i < pathA.size(); i++) - { - Segment a = pathA.elementAt(i); - for (int j = 0; j < pathB.size(); j++) - { - Segment b = pathB.elementAt(j); - createNodes(a, b); - } - } - - // we have intersecting points. - Vector<Segment> segments = new Vector<Segment>(); - - // In a subtraction operation, we keep all - // segments of A oustide B and all B within A - // We outsideness-test only one segment in each path - // and the segments before and after any node - for (int i = 0; i < pathA.size(); i++) - { - Segment v = pathA.elementAt(i); - Segment path = v; - if (v.isSegmentOutside(area) && v.node == null) - segments.add(v); - boolean node = false; - do - { - if ((v.node != null || node)) - { - node = (v.node != null); - if (v.isSegmentOutside(area)) - segments.add(v); - } - v = v.next; - } - while (v != path); - } - - for (int i = 0; i < pathB.size(); i++) - { - Segment v = (Segment) pathB.elementAt(i); - Segment path = v; - if (! v.isSegmentOutside(this) && v.node == null) - segments.add(v); - v = v.next; - boolean node = false; - do - { - if ((v.node != null || node)) - { - node = (v.node != null); - if (! v.isSegmentOutside(this)) - segments.add(v); - } - v = v.next; - } - while (v != path); - } - - Vector<Segment> paths = weilerAtherton(segments); - deleteRedundantPaths(paths); - } - - /** - * Performs an intersection operation on this Area.<BR> - * @param area - the area to be intersected with this area. - * @throws NullPointerException if <code>area</code> is <code>null</code>. - */ - public void intersect(Area area) - { - if (isEmpty() || area.isEmpty()) - { - reset(); - return; - } - if (equals(area)) - return; - - Vector<Segment> pathA = new Vector<Segment>(); - Area B = (Area) area.clone(); - pathA.addAll(solids); - pathA.addAll(holes); - - Vector<Segment> pathB = new Vector<Segment>(); - pathB.addAll(B.solids); - pathB.addAll(B.holes); - - // create nodes - for (int i = 0; i < pathA.size(); i++) - { - Segment a = pathA.elementAt(i); - for (int j = 0; j < pathB.size(); j++) - { - Segment b = pathB.elementAt(j); - createNodes(a, b); - } - } - - // we have intersecting points. - Vector<Segment> segments = new Vector<Segment>(); - - // In an intersection operation, we keep all - // segments of A within B and all B within A - // (The rest must be redundant) - // We outsideness-test only one segment in each path - // and the segments before and after any node - for (int i = 0; i < pathA.size(); i++) - { - Segment v = pathA.elementAt(i); - Segment path = v; - if (! v.isSegmentOutside(area) && v.node == null) - segments.add(v); - boolean node = false; - do - { - if ((v.node != null || node)) - { - node = (v.node != null); - if (! v.isSegmentOutside(area)) - segments.add(v); - } - v = v.next; - } - while (v != path); - } - - for (int i = 0; i < pathB.size(); i++) - { - Segment v = pathB.elementAt(i); - Segment path = v; - if (! v.isSegmentOutside(this) && v.node == null) - segments.add(v); - v = v.next; - boolean node = false; - do - { - if ((v.node != null || node)) - { - node = (v.node != null); - if (! v.isSegmentOutside(this)) - segments.add(v); - } - v = v.next; - } - while (v != path); - } - - Vector<Segment> paths = weilerAtherton(segments); - deleteRedundantPaths(paths); - } - - /** - * Performs an exclusive-or operation on this Area.<BR> - * @param area - the area to be XORed with this area. - * @throws NullPointerException if <code>area</code> is <code>null</code>. - */ - public void exclusiveOr(Area area) - { - if (area.isEmpty()) - return; - - if (isEmpty()) - { - Area B = (Area) area.clone(); - solids = B.solids; - holes = B.holes; - return; - } - if (equals(area)) - { - reset(); - return; - } - - Vector<Segment> pathA = new Vector<Segment>(); - - Area B = (Area) area.clone(); - Vector<Segment> pathB = new Vector<Segment>(); - pathA.addAll(solids); - pathA.addAll(holes); - - // reverse the directions of B paths. - setDirection(B.holes, true); - setDirection(B.solids, false); - pathB.addAll(B.solids); - pathB.addAll(B.holes); - - for (int i = 0; i < pathA.size(); i++) - { - Segment a = pathA.elementAt(i); - for (int j = 0; j < pathB.size(); j++) - { - Segment b = pathB.elementAt(j); - createNodes(a, b); - } - } - - Segment v; - - // we have intersecting points. - Vector<Segment> segments = new Vector<Segment>(); - - // In an XOR operation, we operate on all segments - for (int i = 0; i < pathA.size(); i++) - { - v = pathA.elementAt(i); - Segment path = v; - do - { - segments.add(v); - v = v.next; - } - while (v != path); - } - - for (int i = 0; i < pathB.size(); i++) - { - v = pathB.elementAt(i); - Segment path = v; - do - { - segments.add(v); - v = v.next; - } - while (v != path); - } - - Vector<Segment> paths = weilerAtherton(segments); - deleteRedundantPaths(paths); - } - - /** - * Clears the Area object, creating an empty area. - */ - public void reset() - { - solids = new Vector<Segment>(); - holes = new Vector<Segment>(); - } - - /** - * Returns whether this area encloses any area. - * @return true if the object encloses any area. - */ - public boolean isEmpty() - { - if (solids.size() == 0) - return true; - - double totalArea = 0; - for (int i = 0; i < solids.size(); i++) - totalArea += Math.abs(solids.elementAt(i).getSignedArea()); - for (int i = 0; i < holes.size(); i++) - totalArea -= Math.abs(holes.elementAt(i).getSignedArea()); - if (totalArea <= EPSILON) - return true; - - return false; - } - - /** - * Determines whether the Area consists entirely of line segments - * @return true if the Area lines-only, false otherwise - */ - public boolean isPolygonal() - { - for (int i = 0; i < holes.size(); i++) - if (!holes.elementAt(i).isPolygonal()) - return false; - for (int i = 0; i < solids.size(); i++) - if (!solids.elementAt(i).isPolygonal()) - return false; - return true; - } - - /** - * Determines if the Area is rectangular.<P> - * - * This is strictly qualified. An area is considered rectangular if:<BR> - * <li>It consists of a single polygonal path.<BR> - * <li>It is oriented parallel/perpendicular to the xy axis<BR> - * <li>It must be exactly rectangular, i.e. small errors induced by - * transformations may cause a false result, although the area is - * visibly rectangular.<P> - * @return true if the above criteria are met, false otherwise - */ - public boolean isRectangular() - { - if (isEmpty()) - return true; - - if (holes.size() != 0 || solids.size() != 1) - return false; - - Segment path = solids.elementAt(0); - if (! path.isPolygonal()) - return false; - - int nCorners = 0; - Segment s = path; - do - { - Segment s2 = s.next; - double d1 = (s.P2.getX() - s.P1.getX())*(s2.P2.getX() - s2.P1.getX())/ - ((s.P1.distance(s.P2)) * (s2.P1.distance(s2.P2))); - double d2 = (s.P2.getY() - s.P1.getY())*(s2.P2.getY() - s2.P1.getY())/ - ((s.P1.distance(s.P2)) * (s2.P1.distance(s2.P2))); - double dotproduct = d1 + d2; - - // For some reason, only rectangles on the XY axis count. - if (d1 != 0 && d2 != 0) - return false; - - if (Math.abs(dotproduct) == 0) // 90 degree angle - nCorners++; - else if ((Math.abs(1.0 - dotproduct) > 0)) // 0 degree angle? - return false; // if not, return false - - s = s.next; - } - while (s != path); - - return nCorners == 4; - } - - /** - * Returns whether the Area consists of more than one simple - * (non self-intersecting) subpath. - * - * @return true if the Area consists of none or one simple subpath, - * false otherwise. - */ - public boolean isSingular() - { - return (holes.size() == 0 && solids.size() <= 1); - } - - /** - * Returns the bounding box of the Area.<P> Unlike the CubicCurve2D and - * QuadraticCurve2D classes, this method will return the tightest possible - * bounding box, evaluating the extreme points of each curved segment.<P> - * @return the bounding box - */ - public Rectangle2D getBounds2D() - { - if (solids.size() == 0) - return new Rectangle2D.Double(0.0, 0.0, 0.0, 0.0); - - double xmin; - double xmax; - double ymin; - double ymax; - xmin = xmax = solids.elementAt(0).P1.getX(); - ymin = ymax = solids.elementAt(0).P1.getY(); - - for (int path = 0; path < solids.size(); path++) - { - Rectangle2D r = solids.elementAt(path).getPathBounds(); - xmin = Math.min(r.getMinX(), xmin); - ymin = Math.min(r.getMinY(), ymin); - xmax = Math.max(r.getMaxX(), xmax); - ymax = Math.max(r.getMaxY(), ymax); - } - - return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin))); - } - - /** - * Returns the bounds of this object in Rectangle format. - * Please note that this may lead to loss of precision. - * - * @return The bounds. - * @see #getBounds2D() - */ - public Rectangle getBounds() - { - return getBounds2D().getBounds(); - } - - /** - * Create a new area of the same run-time type with the same contents as - * this one. - * - * @return the clone - */ - public Object clone() - { - try - { - Area clone = new Area(); - for (int i = 0; i < solids.size(); i++) - clone.solids.add(solids.elementAt(i).cloneSegmentList()); - for (int i = 0; i < holes.size(); i++) - clone.holes.add(holes.elementAt(i).cloneSegmentList()); - return clone; - } - catch (CloneNotSupportedException e) - { - throw (Error) new InternalError().initCause(e); // Impossible - } - } - - /** - * Compares two Areas. - * - * @param area the area to compare against this area (<code>null</code> - * permitted). - * @return <code>true</code> if the areas are equal, and <code>false</code> - * otherwise. - */ - public boolean equals(Area area) - { - if (area == null) - return false; - - if (! getBounds2D().equals(area.getBounds2D())) - return false; - - if (solids.size() != area.solids.size() - || holes.size() != area.holes.size()) - return false; - - Vector<Segment> pathA = new Vector<Segment>(); - pathA.addAll(solids); - pathA.addAll(holes); - Vector<Segment> pathB = new Vector<Segment>(); - pathB.addAll(area.solids); - pathB.addAll(area.holes); - - int nPaths = pathA.size(); - boolean[][] match = new boolean[2][nPaths]; - - for (int i = 0; i < nPaths; i++) - { - for (int j = 0; j < nPaths; j++) - { - Segment p1 = pathA.elementAt(i); - Segment p2 = pathB.elementAt(j); - if (! match[0][i] && ! match[1][j]) - if (p1.pathEquals(p2)) - match[0][i] = match[1][j] = true; - } - } - - boolean result = true; - for (int i = 0; i < nPaths; i++) - result = result && match[0][i] && match[1][i]; - return result; - } - - /** - * Transforms this area by the AffineTransform at. - * - * @param at the transform. - */ - public void transform(AffineTransform at) - { - for (int i = 0; i < solids.size(); i++) - solids.elementAt(i).transformSegmentList(at); - for (int i = 0; i < holes.size(); i++) - holes.elementAt(i).transformSegmentList(at); - - // Note that the orientation is not invariant under inversion - if ((at.getType() & AffineTransform.TYPE_FLIP) != 0) - { - setDirection(holes, false); - setDirection(solids, true); - } - } - - /** - * Returns a new Area equal to this one, transformed - * by the AffineTransform at. - * @param at the transform. - * @return the transformed area - * @throws NullPointerException if <code>at</code> is <code>null</code>. - */ - public Area createTransformedArea(AffineTransform at) - { - Area a = (Area) clone(); - a.transform(at); - return a; - } - - /** - * Determines if the point (x,y) is contained within this Area. - * - * @param x the x-coordinate of the point. - * @param y the y-coordinate of the point. - * @return true if the point is contained, false otherwise. - */ - public boolean contains(double x, double y) - { - int n = 0; - for (int i = 0; i < solids.size(); i++) - if (solids.elementAt(i).contains(x, y)) - n++; - - for (int i = 0; i < holes.size(); i++) - if (holes.elementAt(i).contains(x, y)) - n--; - - return (n != 0); - } - - /** - * Determines if the Point2D p is contained within this Area. - * - * @param p the point. - * @return <code>true</code> if the point is contained, <code>false</code> - * otherwise. - * @throws NullPointerException if <code>p</code> is <code>null</code>. - */ - public boolean contains(Point2D p) - { - return contains(p.getX(), p.getY()); - } - - /** - * Determines if the rectangle specified by (x,y) as the upper-left - * and with width w and height h is completely contained within this Area, - * returns false otherwise.<P> - * - * This method should always produce the correct results, unlike for other - * classes in geom. - * - * @param x the x-coordinate of the rectangle. - * @param y the y-coordinate of the rectangle. - * @param w the width of the the rectangle. - * @param h the height of the rectangle. - * @return <code>true</code> if the rectangle is considered contained - */ - public boolean contains(double x, double y, double w, double h) - { - LineSegment[] l = new LineSegment[4]; - l[0] = new LineSegment(x, y, x + w, y); - l[1] = new LineSegment(x, y + h, x + w, y + h); - l[2] = new LineSegment(x, y, x, y + h); - l[3] = new LineSegment(x + w, y, x + w, y + h); - - // Since every segment in the area must a contour - // between inside/outside segments, ANY intersection - // will mean the rectangle is not entirely contained. - for (int i = 0; i < 4; i++) - { - for (int path = 0; path < solids.size(); path++) - { - Segment v; - Segment start; - start = v = solids.elementAt(path); - do - { - if (l[i].hasIntersections(v)) - return false; - v = v.next; - } - while (v != start); - } - for (int path = 0; path < holes.size(); path++) - { - Segment v; - Segment start; - start = v = holes.elementAt(path); - do - { - if (l[i].hasIntersections(v)) - return false; - v = v.next; - } - while (v != start); - } - } - - // Is any point inside? - if (! contains(x, y)) - return false; - - // Final hoop: Is the rectangle non-intersecting and inside, - // but encloses a hole? - Rectangle2D r = new Rectangle2D.Double(x, y, w, h); - for (int path = 0; path < holes.size(); path++) - if (! holes.elementAt(path).isSegmentOutside(r)) - return false; - - return true; - } - - /** - * Determines if the Rectangle2D specified by r is completely contained - * within this Area, returns false otherwise.<P> - * - * This method should always produce the correct results, unlike for other - * classes in geom. - * - * @param r the rectangle. - * @return <code>true</code> if the rectangle is considered contained - * - * @throws NullPointerException if <code>r</code> is <code>null</code>. - */ - public boolean contains(Rectangle2D r) - { - return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - /** - * Determines if the rectangle specified by (x,y) as the upper-left - * and with width w and height h intersects any part of this Area. - * - * @param x the x-coordinate for the rectangle. - * @param y the y-coordinate for the rectangle. - * @param w the width of the rectangle. - * @param h the height of the rectangle. - * @return <code>true</code> if the rectangle intersects the area, - * <code>false</code> otherwise. - */ - public boolean intersects(double x, double y, double w, double h) - { - if (solids.size() == 0) - return false; - - LineSegment[] l = new LineSegment[4]; - l[0] = new LineSegment(x, y, x + w, y); - l[1] = new LineSegment(x, y + h, x + w, y + h); - l[2] = new LineSegment(x, y, x, y + h); - l[3] = new LineSegment(x + w, y, x + w, y + h); - - // Return true on any intersection - for (int i = 0; i < 4; i++) - { - for (int path = 0; path < solids.size(); path++) - { - Segment v; - Segment start; - start = v = solids.elementAt(path); - do - { - if (l[i].hasIntersections(v)) - return true; - v = v.next; - } - while (v != start); - } - for (int path = 0; path < holes.size(); path++) - { - Segment v; - Segment start; - start = v = holes.elementAt(path); - do - { - if (l[i].hasIntersections(v)) - return true; - v = v.next; - } - while (v != start); - } - } - - // Non-intersecting, Is any point inside? - if (contains(x + w * 0.5, y + h * 0.5)) - return true; - - // What if the rectangle encloses the whole shape? - Point2D p = solids.elementAt(0).getMidPoint(); - if ((new Rectangle2D.Double(x, y, w, h)).contains(p)) - return true; - return false; - } - - /** - * Determines if the Rectangle2D specified by r intersects any - * part of this Area. - * @param r the rectangle to test intersection with (<code>null</code> - * not permitted). - * @return <code>true</code> if the rectangle intersects the area, - * <code>false</code> otherwise. - * @throws NullPointerException if <code>r</code> is <code>null</code>. - */ - public boolean intersects(Rectangle2D r) - { - return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - /** - * Returns a PathIterator object defining the contour of this Area, - * transformed by at. - * - * @param at the transform. - * @return A path iterator. - */ - public PathIterator getPathIterator(AffineTransform at) - { - return (new AreaIterator(at)); - } - - /** - * Returns a flattened PathIterator object defining the contour of this - * Area, transformed by at and with a defined flatness. - * - * @param at the transform. - * @param flatness the flatness. - * @return A path iterator. - */ - public PathIterator getPathIterator(AffineTransform at, double flatness) - { - return new FlatteningPathIterator(getPathIterator(at), flatness); - } - - //--------------------------------------------------------------------- - // Non-public methods and classes - - /** - * Private pathiterator object. - */ - private class AreaIterator implements PathIterator - { - private Vector<IteratorSegment> segments; - private int index; - private AffineTransform at; - - // Simple compound type for segments - class IteratorSegment - { - int type; - double[] coords; - - IteratorSegment() - { - coords = new double[6]; - } - } - - /** - * The contructor here does most of the work, - * creates a vector of IteratorSegments, which can - * readily be returned - */ - public AreaIterator(AffineTransform at) - { - this.at = at; - index = 0; - segments = new Vector<IteratorSegment>(); - Vector<Segment> allpaths = new Vector<Segment>(); - allpaths.addAll(solids); - allpaths.addAll(holes); - - for (int i = 0; i < allpaths.size(); i++) - { - Segment v = allpaths.elementAt(i); - Segment start = v; - - IteratorSegment is = new IteratorSegment(); - is.type = SEG_MOVETO; - is.coords[0] = start.P1.getX(); - is.coords[1] = start.P1.getY(); - segments.add(is); - - do - { - is = new IteratorSegment(); - is.type = v.pathIteratorFormat(is.coords); - segments.add(is); - v = v.next; - } - while (v != start); - - is = new IteratorSegment(); - is.type = SEG_CLOSE; - segments.add(is); - } - } - - public int currentSegment(double[] coords) - { - IteratorSegment s = segments.elementAt(index); - if (at != null) - at.transform(s.coords, 0, coords, 0, 3); - else - for (int i = 0; i < 6; i++) - coords[i] = s.coords[i]; - return (s.type); - } - - public int currentSegment(float[] coords) - { - IteratorSegment s = segments.elementAt(index); - double[] d = new double[6]; - if (at != null) - { - at.transform(s.coords, 0, d, 0, 3); - for (int i = 0; i < 6; i++) - coords[i] = (float) d[i]; - } - else - for (int i = 0; i < 6; i++) - coords[i] = (float) s.coords[i]; - return (s.type); - } - - // Note that the winding rule should not matter here, - // EVEN_ODD is chosen because it renders faster. - public int getWindingRule() - { - return (PathIterator.WIND_EVEN_ODD); - } - - public boolean isDone() - { - return (index >= segments.size()); - } - - public void next() - { - index++; - } - } - - /** - * Performs the fundamental task of the Weiler-Atherton algorithm, - * traverse a list of segments, for each segment: - * Follow it, removing segments from the list and switching paths - * at each node. Do so until the starting segment is reached. - * - * Returns a Vector of the resulting paths. - */ - private Vector<Segment> weilerAtherton(Vector<Segment> segments) - { - Vector<Segment> paths = new Vector<Segment>(); - while (segments.size() > 0) - { - // Iterate over the path - Segment start = segments.elementAt(0); - Segment s = start; - do - { - segments.remove(s); - if (s.node != null) - { // switch over - s.next = s.node; - s.node = null; - } - s = s.next; // continue - } - while (s != start); - - paths.add(start); - } - return paths; - } - - /** - * A small wrapper class to store intersection points - */ - private class Intersection - { - Point2D p; // the 2D point of intersection - double ta; // the parametric value on a - double tb; // the parametric value on b - Segment seg; // segment placeholder for node setting - - public Intersection(Point2D p, double ta, double tb) - { - this.p = p; - this.ta = ta; - this.tb = tb; - } - } - - /** - * Returns the recursion depth necessary to approximate the - * curve by line segments within the error RS_EPSILON. - * - * This is done with Wang's formula: - * L0 = max{0<=i<=N-2}(|xi - 2xi+1 + xi+2|,|yi - 2yi+1 + yi+2|) - * r0 = log4(sqrt(2)*N*(N-1)*L0/8e) - * Where e is the maximum distance error (RS_EPSILON) - */ - private int getRecursionDepth(CubicSegment curve) - { - double x0 = curve.P1.getX(); - double y0 = curve.P1.getY(); - - double x1 = curve.cp1.getX(); - double y1 = curve.cp1.getY(); - - double x2 = curve.cp2.getX(); - double y2 = curve.cp2.getY(); - - double x3 = curve.P2.getX(); - double y3 = curve.P2.getY(); - - double L0 = Math.max(Math.max(Math.abs(x0 - 2 * x1 + x2), - Math.abs(x1 - 2 * x2 + x3)), - Math.max(Math.abs(y0 - 2 * y1 + y2), - Math.abs(y1 - 2 * y2 + y3))); - - double f = Math.sqrt(2) * 6.0 * L0 / (8.0 * RS_EPSILON); - - int r0 = (int) Math.ceil(Math.log(f) / Math.log(4.0)); - return (r0); - } - - /** - * Performs recursive subdivision: - * @param c1 - curve 1 - * @param c2 - curve 2 - * @param depth1 - recursion depth of curve 1 - * @param depth2 - recursion depth of curve 2 - * @param t1 - global parametric value of the first curve's starting point - * @param t2 - global parametric value of the second curve's starting point - * @param w1 - global parametric length of curve 1 - * @param w2 - global parametric length of curve 2 - * - * The final four parameters are for keeping track of the parametric - * value of the curve. For a full curve t = 0, w = 1, w is halved with - * each subdivision. - */ - private void recursiveSubdivide(CubicCurve2D c1, CubicCurve2D c2, - int depth1, int depth2, double t1, - double t2, double w1, double w2) - { - boolean flat1 = depth1 <= 0; - boolean flat2 = depth2 <= 0; - - if (flat1 && flat2) - { - double xlk = c1.getP2().getX() - c1.getP1().getX(); - double ylk = c1.getP2().getY() - c1.getP1().getY(); - - double xnm = c2.getP2().getX() - c2.getP1().getX(); - double ynm = c2.getP2().getY() - c2.getP1().getY(); - - double xmk = c2.getP1().getX() - c1.getP1().getX(); - double ymk = c2.getP1().getY() - c1.getP1().getY(); - double det = xnm * ylk - ynm * xlk; - - if (det + 1.0 == 1.0) - return; - - double detinv = 1.0 / det; - double s = (xnm * ymk - ynm * xmk) * detinv; - double t = (xlk * ymk - ylk * xmk) * detinv; - if ((s < 0.0) || (s > 1.0) || (t < 0.0) || (t > 1.0)) - return; - - double[] temp = new double[2]; - temp[0] = t1 + s * w1; - temp[1] = t2 + t * w1; - ccIntersections.add(temp); - return; - } - - CubicCurve2D.Double c11 = new CubicCurve2D.Double(); - CubicCurve2D.Double c12 = new CubicCurve2D.Double(); - CubicCurve2D.Double c21 = new CubicCurve2D.Double(); - CubicCurve2D.Double c22 = new CubicCurve2D.Double(); - - if (! flat1 && ! flat2) - { - depth1--; - depth2--; - w1 = w1 * 0.5; - w2 = w2 * 0.5; - c1.subdivide(c11, c12); - c2.subdivide(c21, c22); - if (c11.getBounds2D().intersects(c21.getBounds2D())) - recursiveSubdivide(c11, c21, depth1, depth2, t1, t2, w1, w2); - if (c11.getBounds2D().intersects(c22.getBounds2D())) - recursiveSubdivide(c11, c22, depth1, depth2, t1, t2 + w2, w1, w2); - if (c12.getBounds2D().intersects(c21.getBounds2D())) - recursiveSubdivide(c12, c21, depth1, depth2, t1 + w1, t2, w1, w2); - if (c12.getBounds2D().intersects(c22.getBounds2D())) - recursiveSubdivide(c12, c22, depth1, depth2, t1 + w1, t2 + w2, w1, w2); - return; - } - - if (! flat1) - { - depth1--; - c1.subdivide(c11, c12); - w1 = w1 * 0.5; - if (c11.getBounds2D().intersects(c2.getBounds2D())) - recursiveSubdivide(c11, c2, depth1, depth2, t1, t2, w1, w2); - if (c12.getBounds2D().intersects(c2.getBounds2D())) - recursiveSubdivide(c12, c2, depth1, depth2, t1 + w1, t2, w1, w2); - return; - } - - depth2--; - c2.subdivide(c21, c22); - w2 = w2 * 0.5; - if (c1.getBounds2D().intersects(c21.getBounds2D())) - recursiveSubdivide(c1, c21, depth1, depth2, t1, t2, w1, w2); - if (c1.getBounds2D().intersects(c22.getBounds2D())) - recursiveSubdivide(c1, c22, depth1, depth2, t1, t2 + w2, w1, w2); - } - - /** - * Returns a set of interesections between two Cubic segments - * Or null if no intersections were found. - * - * The method used to find the intersection is recursive midpoint - * subdivision. Outline description: - * - * 1) Check if the bounding boxes of the curves intersect, - * 2) If so, divide the curves in the middle and test the bounding - * boxes again, - * 3) Repeat until a maximum recursion depth has been reached, where - * the intersecting curves can be approximated by line segments. - * - * This is a reasonably accurate method, although the recursion depth - * is typically around 20, the bounding-box tests allow for significant - * pruning of the subdivision tree. - * - * This is package-private to avoid an accessor method. - */ - Intersection[] cubicCubicIntersect(CubicSegment curve1, CubicSegment curve2) - { - Rectangle2D r1 = curve1.getBounds(); - Rectangle2D r2 = curve2.getBounds(); - - if (! r1.intersects(r2)) - return null; - - ccIntersections = new Vector<double[]>(); - recursiveSubdivide(curve1.getCubicCurve2D(), curve2.getCubicCurve2D(), - getRecursionDepth(curve1), getRecursionDepth(curve2), - 0.0, 0.0, 1.0, 1.0); - - if (ccIntersections.size() == 0) - return null; - - Intersection[] results = new Intersection[ccIntersections.size()]; - for (int i = 0; i < ccIntersections.size(); i++) - { - double[] temp = ccIntersections.elementAt(i); - results[i] = new Intersection(curve1.evaluatePoint(temp[0]), temp[0], - temp[1]); - } - ccIntersections = null; - return (results); - } - - /** - * Returns the intersections between a line and a quadratic bezier - * Or null if no intersections are found. - * This is done through combining the line's equation with the - * parametric form of the Bezier and solving the resulting quadratic. - * This is package-private to avoid an accessor method. - */ - Intersection[] lineQuadIntersect(LineSegment l, QuadSegment c) - { - double[] y = new double[3]; - double[] x = new double[3]; - double[] r = new double[3]; - int nRoots; - double x0 = c.P1.getX(); - double y0 = c.P1.getY(); - double x1 = c.cp.getX(); - double y1 = c.cp.getY(); - double x2 = c.P2.getX(); - double y2 = c.P2.getY(); - - double lx0 = l.P1.getX(); - double ly0 = l.P1.getY(); - double lx1 = l.P2.getX(); - double ly1 = l.P2.getY(); - double dx = lx1 - lx0; - double dy = ly1 - ly0; - - // form r(t) = y(t) - x(t) for the bezier - y[0] = y0; - y[1] = 2 * (y1 - y0); - y[2] = (y2 - 2 * y1 + y0); - - x[0] = x0; - x[1] = 2 * (x1 - x0); - x[2] = (x2 - 2 * x1 + x0); - - // a point, not a line - if (dy == 0 && dx == 0) - return null; - - // line on y axis - if (dx == 0 || (dy / dx) > 1.0) - { - double k = dx / dy; - x[0] -= lx0; - y[0] -= ly0; - y[0] *= k; - y[1] *= k; - y[2] *= k; - } - else - { - double k = dy / dx; - x[0] -= lx0; - y[0] -= ly0; - x[0] *= k; - x[1] *= k; - x[2] *= k; - } - - for (int i = 0; i < 3; i++) - r[i] = y[i] - x[i]; - - if ((nRoots = QuadCurve2D.solveQuadratic(r)) > 0) - { - Intersection[] temp = new Intersection[nRoots]; - int intersections = 0; - for (int i = 0; i < nRoots; i++) - { - double t = r[i]; - if (t >= 0.0 && t <= 1.0) - { - Point2D p = c.evaluatePoint(t); - - // if the line is on an axis, snap the point to that axis. - if (dx == 0) - p.setLocation(lx0, p.getY()); - if (dy == 0) - p.setLocation(p.getX(), ly0); - - if (p.getX() <= Math.max(lx0, lx1) - && p.getX() >= Math.min(lx0, lx1) - && p.getY() <= Math.max(ly0, ly1) - && p.getY() >= Math.min(ly0, ly1)) - { - double lineparameter = p.distance(l.P1) / l.P2.distance(l.P1); - temp[i] = new Intersection(p, lineparameter, t); - intersections++; - } - } - else - temp[i] = null; - } - if (intersections == 0) - return null; - - Intersection[] rValues = new Intersection[intersections]; - - for (int i = 0; i < nRoots; i++) - if (temp[i] != null) - rValues[--intersections] = temp[i]; - return (rValues); - } - return null; - } - - /** - * Returns the intersections between a line and a cubic segment - * This is done through combining the line's equation with the - * parametric form of the Bezier and solving the resulting quadratic. - * This is package-private to avoid an accessor method. - */ - Intersection[] lineCubicIntersect(LineSegment l, CubicSegment c) - { - double[] y = new double[4]; - double[] x = new double[4]; - double[] r = new double[4]; - int nRoots; - double x0 = c.P1.getX(); - double y0 = c.P1.getY(); - double x1 = c.cp1.getX(); - double y1 = c.cp1.getY(); - double x2 = c.cp2.getX(); - double y2 = c.cp2.getY(); - double x3 = c.P2.getX(); - double y3 = c.P2.getY(); - - double lx0 = l.P1.getX(); - double ly0 = l.P1.getY(); - double lx1 = l.P2.getX(); - double ly1 = l.P2.getY(); - double dx = lx1 - lx0; - double dy = ly1 - ly0; - - // form r(t) = y(t) - x(t) for the bezier - y[0] = y0; - y[1] = 3 * (y1 - y0); - y[2] = 3 * (y2 + y0 - 2 * y1); - y[3] = y3 - 3 * y2 + 3 * y1 - y0; - - x[0] = x0; - x[1] = 3 * (x1 - x0); - x[2] = 3 * (x2 + x0 - 2 * x1); - x[3] = x3 - 3 * x2 + 3 * x1 - x0; - - // a point, not a line - if (dy == 0 && dx == 0) - return null; - - // line on y axis - if (dx == 0 || (dy / dx) > 1.0) - { - double k = dx / dy; - x[0] -= lx0; - y[0] -= ly0; - y[0] *= k; - y[1] *= k; - y[2] *= k; - y[3] *= k; - } - else - { - double k = dy / dx; - x[0] -= lx0; - y[0] -= ly0; - x[0] *= k; - x[1] *= k; - x[2] *= k; - x[3] *= k; - } - for (int i = 0; i < 4; i++) - r[i] = y[i] - x[i]; - - if ((nRoots = CubicCurve2D.solveCubic(r)) > 0) - { - Intersection[] temp = new Intersection[nRoots]; - int intersections = 0; - for (int i = 0; i < nRoots; i++) - { - double t = r[i]; - if (t >= 0.0 && t <= 1.0) - { - // if the line is on an axis, snap the point to that axis. - Point2D p = c.evaluatePoint(t); - if (dx == 0) - p.setLocation(lx0, p.getY()); - if (dy == 0) - p.setLocation(p.getX(), ly0); - - if (p.getX() <= Math.max(lx0, lx1) - && p.getX() >= Math.min(lx0, lx1) - && p.getY() <= Math.max(ly0, ly1) - && p.getY() >= Math.min(ly0, ly1)) - { - double lineparameter = p.distance(l.P1) / l.P2.distance(l.P1); - temp[i] = new Intersection(p, lineparameter, t); - intersections++; - } - } - else - temp[i] = null; - } - - if (intersections == 0) - return null; - - Intersection[] rValues = new Intersection[intersections]; - for (int i = 0; i < nRoots; i++) - if (temp[i] != null) - rValues[--intersections] = temp[i]; - return (rValues); - } - return null; - } - - /** - * Returns the intersection between two lines, or null if there is no - * intersection. - * This is package-private to avoid an accessor method. - */ - Intersection linesIntersect(LineSegment a, LineSegment b) - { - Point2D P1 = a.P1; - Point2D P2 = a.P2; - Point2D P3 = b.P1; - Point2D P4 = b.P2; - - if (! Line2D.linesIntersect(P1.getX(), P1.getY(), P2.getX(), P2.getY(), - P3.getX(), P3.getY(), P4.getX(), P4.getY())) - return null; - - double x1 = P1.getX(); - double y1 = P1.getY(); - double rx = P2.getX() - x1; - double ry = P2.getY() - y1; - - double x2 = P3.getX(); - double y2 = P3.getY(); - double sx = P4.getX() - x2; - double sy = P4.getY() - y2; - - double determinant = sx * ry - sy * rx; - double nom = (sx * (y2 - y1) + sy * (x1 - x2)); - - // Parallel lines don't intersect. At least we pretend they don't. - if (Math.abs(determinant) < EPSILON) - return null; - - nom = nom / determinant; - - if (nom == 0.0) - return null; - if (nom == 1.0) - return null; - - Point2D p = new Point2D.Double(x1 + nom * rx, y1 + nom * ry); - - return new Intersection(p, p.distance(P1) / P1.distance(P2), - p.distance(P3) / P3.distance(P4)); - } - - /** - * Determines if two points are equal, within an error margin - * 'snap distance' - * This is package-private to avoid an accessor method. - */ - boolean pointEquals(Point2D a, Point2D b) - { - return (a.equals(b) || a.distance(b) < PE_EPSILON); - } - - /** - * Helper method - * Turns a shape into a Vector of Segments - */ - private Vector<Segment> makeSegment(Shape s) - { - Vector<Segment> paths = new Vector<Segment>(); - PathIterator pi = s.getPathIterator(null); - double[] coords = new double[6]; - Segment subpath = null; - Segment current = null; - double cx; - double cy; - double subpathx; - double subpathy; - cx = cy = subpathx = subpathy = 0.0; - - this.windingRule = pi.getWindingRule(); - - while (! pi.isDone()) - { - Segment v; - switch (pi.currentSegment(coords)) - { - case PathIterator.SEG_MOVETO: - if (subpath != null) - { // close existing open path - current.next = new LineSegment(cx, cy, subpathx, subpathy); - current = current.next; - current.next = subpath; - } - subpath = null; - subpathx = cx = coords[0]; - subpathy = cy = coords[1]; - break; - - // replace 'close' with a line-to. - case PathIterator.SEG_CLOSE: - if (subpath != null && (subpathx != cx || subpathy != cy)) - { - current.next = new LineSegment(cx, cy, subpathx, subpathy); - current = current.next; - current.next = subpath; - cx = subpathx; - cy = subpathy; - subpath = null; - } - else if (subpath != null) - { - current.next = subpath; - subpath = null; - } - break; - case PathIterator.SEG_LINETO: - if (cx != coords[0] || cy != coords[1]) - { - v = new LineSegment(cx, cy, coords[0], coords[1]); - if (subpath == null) - { - subpath = current = v; - paths.add(subpath); - } - else - { - current.next = v; - current = current.next; - } - cx = coords[0]; - cy = coords[1]; - } - break; - case PathIterator.SEG_QUADTO: - v = new QuadSegment(cx, cy, coords[0], coords[1], coords[2], - coords[3]); - if (subpath == null) - { - subpath = current = v; - paths.add(subpath); - } - else - { - current.next = v; - current = current.next; - } - cx = coords[2]; - cy = coords[3]; - break; - case PathIterator.SEG_CUBICTO: - v = new CubicSegment(cx, cy, coords[0], coords[1], coords[2], - coords[3], coords[4], coords[5]); - if (subpath == null) - { - subpath = current = v; - paths.add(subpath); - } - else - { - current.next = v; - current = current.next; - } - - // check if the cubic is self-intersecting - double[] lpts = ((CubicSegment) v).getLoop(); - if (lpts != null) - { - // if it is, break off the loop into its own path. - v.subdivideInsert(lpts[0]); - v.next.subdivideInsert((lpts[1] - lpts[0]) / (1.0 - lpts[0])); - - CubicSegment loop = (CubicSegment) v.next; - v.next = loop.next; - loop.next = loop; - - v.P2 = v.next.P1 = loop.P2 = loop.P1; // snap points - paths.add(loop); - current = v.next; - } - - cx = coords[4]; - cy = coords[5]; - break; - } - pi.next(); - } - - if (subpath != null) - { // close any open path - if (subpathx != cx || subpathy != cy) - { - current.next = new LineSegment(cx, cy, subpathx, subpathy); - current = current.next; - current.next = subpath; - } - else - current.next = subpath; - } - - if (paths.size() == 0) - return (null); - - return (paths); - } - - /** - * Find the intersections of two separate closed paths, - * A and B, split the segments at the intersection points, - * and create nodes pointing from one to the other - */ - private int createNodes(Segment A, Segment B) - { - int nNodes = 0; - - Segment a = A; - Segment b = B; - - do - { - do - { - nNodes += a.splitIntersections(b); - b = b.next; - } - while (b != B); - - a = a.next; // move to the next segment - } - while (a != A); // until one wrap. - - return nNodes; - } - - /** - * Find the intersections of a path with itself. - * Splits the segments at the intersection points, - * and create nodes pointing from one to the other. - */ - private int createNodesSelf(Segment A) - { - int nNodes = 0; - Segment a = A; - - if (A.next == A) - return 0; - - do - { - Segment b = a.next; - do - { - if (b != a) // necessary - nNodes += a.splitIntersections(b); - b = b.next; - } - while (b != A); - a = a.next; // move to the next segment - } - while (a != A); // until one wrap. - - return (nNodes); - } - - /** - * Deletes paths which are redundant from a list, (i.e. solid areas within - * solid areas) Clears any nodes. Sorts the remaining paths into solids - * and holes, sets their orientation and sets the solids and holes lists. - */ - private void deleteRedundantPaths(Vector<Segment> paths) - { - int npaths = paths.size(); - - int[][] contains = new int[npaths][npaths]; - int[][] windingNumbers = new int[npaths][2]; - int neg; - Rectangle2D[] bb = new Rectangle2D[npaths]; // path bounding boxes - - neg = ((windingRule == PathIterator.WIND_NON_ZERO) ? -1 : 1); - - for (int i = 0; i < npaths; i++) - bb[i] = paths.elementAt(i).getPathBounds(); - - // Find which path contains which, assign winding numbers - for (int i = 0; i < npaths; i++) - { - Segment pathA = paths.elementAt(i); - pathA.nullNodes(); // remove any now-redundant nodes, in case. - int windingA = pathA.hasClockwiseOrientation() ? 1 : neg; - - for (int j = 0; j < npaths; j++) - if (i != j) - { - Segment pathB = paths.elementAt(j); - - // A contains B - if (bb[i].intersects(bb[j])) - { - Segment s = pathB.next; - while (s.P1.getY() == s.P2.getY() && s != pathB) - s = s.next; - Point2D p = s.getMidPoint(); - if (pathA.contains(p.getX(), p.getY())) - contains[i][j] = windingA; - } - else - // A does not contain B - contains[i][j] = 0; - } - else - contains[i][j] = windingA; // i == j - } - - for (int i = 0; i < npaths; i++) - { - windingNumbers[i][0] = 0; - for (int j = 0; j < npaths; j++) - windingNumbers[i][0] += contains[j][i]; - windingNumbers[i][1] = contains[i][i]; - } - - Vector<Segment> solids = new Vector<Segment>(); - Vector<Segment> holes = new Vector<Segment>(); - - if (windingRule == PathIterator.WIND_NON_ZERO) - { - for (int i = 0; i < npaths; i++) - { - if (windingNumbers[i][0] == 0) - holes.add(paths.elementAt(i)); - else if (windingNumbers[i][0] - windingNumbers[i][1] == 0 - && Math.abs(windingNumbers[i][0]) == 1) - solids.add(paths.elementAt(i)); - } - } - else - { - windingRule = PathIterator.WIND_NON_ZERO; - for (int i = 0; i < npaths; i++) - { - if ((windingNumbers[i][0] & 1) == 0) - holes.add(paths.elementAt(i)); - else if ((windingNumbers[i][0] & 1) == 1) - solids.add(paths.elementAt(i)); - } - } - - setDirection(holes, false); - setDirection(solids, true); - this.holes = holes; - this.solids = solids; - } - - /** - * Sets the winding direction of a Vector of paths - * @param clockwise gives the direction, - * true = clockwise, false = counter-clockwise - */ - private void setDirection(Vector<Segment> paths, boolean clockwise) - { - Segment v; - for (int i = 0; i < paths.size(); i++) - { - v = paths.elementAt(i); - if (clockwise != v.hasClockwiseOrientation()) - v.reverseAll(); - } - } - - /** - * Class representing a linked-list of vertices forming a closed polygon, - * convex or concave, without holes. - */ - private abstract class Segment implements Cloneable - { - // segment type, PathIterator segment types are used. - Point2D P1; - Point2D P2; - Segment next; - Segment node; - - Segment() - { - P1 = P2 = null; - node = next = null; - } - - /** - * Reverses the direction of a single segment - */ - abstract void reverseCoords(); - - /** - * Returns the segment's midpoint - */ - abstract Point2D getMidPoint(); - - /** - * Returns the bounding box of this segment - */ - abstract Rectangle2D getBounds(); - - /** - * Transforms a single segment - */ - abstract void transform(AffineTransform at); - - /** - * Returns the PathIterator type of a segment - */ - abstract int getType(); - - /** - */ - abstract int splitIntersections(Segment b); - - /** - * Returns the PathIterator coords of a segment - */ - abstract int pathIteratorFormat(double[] coords); - - /** - * Returns the number of intersections on the positive X axis, - * with the origin at (x,y), used for contains()-testing - * - * (Although that could be done by the line-intersect methods, - * a dedicated method is better to guarantee consitent handling - * of endpoint-special-cases) - */ - abstract int rayCrossing(double x, double y); - - /** - * Subdivides the segment at parametric value t, inserting - * the new segment into the linked list after this, - * such that this becomes [0,t] and this.next becomes [t,1] - */ - abstract void subdivideInsert(double t); - - /** - * Returns twice the area of a curve, relative the P1-P2 line - * Used for area calculations. - */ - abstract double curveArea(); - - /** - * Compare two segments. - */ - abstract boolean equals(Segment b); - - /** - * Determines if this path of segments contains the point (x,y) - */ - boolean contains(double x, double y) - { - Segment v = this; - int crossings = 0; - do - { - int n = v.rayCrossing(x, y); - crossings += n; - v = v.next; - } - while (v != this); - return ((crossings & 1) == 1); - } - - /** - * Nulls all nodes of the path. Clean up any 'hairs'. - */ - void nullNodes() - { - Segment v = this; - do - { - v.node = null; - v = v.next; - } - while (v != this); - } - - /** - * Transforms each segment in the closed path - */ - void transformSegmentList(AffineTransform at) - { - Segment v = this; - do - { - v.transform(at); - v = v.next; - } - while (v != this); - } - - /** - * Determines the winding direction of the path - * By the sign of the area. - */ - boolean hasClockwiseOrientation() - { - return (getSignedArea() > 0.0); - } - - /** - * Returns the bounds of this path - */ - public Rectangle2D getPathBounds() - { - double xmin; - double xmax; - double ymin; - double ymax; - xmin = xmax = P1.getX(); - ymin = ymax = P1.getY(); - - Segment v = this; - do - { - Rectangle2D r = v.getBounds(); - xmin = Math.min(r.getMinX(), xmin); - ymin = Math.min(r.getMinY(), ymin); - xmax = Math.max(r.getMaxX(), xmax); - ymax = Math.max(r.getMaxY(), ymax); - v = v.next; - } - while (v != this); - - return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin))); - } - - /** - * Calculates twice the signed area of the path; - */ - double getSignedArea() - { - Segment s; - double area = 0.0; - - s = this; - do - { - area += s.curveArea(); - - area += s.P1.getX() * s.next.P1.getY() - - s.P1.getY() * s.next.P1.getX(); - s = s.next; - } - while (s != this); - - return area; - } - - /** - * Reverses the orientation of the whole polygon - */ - void reverseAll() - { - reverseCoords(); - Segment v = next; - Segment former = this; - while (v != this) - { - v.reverseCoords(); - Segment vnext = v.next; - v.next = former; - former = v; - v = vnext; - } - next = former; - } - - /** - * Inserts a Segment after this one - */ - void insert(Segment v) - { - Segment n = next; - next = v; - v.next = n; - } - - /** - * Returns if this segment path is polygonal - */ - boolean isPolygonal() - { - Segment v = this; - do - { - if (! (v instanceof LineSegment)) - return false; - v = v.next; - } - while (v != this); - return true; - } - - /** - * Clones this path - */ - Segment cloneSegmentList() throws CloneNotSupportedException - { - Vector<Segment> list = new Vector<Segment>(); - Segment v = next; - - while (v != this) - { - list.add(v); - v = v.next; - } - - Segment clone = (Segment) this.clone(); - v = clone; - for (int i = 0; i < list.size(); i++) - { - clone.next = (Segment) list.elementAt(i).clone(); - clone = clone.next; - } - clone.next = v; - return v; - } - - /** - * Creates a node between this segment and segment b - * at the given intersection - * @return the number of nodes created (0 or 1) - */ - int createNode(Segment b, Intersection i) - { - Point2D p = i.p; - if ((pointEquals(P1, p) || pointEquals(P2, p)) - && (pointEquals(b.P1, p) || pointEquals(b.P2, p))) - return 0; - - subdivideInsert(i.ta); - b.subdivideInsert(i.tb); - - // snap points - b.P2 = b.next.P1 = P2 = next.P1 = i.p; - - node = b.next; - b.node = next; - return 1; - } - - /** - * Creates multiple nodes from a list of intersections, - * This must be done in the order of ascending parameters, - * and the parameters must be recalculated in accordance - * with each split. - * @return the number of nodes created - */ - protected int createNodes(Segment b, Intersection[] x) - { - Vector<Intersection> v = new Vector<Intersection>(); - for (int i = 0; i < x.length; i++) - { - Point2D p = x[i].p; - if (! ((pointEquals(P1, p) || pointEquals(P2, p)) - && (pointEquals(b.P1, p) || pointEquals(b.P2, p)))) - v.add(x[i]); - } - - int nNodes = v.size(); - Intersection[] A = new Intersection[nNodes]; - Intersection[] B = new Intersection[nNodes]; - for (int i = 0; i < nNodes; i++) - A[i] = B[i] = v.elementAt(i); - - // Create two lists sorted by the parameter - // Bubble sort, OK I suppose, since the number of intersections - // cannot be larger than 9 (cubic-cubic worst case) anyway - for (int i = 0; i < nNodes - 1; i++) - { - for (int j = i + 1; j < nNodes; j++) - { - if (A[i].ta > A[j].ta) - { - Intersection swap = A[i]; - A[i] = A[j]; - A[j] = swap; - } - if (B[i].tb > B[j].tb) - { - Intersection swap = B[i]; - B[i] = B[j]; - B[j] = swap; - } - } - } - // subdivide a - Segment s = this; - for (int i = 0; i < nNodes; i++) - { - s.subdivideInsert(A[i].ta); - - // renormalize the parameters - for (int j = i + 1; j < nNodes; j++) - A[j].ta = (A[j].ta - A[i].ta) / (1.0 - A[i].ta); - - A[i].seg = s; - s = s.next; - } - - // subdivide b, set nodes - s = b; - for (int i = 0; i < nNodes; i++) - { - s.subdivideInsert(B[i].tb); - - for (int j = i + 1; j < nNodes; j++) - B[j].tb = (B[j].tb - B[i].tb) / (1.0 - B[i].tb); - - // set nodes - B[i].seg.node = s.next; // node a -> b - s.node = B[i].seg.next; // node b -> a - - // snap points - B[i].seg.P2 = B[i].seg.next.P1 = s.P2 = s.next.P1 = B[i].p; - s = s.next; - } - return nNodes; - } - - /** - * Determines if two paths are equal. - * Colinear line segments are ignored in the comparison. - */ - boolean pathEquals(Segment B) - { - if (! getPathBounds().equals(B.getPathBounds())) - return false; - - Segment startA = getTopLeft(); - Segment startB = B.getTopLeft(); - Segment a = startA; - Segment b = startB; - do - { - if (! a.equals(b)) - return false; - - if (a instanceof LineSegment) - a = ((LineSegment) a).lastCoLinear(); - if (b instanceof LineSegment) - b = ((LineSegment) b).lastCoLinear(); - - a = a.next; - b = b.next; - } - while (a != startA && b != startB); - return true; - } - - /** - * Return the segment with the top-leftmost first point - */ - Segment getTopLeft() - { - Segment v = this; - Segment tl = this; - do - { - if (v.P1.getY() < tl.P1.getY()) - tl = v; - else if (v.P1.getY() == tl.P1.getY()) - { - if (v.P1.getX() < tl.P1.getX()) - tl = v; - } - v = v.next; - } - while (v != this); - return tl; - } - - /** - * Returns if the path has a segment outside a shape - */ - boolean isSegmentOutside(Shape shape) - { - return ! shape.contains(getMidPoint()); - } - } // class Segment - - private class LineSegment extends Segment - { - public LineSegment(double x1, double y1, double x2, double y2) - { - super(); - P1 = new Point2D.Double(x1, y1); - P2 = new Point2D.Double(x2, y2); - } - - public LineSegment(Point2D p1, Point2D p2) - { - super(); - P1 = (Point2D) p1.clone(); - P2 = (Point2D) p2.clone(); - } - - /** - * Clones this segment - */ - public Object clone() - { - return new LineSegment(P1, P2); - } - - /** - * Transforms the segment - */ - void transform(AffineTransform at) - { - P1 = at.transform(P1, null); - P2 = at.transform(P2, null); - } - - /** - * Swap start and end points - */ - void reverseCoords() - { - Point2D p = P1; - P1 = P2; - P2 = p; - } - - /** - * Returns the segment's midpoint - */ - Point2D getMidPoint() - { - return (new Point2D.Double(0.5 * (P1.getX() + P2.getX()), - 0.5 * (P1.getY() + P2.getY()))); - } - - /** - * Returns twice the area of a curve, relative the P1-P2 line - * Obviously, a line does not enclose any area besides the line - */ - double curveArea() - { - return 0; - } - - /** - * Returns the PathIterator type of a segment - */ - int getType() - { - return (PathIterator.SEG_LINETO); - } - - /** - * Subdivides the segment at parametric value t, inserting - * the new segment into the linked list after this, - * such that this becomes [0,t] and this.next becomes [t,1] - */ - void subdivideInsert(double t) - { - Point2D p = new Point2D.Double((P2.getX() - P1.getX()) * t + P1.getX(), - (P2.getY() - P1.getY()) * t + P1.getY()); - insert(new LineSegment(p, P2)); - P2 = p; - next.node = node; - node = null; - } - - /** - * Determines if two line segments are strictly colinear - */ - boolean isCoLinear(LineSegment b) - { - double x1 = P1.getX(); - double y1 = P1.getY(); - double x2 = P2.getX(); - double y2 = P2.getY(); - double x3 = b.P1.getX(); - double y3 = b.P1.getY(); - double x4 = b.P2.getX(); - double y4 = b.P2.getY(); - - if ((y1 - y3) * (x4 - x3) - (x1 - x3) * (y4 - y3) != 0.0) - return false; - - return ((x2 - x1) * (y4 - y3) - (y2 - y1) * (x4 - x3) == 0.0); - } - - /** - * Return the last segment colinear with this one. - * Used in comparing paths. - */ - Segment lastCoLinear() - { - Segment prev = this; - Segment v = next; - - while (v instanceof LineSegment) - { - if (isCoLinear((LineSegment) v)) - { - prev = v; - v = v.next; - } - else - return prev; - } - return prev; - } - - /** - * Compare two segments. - * We must take into account that the lines may be broken into colinear - * subsegments and ignore them. - */ - boolean equals(Segment b) - { - if (! (b instanceof LineSegment)) - return false; - Point2D p1 = P1; - Point2D p3 = b.P1; - - if (! p1.equals(p3)) - return false; - - Point2D p2 = lastCoLinear().P2; - Point2D p4 = ((LineSegment) b).lastCoLinear().P2; - return (p2.equals(p4)); - } - - /** - * Returns a line segment - */ - int pathIteratorFormat(double[] coords) - { - coords[0] = P2.getX(); - coords[1] = P2.getY(); - return (PathIterator.SEG_LINETO); - } - - /** - * Returns if the line has intersections. - */ - boolean hasIntersections(Segment b) - { - if (b instanceof LineSegment) - return (linesIntersect(this, (LineSegment) b) != null); - - if (b instanceof QuadSegment) - return (lineQuadIntersect(this, (QuadSegment) b) != null); - - if (b instanceof CubicSegment) - return (lineCubicIntersect(this, (CubicSegment) b) != null); - - return false; - } - - /** - * Splits intersections into nodes, - * This one handles line-line, line-quadratic, line-cubic - */ - int splitIntersections(Segment b) - { - if (b instanceof LineSegment) - { - Intersection i = linesIntersect(this, (LineSegment) b); - - if (i == null) - return 0; - - return createNode(b, i); - } - - Intersection[] x = null; - - if (b instanceof QuadSegment) - x = lineQuadIntersect(this, (QuadSegment) b); - - if (b instanceof CubicSegment) - x = lineCubicIntersect(this, (CubicSegment) b); - - if (x == null) - return 0; - - if (x.length == 1) - return createNode(b, (Intersection) x[0]); - - return createNodes(b, x); - } - - /** - * Returns the bounding box of this segment - */ - Rectangle2D getBounds() - { - return (new Rectangle2D.Double(Math.min(P1.getX(), P2.getX()), - Math.min(P1.getY(), P2.getY()), - Math.abs(P1.getX() - P2.getX()), - Math.abs(P1.getY() - P2.getY()))); - } - - /** - * Returns the number of intersections on the positive X axis, - * with the origin at (x,y), used for contains()-testing - */ - int rayCrossing(double x, double y) - { - double x0 = P1.getX() - x; - double y0 = P1.getY() - y; - double x1 = P2.getX() - x; - double y1 = P2.getY() - y; - - if (y0 * y1 > 0) - return 0; - - if (x0 < 0 && x1 < 0) - return 0; - - if (y0 == 0.0) - y0 -= EPSILON; - - if (y1 == 0.0) - y1 -= EPSILON; - - if (Line2D.linesIntersect(x0, y0, x1, y1, - EPSILON, 0.0, Double.MAX_VALUE, 0.0)) - return 1; - return 0; - } - } // class LineSegment - - /** - * Quadratic Bezier curve segment - * - * Note: Most peers don't support quadratics directly, so it might make - * sense to represent them as cubics internally and just be done with it. - * I think we should be peer-agnostic, however, and stay faithful to the - * input geometry types as far as possible. - */ - private class QuadSegment extends Segment - { - Point2D cp; // control point - - /** - * Constructor, takes the coordinates of the start, control, - * and end point, respectively. - */ - QuadSegment(double x1, double y1, double cx, double cy, double x2, - double y2) - { - super(); - P1 = new Point2D.Double(x1, y1); - P2 = new Point2D.Double(x2, y2); - cp = new Point2D.Double(cx, cy); - } - - /** - * Clones this segment - */ - public Object clone() - { - return new QuadSegment(P1.getX(), P1.getY(), cp.getX(), cp.getY(), - P2.getX(), P2.getY()); - } - - /** - * Returns twice the area of a curve, relative the P1-P2 line - * - * The area formula can be derived by using Green's formula in the - * plane on the parametric form of the bezier. - */ - double curveArea() - { - double x0 = P1.getX(); - double y0 = P1.getY(); - double x1 = cp.getX(); - double y1 = cp.getY(); - double x2 = P2.getX(); - double y2 = P2.getY(); - - double P = (y2 - 2 * y1 + y0); - double Q = 2 * (y1 - y0); - - double A = (x2 - 2 * x1 + x0); - double B = 2 * (x1 - x0); - - double area = (B * P - A * Q) / 3.0; - return (area); - } - - /** - * Compare two segments. - */ - boolean equals(Segment b) - { - if (! (b instanceof QuadSegment)) - return false; - - return (P1.equals(b.P1) && cp.equals(((QuadSegment) b).cp) - && P2.equals(b.P2)); - } - - /** - * Returns a Point2D corresponding to the parametric value t - * of the curve - */ - Point2D evaluatePoint(double t) - { - double x0 = P1.getX(); - double y0 = P1.getY(); - double x1 = cp.getX(); - double y1 = cp.getY(); - double x2 = P2.getX(); - double y2 = P2.getY(); - - return new Point2D.Double(t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0) - + x0, - t * t * (y2 - 2 * y1 + y0) + 2 * t * (y1 - y0) - + y0); - } - - /** - * Returns the bounding box of this segment - */ - Rectangle2D getBounds() - { - double x0 = P1.getX(); - double y0 = P1.getY(); - double x1 = cp.getX(); - double y1 = cp.getY(); - double x2 = P2.getX(); - double y2 = P2.getY(); - double r0; - double r1; - - double xmax = Math.max(x0, x2); - double ymax = Math.max(y0, y2); - double xmin = Math.min(x0, x2); - double ymin = Math.min(y0, y2); - - r0 = 2 * (y1 - y0); - r1 = 2 * (y2 - 2 * y1 + y0); - if (r1 != 0.0) - { - double t = -r0 / r1; - if (t > 0.0 && t < 1.0) - { - double y = evaluatePoint(t).getY(); - ymax = Math.max(y, ymax); - ymin = Math.min(y, ymin); - } - } - r0 = 2 * (x1 - x0); - r1 = 2 * (x2 - 2 * x1 + x0); - if (r1 != 0.0) - { - double t = -r0 / r1; - if (t > 0.0 && t < 1.0) - { - double x = evaluatePoint(t).getY(); - xmax = Math.max(x, xmax); - xmin = Math.min(x, xmin); - } - } - - return (new Rectangle2D.Double(xmin, ymin, xmax - xmin, ymax - ymin)); - } - - /** - * Returns a cubic segment corresponding to this curve - */ - CubicSegment getCubicSegment() - { - double x1 = P1.getX() + 2.0 * (cp.getX() - P1.getX()) / 3.0; - double y1 = P1.getY() + 2.0 * (cp.getY() - P1.getY()) / 3.0; - double x2 = cp.getX() + (P2.getX() - cp.getX()) / 3.0; - double y2 = cp.getY() + (P2.getY() - cp.getY()) / 3.0; - - return new CubicSegment(P1.getX(), P1.getY(), x1, y1, x2, y2, P2.getX(), - P2.getY()); - } - - /** - * Returns the segment's midpoint - */ - Point2D getMidPoint() - { - return evaluatePoint(0.5); - } - - /** - * Returns the PathIterator type of a segment - */ - int getType() - { - return (PathIterator.SEG_QUADTO); - } - - /** - * Returns the PathIterator coords of a segment - */ - int pathIteratorFormat(double[] coords) - { - coords[0] = cp.getX(); - coords[1] = cp.getY(); - coords[2] = P2.getX(); - coords[3] = P2.getY(); - return (PathIterator.SEG_QUADTO); - } - - /** - * Returns the number of intersections on the positive X axis, - * with the origin at (x,y), used for contains()-testing - */ - int rayCrossing(double x, double y) - { - double x0 = P1.getX() - x; - double y0 = P1.getY() - y; - double x1 = cp.getX() - x; - double y1 = cp.getY() - y; - double x2 = P2.getX() - x; - double y2 = P2.getY() - y; - double[] r = new double[3]; - int nRoots; - int nCrossings = 0; - - /* 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); - - nRoots = QuadCurve2D.solveQuadratic(r); - for (int i = 0; i < nRoots; i++) - if (r[i] > 0.0f && r[i] < 1.0f) - { - double t = r[i]; - if (t * t * (x2 - 2 * x1 + x0) + 2 * t * (x1 - x0) + x0 > 0.0) - nCrossings++; - } - } - return nCrossings; - } - - /** - * Swap start and end points - */ - void reverseCoords() - { - Point2D temp = P1; - P1 = P2; - P2 = temp; - } - - /** - * Splits intersections into nodes, - * This one handles quadratic-quadratic only, - * Quadratic-line is passed on to the LineSegment class, - * Quadratic-cubic is passed on to the CubicSegment class - */ - int splitIntersections(Segment b) - { - if (b instanceof LineSegment) - return (b.splitIntersections(this)); - - if (b instanceof CubicSegment) - return (b.splitIntersections(this)); - - if (b instanceof QuadSegment) - { - // Use the cubic-cubic intersection routine for quads as well, - // Since a quadratic can be exactly described as a cubic, this - // should not be a problem; - // The recursion depth will be the same in any case. - Intersection[] x = cubicCubicIntersect(getCubicSegment(), - ((QuadSegment) b) - .getCubicSegment()); - if (x == null) - return 0; - - if (x.length == 1) - return createNode(b, (Intersection) x[0]); - - return createNodes(b, x); - } - return 0; - } - - /** - * Subdivides the segment at parametric value t, inserting - * the new segment into the linked list after this, - * such that this becomes [0,t] and this.next becomes [t,1] - */ - void subdivideInsert(double t) - { - double x0 = P1.getX(); - double y0 = P1.getY(); - double x1 = cp.getX(); - double y1 = cp.getY(); - double x2 = P2.getX(); - double y2 = P2.getY(); - - double p10x = x0 + t * (x1 - x0); - double p10y = y0 + t * (y1 - y0); - double p11x = x1 + t * (x2 - x1); - double p11y = y1 + t * (y2 - y1); - double p20x = p10x + t * (p11x - p10x); - double p20y = p10y + t * (p11y - p10y); - - insert(new QuadSegment(p20x, p20y, p11x, p11y, x2, y2)); - P2 = next.P1; - cp.setLocation(p10x, p10y); - - next.node = node; - node = null; - } - - /** - * Transforms the segment - */ - void transform(AffineTransform at) - { - P1 = at.transform(P1, null); - P2 = at.transform(P2, null); - cp = at.transform(cp, null); - } - } // class QuadSegment - - /** - * Cubic Bezier curve segment - */ - private class CubicSegment extends Segment - { - Point2D cp1; // control points - Point2D cp2; // control points - - /** - * Constructor - takes coordinates of the starting point, - * first control point, second control point and end point, - * respecively. - */ - public CubicSegment(double x1, double y1, double c1x, double c1y, - double c2x, double c2y, double x2, double y2) - { - super(); - P1 = new Point2D.Double(x1, y1); - P2 = new Point2D.Double(x2, y2); - cp1 = new Point2D.Double(c1x, c1y); - cp2 = new Point2D.Double(c2x, c2y); - } - - /** - * Clones this segment - */ - public Object clone() - { - return new CubicSegment(P1.getX(), P1.getY(), cp1.getX(), cp1.getY(), - cp2.getX(), cp2.getY(), P2.getX(), P2.getY()); - } - - /** - * Returns twice the area of a curve, relative the P1-P2 line - * - * The area formula can be derived by using Green's formula in the - * plane on the parametric form of the bezier. - */ - double curveArea() - { - double x0 = P1.getX(); - double y0 = P1.getY(); - double x1 = cp1.getX(); - double y1 = cp1.getY(); - double x2 = cp2.getX(); - double y2 = cp2.getY(); - double x3 = P2.getX(); - double y3 = P2.getY(); - - double P = y3 - 3 * y2 + 3 * y1 - y0; - double Q = 3 * (y2 + y0 - 2 * y1); - double R = 3 * (y1 - y0); - - double A = x3 - 3 * x2 + 3 * x1 - x0; - double B = 3 * (x2 + x0 - 2 * x1); - double C = 3 * (x1 - x0); - - double area = (B * P - A * Q) / 5.0 + (C * P - A * R) / 2.0 - + (C * Q - B * R) / 3.0; - - return (area); - } - - /** - * Compare two segments. - */ - boolean equals(Segment b) - { - if (! (b instanceof CubicSegment)) - return false; - - return (P1.equals(b.P1) && cp1.equals(((CubicSegment) b).cp1) - && cp2.equals(((CubicSegment) b).cp2) && P2.equals(b.P2)); - } - - /** - * Returns a Point2D corresponding to the parametric value t - * of the curve - */ - Point2D evaluatePoint(double t) - { - double x0 = P1.getX(); - double y0 = P1.getY(); - double x1 = cp1.getX(); - double y1 = cp1.getY(); - double x2 = cp2.getX(); - double y2 = cp2.getY(); - double x3 = P2.getX(); - double y3 = P2.getY(); - - return new Point2D.Double(-(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3) - + 3 * t * t * (x0 - 2 * x1 + x2) - + 3 * t * (x1 - x0) + x0, - -(t * t * t) * (y0 - 3 * y1 + 3 * y2 - y3) - + 3 * t * t * (y0 - 2 * y1 + y2) - + 3 * t * (y1 - y0) + y0); - } - - /** - * Returns the bounding box of this segment - */ - Rectangle2D getBounds() - { - double x0 = P1.getX(); - double y0 = P1.getY(); - double x1 = cp1.getX(); - double y1 = cp1.getY(); - double x2 = cp2.getX(); - double y2 = cp2.getY(); - double x3 = P2.getX(); - double y3 = P2.getY(); - double[] r = new double[3]; - - double xmax = Math.max(x0, x3); - double ymax = Math.max(y0, y3); - double xmin = Math.min(x0, x3); - double ymin = Math.min(y0, y3); - - r[0] = 3 * (y1 - y0); - r[1] = 6.0 * (y2 + y0 - 2 * y1); - r[2] = 3.0 * (y3 - 3 * y2 + 3 * y1 - y0); - - int n = QuadCurve2D.solveQuadratic(r); - for (int i = 0; i < n; i++) - { - double t = r[i]; - if (t > 0 && t < 1.0) - { - double y = evaluatePoint(t).getY(); - ymax = Math.max(y, ymax); - ymin = Math.min(y, ymin); - } - } - - r[0] = 3 * (x1 - x0); - r[1] = 6.0 * (x2 + x0 - 2 * x1); - r[2] = 3.0 * (x3 - 3 * x2 + 3 * x1 - x0); - n = QuadCurve2D.solveQuadratic(r); - for (int i = 0; i < n; i++) - { - double t = r[i]; - if (t > 0 && t < 1.0) - { - double x = evaluatePoint(t).getX(); - xmax = Math.max(x, xmax); - xmin = Math.min(x, xmin); - } - } - return (new Rectangle2D.Double(xmin, ymin, (xmax - xmin), (ymax - ymin))); - } - - /** - * Returns a CubicCurve2D object corresponding to this segment. - */ - CubicCurve2D getCubicCurve2D() - { - return new CubicCurve2D.Double(P1.getX(), P1.getY(), cp1.getX(), - cp1.getY(), cp2.getX(), cp2.getY(), - P2.getX(), P2.getY()); - } - - /** - * Returns the parametric points of self-intersection if the cubic - * is self-intersecting, null otherwise. - */ - double[] getLoop() - { - double x0 = P1.getX(); - double y0 = P1.getY(); - double x1 = cp1.getX(); - double y1 = cp1.getY(); - double x2 = cp2.getX(); - double y2 = cp2.getY(); - double x3 = P2.getX(); - double y3 = P2.getY(); - double[] r = new double[4]; - double k; - double R; - double T; - double A; - double B; - double[] results = new double[2]; - - R = x3 - 3 * x2 + 3 * x1 - x0; - T = y3 - 3 * y2 + 3 * y1 - y0; - - // A qudratic - if (R == 0.0 && T == 0.0) - return null; - - // true cubic - if (R != 0.0 && T != 0.0) - { - A = 3 * (x2 + x0 - 2 * x1) / R; - B = 3 * (x1 - x0) / R; - - double P = 3 * (y2 + y0 - 2 * y1) / T; - double Q = 3 * (y1 - y0) / T; - - if (A == P || Q == B) - return null; - - k = (Q - B) / (A - P); - } - else - { - if (R == 0.0) - { - // quadratic in x - k = -(3 * (x1 - x0)) / (3 * (x2 + x0 - 2 * x1)); - A = 3 * (y2 + y0 - 2 * y1) / T; - B = 3 * (y1 - y0) / T; - } - else - { - // quadratic in y - k = -(3 * (y1 - y0)) / (3 * (y2 + y0 - 2 * y1)); - A = 3 * (x2 + x0 - 2 * x1) / R; - B = 3 * (x1 - x0) / R; - } - } - - r[0] = -k * k * k - A * k * k - B * k; - r[1] = 3 * k * k + 2 * k * A + 2 * B; - r[2] = -3 * k; - r[3] = 2; - - int n = CubicCurve2D.solveCubic(r); - if (n != 3) - return null; - - // sort r - double t; - for (int i = 0; i < 2; i++) - for (int j = i + 1; j < 3; j++) - if (r[j] < r[i]) - { - t = r[i]; - r[i] = r[j]; - r[j] = t; - } - - if (Math.abs(r[0] + r[2] - k) < 1E-13) - if (r[0] >= 0.0 && r[0] <= 1.0 && r[2] >= 0.0 && r[2] <= 1.0) - if (evaluatePoint(r[0]).distance(evaluatePoint(r[2])) < PE_EPSILON * 10) - { // we snap the points anyway - results[0] = r[0]; - results[1] = r[2]; - return (results); - } - return null; - } - - /** - * Returns the segment's midpoint - */ - Point2D getMidPoint() - { - return evaluatePoint(0.5); - } - - /** - * Returns the PathIterator type of a segment - */ - int getType() - { - return (PathIterator.SEG_CUBICTO); - } - - /** - * Returns the PathIterator coords of a segment - */ - int pathIteratorFormat(double[] coords) - { - coords[0] = cp1.getX(); - coords[1] = cp1.getY(); - coords[2] = cp2.getX(); - coords[3] = cp2.getY(); - coords[4] = P2.getX(); - coords[5] = P2.getY(); - return (PathIterator.SEG_CUBICTO); - } - - /** - * Returns the number of intersections on the positive X axis, - * with the origin at (x,y), used for contains()-testing - */ - int rayCrossing(double x, double y) - { - double x0 = P1.getX() - x; - double y0 = P1.getY() - y; - double x1 = cp1.getX() - x; - double y1 = cp1.getY() - y; - double x2 = cp2.getX() - x; - double y2 = cp2.getY() - y; - double x3 = P2.getX() - x; - double y3 = P2.getY() - y; - double[] r = new double[4]; - int nRoots; - int nCrossings = 0; - - /* 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++) - { - if (r[i] > 0.0 && r[i] < 1.0) - { - double t = r[i]; - if (-(t * t * t) * (x0 - 3 * x1 + 3 * x2 - x3) - + 3 * t * t * (x0 - 2 * x1 + x2) + 3 * t * (x1 - x0) - + x0 > 0.0) - nCrossings++; - } - } - } - return nCrossings; - } - - /** - * Swap start and end points - */ - void reverseCoords() - { - Point2D p = P1; - P1 = P2; - P2 = p; - p = cp1; // swap control points - cp1 = cp2; - cp2 = p; - } - - /** - * Splits intersections into nodes, - * This one handles cubic-cubic and cubic-quadratic intersections - */ - int splitIntersections(Segment b) - { - if (b instanceof LineSegment) - return (b.splitIntersections(this)); - - Intersection[] x = null; - - if (b instanceof QuadSegment) - x = cubicCubicIntersect(this, ((QuadSegment) b).getCubicSegment()); - - if (b instanceof CubicSegment) - x = cubicCubicIntersect(this, (CubicSegment) b); - - if (x == null) - return 0; - - if (x.length == 1) - return createNode(b, x[0]); - - return createNodes(b, x); - } - - /** - * Subdivides the segment at parametric value t, inserting - * the new segment into the linked list after this, - * such that this becomes [0,t] and this.next becomes [t,1] - */ - void subdivideInsert(double t) - { - CubicSegment s = (CubicSegment) clone(); - double p1x = (s.cp1.getX() - s.P1.getX()) * t + s.P1.getX(); - double p1y = (s.cp1.getY() - s.P1.getY()) * t + s.P1.getY(); - - double px = (s.cp2.getX() - s.cp1.getX()) * t + s.cp1.getX(); - double py = (s.cp2.getY() - s.cp1.getY()) * t + s.cp1.getY(); - - s.cp2.setLocation((s.P2.getX() - s.cp2.getX()) * t + s.cp2.getX(), - (s.P2.getY() - s.cp2.getY()) * t + s.cp2.getY()); - - s.cp1.setLocation((s.cp2.getX() - px) * t + px, - (s.cp2.getY() - py) * t + py); - - double p2x = (px - p1x) * t + p1x; - double p2y = (py - p1y) * t + p1y; - - double p3x = (s.cp1.getX() - p2x) * t + p2x; - double p3y = (s.cp1.getY() - p2y) * t + p2y; - s.P1.setLocation(p3x, p3y); - - // insert new curve - insert(s); - - // set this curve - cp1.setLocation(p1x, p1y); - cp2.setLocation(p2x, p2y); - P2 = s.P1; - next.node = node; - node = null; - } - - /** - * Transforms the segment - */ - void transform(AffineTransform at) - { - P1 = at.transform(P1, null); - P2 = at.transform(P2, null); - cp1 = at.transform(cp1, null); - cp2 = at.transform(cp2, null); - } - } // class CubicSegment -} // class Area diff --git a/libjava/classpath/java/awt/geom/CubicCurve2D.java b/libjava/classpath/java/awt/geom/CubicCurve2D.java deleted file mode 100644 index 5cb11fe..0000000 --- a/libjava/classpath/java/awt/geom/CubicCurve2D.java +++ /dev/null @@ -1,1724 +0,0 @@ -/* CubicCurve2D.java -- represents a parameterized cubic curve in 2-D space - Copyright (C) 2002, 2003, 2004 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.awt.geom; - -import java.awt.Rectangle; -import java.awt.Shape; -import java.util.NoSuchElementException; - - -/** - * A two-dimensional curve that is parameterized with a cubic - * function. - * - * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" - * alt="A drawing of a CubicCurve2D" /> - * - * @author Eric Blake (ebb9@email.byu.edu) - * @author Graydon Hoare (graydon@redhat.com) - * @author Sascha Brawer (brawer@dandelis.ch) - * @author Sven de Marothy (sven@physto.se) - * - * @since 1.2 - */ -public abstract class CubicCurve2D implements Shape, Cloneable -{ - private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0; - private static final double EPSILON = 1E-10; - - /** - * Constructs a new CubicCurve2D. Typical users will want to - * construct instances of a subclass, such as {@link - * CubicCurve2D.Float} or {@link CubicCurve2D.Double}. - */ - protected CubicCurve2D() - { - } - - /** - * Returns the <i>x</i> coordinate of the curve’s start - * point. - */ - public abstract double getX1(); - - /** - * Returns the <i>y</i> coordinate of the curve’s start - * point. - */ - public abstract double getY1(); - - /** - * Returns the curve’s start point. - */ - public abstract Point2D getP1(); - - /** - * Returns the <i>x</i> coordinate of the curve’s first - * control point. - */ - public abstract double getCtrlX1(); - - /** - * Returns the <i>y</i> coordinate of the curve’s first - * control point. - */ - public abstract double getCtrlY1(); - - /** - * Returns the curve’s first control point. - */ - public abstract Point2D getCtrlP1(); - - /** - * Returns the <i>x</i> coordinate of the curve’s second - * control point. - */ - public abstract double getCtrlX2(); - - /** - * Returns the <i>y</i> coordinate of the curve’s second - * control point. - */ - public abstract double getCtrlY2(); - - /** - * Returns the curve’s second control point. - */ - public abstract Point2D getCtrlP2(); - - /** - * Returns the <i>x</i> coordinate of the curve’s end - * point. - */ - public abstract double getX2(); - - /** - * Returns the <i>y</i> coordinate of the curve’s end - * point. - */ - public abstract double getY2(); - - /** - * Returns the curve’s end point. - */ - public abstract Point2D getP2(); - - /** - * Changes the curve geometry, separately specifying each coordinate - * value. - * - * <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 new start - * point. - * - * @param y1 the <i>y</i> coordinate of the curve’s new start - * point. - * - * @param cx1 the <i>x</i> coordinate of the curve’s new - * first control point. - * - * @param cy1 the <i>y</i> coordinate of the curve’s new - * first control point. - * - * @param cx2 the <i>x</i> coordinate of the curve’s new - * second control point. - * - * @param cy2 the <i>y</i> coordinate of the curve’s new - * second control point. - * - * @param x2 the <i>x</i> coordinate of the curve’s new end - * point. - * - * @param y2 the <i>y</i> coordinate of the curve’s new end - * point. - */ - public abstract void setCurve(double x1, double y1, double cx1, double cy1, - double cx2, double cy2, double x2, double y2); - - /** - * Changes the curve geometry, specifying coordinate values in an - * array. - * - * @param coords an array containing the new coordinate values. The - * <i>x</i> coordinate of the new start point is located at - * <code>coords[offset]</code>, its <i>y</i> coordinate at - * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the - * new first control point is located at <code>coords[offset + - * 2]</code>, its <i>y</i> coordinate at <code>coords[offset + - * 3]</code>. The <i>x</i> coordinate of the new second control - * point is located at <code>coords[offset + 4]</code>, its <i>y</i> - * coordinate at <code>coords[offset + 5]</code>. The <i>x</i> - * coordinate of the new end point is located at <code>coords[offset - * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset + - * 7]</code>. - * - * @param offset the offset of the first coordinate value in - * <code>coords</code>. - */ - public void setCurve(double[] coords, int offset) - { - setCurve(coords[offset++], coords[offset++], coords[offset++], - coords[offset++], coords[offset++], coords[offset++], - coords[offset++], coords[offset++]); - } - - /** - * Changes the curve geometry, specifying coordinate values in - * separate Point objects. - * - * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" - * alt="A drawing of a CubicCurve2D" /> - * - * <p>The curve does not keep any reference to the passed point - * objects. Therefore, a later change to <code>p1</code>, - * <code>c1</code>, <code>c2</code> or <code>p2</code> will not - * affect the curve geometry. - * - * @param p1 the new start point. - * @param c1 the new first control point. - * @param c2 the new second control point. - * @param p2 the new end point. - */ - public void setCurve(Point2D p1, Point2D c1, Point2D c2, Point2D p2) - { - setCurve(p1.getX(), p1.getY(), c1.getX(), c1.getY(), c2.getX(), c2.getY(), - p2.getX(), p2.getY()); - } - - /** - * Changes the curve geometry, specifying coordinate values in an - * array of Point objects. - * - * <p><img src="doc-files/CubicCurve2D-1.png" width="350" height="180" - * alt="A drawing of a CubicCurve2D" /> - * - * <p>The curve does not keep references to the passed point - * objects. Therefore, a later change to the <code>pts</code> array - * or any of its elements will not affect the curve geometry. - * - * @param pts an array containing the points. The new start point - * is located at <code>pts[offset]</code>, the new first control - * point at <code>pts[offset + 1]</code>, the new second control - * point at <code>pts[offset + 2]</code>, and the new end point - * at <code>pts[offset + 3]</code>. - * - * @param offset the offset of the start point in <code>pts</code>. - */ - public void setCurve(Point2D[] pts, int offset) - { - setCurve(pts[offset].getX(), pts[offset++].getY(), pts[offset].getX(), - pts[offset++].getY(), pts[offset].getX(), pts[offset++].getY(), - pts[offset].getX(), pts[offset++].getY()); - } - - /** - * Changes the curve geometry to that of another curve. - * - * @param c the curve whose coordinates will be copied. - */ - public void setCurve(CubicCurve2D c) - { - setCurve(c.getX1(), c.getY1(), c.getCtrlX1(), c.getCtrlY1(), - c.getCtrlX2(), c.getCtrlY2(), c.getX2(), c.getY2()); - } - - /** - * Calculates the squared flatness of a cubic curve, directly - * specifying each coordinate value. The flatness is the maximal - * distance of a control point to the line between start and end - * point. - * - * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. In comparison to C1, - * control point C2 is father away from the gray line. Therefore, - * the result will be the square of the distance between C2 and the - * gray line, i.e. the squared length of the red line. - * - * @param x1 the <i>x</i> coordinate of the start point P1. - * @param y1 the <i>y</i> coordinate of the start point P1. - * @param cx1 the <i>x</i> coordinate of the first control point C1. - * @param cy1 the <i>y</i> coordinate of the first control point C1. - * @param cx2 the <i>x</i> coordinate of the second control point C2. - * @param cy2 the <i>y</i> coordinate of the second control point C2. - * @param x2 the <i>x</i> coordinate of the end point P2. - * @param y2 the <i>y</i> coordinate of the end point P2. - */ - public static double getFlatnessSq(double x1, double y1, double cx1, - double cy1, double cx2, double cy2, - double x2, double y2) - { - return Math.max(Line2D.ptSegDistSq(x1, y1, x2, y2, cx1, cy1), - Line2D.ptSegDistSq(x1, y1, x2, y2, cx2, cy2)); - } - - /** - * Calculates the flatness of a cubic curve, directly specifying - * each coordinate value. The flatness is the maximal distance of a - * control point to the line between start and end point. - * - * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. In comparison to C1, - * control point C2 is father away from the gray line. Therefore, - * the result will be the distance between C2 and the gray line, - * i.e. the length of the red line. - * - * @param x1 the <i>x</i> coordinate of the start point P1. - * @param y1 the <i>y</i> coordinate of the start point P1. - * @param cx1 the <i>x</i> coordinate of the first control point C1. - * @param cy1 the <i>y</i> coordinate of the first control point C1. - * @param cx2 the <i>x</i> coordinate of the second control point C2. - * @param cy2 the <i>y</i> coordinate of the second control point C2. - * @param x2 the <i>x</i> coordinate of the end point P2. - * @param y2 the <i>y</i> coordinate of the end point P2. - */ - public static double getFlatness(double x1, double y1, double cx1, - double cy1, double cx2, double cy2, - double x2, double y2) - { - return Math.sqrt(getFlatnessSq(x1, y1, cx1, cy1, cx2, cy2, x2, y2)); - } - - /** - * Calculates the squared flatness of a cubic curve, specifying the - * coordinate values in an array. The flatness is the maximal - * distance of a control point to the line between start and end - * point. - * - * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. In comparison to C1, - * control point C2 is father away from the gray line. Therefore, - * the result will be the square of the distance between C2 and the - * gray line, i.e. the squared length of the red line. - * - * @param coords an array containing the coordinate values. The - * <i>x</i> coordinate of the start point P1 is located at - * <code>coords[offset]</code>, its <i>y</i> coordinate at - * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the - * first control point C1 is located at <code>coords[offset + - * 2]</code>, its <i>y</i> coordinate at <code>coords[offset + - * 3]</code>. The <i>x</i> coordinate of the second control point C2 - * is located at <code>coords[offset + 4]</code>, its <i>y</i> - * coordinate at <code>coords[offset + 5]</code>. The <i>x</i> - * coordinate of the end point P2 is located at <code>coords[offset - * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset + - * 7]</code>. - * - * @param offset the offset of the first coordinate value in - * <code>coords</code>. - */ - public static double getFlatnessSq(double[] coords, int offset) - { - return getFlatnessSq(coords[offset++], coords[offset++], coords[offset++], - coords[offset++], coords[offset++], coords[offset++], - coords[offset++], coords[offset++]); - } - - /** - * Calculates the flatness of a cubic curve, specifying the - * coordinate values in an array. The flatness is the maximal - * distance of a control point to the line between start and end - * point. - * - * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. In comparison to C1, - * control point C2 is father away from the gray line. Therefore, - * the result will be the distance between C2 and the gray line, - * i.e. the length of the red line. - * - * @param coords an array containing the coordinate values. The - * <i>x</i> coordinate of the start point P1 is located at - * <code>coords[offset]</code>, its <i>y</i> coordinate at - * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the - * first control point C1 is located at <code>coords[offset + - * 2]</code>, its <i>y</i> coordinate at <code>coords[offset + - * 3]</code>. The <i>x</i> coordinate of the second control point C2 - * is located at <code>coords[offset + 4]</code>, its <i>y</i> - * coordinate at <code>coords[offset + 5]</code>. The <i>x</i> - * coordinate of the end point P2 is located at <code>coords[offset - * + 6]</code>, its <i>y</i> coordinate at <code>coords[offset + - * 7]</code>. - * - * @param offset the offset of the first coordinate value in - * <code>coords</code>. - */ - public static double getFlatness(double[] coords, int offset) - { - return Math.sqrt(getFlatnessSq(coords[offset++], coords[offset++], - coords[offset++], coords[offset++], - coords[offset++], coords[offset++], - coords[offset++], coords[offset++])); - } - - /** - * Calculates the squared flatness of this curve. The flatness is - * the maximal distance of a control point to the line between start - * and end point. - * - * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. In comparison to C1, - * control point C2 is father away from the gray line. Therefore, - * the result will be the square of the distance between C2 and the - * gray line, i.e. the squared length of the red line. - */ - public double getFlatnessSq() - { - return getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(), - getCtrlX2(), getCtrlY2(), getX2(), getY2()); - } - - /** - * Calculates the flatness of this curve. The flatness is the - * maximal distance of a control point to the line between start and - * end point. - * - * <p><img src="doc-files/CubicCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. In comparison to C1, - * control point C2 is father away from the gray line. Therefore, - * the result will be the distance between C2 and the gray line, - * i.e. the length of the red line. - */ - public double getFlatness() - { - return Math.sqrt(getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(), - getCtrlX2(), getCtrlY2(), getX2(), getY2())); - } - - /** - * Subdivides this curve into two halves. - * - * <p><img src="doc-files/CubicCurve2D-3.png" width="700" - * height="180" alt="A drawing that illustrates the effects of - * subdividing a CubicCurve2D" /> - * - * @param left a curve whose geometry will be set to the left half - * of this curve, or <code>null</code> if the caller is not - * interested in the left half. - * - * @param right a curve whose geometry will be set to the right half - * of this curve, or <code>null</code> if the caller is not - * interested in the right half. - */ - public void subdivide(CubicCurve2D left, CubicCurve2D right) - { - // Use empty slots at end to share single array. - double[] d = new double[] - { - getX1(), getY1(), getCtrlX1(), getCtrlY1(), getCtrlX2(), - getCtrlY2(), getX2(), getY2(), 0, 0, 0, 0, 0, 0 - }; - subdivide(d, 0, d, 0, d, 6); - if (left != null) - left.setCurve(d, 0); - if (right != null) - right.setCurve(d, 6); - } - - /** - * Subdivides a cubic curve into two halves. - * - * <p><img src="doc-files/CubicCurve2D-3.png" width="700" - * height="180" alt="A drawing that illustrates the effects of - * subdividing a CubicCurve2D" /> - * - * @param src the curve to be subdivided. - * - * @param left a curve whose geometry will be set to the left half - * of <code>src</code>, or <code>null</code> if the caller is not - * interested in the left half. - * - * @param right a curve whose geometry will be set to the right half - * of <code>src</code>, or <code>null</code> if the caller is not - * interested in the right half. - */ - public static void subdivide(CubicCurve2D src, CubicCurve2D left, - CubicCurve2D right) - { - src.subdivide(left, right); - } - - /** - * Subdivides a cubic curve into two halves, passing all coordinates - * in an array. - * - * <p><img src="doc-files/CubicCurve2D-3.png" width="700" - * height="180" alt="A drawing that illustrates the effects of - * subdividing a CubicCurve2D" /> - * - * <p>The left end point and the right start point will always be - * identical. Memory-concious programmers thus may want to pass the - * same array for both <code>left</code> and <code>right</code>, and - * set <code>rightOff</code> to <code>leftOff + 6</code>. - * - * @param src an array containing the coordinates of the curve to be - * subdivided. The <i>x</i> coordinate of the start point P1 is - * located at <code>src[srcOff]</code>, its <i>y</i> at - * <code>src[srcOff + 1]</code>. The <i>x</i> coordinate of the - * first control point C1 is located at <code>src[srcOff + - * 2]</code>, its <i>y</i> at <code>src[srcOff + 3]</code>. The - * <i>x</i> coordinate of the second control point C2 is located at - * <code>src[srcOff + 4]</code>, its <i>y</i> at <code>src[srcOff + - * 5]</code>. The <i>x</i> coordinate of the end point is located at - * <code>src[srcOff + 6]</code>, its <i>y</i> at <code>src[srcOff + - * 7]</code>. - * - * @param srcOff an offset into <code>src</code>, specifying - * the index of the start point’s <i>x</i> coordinate. - * - * @param left an array that will receive the coordinates of the - * left half of <code>src</code>. It is acceptable to pass - * <code>src</code>. A caller who is not interested in the left half - * can pass <code>null</code>. - * - * @param leftOff an offset into <code>left</code>, specifying the - * index where the start point’s <i>x</i> coordinate will be - * stored. - * - * @param right an array that will receive the coordinates of the - * right half of <code>src</code>. It is acceptable to pass - * <code>src</code> or <code>left</code>. A caller who is not - * interested in the right half can pass <code>null</code>. - * - * @param rightOff an offset into <code>right</code>, specifying the - * index where the start point’s <i>x</i> coordinate will be - * stored. - */ - public static void subdivide(double[] src, int srcOff, double[] left, - int leftOff, double[] right, int rightOff) - { - // To understand this code, please have a look at the image - // "CubicCurve2D-3.png" in the sub-directory "doc-files". - double src_C1_x; - double src_C1_y; - double src_C2_x; - double src_C2_y; - double left_P1_x; - double left_P1_y; - double left_C1_x; - double left_C1_y; - double left_C2_x; - double left_C2_y; - double right_C1_x; - double right_C1_y; - double right_C2_x; - double right_C2_y; - double right_P2_x; - double right_P2_y; - double Mid_x; // Mid = left.P2 = right.P1 - double Mid_y; // Mid = left.P2 = right.P1 - - left_P1_x = src[srcOff]; - left_P1_y = src[srcOff + 1]; - src_C1_x = src[srcOff + 2]; - src_C1_y = src[srcOff + 3]; - src_C2_x = src[srcOff + 4]; - src_C2_y = src[srcOff + 5]; - right_P2_x = src[srcOff + 6]; - right_P2_y = src[srcOff + 7]; - - left_C1_x = (left_P1_x + src_C1_x) / 2; - left_C1_y = (left_P1_y + src_C1_y) / 2; - right_C2_x = (right_P2_x + src_C2_x) / 2; - right_C2_y = (right_P2_y + src_C2_y) / 2; - Mid_x = (src_C1_x + src_C2_x) / 2; - Mid_y = (src_C1_y + src_C2_y) / 2; - left_C2_x = (left_C1_x + Mid_x) / 2; - left_C2_y = (left_C1_y + Mid_y) / 2; - right_C1_x = (Mid_x + right_C2_x) / 2; - right_C1_y = (Mid_y + right_C2_y) / 2; - Mid_x = (left_C2_x + right_C1_x) / 2; - Mid_y = (left_C2_y + right_C1_y) / 2; - - if (left != null) - { - left[leftOff] = left_P1_x; - left[leftOff + 1] = left_P1_y; - left[leftOff + 2] = left_C1_x; - left[leftOff + 3] = left_C1_y; - left[leftOff + 4] = left_C2_x; - left[leftOff + 5] = left_C2_y; - left[leftOff + 6] = Mid_x; - left[leftOff + 7] = Mid_y; - } - - if (right != null) - { - right[rightOff] = Mid_x; - right[rightOff + 1] = Mid_y; - right[rightOff + 2] = right_C1_x; - right[rightOff + 3] = right_C1_y; - right[rightOff + 4] = right_C2_x; - right[rightOff + 5] = right_C2_y; - right[rightOff + 6] = right_P2_x; - right[rightOff + 7] = right_P2_y; - } - } - - /** - * Finds the non-complex roots of a cubic equation, placing the - * results into the same array as the equation coefficients. The - * following equation is being solved: - * - * <blockquote><code>eqn[3]</code> · <i>x</i><sup>3</sup> - * + <code>eqn[2]</code> · <i>x</i><sup>2</sup> - * + <code>eqn[1]</code> · <i>x</i> - * + <code>eqn[0]</code> - * = 0 - * </blockquote> - * - * <p>For some background about solving cubic equations, see the - * article <a - * href="http://planetmath.org/encyclopedia/CubicFormula.html" - * >“Cubic Formula”</a> in <a - * href="http://planetmath.org/" >PlanetMath</a>. For an extensive - * library of numerical algorithms written in the C programming - * language, see the <a href= "http://www.gnu.org/software/gsl/">GNU - * Scientific Library</a>, from which this implementation was - * adapted. - * - * @param eqn an array with the coefficients of the equation. When - * this procedure has returned, <code>eqn</code> will contain the - * non-complex solutions of the equation, in no particular order. - * - * @return the number of non-complex solutions. A result of 0 - * indicates that the equation has no non-complex solutions. A - * result of -1 indicates that the equation is constant (i.e., - * always or never zero). - * - * @see #solveCubic(double[], double[]) - * @see QuadCurve2D#solveQuadratic(double[],double[]) - * - * @author Brian Gough (bjg@network-theory.com) - * (original C implementation in the <a href= - * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>) - * - * @author Sascha Brawer (brawer@dandelis.ch) - * (adaptation to Java) - */ - public static int solveCubic(double[] eqn) - { - return solveCubic(eqn, eqn); - } - - /** - * Finds the non-complex roots of a cubic equation. The following - * equation is being solved: - * - * <blockquote><code>eqn[3]</code> · <i>x</i><sup>3</sup> - * + <code>eqn[2]</code> · <i>x</i><sup>2</sup> - * + <code>eqn[1]</code> · <i>x</i> - * + <code>eqn[0]</code> - * = 0 - * </blockquote> - * - * <p>For some background about solving cubic equations, see the - * article <a - * href="http://planetmath.org/encyclopedia/CubicFormula.html" - * >“Cubic Formula”</a> in <a - * href="http://planetmath.org/" >PlanetMath</a>. For an extensive - * library of numerical algorithms written in the C programming - * language, see the <a href= "http://www.gnu.org/software/gsl/">GNU - * Scientific Library</a>, from which this implementation was - * adapted. - * - * @see QuadCurve2D#solveQuadratic(double[],double[]) - * - * @param eqn an array with the coefficients of the equation. - * - * @param res an array into which the non-complex roots will be - * stored. The results may be in an arbitrary order. It is safe to - * pass the same array object reference for both <code>eqn</code> - * and <code>res</code>. - * - * @return the number of non-complex solutions. A result of 0 - * indicates that the equation has no non-complex solutions. A - * result of -1 indicates that the equation is constant (i.e., - * always or never zero). - * - * @author Brian Gough (bjg@network-theory.com) - * (original C implementation in the <a href= - * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>) - * - * @author Sascha Brawer (brawer@dandelis.ch) - * (adaptation to Java) - */ - public static int solveCubic(double[] eqn, double[] res) - { - // Adapted from poly/solve_cubic.c in the GNU Scientific Library - // (GSL), revision 1.7 of 2003-07-26. For the original source, see - // http://www.gnu.org/software/gsl/ - // - // Brian Gough, the author of that code, has granted the - // permission to use it in GNU Classpath under the GNU Classpath - // license, and has assigned the copyright to the Free Software - // Foundation. - // - // The Java implementation is very similar to the GSL code, but - // not a strict one-to-one copy. For example, GSL would sort the - // result. - - double a; - double b; - double c; - double q; - double r; - double Q; - double R; - double c3; - double Q3; - double R2; - double CR2; - double CQ3; - - // If the cubic coefficient is zero, we have a quadratic equation. - c3 = eqn[3]; - if (c3 == 0) - return QuadCurve2D.solveQuadratic(eqn, res); - - // Divide the equation by the cubic coefficient. - c = eqn[0] / c3; - b = eqn[1] / c3; - a = eqn[2] / c3; - - // We now need to solve x^3 + ax^2 + bx + c = 0. - q = a * a - 3 * b; - r = 2 * a * a * a - 9 * a * b + 27 * c; - - Q = q / 9; - R = r / 54; - - Q3 = Q * Q * Q; - R2 = R * R; - - CR2 = 729 * r * r; - CQ3 = 2916 * q * q * q; - - if (R == 0 && Q == 0) - { - // The GNU Scientific Library would return three identical - // solutions in this case. - res[0] = -a / 3; - return 1; - } - - if (CR2 == CQ3) - { - /* this test is actually R2 == Q3, written in a form suitable - for exact computation with integers */ - /* Due to finite precision some double roots may be missed, and - considered to be a pair of complex roots z = x +/- epsilon i - close to the real axis. */ - double sqrtQ = Math.sqrt(Q); - - if (R > 0) - { - res[0] = -2 * sqrtQ - a / 3; - res[1] = sqrtQ - a / 3; - } - else - { - res[0] = -sqrtQ - a / 3; - res[1] = 2 * sqrtQ - a / 3; - } - return 2; - } - - if (CR2 < CQ3) /* equivalent to R2 < Q3 */ - { - double sqrtQ = Math.sqrt(Q); - double sqrtQ3 = sqrtQ * sqrtQ * sqrtQ; - double theta = Math.acos(R / sqrtQ3); - double norm = -2 * sqrtQ; - res[0] = norm * Math.cos(theta / 3) - a / 3; - res[1] = norm * Math.cos((theta + 2.0 * Math.PI) / 3) - a / 3; - res[2] = norm * Math.cos((theta - 2.0 * Math.PI) / 3) - a / 3; - - // The GNU Scientific Library sorts the results. We don't. - return 3; - } - - double sgnR = (R >= 0 ? 1 : -1); - double A = -sgnR * Math.pow(Math.abs(R) + Math.sqrt(R2 - Q3), 1.0 / 3.0); - double B = Q / A; - res[0] = A + B - a / 3; - return 1; - } - - /** - * Determines whether a position lies inside the area 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. - */ - public boolean contains(double x, double y) - { - if (! getBounds2D().contains(x, y)) - return false; - - return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0); - } - - /** - * Determines whether a point lies inside the area 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. - */ - public boolean contains(Point2D p) - { - return contains(p.getX(), p.getY()); - } - - /** - * Determines whether any part of a rectangle is inside the area 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” in a CubicCurve2D. - * @see #contains(double, double) - */ - public boolean intersects(double x, double y, double w, double h) - { - if (! getBounds2D().contains(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 true; - - /* No intersections, is any point inside? */ - if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0) - return true; - - return false; - } - - /** - * 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() - { - return ctrlx2; - } - - /** - * Returns the <i>y</i> coordinate of the curve’s second - * control point. - */ - public double getCtrlY2() - { - return ctrly2; - } - - /** - * Returns the curve’s second control point. - */ - public Point2D getCtrlP2() - { - return new Point2D.Double(ctrlx2, ctrly2); - } - - /** - * Returns the <i>x</i> coordinate of the curve’s end - * point. - */ - public double getX2() - { - return x2; - } - - /** - * Returns the <i>y</i> coordinate of the curve’s end - * point. - */ - public double getY2() - { - return y2; - } - - /** - * Returns the curve’s end point. - */ - public Point2D getP2() - { - return new Point2D.Double(x2, y2); - } - - /** - * Changes the curve geometry, separately specifying each coordinate - * value. - * - * <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 new start - * point. - * - * @param y1 the <i>y</i> coordinate of the curve’s new start - * point. - * - * @param cx1 the <i>x</i> coordinate of the curve’s new - * first control point. - * - * @param cy1 the <i>y</i> coordinate of the curve’s new - * first control point. - * - * @param cx2 the <i>x</i> coordinate of the curve’s new - * second control point. - * - * @param cy2 the <i>y</i> coordinate of the curve’s new - * second control point. - * - * @param x2 the <i>x</i> coordinate of the curve’s new end - * point. - * - * @param y2 the <i>y</i> coordinate of the curve’s new end - * point. - */ - public void setCurve(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; - } - - /** - * Determines the smallest rectangle that encloses the - * curve’s start, end and control points. As the - * illustration below shows, the invisible control points may cause - * the bounds to be much larger than the area that is actually - * covered by the curve. - * - * <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180" - * alt="An illustration of the bounds of a CubicCurve2D" /> - */ - public Rectangle2D getBounds2D() - { - double nx1 = Math.min(Math.min(x1, ctrlx1), Math.min(ctrlx2, x2)); - double ny1 = Math.min(Math.min(y1, ctrly1), Math.min(ctrly2, y2)); - double nx2 = Math.max(Math.max(x1, ctrlx1), Math.max(ctrlx2, x2)); - double ny2 = Math.max(Math.max(y1, ctrly1), Math.max(ctrly2, y2)); - return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1); - } - } - - /** - * A two-dimensional curve that is parameterized with a cubic - * function and stores coordinate values in single-precision - * floating-point format. - * - * @see CubicCurve2D.Float - * - * @author Eric Blake (ebb9@email.byu.edu) - * @author Sascha Brawer (brawer@dandelis.ch) - */ - public static class Float extends CubicCurve2D - { - /** - * The <i>x</i> coordinate of the curve’s start point. - */ - public float x1; - - /** - * The <i>y</i> coordinate of the curve’s start point. - */ - public float y1; - - /** - * The <i>x</i> coordinate of the curve’s first control point. - */ - public float ctrlx1; - - /** - * The <i>y</i> coordinate of the curve’s first control point. - */ - public float ctrly1; - - /** - * The <i>x</i> coordinate of the curve’s second control point. - */ - public float ctrlx2; - - /** - * The <i>y</i> coordinate of the curve’s second control point. - */ - public float ctrly2; - - /** - * The <i>x</i> coordinate of the curve’s end point. - */ - public float x2; - - /** - * The <i>y</i> coordinate of the curve’s end point. - */ - public float y2; - - /** - * Constructs a new CubicCurve2D that stores its coordinate values - * in single-precision floating-point format. All points are - * initially at position (0, 0). - */ - public Float() - { - } - - /** - * Constructs a new CubicCurve2D that stores its coordinate values - * in single-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 Float(float x1, float y1, float cx1, float cy1, float cx2, - float cy2, float x2, float 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.Float(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.Float(ctrlx1, ctrly1); - } - - /** - * Returns the <i>s</i> coordinate of the curve’s second - * control point. - */ - public double getCtrlX2() - { - return ctrlx2; - } - - /** - * Returns the <i>y</i> coordinate of the curve’s second - * control point. - */ - public double getCtrlY2() - { - return ctrly2; - } - - /** - * Returns the curve’s second control point. - */ - public Point2D getCtrlP2() - { - return new Point2D.Float(ctrlx2, ctrly2); - } - - /** - * Returns the <i>x</i> coordinate of the curve’s end - * point. - */ - public double getX2() - { - return x2; - } - - /** - * Returns the <i>y</i> coordinate of the curve’s end - * point. - */ - public double getY2() - { - return y2; - } - - /** - * Returns the curve’s end point. - */ - public Point2D getP2() - { - return new Point2D.Float(x2, y2); - } - - /** - * Changes the curve geometry, separately specifying each coordinate - * value as a double-precision floating-point number. - * - * <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 new start - * point. - * - * @param y1 the <i>y</i> coordinate of the curve’s new start - * point. - * - * @param cx1 the <i>x</i> coordinate of the curve’s new - * first control point. - * - * @param cy1 the <i>y</i> coordinate of the curve’s new - * first control point. - * - * @param cx2 the <i>x</i> coordinate of the curve’s new - * second control point. - * - * @param cy2 the <i>y</i> coordinate of the curve’s new - * second control point. - * - * @param x2 the <i>x</i> coordinate of the curve’s new end - * point. - * - * @param y2 the <i>y</i> coordinate of the curve’s new end - * point. - */ - public void setCurve(double x1, double y1, double cx1, double cy1, - double cx2, double cy2, double x2, double y2) - { - this.x1 = (float) x1; - this.y1 = (float) y1; - ctrlx1 = (float) cx1; - ctrly1 = (float) cy1; - ctrlx2 = (float) cx2; - ctrly2 = (float) cy2; - this.x2 = (float) x2; - this.y2 = (float) y2; - } - - /** - * Changes the curve geometry, separately specifying each coordinate - * value as a single-precision floating-point number. - * - * <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 new start - * point. - * - * @param y1 the <i>y</i> coordinate of the curve’s new start - * point. - * - * @param cx1 the <i>x</i> coordinate of the curve’s new - * first control point. - * - * @param cy1 the <i>y</i> coordinate of the curve’s new - * first control point. - * - * @param cx2 the <i>x</i> coordinate of the curve’s new - * second control point. - * - * @param cy2 the <i>y</i> coordinate of the curve’s new - * second control point. - * - * @param x2 the <i>x</i> coordinate of the curve’s new end - * point. - * - * @param y2 the <i>y</i> coordinate of the curve’s new end - * point. - */ - public void setCurve(float x1, float y1, float cx1, float cy1, float cx2, - float cy2, float x2, float y2) - { - this.x1 = x1; - this.y1 = y1; - ctrlx1 = cx1; - ctrly1 = cy1; - ctrlx2 = cx2; - ctrly2 = cy2; - this.x2 = x2; - this.y2 = y2; - } - - /** - * Determines the smallest rectangle that encloses the - * curve’s start, end and control points. As the - * illustration below shows, the invisible control points may cause - * the bounds to be much larger than the area that is actually - * covered by the curve. - * - * <p><img src="doc-files/CubicCurve2D-2.png" width="350" height="180" - * alt="An illustration of the bounds of a CubicCurve2D" /> - */ - public Rectangle2D getBounds2D() - { - float nx1 = Math.min(Math.min(x1, ctrlx1), Math.min(ctrlx2, x2)); - float ny1 = Math.min(Math.min(y1, ctrly1), Math.min(ctrly2, y2)); - float nx2 = Math.max(Math.max(x1, ctrlx1), Math.max(ctrlx2, x2)); - float ny2 = Math.max(Math.max(y1, ctrly1), Math.max(ctrly2, y2)); - return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1); - } - } -} diff --git a/libjava/classpath/java/awt/geom/Dimension2D.java b/libjava/classpath/java/awt/geom/Dimension2D.java deleted file mode 100644 index 6b5ce88..0000000 --- a/libjava/classpath/java/awt/geom/Dimension2D.java +++ /dev/null @@ -1,118 +0,0 @@ -/* Dimension2D.java -- abstraction of a dimension - Copyright (C) 1999, 2000, 2002 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.awt.geom; - -/** - * This stores a dimension in 2-dimensional space - a width (along the x-axis) - * and height (along the y-axis). The storage is left to subclasses. - * - * @author Per Bothner (bothner@cygnus.com) - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @status updated to 1.4 - */ -public abstract class Dimension2D implements Cloneable -{ - /** - * The default constructor. - */ - protected Dimension2D() - { - } - - /** - * Get the width of this dimension. A negative result, while legal, is - * undefined in meaning. - * - * @return the width - */ - public abstract double getWidth(); - - /** - * Get the height of this dimension. A negative result, while legal, is - * undefined in meaning. - * - * @return the height - */ - public abstract double getHeight(); - - /** - * Set the size of this dimension to the requested values. Loss of precision - * may occur. - * - * @param w the new width - * @param h the new height - */ - public abstract void setSize(double w, double h); - - /** - * Set the size of this dimension to the requested value. Loss of precision - * may occur. - * - * @param d the dimension containing the new values - * - * @throws NullPointerException if d is null - */ - public void setSize(Dimension2D d) - { - setSize(d.getWidth(), d.getHeight()); - } - - /** - * Create a new dimension 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() - { - try - { - return super.clone(); - } - catch (CloneNotSupportedException e) - { - throw (Error) new InternalError().initCause(e); // Impossible - } - } -} // class Dimension2D diff --git a/libjava/classpath/java/awt/geom/Ellipse2D.java b/libjava/classpath/java/awt/geom/Ellipse2D.java deleted file mode 100644 index 3bbf2f0..0000000 --- a/libjava/classpath/java/awt/geom/Ellipse2D.java +++ /dev/null @@ -1,413 +0,0 @@ -/* Ellipse2D.java -- represents an ellipse in 2-D space - Copyright (C) 2000, 2002, 2004 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.awt.geom; - - -/** - * Ellipse2D is the shape of an ellipse. - * <BR> - * <img src="doc-files/Ellipse-1.png" width="347" height="221" - * alt="A drawing of an ellipse" /><BR> - * The ellipse is defined by it's bounding box (shown in red), - * and is defined by the implicit curve:<BR> - * <blockquote>(<i>x</i>/<i>a</i>)<sup>2</sup> + - * (<i>y</i>/<i>b</i>)<sup>2</sup> = 1<BR><BR></blockquote> - * - * @author Tom Tromey (tromey@cygnus.com) - * @author Eric Blake (ebb9@email.byu.edu) - * - * @since 1.2 - */ -public abstract class Ellipse2D extends RectangularShape -{ - /** - * Ellipse2D is defined as abstract. - * Implementing classes are Ellipse2D.Float and Ellipse2D.Double. - */ - protected Ellipse2D() - { - } - - /** - * Determines if a point is contained within the ellipse. <P> - * @param x - x coordinate of the point. - * @param y - y coordinate of the point. - * @return true if the point is within the ellipse, false otherwise. - */ - public boolean contains(double x, double y) - { - double rx = getWidth() / 2; - double ry = getHeight() / 2; - double tx = (x - (getX() + rx)) / rx; - double ty = (y - (getY() + ry)) / ry; - return tx * tx + ty * ty < 1.0; - } - - /** - * Determines if a rectangle is completely contained within the - * ellipse. <P> - * @param x - x coordinate of the upper-left corner of the rectangle - * @param y - y coordinate of the upper-left corner of the rectangle - * @param w - width of the rectangle - * @param h - height of the rectangle - * @return true if the rectangle is completely contained, false otherwise. - */ - public boolean contains(double x, double y, double w, double h) - { - double x2 = x + w; - double y2 = y + h; - return (contains(x, y) && contains(x, y2) && contains(x2, y) - && contains(x2, y2)); - } - - /** - * Returns a PathIterator object corresponding to the ellipse.<P> - * - * Note: An ellipse cannot be represented exactly in PathIterator - * segments, the outline is thefore approximated with cubic - * Bezier segments. - * - * @param at an optional transform. - * @return A path iterator. - */ - public PathIterator getPathIterator(AffineTransform at) - { - // An ellipse is just a complete arc. - return new Arc2D.ArcIterator(this, at); - } - - /** - * Determines if a rectangle intersects any part of the ellipse.<P> - * @param x - x coordinate of the upper-left corner of the rectangle - * @param y - y coordinate of the upper-left corner of the rectangle - * @param w - width of the rectangle - * @param h - height of the rectangle - * @return true if the rectangle intersects the ellipse, false otherwise. - */ - public boolean intersects(double x, double y, double w, double h) - { - Rectangle2D r = new Rectangle2D.Double(x, y, w, h); - if (! r.intersects(getX(), getY(), getWidth(), getHeight())) - return false; - - if (contains(x, y) || contains(x, y + h) || contains(x + w, y) - || contains(x + w, y + h)) - return true; - - Line2D l1 = new Line2D.Double(getX(), getY() + (getHeight() / 2), - getX() + getWidth(), - getY() + (getHeight() / 2)); - Line2D l2 = new Line2D.Double(getX() + (getWidth() / 2), getY(), - getX() + (getWidth() / 2), - getY() + getHeight()); - - if (l1.intersects(r) || l2.intersects(r)) - return true; - - return false; - } - - /** - * An {@link Ellipse2D} that stores its coordinates using <code>double</code> - * primitives. - */ - public static class Double extends Ellipse2D - { - /** - * The height of the ellipse. - */ - public double height; - - /** - * The width of the ellipse. - */ - public double width; - - /** - * The upper-left x coordinate of the bounding-box - */ - public double x; - - /** - * The upper-left y coordinate of the bounding-box - */ - public double y; - - /** - * Creates a new Ellipse2D with an upper-left coordinate of (0,0) - * and a zero size. - */ - public Double() - { - } - - /** - * Creates a new Ellipse2D within a given rectangle - * using double-precision coordinates.<P> - * @param x - x coordinate of the upper-left of the bounding rectangle - * @param y - y coordinate of the upper-left of the bounding rectangle - * @param w - width of the ellipse - * @param h - height of the ellipse - */ - public Double(double x, double y, double w, double h) - { - this.x = x; - this.y = y; - height = h; - width = w; - } - - /** - * Returns the bounding-box of the ellipse. - * @return The bounding box. - */ - public Rectangle2D getBounds2D() - { - return new Rectangle2D.Double(x, y, width, height); - } - - /** - * Returns the height of the ellipse. - * @return The height of the ellipse. - */ - public double getHeight() - { - return height; - } - - /** - * Returns the width of the ellipse. - * @return The width of the ellipse. - */ - public double getWidth() - { - return width; - } - - /** - * Returns x coordinate of the upper-left corner of - * the ellipse's bounding-box. - * @return The x coordinate. - */ - public double getX() - { - return x; - } - - /** - * Returns y coordinate of the upper-left corner of - * the ellipse's bounding-box. - * @return The y coordinate. - */ - public double getY() - { - return y; - } - - /** - * Returns <code>true</code> if the ellipse encloses no area, and - * <code>false</code> otherwise. - * - * @return A boolean. - */ - public boolean isEmpty() - { - return height <= 0 || width <= 0; - } - - /** - * Sets the geometry of the ellipse's bounding box.<P> - * - * @param x - x coordinate of the upper-left of the bounding rectangle - * @param y - y coordinate of the upper-left of the bounding rectangle - * @param w - width of the ellipse - * @param h - height of the ellipse - */ - public void setFrame(double x, double y, double w, double h) - { - this.x = x; - this.y = y; - height = h; - width = w; - } - } // class Double - - /** - * An {@link Ellipse2D} that stores its coordinates using <code>float</code> - * primitives. - */ - public static class Float extends Ellipse2D - { - /** - * The height of the ellipse. - */ - public float height; - - /** - * The width of the ellipse. - */ - public float width; - - /** - * The upper-left x coordinate of the bounding-box - */ - public float x; - - /** - * The upper-left y coordinate of the bounding-box - */ - public float y; - - /** - * Creates a new Ellipse2D with an upper-left coordinate of (0,0) - * and a zero size. - */ - public Float() - { - } - - /** - * Creates a new Ellipse2D within a given rectangle - * using floating-point precision.<P> - * @param x - x coordinate of the upper-left of the bounding rectangle - * @param y - y coordinate of the upper-left of the bounding rectangle - * @param w - width of the ellipse - * @param h - height of the ellipse - * - */ - public Float(float x, float y, float w, float h) - { - this.x = x; - this.y = y; - this.height = h; - this.width = w; - } - - /** - * Returns the bounding-box of the ellipse. - * @return The bounding box. - */ - public Rectangle2D getBounds2D() - { - return new Rectangle2D.Float(x, y, width, height); - } - - /** - * Returns the height of the ellipse. - * @return The height of the ellipse. - */ - public double getHeight() - { - return height; - } - - /** - * Returns the width of the ellipse. - * @return The width of the ellipse. - */ - public double getWidth() - { - return width; - } - - /** - * Returns x coordinate of the upper-left corner of - * the ellipse's bounding-box. - * @return The x coordinate. - */ - public double getX() - { - return x; - } - - /** - * Returns y coordinate of the upper-left corner of - * the ellipse's bounding-box. - * @return The y coordinate. - */ - public double getY() - { - return y; - } - - /** - * Returns <code>true</code> if the ellipse encloses no area, and - * <code>false</code> otherwise. - * - * @return A boolean. - */ - public boolean isEmpty() - { - return height <= 0 || width <= 0; - } - - /** - * Sets the geometry of the ellipse's bounding box.<P> - * - * @param x - x coordinate of the upper-left of the bounding rectangle - * @param y - y coordinate of the upper-left of the bounding rectangle - * @param w - width of the ellipse - * @param h - height of the ellipse - */ - public void setFrame(float x, float y, float w, float h) - { - this.x = x; - this.y = y; - height = h; - width = w; - } - - /** - * Sets the geometry of the ellipse's bounding box. - * - * Note: This leads to a loss of precision.<P> - * - * @param x - x coordinate of the upper-left of the bounding rectangle - * @param y - y coordinate of the upper-left of the bounding rectangle - * @param w - width of the ellipse - * @param h - height of the ellipse - */ - public void setFrame(double x, double y, double w, double h) - { - this.x = (float) x; - this.y = (float) y; - height = (float) h; - width = (float) w; - } - } // class Float -} // class Ellipse2D diff --git a/libjava/classpath/java/awt/geom/FlatteningPathIterator.java b/libjava/classpath/java/awt/geom/FlatteningPathIterator.java deleted file mode 100644 index 629936b..0000000 --- a/libjava/classpath/java/awt/geom/FlatteningPathIterator.java +++ /dev/null @@ -1,579 +0,0 @@ -/* FlatteningPathIterator.java -- Approximates curves by straight lines - Copyright (C) 2003 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.awt.geom; - -import java.util.NoSuchElementException; - - -/** - * A PathIterator for approximating curved path segments by sequences - * of straight lines. Instances of this class will only return - * segments of type {@link PathIterator#SEG_MOVETO}, {@link - * PathIterator#SEG_LINETO}, and {@link PathIterator#SEG_CLOSE}. - * - * <p>The accuracy of the approximation is determined by two - * parameters: - * - * <ul><li>The <i>flatness</i> is a threshold value for deciding when - * a curved segment is consided flat enough for being approximated by - * a single straight line. Flatness is defined as the maximal distance - * of a curve control point to the straight line that connects the - * curve start and end. A lower flatness threshold means a closer - * approximation. See {@link QuadCurve2D#getFlatness()} and {@link - * CubicCurve2D#getFlatness()} for drawings which illustrate the - * meaning of flatness.</li> - * - * <li>The <i>recursion limit</i> imposes an upper bound for how often - * a curved segment gets subdivided. A limit of <i>n</i> means that - * for each individual quadratic and cubic Bézier spline - * segment, at most 2<sup><small><i>n</i></small></sup> {@link - * PathIterator#SEG_LINETO} segments will be created.</li></ul> - * - * <p><b>Memory Efficiency:</b> The memory consumption grows linearly - * with the recursion limit. Neither the <i>flatness</i> parameter nor - * the number of segments in the flattened path will affect the memory - * consumption. - * - * <p><b>Thread Safety:</b> Multiple threads can safely work on - * separate instances of this class. However, multiple threads should - * not concurrently access the same instance, as no synchronization is - * performed. - * - * @see <a href="doc-files/FlatteningPathIterator-1.html" - * >Implementation Note</a> - * - * @author Sascha Brawer (brawer@dandelis.ch) - * - * @since 1.2 - */ -public class FlatteningPathIterator - implements PathIterator -{ - /** - * The PathIterator whose curved segments are being approximated. - */ - private final PathIterator srcIter; - - - /** - * The square of the flatness threshold value, which determines when - * a curve segment is considered flat enough that no further - * subdivision is needed. - * - * <p>Calculating flatness actually produces the squared flatness - * value. To avoid the relatively expensive calculation of a square - * root for each curve segment, we perform all flatness comparisons - * on squared values. - * - * @see QuadCurve2D#getFlatnessSq() - * @see CubicCurve2D#getFlatnessSq() - */ - private final double flatnessSq; - - - /** - * The maximal number of subdivions that are performed to - * approximate a quadratic or cubic curve segment. - */ - private final int recursionLimit; - - - /** - * A stack for holding the coordinates of subdivided segments. - * - * @see <a href="doc-files/FlatteningPathIterator-1.html" - * >Implementation Note</a> - */ - private double[] stack; - - - /** - * The current stack size. - * - * @see <a href="doc-files/FlatteningPathIterator-1.html" - * >Implementation Note</a> - */ - private int stackSize; - - - /** - * The number of recursions that were performed to arrive at - * a segment on the stack. - * - * @see <a href="doc-files/FlatteningPathIterator-1.html" - * >Implementation Note</a> - */ - private int[] recLevel; - - - - private final double[] scratch = new double[6]; - - - /** - * The segment type of the last segment that was returned by - * the source iterator. - */ - private int srcSegType; - - - /** - * The current <i>x</i> position of the source iterator. - */ - private double srcPosX; - - - /** - * The current <i>y</i> position of the source iterator. - */ - private double srcPosY; - - - /** - * A flag that indicates when this path iterator has finished its - * iteration over path segments. - */ - private boolean done; - - - /** - * Constructs a new PathIterator for approximating an input - * PathIterator with straight lines. The approximation works by - * recursive subdivisons, until the specified flatness threshold is - * not exceeded. - * - * <p>There will not be more than 10 nested recursion steps, which - * means that a single <code>SEG_QUADTO</code> or - * <code>SEG_CUBICTO</code> segment is approximated by at most - * 2<sup><small>10</small></sup> = 1024 straight lines. - */ - public FlatteningPathIterator(PathIterator src, double flatness) - { - this(src, flatness, 10); - } - - - /** - * Constructs a new PathIterator for approximating an input - * PathIterator with straight lines. The approximation works by - * recursive subdivisons, until the specified flatness threshold is - * not exceeded. Additionally, the number of recursions is also - * bound by the specified recursion limit. - */ - public FlatteningPathIterator(PathIterator src, double flatness, - int limit) - { - if (flatness < 0 || limit < 0) - throw new IllegalArgumentException(); - - srcIter = src; - flatnessSq = flatness * flatness; - recursionLimit = limit; - fetchSegment(); - } - - - /** - * Returns the maximally acceptable flatness. - * - * @see QuadCurve2D#getFlatness() - * @see CubicCurve2D#getFlatness() - */ - public double getFlatness() - { - return Math.sqrt(flatnessSq); - } - - - /** - * Returns the maximum number of recursive curve subdivisions. - */ - public int getRecursionLimit() - { - return recursionLimit; - } - - - // Documentation will be copied from PathIterator. - public int getWindingRule() - { - return srcIter.getWindingRule(); - } - - - // Documentation will be copied from PathIterator. - public boolean isDone() - { - return done; - } - - - // Documentation will be copied from PathIterator. - public void next() - { - if (stackSize > 0) - { - --stackSize; - if (stackSize > 0) - { - switch (srcSegType) - { - case PathIterator.SEG_QUADTO: - subdivideQuadratic(); - return; - - case PathIterator.SEG_CUBICTO: - subdivideCubic(); - return; - - default: - throw new IllegalStateException(); - } - } - } - - srcIter.next(); - fetchSegment(); - } - - - // Documentation will be copied from PathIterator. - public int currentSegment(double[] coords) - { - if (done) - throw new NoSuchElementException(); - - switch (srcSegType) - { - case PathIterator.SEG_CLOSE: - return srcSegType; - - case PathIterator.SEG_MOVETO: - case PathIterator.SEG_LINETO: - coords[0] = srcPosX; - coords[1] = srcPosY; - return srcSegType; - - case PathIterator.SEG_QUADTO: - if (stackSize == 0) - { - coords[0] = srcPosX; - coords[1] = srcPosY; - } - else - { - int sp = stack.length - 4 * stackSize; - coords[0] = stack[sp + 2]; - coords[1] = stack[sp + 3]; - } - return PathIterator.SEG_LINETO; - - case PathIterator.SEG_CUBICTO: - if (stackSize == 0) - { - coords[0] = srcPosX; - coords[1] = srcPosY; - } - else - { - int sp = stack.length - 6 * stackSize; - coords[0] = stack[sp + 4]; - coords[1] = stack[sp + 5]; - } - return PathIterator.SEG_LINETO; - } - - throw new IllegalStateException(); - } - - - // Documentation will be copied from PathIterator. - public int currentSegment(float[] coords) - { - if (done) - throw new NoSuchElementException(); - - switch (srcSegType) - { - case PathIterator.SEG_CLOSE: - return srcSegType; - - case PathIterator.SEG_MOVETO: - case PathIterator.SEG_LINETO: - coords[0] = (float) srcPosX; - coords[1] = (float) srcPosY; - return srcSegType; - - case PathIterator.SEG_QUADTO: - if (stackSize == 0) - { - coords[0] = (float) srcPosX; - coords[1] = (float) srcPosY; - } - else - { - int sp = stack.length - 4 * stackSize; - coords[0] = (float) stack[sp + 2]; - coords[1] = (float) stack[sp + 3]; - } - return PathIterator.SEG_LINETO; - - case PathIterator.SEG_CUBICTO: - if (stackSize == 0) - { - coords[0] = (float) srcPosX; - coords[1] = (float) srcPosY; - } - else - { - int sp = stack.length - 6 * stackSize; - coords[0] = (float) stack[sp + 4]; - coords[1] = (float) stack[sp + 5]; - } - return PathIterator.SEG_LINETO; - } - - throw new IllegalStateException(); - } - - - /** - * Fetches the next segment from the source iterator. - */ - private void fetchSegment() - { - int sp; - - if (srcIter.isDone()) - { - done = true; - return; - } - - srcSegType = srcIter.currentSegment(scratch); - - switch (srcSegType) - { - case PathIterator.SEG_CLOSE: - return; - - case PathIterator.SEG_MOVETO: - case PathIterator.SEG_LINETO: - srcPosX = scratch[0]; - srcPosY = scratch[1]; - return; - - case PathIterator.SEG_QUADTO: - if (recursionLimit == 0) - { - srcPosX = scratch[2]; - srcPosY = scratch[3]; - stackSize = 0; - return; - } - sp = 4 * recursionLimit; - stackSize = 1; - if (stack == null) - { - stack = new double[sp + /* 4 + 2 */ 6]; - recLevel = new int[recursionLimit + 1]; - } - recLevel[0] = 0; - stack[sp] = srcPosX; // P1.x - stack[sp + 1] = srcPosY; // P1.y - stack[sp + 2] = scratch[0]; // C.x - stack[sp + 3] = scratch[1]; // C.y - srcPosX = stack[sp + 4] = scratch[2]; // P2.x - srcPosY = stack[sp + 5] = scratch[3]; // P2.y - subdivideQuadratic(); - break; - - case PathIterator.SEG_CUBICTO: - if (recursionLimit == 0) - { - srcPosX = scratch[4]; - srcPosY = scratch[5]; - stackSize = 0; - return; - } - sp = 6 * recursionLimit; - stackSize = 1; - if ((stack == null) || (stack.length < sp + 8)) - { - stack = new double[sp + /* 6 + 2 */ 8]; - recLevel = new int[recursionLimit + 1]; - } - recLevel[0] = 0; - stack[sp] = srcPosX; // P1.x - stack[sp + 1] = srcPosY; // P1.y - stack[sp + 2] = scratch[0]; // C1.x - stack[sp + 3] = scratch[1]; // C1.y - stack[sp + 4] = scratch[2]; // C2.x - stack[sp + 5] = scratch[3]; // C2.y - srcPosX = stack[sp + 6] = scratch[4]; // P2.x - srcPosY = stack[sp + 7] = scratch[5]; // P2.y - subdivideCubic(); - return; - } - } - - - /** - * Repeatedly subdivides the quadratic curve segment that is on top - * of the stack. The iteration terminates when the recursion limit - * has been reached, or when the resulting segment is flat enough. - */ - private void subdivideQuadratic() - { - int sp; - int level; - - sp = stack.length - 4 * stackSize - 2; - level = recLevel[stackSize - 1]; - while ((level < recursionLimit) - && (QuadCurve2D.getFlatnessSq(stack, sp) >= flatnessSq)) - { - recLevel[stackSize] = recLevel[stackSize - 1] = ++level; - QuadCurve2D.subdivide(stack, sp, stack, sp - 4, stack, sp); - ++stackSize; - sp -= 4; - } - } - - - /** - * Repeatedly subdivides the cubic curve segment that is on top - * of the stack. The iteration terminates when the recursion limit - * has been reached, or when the resulting segment is flat enough. - */ - private void subdivideCubic() - { - int sp; - int level; - - sp = stack.length - 6 * stackSize - 2; - level = recLevel[stackSize - 1]; - while ((level < recursionLimit) - && (CubicCurve2D.getFlatnessSq(stack, sp) >= flatnessSq)) - { - recLevel[stackSize] = recLevel[stackSize - 1] = ++level; - - CubicCurve2D.subdivide(stack, sp, stack, sp - 6, stack, sp); - ++stackSize; - sp -= 6; - } - } - - - /* These routines were useful for debugging. Since they would - * just bloat the implementation, they are commented out. - * - * - - private static String segToString(int segType, double[] d, int offset) - { - String s; - - switch (segType) - { - case PathIterator.SEG_CLOSE: - return "SEG_CLOSE"; - - case PathIterator.SEG_MOVETO: - return "SEG_MOVETO (" + d[offset] + ", " + d[offset + 1] + ")"; - - case PathIterator.SEG_LINETO: - return "SEG_LINETO (" + d[offset] + ", " + d[offset + 1] + ")"; - - case PathIterator.SEG_QUADTO: - return "SEG_QUADTO (" + d[offset] + ", " + d[offset + 1] - + ") (" + d[offset + 2] + ", " + d[offset + 3] + ")"; - - case PathIterator.SEG_CUBICTO: - return "SEG_CUBICTO (" + d[offset] + ", " + d[offset + 1] - + ") (" + d[offset + 2] + ", " + d[offset + 3] - + ") (" + d[offset + 4] + ", " + d[offset + 5] + ")"; - } - - throw new IllegalStateException(); - } - - - private void dumpQuadraticStack(String msg) - { - int sp = stack.length - 4 * stackSize - 2; - int i = 0; - System.err.print(" " + msg + ":"); - while (sp < stack.length) - { - System.err.print(" (" + stack[sp] + ", " + stack[sp+1] + ")"); - if (i < recLevel.length) - System.out.print("/" + recLevel[i++]); - if (sp + 3 < stack.length) - System.err.print(" [" + stack[sp+2] + ", " + stack[sp+3] + "]"); - sp += 4; - } - System.err.println(); - } - - - private void dumpCubicStack(String msg) - { - int sp = stack.length - 6 * stackSize - 2; - int i = 0; - System.err.print(" " + msg + ":"); - while (sp < stack.length) - { - System.err.print(" (" + stack[sp] + ", " + stack[sp+1] + ")"); - if (i < recLevel.length) - System.out.print("/" + recLevel[i++]); - if (sp + 3 < stack.length) - { - System.err.print(" [" + stack[sp+2] + ", " + stack[sp+3] + "]"); - System.err.print(" [" + stack[sp+4] + ", " + stack[sp+5] + "]"); - } - sp += 6; - } - System.err.println(); - } - - * - * - */ -} diff --git a/libjava/classpath/java/awt/geom/GeneralPath.java b/libjava/classpath/java/awt/geom/GeneralPath.java deleted file mode 100644 index 99f1905..0000000 --- a/libjava/classpath/java/awt/geom/GeneralPath.java +++ /dev/null @@ -1,992 +0,0 @@ -/* GeneralPath.java -- represents a shape built from subpaths - Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.awt.geom; - -import java.awt.Rectangle; -import java.awt.Shape; - - -/** - * A general geometric path, consisting of any number of subpaths - * constructed out of straight lines and cubic or quadratic Bezier - * curves. - * - * <p>The inside of the curve is defined for drawing purposes by a winding - * rule. Either the WIND_EVEN_ODD or WIND_NON_ZERO winding rule can be chosen. - * - * <p><img src="doc-files/GeneralPath-1.png" width="300" height="210" - * alt="A drawing of a GeneralPath" /> - * <p>The EVEN_ODD winding rule defines a point as inside a path if: - * A ray from the point towards infinity in an arbitrary direction - * intersects the path an odd number of times. Points <b>A</b> and - * <b>C</b> in the image are considered to be outside the path. - * (both intersect twice) - * Point <b>B</b> intersects once, and is inside. - * - * <p>The NON_ZERO winding rule defines a point as inside a path if: - * The path intersects the ray in an equal number of opposite directions. - * Point <b>A</b> in the image is outside (one intersection in the - * ’up’ - * direction, one in the ’down’ direction) Point <b>B</b> in - * the image is inside (one intersection ’down’) - * Point <b>C</b> in the image is inside (two intersections in the - * ’down’ direction) - * - * @see Line2D - * @see CubicCurve2D - * @see QuadCurve2D - * - * @author Sascha Brawer (brawer@dandelis.ch) - * @author Sven de Marothy (sven@physto.se) - * - * @since 1.2 - */ -public final class GeneralPath implements Shape, Cloneable -{ - /** Same constant as {@link PathIterator#WIND_EVEN_ODD}. */ - public static final int WIND_EVEN_ODD = PathIterator.WIND_EVEN_ODD; - - /** Same constant as {@link PathIterator#WIND_NON_ZERO}. */ - public static final int WIND_NON_ZERO = PathIterator.WIND_NON_ZERO; - - /** Initial size if not specified. */ - private static final int INIT_SIZE = 10; - - /** A big number, but not so big it can't survive a few float operations */ - private static final double BIG_VALUE = Double.MAX_VALUE / 10.0; - - /** The winding rule. - * This is package-private to avoid an accessor method. - */ - int rule; - - /** - * The path type in points. Note that xpoints[index] and ypoints[index] maps - * to types[index]; the control points of quad and cubic paths map as - * well but are ignored. - * This is package-private to avoid an accessor method. - */ - byte[] types; - - /** - * The list of all points seen. Since you can only append floats, it makes - * sense for these to be float[]. I have no idea why Sun didn't choose to - * allow a general path of double precision points. - * Note: Storing x and y coords seperately makes for a slower transforms, - * But it speeds up and simplifies box-intersection checking a lot. - * These are package-private to avoid accessor methods. - */ - float[] xpoints; - float[] ypoints; - - /** The index of the most recent moveto point, or null. */ - private int subpath = -1; - - /** The next available index into points. - * This is package-private to avoid an accessor method. - */ - int index; - - /** - * Constructs a GeneralPath with the default (NON_ZERO) - * winding rule and initial capacity (20). - */ - public GeneralPath() - { - this(WIND_NON_ZERO, INIT_SIZE); - } - - /** - * Constructs a GeneralPath with a specific winding rule - * and the default initial capacity (20). - * @param rule the winding rule ({@link #WIND_NON_ZERO} or - * {@link #WIND_EVEN_ODD}) - * - * @throws IllegalArgumentException if <code>rule</code> is not one of the - * listed values. - */ - public GeneralPath(int rule) - { - this(rule, INIT_SIZE); - } - - /** - * Constructs a GeneralPath with a specific winding rule - * and the initial capacity. The initial capacity should be - * the approximate number of path segments to be used. - * @param rule the winding rule ({@link #WIND_NON_ZERO} or - * {@link #WIND_EVEN_ODD}) - * @param capacity the inital capacity, in path segments - * - * @throws IllegalArgumentException if <code>rule</code> is not one of the - * listed values. - */ - public GeneralPath(int rule, int capacity) - { - if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) - throw new IllegalArgumentException(); - this.rule = rule; - if (capacity < INIT_SIZE) - capacity = INIT_SIZE; - types = new byte[capacity]; - xpoints = new float[capacity]; - ypoints = new float[capacity]; - } - - /** - * Constructs a GeneralPath from an arbitrary shape object. - * The Shapes PathIterator path and winding rule will be used. - * - * @param s the shape (<code>null</code> not permitted). - * - * @throws NullPointerException if <code>shape</code> is <code>null</code>. - */ - public GeneralPath(Shape s) - { - types = new byte[INIT_SIZE]; - xpoints = new float[INIT_SIZE]; - ypoints = new float[INIT_SIZE]; - PathIterator pi = s.getPathIterator(null); - setWindingRule(pi.getWindingRule()); - append(pi, false); - } - - /** - * Adds a new point to a path. - * - * @param x the x-coordinate. - * @param y the y-coordinate. - */ - public void moveTo(float x, float y) - { - subpath = index; - ensureSize(index + 1); - types[index] = PathIterator.SEG_MOVETO; - xpoints[index] = x; - ypoints[index++] = y; - } - - /** - * Appends a straight line to the current path. - * @param x x coordinate of the line endpoint. - * @param y y coordinate of the line endpoint. - */ - public void lineTo(float x, float y) - { - ensureSize(index + 1); - types[index] = PathIterator.SEG_LINETO; - xpoints[index] = x; - ypoints[index++] = y; - } - - /** - * Appends a quadratic Bezier curve to the current path. - * @param x1 x coordinate of the control point - * @param y1 y coordinate of the control point - * @param x2 x coordinate of the curve endpoint. - * @param y2 y coordinate of the curve endpoint. - */ - public void quadTo(float x1, float y1, float x2, float y2) - { - ensureSize(index + 2); - types[index] = PathIterator.SEG_QUADTO; - xpoints[index] = x1; - ypoints[index++] = y1; - xpoints[index] = x2; - ypoints[index++] = y2; - } - - /** - * Appends a cubic Bezier curve to the current path. - * @param x1 x coordinate of the first control point - * @param y1 y coordinate of the first control point - * @param x2 x coordinate of the second control point - * @param y2 y coordinate of the second control point - * @param x3 x coordinate of the curve endpoint. - * @param y3 y coordinate of the curve endpoint. - */ - public void curveTo(float x1, float y1, float x2, float y2, float x3, - float y3) - { - ensureSize(index + 3); - types[index] = PathIterator.SEG_CUBICTO; - xpoints[index] = x1; - ypoints[index++] = y1; - xpoints[index] = x2; - ypoints[index++] = y2; - xpoints[index] = x3; - ypoints[index++] = y3; - } - - /** - * Closes the current subpath by drawing a line - * back to the point of the last moveTo, unless the path is already closed. - */ - public void closePath() - { - if (index >= 1 && types[index - 1] == PathIterator.SEG_CLOSE) - return; - ensureSize(index + 1); - types[index] = PathIterator.SEG_CLOSE; - xpoints[index] = xpoints[subpath]; - ypoints[index++] = ypoints[subpath]; - } - - /** - * Appends the segments of a Shape to the path. If <code>connect</code> is - * true, the new path segments are connected to the existing one with a line. - * The winding rule of the Shape is ignored. - * - * @param s the shape (<code>null</code> not permitted). - * @param connect whether to connect the new shape to the existing path. - * - * @throws NullPointerException if <code>s</code> is <code>null</code>. - */ - public void append(Shape s, boolean connect) - { - append(s.getPathIterator(null), connect); - } - - /** - * Appends the segments of a PathIterator to this GeneralPath. - * Optionally, the initial {@link PathIterator#SEG_MOVETO} segment - * of the appended path is changed into a {@link - * PathIterator#SEG_LINETO} segment. - * - * @param iter the PathIterator specifying which segments shall be - * appended (<code>null</code> not permitted). - * - * @param connect <code>true</code> for substituting the initial - * {@link PathIterator#SEG_MOVETO} segment by a {@link - * PathIterator#SEG_LINETO}, or <code>false</code> for not - * performing any substitution. If this GeneralPath is currently - * empty, <code>connect</code> is assumed to be <code>false</code>, - * thus leaving the initial {@link PathIterator#SEG_MOVETO} - * unchanged. - */ - public void append(PathIterator iter, boolean connect) - { - // A bad implementation of this method had caused Classpath bug #6076. - float[] f = new float[6]; - while (! iter.isDone()) - { - switch (iter.currentSegment(f)) - { - case PathIterator.SEG_MOVETO: - if (! connect || (index == 0)) - { - moveTo(f[0], f[1]); - break; - } - if ((index >= 1) && (types[index - 1] == PathIterator.SEG_CLOSE) - && (f[0] == xpoints[index - 1]) - && (f[1] == ypoints[index - 1])) - break; - - // Fall through. - case PathIterator.SEG_LINETO: - lineTo(f[0], f[1]); - break; - case PathIterator.SEG_QUADTO: - quadTo(f[0], f[1], f[2], f[3]); - break; - case PathIterator.SEG_CUBICTO: - curveTo(f[0], f[1], f[2], f[3], f[4], f[5]); - break; - case PathIterator.SEG_CLOSE: - closePath(); - break; - } - - connect = false; - iter.next(); - } - } - - /** - * Returns the path’s current winding rule. - * - * @return {@link #WIND_EVEN_ODD} or {@link #WIND_NON_ZERO}. - */ - public int getWindingRule() - { - return rule; - } - - /** - * Sets the path’s winding rule, which controls which areas are - * considered ’inside’ or ’outside’ the path - * on drawing. Valid rules are WIND_EVEN_ODD for an even-odd winding rule, - * or WIND_NON_ZERO for a non-zero winding rule. - * - * @param rule the rule ({@link #WIND_EVEN_ODD} or {@link #WIND_NON_ZERO}). - */ - public void setWindingRule(int rule) - { - if (rule != WIND_EVEN_ODD && rule != WIND_NON_ZERO) - throw new IllegalArgumentException(); - this.rule = rule; - } - - /** - * Returns the current appending point of the path. - * - * @return The point. - */ - public Point2D getCurrentPoint() - { - if (subpath < 0) - return null; - return new Point2D.Float(xpoints[index - 1], ypoints[index - 1]); - } - - /** - * Resets the path. All points and segments are destroyed. - */ - public void reset() - { - subpath = -1; - index = 0; - } - - /** - * Applies a transform to the path. - * - * @param xform the transform (<code>null</code> not permitted). - */ - public void transform(AffineTransform xform) - { - double nx; - double ny; - double[] m = new double[6]; - xform.getMatrix(m); - for (int i = 0; i < index; i++) - { - nx = m[0] * xpoints[i] + m[2] * ypoints[i] + m[4]; - ny = m[1] * xpoints[i] + m[3] * ypoints[i] + m[5]; - xpoints[i] = (float) nx; - ypoints[i] = (float) ny; - } - } - - /** - * Creates a transformed version of the path. - * @param xform the transform to apply - * @return a new transformed GeneralPath - */ - public Shape createTransformedShape(AffineTransform xform) - { - GeneralPath p = new GeneralPath(this); - p.transform(xform); - return p; - } - - /** - * Returns the path’s bounding box. - */ - public Rectangle getBounds() - { - return getBounds2D().getBounds(); - } - - /** - * Returns the path’s bounding box, in <code>float</code> precision - */ - public Rectangle2D getBounds2D() - { - float x1; - float y1; - float x2; - float y2; - - if (index > 0) - { - x1 = x2 = xpoints[0]; - y1 = y2 = ypoints[0]; - } - else - x1 = x2 = y1 = y2 = 0.0f; - - for (int i = 0; i < index; i++) - { - x1 = Math.min(xpoints[i], x1); - y1 = Math.min(ypoints[i], y1); - x2 = Math.max(xpoints[i], x2); - y2 = Math.max(ypoints[i], y2); - } - return (new Rectangle2D.Float(x1, y1, x2 - x1, y2 - y1)); - } - - /** - * Evaluates if a point is within the GeneralPath, - * The NON_ZERO winding rule is used, regardless of the - * set winding rule. - * @param x x coordinate of the point to evaluate - * @param y y coordinate of the point to evaluate - * @return true if the point is within the path, false otherwise - */ - public boolean contains(double x, double y) - { - return (getWindingNumber(x, y) != 0); - } - - /** - * Evaluates if a Point2D is within the GeneralPath, - * The NON_ZERO winding rule is used, regardless of the - * set winding rule. - * @param p The Point2D to evaluate - * @return true if the point is within the path, false otherwise - */ - public boolean contains(Point2D p) - { - return contains(p.getX(), p.getY()); - } - - /** - * Evaluates if a rectangle is completely contained within the path. - * This method will return false in the cases when the box - * intersects an inner segment of the path. - * (i.e.: The method is accurate for the EVEN_ODD winding rule) - */ - 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, 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 false; - - /* No intersections, is any point inside? */ - if (getWindingNumber(x, y) != 0) - return true; - - return false; - } - - /** - * Evaluates if a rectangle is completely contained within the path. - * This method will return false in the cases when the box - * intersects an inner segment of the path. - * (i.e.: The method is accurate for the EVEN_ODD winding rule) - * @param r the rectangle - * @return <code>true</code> if the rectangle is completely contained - * 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 - * - * @param size the minimum array 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 diff --git a/libjava/classpath/java/awt/geom/IllegalPathStateException.java b/libjava/classpath/java/awt/geom/IllegalPathStateException.java deleted file mode 100644 index 4d190c7..0000000 --- a/libjava/classpath/java/awt/geom/IllegalPathStateException.java +++ /dev/null @@ -1,71 +0,0 @@ -/* IllegalPathStateException.java -- an operation was in an illegal path state - Copyright (C) 2000, 2002 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.awt.geom; - -/** - * Thrown when an operation on a path is in an illegal state, such as appending - * a segment to a <code>GeneralPath</code> without an initial moveto. - * - * @author Tom Tromey (tromey@cygnus.com) - * @see GeneralPath - * @status updated to 1.4 - */ -public class IllegalPathStateException extends RuntimeException -{ - /** - * Compatible with JDK 1.2+. - */ - private static final long serialVersionUID = -5158084205220481094L; - - /** - * Create an exception with no message. - */ - public IllegalPathStateException() - { - } - - /** - * Create an exception with a message. - * - * @param msg the message - */ - public IllegalPathStateException(String msg) - { - super(msg); - } -} diff --git a/libjava/classpath/java/awt/geom/Line2D.java b/libjava/classpath/java/awt/geom/Line2D.java deleted file mode 100644 index c92aab0..0000000 --- a/libjava/classpath/java/awt/geom/Line2D.java +++ /dev/null @@ -1,1182 +0,0 @@ -/* Line2D.java -- represents a line in 2-D space, plus operations on a line - Copyright (C) 2000, 2001, 2002 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.awt.geom; - -import java.awt.Rectangle; -import java.awt.Shape; -import java.util.NoSuchElementException; - -/** - * Represents a directed line bewteen two points in (x,y) Cartesian space. - * Remember, on-screen graphics have increasing x from left-to-right, and - * increasing y from top-to-bottom. The storage is left to subclasses. - * - * @author Tom Tromey (tromey@cygnus.com) - * @author Eric Blake (ebb9@email.byu.edu) - * @author David Gilbert - * @since 1.2 - * @status updated to 1.4 - */ -public abstract class Line2D implements Shape, Cloneable -{ - /** - * The default constructor. - */ - protected Line2D() - { - } - - /** - * Return the x coordinate of the first point. - * - * @return the starting x coordinate - */ - public abstract double getX1(); - - /** - * Return the y coordinate of the first point. - * - * @return the starting y coordinate - */ - public abstract double getY1(); - - /** - * Return the first point. - * - * @return the starting point - */ - public abstract Point2D getP1(); - - /** - * Return the x coordinate of the second point. - * - * @return the ending x coordinate - */ - public abstract double getX2(); - - /** - * Return the y coordinate of the second point. - * - * @return the ending y coordinate - */ - public abstract double getY2(); - - /** - * Return the second point. - * - * @return the ending point - */ - public abstract Point2D getP2(); - - /** - * Set the coordinates of the line to the given coordinates. Loss of - * precision may occur due to rounding issues. - * - * @param x1 the first x coordinate - * @param y1 the first y coordinate - * @param x2 the second x coordinate - * @param y2 the second y coordinate - */ - public abstract void setLine(double x1, double y1, double x2, double y2); - - /** - * Set the coordinates to the given points. - * - * @param p1 the first point - * @param p2 the second point - * @throws NullPointerException if either point is null - */ - public void setLine(Point2D p1, Point2D p2) - { - setLine(p1.getX(), p1.getY(), p2.getX(), p2.getY()); - } - - /** - * Set the coordinates to those of the given line. - * - * @param l the line to copy - * @throws NullPointerException if l is null - */ - public void setLine(Line2D l) - { - setLine(l.getX1(), l.getY1(), l.getX2(), l.getY2()); - } - - /** - * Computes the relative rotation direction needed to pivot the line about - * the first point in order to have the second point colinear with point p. - * Because of floating point rounding, don't expect this to be a perfect - * measure of colinearity. The answer is 1 if the line has a shorter rotation - * in the direction of the positive X axis to the negative Y axis - * (counter-clockwise in the default Java coordinate system), or -1 if the - * shortest rotation is in the opposite direction (clockwise). If p - * is already colinear, the return value is -1 if it lies beyond the first - * point, 0 if it lies in the segment, or 1 if it lies beyond the second - * point. If the first and second point are coincident, this returns 0. - * - * @param x1 the first x coordinate - * @param y1 the first y coordinate - * @param x2 the second x coordinate - * @param y2 the second y coordinate - * @param px the reference x coordinate - * @param py the reference y coordinate - * @return the relative rotation direction - */ - public static int relativeCCW(double x1, double y1, double x2, double y2, - double px, double py) - { - if ((x1 == x2 && y1 == y2) - || (x1 == px && y1 == py)) - return 0; // Coincident points. - // Translate to the origin. - x2 -= x1; - y2 -= y1; - px -= x1; - py -= y1; - double slope2 = y2 / x2; - double slopep = py / px; - if (slope2 == slopep || (x2 == 0 && px == 0)) - return y2 > 0 // Colinear. - ? (py < 0 ? -1 : py > y2 ? 1 : 0) - : (py > 0 ? -1 : py < y2 ? 1 : 0); - if (x2 >= 0 && slope2 >= 0) - return px >= 0 // Quadrant 1. - ? (slope2 > slopep ? 1 : -1) - : (slope2 < slopep ? 1 : -1); - if (y2 > 0) - return px < 0 // Quadrant 2. - ? (slope2 > slopep ? 1 : -1) - : (slope2 < slopep ? 1 : -1); - if (slope2 >= 0.0) - return px >= 0 // Quadrant 3. - ? (slope2 < slopep ? 1 : -1) - : (slope2 > slopep ? 1 : -1); - return px < 0 // Quadrant 4. - ? (slope2 < slopep ? 1 : -1) - : (slope2 > slopep ? 1 : -1); - } - - /** - * Computes the relative rotation direction needed to pivot this line about - * the first point in order to have the second point colinear with point p. - * Because of floating point rounding, don't expect this to be a perfect - * measure of colinearity. The answer is 1 if the line has a shorter rotation - * in the direction of the positive X axis to the negative Y axis - * (counter-clockwise in the default Java coordinate system), or -1 if the - * shortest rotation is in the opposite direction (clockwise). If p - * is already colinear, the return value is -1 if it lies beyond the first - * point, 0 if it lies in the segment, or 1 if it lies beyond the second - * point. If the first and second point are coincident, this returns 0. - * - * @param px the reference x coordinate - * @param py the reference y coordinate - * @return the relative rotation direction - * @see #relativeCCW(double, double, double, double, double, double) - */ - public int relativeCCW(double px, double py) - { - return relativeCCW(getX1(), getY1(), getX2(), getY2(), px, py); - } - - /** - * Computes the relative rotation direction needed to pivot this line about - * the first point in order to have the second point colinear with point p. - * Because of floating point rounding, don't expect this to be a perfect - * measure of colinearity. The answer is 1 if the line has a shorter rotation - * in the direction of the positive X axis to the negative Y axis - * (counter-clockwise in the default Java coordinate system), or -1 if the - * shortest rotation is in the opposite direction (clockwise). If p - * is already colinear, the return value is -1 if it lies beyond the first - * point, 0 if it lies in the segment, or 1 if it lies beyond the second - * point. If the first and second point are coincident, this returns 0. - * - * @param p the reference point - * @return the relative rotation direction - * @throws NullPointerException if p is null - * @see #relativeCCW(double, double, double, double, double, double) - */ - public int relativeCCW(Point2D p) - { - return relativeCCW(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY()); - } - - /** - * Computes twice the (signed) area of the triangle defined by the three - * points. This method is used for intersection testing. - * - * @param x1 the x-coordinate of the first point. - * @param y1 the y-coordinate of the first point. - * @param x2 the x-coordinate of the second point. - * @param y2 the y-coordinate of the second point. - * @param x3 the x-coordinate of the third point. - * @param y3 the y-coordinate of the third point. - * - * @return Twice the area. - */ - private static double area2(double x1, double y1, - double x2, double y2, - double x3, double y3) - { - return (x2 - x1) * (y3 - y1) - (x3 - x1) * (y2 - y1); - } - - /** - * Returns <code>true</code> if (x3, y3) lies between (x1, y1) and (x2, y2), - * and false otherwise, This test assumes that the three points are - * collinear, and is used for intersection testing. - * - * @param x1 the x-coordinate of the first point. - * @param y1 the y-coordinate of the first point. - * @param x2 the x-coordinate of the second point. - * @param y2 the y-coordinate of the second point. - * @param x3 the x-coordinate of the third point. - * @param y3 the y-coordinate of the third point. - * - * @return A boolean. - */ - private static boolean between(double x1, double y1, - double x2, double y2, - double x3, double y3) - { - if (x1 != x2) { - return (x1 <= x3 && x3 <= x2) || (x1 >= x3 && x3 >= x2); - } - else { - return (y1 <= y3 && y3 <= y2) || (y1 >= y3 && y3 >= y2); - } - } - - /** - * Test if the line segment (x1,y1)->(x2,y2) intersects the line segment - * (x3,y3)->(x4,y4). - * - * @param x1 the first x coordinate of the first segment - * @param y1 the first y coordinate of the first segment - * @param x2 the second x coordinate of the first segment - * @param y2 the second y coordinate of the first segment - * @param x3 the first x coordinate of the second segment - * @param y3 the first y coordinate of the second segment - * @param x4 the second x coordinate of the second segment - * @param y4 the second y coordinate of the second segment - * @return true if the segments intersect - */ - public static boolean linesIntersect(double x1, double y1, - double x2, double y2, - double x3, double y3, - double x4, double y4) - { - double a1, a2, a3, a4; - - // deal with special cases - if ((a1 = area2(x1, y1, x2, y2, x3, y3)) == 0.0) - { - // check if p3 is between p1 and p2 OR - // p4 is collinear also AND either between p1 and p2 OR at opposite ends - if (between(x1, y1, x2, y2, x3, y3)) - { - return true; - } - else - { - if (area2(x1, y1, x2, y2, x4, y4) == 0.0) - { - return between(x3, y3, x4, y4, x1, y1) - || between (x3, y3, x4, y4, x2, y2); - } - else { - return false; - } - } - } - else if ((a2 = area2(x1, y1, x2, y2, x4, y4)) == 0.0) - { - // check if p4 is between p1 and p2 (we already know p3 is not - // collinear) - return between(x1, y1, x2, y2, x4, y4); - } - - if ((a3 = area2(x3, y3, x4, y4, x1, y1)) == 0.0) { - // check if p1 is between p3 and p4 OR - // p2 is collinear also AND either between p1 and p2 OR at opposite ends - if (between(x3, y3, x4, y4, x1, y1)) { - return true; - } - else { - if (area2(x3, y3, x4, y4, x2, y2) == 0.0) { - return between(x1, y1, x2, y2, x3, y3) - || between (x1, y1, x2, y2, x4, y4); - } - else { - return false; - } - } - } - else if ((a4 = area2(x3, y3, x4, y4, x2, y2)) == 0.0) { - // check if p2 is between p3 and p4 (we already know p1 is not - // collinear) - return between(x3, y3, x4, y4, x2, y2); - } - else { // test for regular intersection - return ((a1 > 0.0) ^ (a2 > 0.0)) && ((a3 > 0.0) ^ (a4 > 0.0)); - } - } - - /** - * Test if this line intersects the line given by (x1,y1)->(x2,y2). - * - * @param x1 the first x coordinate of the other segment - * @param y1 the first y coordinate of the other segment - * @param x2 the second x coordinate of the other segment - * @param y2 the second y coordinate of the other segment - * @return true if the segments intersect - * @see #linesIntersect(double, double, double, double, - * double, double, double, double) - */ - public boolean intersectsLine(double x1, double y1, double x2, double y2) - { - return linesIntersect(getX1(), getY1(), getX2(), getY2(), - x1, y1, x2, y2); - } - - /** - * Test if this line intersects the given line. - * - * @param l the other segment - * @return true if the segments intersect - * @throws NullPointerException if l is null - * @see #linesIntersect(double, double, double, double, - * double, double, double, double) - */ - public boolean intersectsLine(Line2D l) - { - return linesIntersect(getX1(), getY1(), getX2(), getY2(), - l.getX1(), l.getY1(), l.getX2(), l.getY2()); - } - - /** - * Measures the square of the shortest distance from the reference point - * to a point on the line segment. If the point is on the segment, the - * result will be 0. - * - * @param x1 the first x coordinate of the segment - * @param y1 the first y coordinate of the segment - * @param x2 the second x coordinate of the segment - * @param y2 the second y coordinate of the segment - * @param px the x coordinate of the point - * @param py the y coordinate of the point - * @return the square of the distance from the point to the segment - * @see #ptSegDist(double, double, double, double, double, double) - * @see #ptLineDistSq(double, double, double, double, double, double) - */ - public static double ptSegDistSq(double x1, double y1, double x2, double y2, - double px, double py) - { - double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); - - double x, y; - if (pd2 == 0) - { - // Points are coincident. - x = x1; - y = y2; - } - else - { - double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2; - - if (u < 0) - { - // "Off the end" - x = x1; - y = y1; - } - else if (u > 1.0) - { - x = x2; - y = y2; - } - else - { - x = x1 + u * (x2 - x1); - y = y1 + u * (y2 - y1); - } - } - - return (x - px) * (x - px) + (y - py) * (y - py); - } - - /** - * Measures the shortest distance from the reference point to a point on - * the line segment. If the point is on the segment, the result will be 0. - * - * @param x1 the first x coordinate of the segment - * @param y1 the first y coordinate of the segment - * @param x2 the second x coordinate of the segment - * @param y2 the second y coordinate of the segment - * @param px the x coordinate of the point - * @param py the y coordinate of the point - * @return the distance from the point to the segment - * @see #ptSegDistSq(double, double, double, double, double, double) - * @see #ptLineDist(double, double, double, double, double, double) - */ - public static double ptSegDist(double x1, double y1, double x2, double y2, - double px, double py) - { - return Math.sqrt(ptSegDistSq(x1, y1, x2, y2, px, py)); - } - - /** - * Measures the square of the shortest distance from the reference point - * to a point on this line segment. If the point is on the segment, the - * result will be 0. - * - * @param px the x coordinate of the point - * @param py the y coordinate of the point - * @return the square of the distance from the point to the segment - * @see #ptSegDistSq(double, double, double, double, double, double) - */ - public double ptSegDistSq(double px, double py) - { - return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), px, py); - } - - /** - * Measures the square of the shortest distance from the reference point - * to a point on this line segment. If the point is on the segment, the - * result will be 0. - * - * @param p the point - * @return the square of the distance from the point to the segment - * @throws NullPointerException if p is null - * @see #ptSegDistSq(double, double, double, double, double, double) - */ - public double ptSegDistSq(Point2D p) - { - return ptSegDistSq(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY()); - } - - /** - * Measures the shortest distance from the reference point to a point on - * this line segment. If the point is on the segment, the result will be 0. - * - * @param px the x coordinate of the point - * @param py the y coordinate of the point - * @return the distance from the point to the segment - * @see #ptSegDist(double, double, double, double, double, double) - */ - public double ptSegDist(double px, double py) - { - return ptSegDist(getX1(), getY1(), getX2(), getY2(), px, py); - } - - /** - * Measures the shortest distance from the reference point to a point on - * this line segment. If the point is on the segment, the result will be 0. - * - * @param p the point - * @return the distance from the point to the segment - * @throws NullPointerException if p is null - * @see #ptSegDist(double, double, double, double, double, double) - */ - public double ptSegDist(Point2D p) - { - return ptSegDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY()); - } - - /** - * Measures the square of the shortest distance from the reference point - * to a point on the infinite line extended from the segment. If the point - * is on the segment, the result will be 0. If the segment is length 0, - * the distance is to the common endpoint. - * - * @param x1 the first x coordinate of the segment - * @param y1 the first y coordinate of the segment - * @param x2 the second x coordinate of the segment - * @param y2 the second y coordinate of the segment - * @param px the x coordinate of the point - * @param py the y coordinate of the point - * @return the square of the distance from the point to the extended line - * @see #ptLineDist(double, double, double, double, double, double) - * @see #ptSegDistSq(double, double, double, double, double, double) - */ - public static double ptLineDistSq(double x1, double y1, double x2, double y2, - double px, double py) - { - double pd2 = (x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2); - - double x, y; - if (pd2 == 0) - { - // Points are coincident. - x = x1; - y = y2; - } - else - { - double u = ((px - x1) * (x2 - x1) + (py - y1) * (y2 - y1)) / pd2; - x = x1 + u * (x2 - x1); - y = y1 + u * (y2 - y1); - } - - return (x - px) * (x - px) + (y - py) * (y - py); - } - - /** - * Measures the shortest distance from the reference point to a point on - * the infinite line extended from the segment. If the point is on the - * segment, the result will be 0. If the segment is length 0, the distance - * is to the common endpoint. - * - * @param x1 the first x coordinate of the segment - * @param y1 the first y coordinate of the segment - * @param x2 the second x coordinate of the segment - * @param y2 the second y coordinate of the segment - * @param px the x coordinate of the point - * @param py the y coordinate of the point - * @return the distance from the point to the extended line - * @see #ptLineDistSq(double, double, double, double, double, double) - * @see #ptSegDist(double, double, double, double, double, double) - */ - public static double ptLineDist(double x1, double y1, - double x2, double y2, - double px, double py) - { - return Math.sqrt(ptLineDistSq(x1, y1, x2, y2, px, py)); - } - - /** - * Measures the square of the shortest distance from the reference point - * to a point on the infinite line extended from this segment. If the point - * is on the segment, the result will be 0. If the segment is length 0, - * the distance is to the common endpoint. - * - * @param px the x coordinate of the point - * @param py the y coordinate of the point - * @return the square of the distance from the point to the extended line - * @see #ptLineDistSq(double, double, double, double, double, double) - */ - public double ptLineDistSq(double px, double py) - { - return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), px, py); - } - - /** - * Measures the square of the shortest distance from the reference point - * to a point on the infinite line extended from this segment. If the point - * is on the segment, the result will be 0. If the segment is length 0, - * the distance is to the common endpoint. - * - * @param p the point - * @return the square of the distance from the point to the extended line - * @throws NullPointerException if p is null - * @see #ptLineDistSq(double, double, double, double, double, double) - */ - public double ptLineDistSq(Point2D p) - { - return ptLineDistSq(getX1(), getY1(), getX2(), getY2(), - p.getX(), p.getY()); - } - - /** - * Measures the shortest distance from the reference point to a point on - * the infinite line extended from this segment. If the point is on the - * segment, the result will be 0. If the segment is length 0, the distance - * is to the common endpoint. - * - * @param px the x coordinate of the point - * @param py the y coordinate of the point - * @return the distance from the point to the extended line - * @see #ptLineDist(double, double, double, double, double, double) - */ - public double ptLineDist(double px, double py) - { - return ptLineDist(getX1(), getY1(), getX2(), getY2(), px, py); - } - - /** - * Measures the shortest distance from the reference point to a point on - * the infinite line extended from this segment. If the point is on the - * segment, the result will be 0. If the segment is length 0, the distance - * is to the common endpoint. - * - * @param p the point - * @return the distance from the point to the extended line - * @throws NullPointerException if p is null - * @see #ptLineDist(double, double, double, double, double, double) - */ - public double ptLineDist(Point2D p) - { - return ptLineDist(getX1(), getY1(), getX2(), getY2(), p.getX(), p.getY()); - } - - /** - * Test if a point is contained inside the line. Since a line has no area, - * this returns false. - * - * @param x the x coordinate - * @param y the y coordinate - * @return false; the line does not contain points - */ - public boolean contains(double x, double y) - { - return false; - } - - /** - * Test if a point is contained inside the line. Since a line has no area, - * this returns false. - * - * @param p the point - * @return false; the line does not contain points - */ - public boolean contains(Point2D p) - { - return false; - } - - /** - * Tests if this line intersects the interior of the specified rectangle. - * - * @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 line intersects the rectangle - */ - public boolean intersects(double x, double y, double w, double h) - { - if (w <= 0 || h <= 0) - return false; - double x1 = getX1(); - double y1 = getY1(); - double x2 = getX2(); - double y2 = getY2(); - - if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h) - return true; - if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h) - return true; - - double x3 = x + w; - double y3 = y + h; - - return (linesIntersect(x1, y1, x2, y2, x, y, x, y3) - || linesIntersect(x1, y1, x2, y2, x, y3, x3, y3) - || linesIntersect(x1, y1, x2, y2, x3, y3, x3, y) - || linesIntersect(x1, y1, x2, y2, x3, y, x, y)); - } - - /** - * Tests if this line intersects the interior of the specified rectangle. - * - * @param r the rectangle - * @return true if the line intersects the rectangle - * @throws NullPointerException if r is null - */ - public boolean intersects(Rectangle2D r) - { - return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - /** - * Tests if the line contains a rectangle. Since lines have no area, this - * always returns false. - * - * @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 false; the line does not contain points - */ - public boolean contains(double x, double y, double w, double h) - { - return false; - } - - /** - * Tests if the line contains a rectangle. Since lines have no area, this - * always returns false. - * - * @param r the rectangle - * @return false; the line does not contain points - */ - public boolean contains(Rectangle2D r) - { - return false; - } - - /** - * Gets a bounding box (not necessarily minimal) for this line. - * - * @return the integer bounding box - * @see #getBounds2D() - */ - public Rectangle getBounds() - { - return getBounds2D().getBounds(); - } - - /** - * Return a path iterator, possibly applying a transform on the result. This - * iterator is not threadsafe. - * - * @param at the transform, or null - * @return a new path iterator - */ - 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) getX2(); - coords[1] = (float) getY2(); - result = SEG_LINETO; - break; - default: - throw new NoSuchElementException("line iterator out of bounds"); - } - if (at != null) - at.transform(coords, 0, coords, 0, 1); - 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] = getX2(); - coords[1] = getY2(); - result = SEG_LINETO; - break; - default: - throw new NoSuchElementException("line iterator out of bounds"); - } - if (at != null) - at.transform(coords, 0, coords, 0, 1); - return result; - } - }; - } - - /** - * Return a flat path iterator, possibly applying a transform on the result. - * This iterator is not threadsafe. - * - * @param at the transform, or null - * @param flatness ignored, since lines are already flat - * @return a new path iterator - * @see #getPathIterator(AffineTransform) - */ - public PathIterator getPathIterator(AffineTransform at, double flatness) - { - return getPathIterator(at); - } - - /** - * Create a new line 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() - { - try - { - return super.clone(); - } - catch (CloneNotSupportedException e) - { - throw (Error) new InternalError().initCause(e); // Impossible - } - } - - /** - * This class defines a point in <code>double</code> precision. - * - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @status updated to 1.4 - */ - public static class Double extends Line2D - { - /** The x coordinate of the first point. */ - public double x1; - - /** The y coordinate of the first point. */ - public double y1; - - /** The x coordinate of the second point. */ - public double x2; - - /** The y coordinate of the second point. */ - public double y2; - - /** - * Construct the line segment (0,0)->(0,0). - */ - public Double() - { - } - - /** - * Construct the line segment with the specified points. - * - * @param x1 the x coordinate of the first point - * @param y1 the y coordinate of the first point - * @param x2 the x coordinate of the second point - * @param y2 the y coordinate of the second point - */ - public Double(double x1, double y1, double x2, double y2) - { - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - } - - /** - * Construct the line segment with the specified points. - * - * @param p1 the first point - * @param p2 the second point - * @throws NullPointerException if either point is null - */ - public Double(Point2D p1, Point2D p2) - { - x1 = p1.getX(); - y1 = p1.getY(); - x2 = p2.getX(); - y2 = p2.getY(); - } - - /** - * Return the x coordinate of the first point. - * - * @return the value of x1 - */ - public double getX1() - { - return x1; - } - - /** - * Return the y coordinate of the first point. - * - * @return the value of y1 - */ - public double getY1() - { - return y1; - } - - /** - * Return the first point. - * - * @return the point (x1,y1) - */ - public Point2D getP1() - { - return new Point2D.Double(x1, y1); - } - - /** - * Return the x coordinate of the second point. - * - * @return the value of x2 - */ - public double getX2() - { - return x2; - } - - /** - * Return the y coordinate of the second point. - * - * @return the value of y2 - */ - public double getY2() - { - return y2; - } - - /** - * Return the second point. - * - * @return the point (x2,y2) - */ - public Point2D getP2() - { - return new Point2D.Double(x2, y2); - } - - /** - * Set this line to the given points. - * - * @param x1 the new x coordinate of the first point - * @param y1 the new y coordinate of the first point - * @param x2 the new x coordinate of the second point - * @param y2 the new y coordinate of the second point - */ - public void setLine(double x1, double y1, double x2, double y2) - { - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - } - - /** - * Return the exact bounds of this line segment. - * - * @return the bounding box - */ - public Rectangle2D getBounds2D() - { - double x = Math.min(x1, x2); - double y = Math.min(y1, y2); - double w = Math.abs(x1 - x2); - double h = Math.abs(y1 - y2); - return new Rectangle2D.Double(x, y, w, h); - } - } // class Double - - /** - * This class defines a point in <code>float</code> precision. - * - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @status updated to 1.4 - */ - public static class Float extends Line2D - { - /** The x coordinate of the first point. */ - public float x1; - - /** The y coordinate of the first point. */ - public float y1; - - /** The x coordinate of the second point. */ - public float x2; - - /** The y coordinate of the second point. */ - public float y2; - - /** - * Construct the line segment (0,0)->(0,0). - */ - public Float() - { - } - - /** - * Construct the line segment with the specified points. - * - * @param x1 the x coordinate of the first point - * @param y1 the y coordinate of the first point - * @param x2 the x coordinate of the second point - * @param y2 the y coordinate of the second point - */ - public Float(float x1, float y1, float x2, float y2) - { - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - } - - /** - * Construct the line segment with the specified points. - * - * @param p1 the first point - * @param p2 the second point - * @throws NullPointerException if either point is null - */ - public Float(Point2D p1, Point2D p2) - { - x1 = (float) p1.getX(); - y1 = (float) p1.getY(); - x2 = (float) p2.getX(); - y2 = (float) p2.getY(); - } - - /** - * Return the x coordinate of the first point. - * - * @return the value of x1 - */ - public double getX1() - { - return x1; - } - - /** - * Return the y coordinate of the first point. - * - * @return the value of y1 - */ - public double getY1() - { - return y1; - } - - /** - * Return the first point. - * - * @return the point (x1,y1) - */ - public Point2D getP1() - { - return new Point2D.Float(x1, y1); - } - - /** - * Return the x coordinate of the second point. - * - * @return the value of x2 - */ - public double getX2() - { - return x2; - } - - /** - * Return the y coordinate of the second point. - * - * @return the value of y2 - */ - public double getY2() - { - return y2; - } - - /** - * Return the second point. - * - * @return the point (x2,y2) - */ - public Point2D getP2() - { - return new Point2D.Float(x2, y2); - } - - /** - * Set this line to the given points. - * - * @param x1 the new x coordinate of the first point - * @param y1 the new y coordinate of the first point - * @param x2 the new x coordinate of the second point - * @param y2 the new y coordinate of the second point - */ - public void setLine(double x1, double y1, double x2, double y2) - { - this.x1 = (float) x1; - this.y1 = (float) y1; - this.x2 = (float) x2; - this.y2 = (float) y2; - } - - /** - * Set this line to the given points. - * - * @param x1 the new x coordinate of the first point - * @param y1 the new y coordinate of the first point - * @param x2 the new x coordinate of the second point - * @param y2 the new y coordinate of the second point - */ - public void setLine(float x1, float y1, float x2, float y2) - { - this.x1 = x1; - this.y1 = y1; - this.x2 = x2; - this.y2 = y2; - } - - /** - * Return the exact bounds of this line segment. - * - * @return the bounding box - */ - public Rectangle2D getBounds2D() - { - float x = Math.min(x1, x2); - float y = Math.min(y1, y2); - float w = Math.abs(x1 - x2); - float h = Math.abs(y1 - y2); - return new Rectangle2D.Float(x, y, w, h); - } - } // class Float -} // class Line2D diff --git a/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java b/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java deleted file mode 100644 index 7995a52..0000000 --- a/libjava/classpath/java/awt/geom/NoninvertibleTransformException.java +++ /dev/null @@ -1,65 +0,0 @@ -/* NoninvertibleTransformException.java -- a transform can't be inverted - Copyright (C) 2000, 2002 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.awt.geom; - -/** - * Thrown if an operation requires an inverse of an - * <code>AffineTransform</code>, but the transform is in a non-invertible - * state. - * - * @author Tom Tromey (tromey@cygnus.com) - * @see AffineTransform - * @status updated to 1.4 - */ -public class NoninvertibleTransformException extends Exception -{ - /** - * Compatible with JDK 1.2+. - */ - private static final long serialVersionUID = 6137225240503990466L; - - /** - * Create an exception with a message. - * - * @param s the message - */ - public NoninvertibleTransformException(String s) - { - super(s); - } -} diff --git a/libjava/classpath/java/awt/geom/PathIterator.java b/libjava/classpath/java/awt/geom/PathIterator.java deleted file mode 100644 index 2cd08b9..0000000 --- a/libjava/classpath/java/awt/geom/PathIterator.java +++ /dev/null @@ -1,189 +0,0 @@ -/* PathIterator.java -- describes a shape by iterating over its vertices - Copyright (C) 2000, 2002, 2003 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.awt.geom; - -/** - * This interface provides a directed path over the boundary of a shape. The - * path can contain 1st through 3rd order Bezier curves (lines, and quadratic - * and cubic splines). A shape can have multiple disjoint paths via the - * MOVETO directive, and can close a circular path back to the previos - * MOVETO via the CLOSE directive. - * - * @author Tom Tromey (tromey@cygnus.com) - * @author Eric Blake (ebb9@email.byu.edu) - * @see java.awt.Shape - * @see java.awt.Stroke - * @see FlatteningPathIterator - * @since 1.2 - * @status updated to 1.4 - */ -public interface PathIterator -{ - /** - * The even-odd winding mode: a point is internal to the shape if a ray - * from the point to infinity (in any direction) crosses an odd number of - * segments. - */ - int WIND_EVEN_ODD = 0; - - /** - * The non-zero winding mode: a point is internal to the shape if a ray - * from the point to infinity (in any direction) crosses a different number - * of segments headed clockwise than those headed counterclockwise. - */ - int WIND_NON_ZERO = 1; - - /** - * Starts a new subpath. There is no segment from the previous vertex. - */ - int SEG_MOVETO = 0; - - /** - * The current segment is a line. - */ - int SEG_LINETO = 1; - - /** - * The current segment is a quadratic parametric curve. It is interpolated - * as t varies from 0 to 1 over the current point (CP), first control point - * (P1), and final interpolated control point (P2): - * <pre> - * P(t) = B(2,0)*CP + B(2,1)*P1 + B(2,2)*P2 - * 0 <= t <= 1 - * B(n,m) = mth coefficient of nth degree Bernstein polynomial - * = C(n,m) * t^(m) * (1 - t)^(n-m) - * C(n,m) = Combinations of n things, taken m at a time - * = n! / (m! * (n-m)!) - * </pre> - */ - int SEG_QUADTO = 2; - - /** - * The current segment is a cubic parametric curve (more commonly known as - * a Bezier curve). It is interpolated as t varies from 0 to 1 over the - * current point (CP), first control point (P1), the second control point - * (P2), and final interpolated control point (P3): - * <pre> - * P(t) = B(3,0)*CP + B(3,1)*P1 + B(3,2)*P2 + B(3,3)*P3 - * 0 <= t <= 1 - * B(n,m) = mth coefficient of nth degree Bernstein polynomial - * = C(n,m) * t^(m) * (1 - t)^(n-m) - * C(n,m) = Combinations of n things, taken m at a time - * = n! / (m! * (n-m)!) - * </pre> - */ - int SEG_CUBICTO = 3; - - /** - * The current segment closes a loop by an implicit line to the previous - * SEG_MOVETO coordinate. - */ - int SEG_CLOSE = 4; - - /** - * Returns the winding rule to determine which points are inside this path. - * - * @return the winding rule - * @see #WIND_EVEN_ODD - * @see #WIND_NON_ZERO - */ - int getWindingRule(); - - /** - * Tests if the iterator is exhausted. If this returns true, currentSegment - * and next may throw a NoSuchElementException (although this is not - * required). - * - * @return true if the iteration is complete - */ - boolean isDone(); - - /** - * Advance to the next segment in the iteration. It is not specified what - * this does if called when isDone() returns true. - * - * @throws java.util.NoSuchElementException optional when isDone() is true - */ - void next(); - - /** - * Returns the coordinates of the next point(s), as well as the type of - * line segment. The input array must be at least a float[6], to accomodate - * up to three (x,y) point pairs (although if you know the iterator is - * flat, you can probably get by with a float[2]). If the returned type is - * SEG_MOVETO or SEG_LINETO, the first point in the array is modified; if - * the returned type is SEG_QUADTO, the first two points are modified; if - * the returned type is SEG_CUBICTO, all three points are modified; and if - * the returned type is SEG_CLOSE, the array is untouched. - * - * @param coords the array to place the point coordinates in - * @return the segment type - * @throws NullPointerException if coords is null - * @throws ArrayIndexOutOfBoundsException if coords is too small - * @throws java.util.NoSuchElementException optional when isDone() is true - * @see #SEG_MOVETO - * @see #SEG_LINETO - * @see #SEG_QUADTO - * @see #SEG_CUBICTO - * @see #SEG_CLOSE - */ - int currentSegment(float[] coords); - - /** - * Returns the coordinates of the next point(s), as well as the type of - * line segment. The input array must be at least a double[6], to accomodate - * up to three (x,y) point pairs (although if you know the iterator is - * flat, you can probably get by with a double[2]). If the returned type is - * SEG_MOVETO or SEG_LINETO, the first point in the array is modified; if - * the returned type is SEG_QUADTO, the first two points are modified; if - * the returned type is SEG_CUBICTO, all three points are modified; and if - * the returned type is SEG_CLOSE, the array is untouched. - * - * @param coords the array to place the point coordinates in - * @return the segment type - * @throws NullPointerException if coords is null - * @throws ArrayIndexOutOfBoundsException if coords is too small - * @throws java.util.NoSuchElementException optional when isDone() is true - * @see #SEG_MOVETO - * @see #SEG_LINETO - * @see #SEG_QUADTO - * @see #SEG_CUBICTO - * @see #SEG_CLOSE - */ - int currentSegment(double[] coords); -} // interface PathIterator diff --git a/libjava/classpath/java/awt/geom/Point2D.java b/libjava/classpath/java/awt/geom/Point2D.java deleted file mode 100644 index a2689ab..0000000 --- a/libjava/classpath/java/awt/geom/Point2D.java +++ /dev/null @@ -1,396 +0,0 @@ -/* Point2D.java -- generic point in 2-D space - Copyright (C) 1999, 2000, 2002, 2004, 2006, Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.awt.geom; - -/** - * This class implements a generic point in 2D Cartesian space. The storage - * representation is left up to the subclass. Point includes two useful - * nested classes, for float and double storage respectively. - * - * @author Per Bothner (bothner@cygnus.com) - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @status updated to 1.4 - */ -public abstract class Point2D implements Cloneable -{ - /** - * The default constructor. - * - * @see java.awt.Point - * @see Point2D.Float - * @see Point2D.Double - */ - protected Point2D() - { - } - - /** - * Get the X coordinate, in double precision. - * - * @return the x coordinate - */ - public abstract double getX(); - - /** - * Get the Y coordinate, in double precision. - * - * @return the y coordinate - */ - public abstract double getY(); - - /** - * Set the location of this point to the new coordinates. There may be a - * loss of precision. - * - * @param x the new x coordinate - * @param y the new y coordinate - */ - public abstract void setLocation(double x, double y); - - /** - * Set the location of this point to the new coordinates. There may be a - * loss of precision. - * - * @param p the point to copy - * @throws NullPointerException if p is null - */ - public void setLocation(Point2D p) - { - setLocation(p.getX(), p.getY()); - } - - /** - * Return the square of the distance between two points. - * - * @param x1 the x coordinate of point 1 - * @param y1 the y coordinate of point 1 - * @param x2 the x coordinate of point 2 - * @param y2 the y coordinate of point 2 - * @return (x2 - x1)^2 + (y2 - y1)^2 - */ - public static double distanceSq(double x1, double y1, double x2, double y2) - { - x2 -= x1; - y2 -= y1; - return x2 * x2 + y2 * y2; - } - - /** - * Return the distance between two points. - * - * @param x1 the x coordinate of point 1 - * @param y1 the y coordinate of point 1 - * @param x2 the x coordinate of point 2 - * @param y2 the y coordinate of point 2 - * @return the distance from (x1,y1) to (x2,y2) - */ - public static double distance(double x1, double y1, double x2, double y2) - { - return Math.sqrt(distanceSq(x1, y1, x2, y2)); - } - - /** - * Return the square of the distance from this point to the given one. - * - * @param x the x coordinate of the other point - * @param y the y coordinate of the other point - * @return the square of the distance - */ - public double distanceSq(double x, double y) - { - return distanceSq(getX(), getY(), x, y); - } - - /** - * Return the square of the distance from this point to the given one. - * - * @param p the other point - * @return the square of the distance - * @throws NullPointerException if p is null - */ - public double distanceSq(Point2D p) - { - return distanceSq(getX(), getY(), p.getX(), p.getY()); - } - - /** - * Return the distance from this point to the given one. - * - * @param x the x coordinate of the other point - * @param y the y coordinate of the other point - * @return the distance - */ - public double distance(double x, double y) - { - return distance(getX(), getY(), x, y); - } - - /** - * Return the distance from this point to the given one. - * - * @param p the other point - * @return the distance - * @throws NullPointerException if p is null - */ - public double distance(Point2D p) - { - return distance(getX(), getY(), p.getX(), p.getY()); - } - - /** - * Create a new point of the same run-time type 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 - } - } - - /** - * Return the hashcode for this point. The formula is not documented, but - * appears to be the same as: - * <pre> - * long l = Double.doubleToLongBits(getY()); - * l = l * 31 ^ Double.doubleToLongBits(getX()); - * return (int) ((l >> 32) ^ l); - * </pre> - * - * @return the hashcode - */ - public int hashCode() - { - // Talk about a fun time reverse engineering this one! - long l = java.lang.Double.doubleToLongBits(getY()); - l = l * 31 ^ java.lang.Double.doubleToLongBits(getX()); - return (int) ((l >> 32) ^ l); - } - - /** - * Compares two points for equality. This returns true if they have the - * same coordinates. - * - * @param o the point to compare - * @return true if it is equal - */ - public boolean equals(Object o) - { - if (! (o instanceof Point2D)) - return false; - Point2D p = (Point2D) o; - return getX() == p.getX() && getY() == p.getY(); - } - - /** - * This class defines a point in <code>double</code> precision. - * - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @status updated to 1.4 - */ - public static class Double extends Point2D - { - /** The X coordinate. */ - public double x; - - /** The Y coordinate. */ - public double y; - - /** - * Create a new point at (0,0). - */ - public Double() - { - } - - /** - * Create a new point at (x,y). - * - * @param x the x coordinate - * @param y the y coordinate - */ - public Double(double x, double y) - { - this.x = x; - this.y = y; - } - - /** - * Return the x coordinate. - * - * @return the x coordinate - */ - public double getX() - { - return x; - } - - /** - * Return the y coordinate. - * - * @return the y coordinate - */ - public double getY() - { - return y; - } - - /** - * Sets the location of this point. - * - * @param x the new x coordinate - * @param y the new y coordinate - */ - public void setLocation(double x, double y) - { - this.x = x; - this.y = y; - } - - /** - * Returns a string representation of this object. The format is: - * <code>"Point2D.Double[" + x + ", " + y + ']'</code>. - * - * @return a string representation of this object - */ - public String toString() - { - return "Point2D.Double[" + x + ", " + y + ']'; - } - } // class Double - - /** - * This class defines a point in <code>float</code> precision. - * - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @status updated to 1.4 - */ - public static class Float extends Point2D - { - /** The X coordinate. */ - public float x; - - /** The Y coordinate. */ - public float y; - - /** - * Create a new point at (0,0). - */ - public Float() - { - } - - /** - * Create a new point at (x,y). - * - * @param x the x coordinate - * @param y the y coordinate - */ - public Float(float x, float y) - { - this.x = x; - this.y = y; - } - - /** - * Return the x coordinate. - * - * @return the x coordinate - */ - public double getX() - { - return x; - } - - /** - * Return the y coordinate. - * - * @return the y coordinate - */ - public double getY() - { - return y; - } - - /** - * Sets the location of this point. - * - * @param x the new x coordinate - * @param y the new y coordinate - */ - public void setLocation(double x, double y) - { - this.x = (float) x; - this.y = (float) y; - } - - /** - * Sets the location of this point. - * - * @param x the new x coordinate - * @param y the new y coordinate - */ - public void setLocation(float x, float y) - { - this.x = x; - this.y = y; - } - - /** - * Returns a string representation of this object. The format is: - * <code>"Point2D.Float[" + x + ", " + y + ']'</code>. - * - * @return a string representation of this object - */ - public String toString() - { - return "Point2D.Float[" + x + ", " + y + ']'; - } - } // class Float -} // class Point2D diff --git a/libjava/classpath/java/awt/geom/QuadCurve2D.java b/libjava/classpath/java/awt/geom/QuadCurve2D.java deleted file mode 100644 index 62c829d..0000000 --- a/libjava/classpath/java/awt/geom/QuadCurve2D.java +++ /dev/null @@ -1,1467 +0,0 @@ -/* QuadCurve2D.java -- represents a parameterized quadratic curve in 2-D space - Copyright (C) 2002, 2003, 2004 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.awt.geom; - -import java.awt.Rectangle; -import java.awt.Shape; -import java.util.NoSuchElementException; - -/** - * A two-dimensional curve that is parameterized with a quadratic - * function. - * - * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180" - * alt="A drawing of a QuadCurve2D" /> - * - * @author Eric Blake (ebb9@email.byu.edu) - * @author Graydon Hoare (graydon@redhat.com) - * @author Sascha Brawer (brawer@dandelis.ch) - * @author Sven de Marothy (sven@physto.se) - * - * @since 1.2 - */ -public abstract class QuadCurve2D implements Shape, Cloneable -{ - private static final double BIG_VALUE = java.lang.Double.MAX_VALUE / 10.0; - private static final double EPSILON = 1E-10; - - /** - * Constructs a new QuadCurve2D. Typical users will want to - * construct instances of a subclass, such as {@link - * QuadCurve2D.Float} or {@link QuadCurve2D.Double}. - */ - protected QuadCurve2D() - { - } - - /** - * Returns the <i>x</i> coordinate of the curve’s start - * point. - */ - public abstract double getX1(); - - /** - * Returns the <i>y</i> coordinate of the curve’s start - * point. - */ - public abstract double getY1(); - - /** - * Returns the curve’s start point. - */ - public abstract Point2D getP1(); - - /** - * Returns the <i>x</i> coordinate of the curve’s control - * point. - */ - public abstract double getCtrlX(); - - /** - * Returns the <i>y</i> coordinate of the curve’s control - * point. - */ - public abstract double getCtrlY(); - - /** - * Returns the curve’s control point. - */ - public abstract Point2D getCtrlPt(); - - /** - * Returns the <i>x</i> coordinate of the curve’s end - * point. - */ - public abstract double getX2(); - - /** - * Returns the <i>y</i> coordinate of the curve’s end - * point. - */ - public abstract double getY2(); - - /** - * Returns the curve’s end point. - */ - public abstract Point2D getP2(); - - /** - * Changes the curve geometry, separately specifying each coordinate - * value. - * - * @param x1 the <i>x</i> coordinate of the curve’s new start - * point. - * - * @param y1 the <i>y</i> coordinate of the curve’s new start - * point. - * - * @param cx the <i>x</i> coordinate of the curve’s new - * control point. - * - * @param cy the <i>y</i> coordinate of the curve’s new - * control point. - * - * @param x2 the <i>x</i> coordinate of the curve’s new end - * point. - * - * @param y2 the <i>y</i> coordinate of the curve’s new end - * point. - */ - public abstract void setCurve(double x1, double y1, double cx, double cy, - double x2, double y2); - - /** - * Changes the curve geometry, passing coordinate values in an - * array. - * - * @param coords an array containing the new coordinate values. The - * <i>x</i> coordinate of the new start point is located at - * <code>coords[offset]</code>, its <i>y</i> coordinate at - * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the - * new control point is located at <code>coords[offset + 2]</code>, - * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The - * <i>x</i> coordinate of the new end point is located at - * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at - * <code>coords[offset + 5]</code>. - * - * @param offset the offset of the first coordinate value in - * <code>coords</code>. - */ - public void setCurve(double[] coords, int offset) - { - setCurve(coords[offset++], coords[offset++], coords[offset++], - coords[offset++], coords[offset++], coords[offset++]); - } - - /** - * Changes the curve geometry, specifying coordinate values in - * separate Point objects. - * - * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180" - * alt="A drawing of a QuadCurve2D" /> - * - * <p>The curve does not keep any reference to the passed point - * objects. Therefore, a later change to <code>p1</code>, - * <code>c</code> <code>p2</code> will not affect the curve - * geometry. - * - * @param p1 the new start point. - * @param c the new control point. - * @param p2 the new end point. - */ - public void setCurve(Point2D p1, Point2D c, Point2D p2) - { - setCurve(p1.getX(), p1.getY(), c.getX(), c.getY(), p2.getX(), p2.getY()); - } - - /** - * Changes the curve geometry, specifying coordinate values in an - * array of Point objects. - * - * <p><img src="doc-files/QuadCurve2D-1.png" width="350" height="180" - * alt="A drawing of a QuadCurve2D" /> - * - * <p>The curve does not keep references to the passed point - * objects. Therefore, a later change to the <code>pts</code> array - * or any of its elements will not affect the curve geometry. - * - * @param pts an array containing the points. The new start point - * is located at <code>pts[offset]</code>, the new control - * point at <code>pts[offset + 1]</code>, and the new end point - * at <code>pts[offset + 2]</code>. - * - * @param offset the offset of the start point in <code>pts</code>. - */ - public void setCurve(Point2D[] pts, int offset) - { - setCurve(pts[offset].getX(), pts[offset].getY(), pts[offset + 1].getX(), - pts[offset + 1].getY(), pts[offset + 2].getX(), - pts[offset + 2].getY()); - } - - /** - * Changes the geometry of the curve to that of another curve. - * - * @param c the curve whose coordinates will be copied. - */ - public void setCurve(QuadCurve2D c) - { - setCurve(c.getX1(), c.getY1(), c.getCtrlX(), c.getCtrlY(), c.getX2(), - c.getY2()); - } - - /** - * Calculates the squared flatness of a quadratic curve, directly - * specifying each coordinate value. The flatness is the distance of - * the control point to the line between start and end point. - * - * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. The result will be the - * the square of the distance between C and the gray line, i.e. - * the squared length of the red line. - * - * @param x1 the <i>x</i> coordinate of the start point P1. - * @param y1 the <i>y</i> coordinate of the start point P1. - * @param cx the <i>x</i> coordinate of the control point C. - * @param cy the <i>y</i> coordinate of the control point C. - * @param x2 the <i>x</i> coordinate of the end point P2. - * @param y2 the <i>y</i> coordinate of the end point P2. - */ - public static double getFlatnessSq(double x1, double y1, double cx, - double cy, double x2, double y2) - { - return Line2D.ptSegDistSq(x1, y1, x2, y2, cx, cy); - } - - /** - * Calculates the flatness of a quadratic curve, directly specifying - * each coordinate value. The flatness is the distance of the - * control point to the line between start and end point. - * - * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. The result will be the - * the distance between C and the gray line, i.e. the length of - * the red line. - * - * @param x1 the <i>x</i> coordinate of the start point P1. - * @param y1 the <i>y</i> coordinate of the start point P1. - * @param cx the <i>x</i> coordinate of the control point C. - * @param cy the <i>y</i> coordinate of the control point C. - * @param x2 the <i>x</i> coordinate of the end point P2. - * @param y2 the <i>y</i> coordinate of the end point P2. - */ - public static double getFlatness(double x1, double y1, double cx, double cy, - double x2, double y2) - { - return Line2D.ptSegDist(x1, y1, x2, y2, cx, cy); - } - - /** - * Calculates the squared flatness of a quadratic curve, specifying - * the coordinate values in an array. The flatness is the distance - * of the control point to the line between start and end point. - * - * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. The result will be the - * the square of the distance between C and the gray line, i.e. - * the squared length of the red line. - * - * @param coords an array containing the coordinate values. The - * <i>x</i> coordinate of the start point P1 is located at - * <code>coords[offset]</code>, its <i>y</i> coordinate at - * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the - * control point C is located at <code>coords[offset + 2]</code>, - * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The - * <i>x</i> coordinate of the end point P2 is located at - * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at - * <code>coords[offset + 5]</code>. - * - * @param offset the offset of the first coordinate value in - * <code>coords</code>. - */ - public static double getFlatnessSq(double[] coords, int offset) - { - return Line2D.ptSegDistSq(coords[offset], coords[offset + 1], - coords[offset + 4], coords[offset + 5], - coords[offset + 2], coords[offset + 3]); - } - - /** - * Calculates the flatness of a quadratic curve, specifying the - * coordinate values in an array. The flatness is the distance of - * the control point to the line between start and end point. - * - * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. The result will be the - * the the distance between C and the gray line, i.e. the length of - * the red line. - * - * @param coords an array containing the coordinate values. The - * <i>x</i> coordinate of the start point P1 is located at - * <code>coords[offset]</code>, its <i>y</i> coordinate at - * <code>coords[offset + 1]</code>. The <i>x</i> coordinate of the - * control point C is located at <code>coords[offset + 2]</code>, - * its <i>y</i> coordinate at <code>coords[offset + 3]</code>. The - * <i>x</i> coordinate of the end point P2 is located at - * <code>coords[offset + 4]</code>, its <i>y</i> coordinate at - * <code>coords[offset + 5]</code>. - * - * @param offset the offset of the first coordinate value in - * <code>coords</code>. - */ - public static double getFlatness(double[] coords, int offset) - { - return Line2D.ptSegDist(coords[offset], coords[offset + 1], - coords[offset + 4], coords[offset + 5], - coords[offset + 2], coords[offset + 3]); - } - - /** - * Calculates the squared flatness of this curve. The flatness is - * the distance of the control point to the line between start and - * end point. - * - * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. The result will be the - * the square of the distance between C and the gray line, i.e. the - * squared length of the red line. - */ - public double getFlatnessSq() - { - return Line2D.ptSegDistSq(getX1(), getY1(), getX2(), getY2(), getCtrlX(), - getCtrlY()); - } - - /** - * Calculates the flatness of this curve. The flatness is the - * distance of the control point to the line between start and end - * point. - * - * <p><img src="doc-files/QuadCurve2D-4.png" width="350" height="180" - * alt="A drawing that illustrates the flatness" /> - * - * <p>In the above drawing, the straight line connecting start point - * P1 and end point P2 is depicted in gray. The result will be the - * the distance between C and the gray line, i.e. the length of the - * red line. - */ - public double getFlatness() - { - return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(), getCtrlX(), - getCtrlY()); - } - - /** - * Subdivides this curve into two halves. - * - * <p><img src="doc-files/QuadCurve2D-3.png" width="700" - * height="180" alt="A drawing that illustrates the effects of - * subdividing a QuadCurve2D" /> - * - * @param left a curve whose geometry will be set to the left half - * of this curve, or <code>null</code> if the caller is not - * interested in the left half. - * - * @param right a curve whose geometry will be set to the right half - * of this curve, or <code>null</code> if the caller is not - * interested in the right half. - */ - public void subdivide(QuadCurve2D left, QuadCurve2D right) - { - // Use empty slots at end to share single array. - double[] d = new double[] - { - getX1(), getY1(), getCtrlX(), getCtrlY(), getX2(), getY2(), - 0, 0, 0, 0 - }; - subdivide(d, 0, d, 0, d, 4); - if (left != null) - left.setCurve(d, 0); - if (right != null) - right.setCurve(d, 4); - } - - /** - * Subdivides a quadratic curve into two halves. - * - * <p><img src="doc-files/QuadCurve2D-3.png" width="700" - * height="180" alt="A drawing that illustrates the effects of - * subdividing a QuadCurve2D" /> - * - * @param src the curve to be subdivided. - * - * @param left a curve whose geometry will be set to the left half - * of <code>src</code>, or <code>null</code> if the caller is not - * interested in the left half. - * - * @param right a curve whose geometry will be set to the right half - * of <code>src</code>, or <code>null</code> if the caller is not - * interested in the right half. - */ - public static void subdivide(QuadCurve2D src, QuadCurve2D left, - QuadCurve2D right) - { - src.subdivide(left, right); - } - - /** - * Subdivides a quadratic curve into two halves, passing all - * coordinates in an array. - * - * <p><img src="doc-files/QuadCurve2D-3.png" width="700" - * height="180" alt="A drawing that illustrates the effects of - * subdividing a QuadCurve2D" /> - * - * <p>The left end point and the right start point will always be - * identical. Memory-concious programmers thus may want to pass the - * same array for both <code>left</code> and <code>right</code>, and - * set <code>rightOff</code> to <code>leftOff + 4</code>. - * - * @param src an array containing the coordinates of the curve to be - * subdivided. The <i>x</i> coordinate of the start point is - * located at <code>src[srcOff]</code>, its <i>y</i> at - * <code>src[srcOff + 1]</code>. The <i>x</i> coordinate of the - * control point is located at <code>src[srcOff + 2]</code>, its - * <i>y</i> at <code>src[srcOff + 3]</code>. The <i>x</i> - * coordinate of the end point is located at <code>src[srcOff + - * 4]</code>, its <i>y</i> at <code>src[srcOff + 5]</code>. - * - * @param srcOff an offset into <code>src</code>, specifying - * the index of the start point’s <i>x</i> coordinate. - * - * @param left an array that will receive the coordinates of the - * left half of <code>src</code>. It is acceptable to pass - * <code>src</code>. A caller who is not interested in the left half - * can pass <code>null</code>. - * - * @param leftOff an offset into <code>left</code>, specifying the - * index where the start point’s <i>x</i> coordinate will be - * stored. - * - * @param right an array that will receive the coordinates of the - * right half of <code>src</code>. It is acceptable to pass - * <code>src</code> or <code>left</code>. A caller who is not - * interested in the right half can pass <code>null</code>. - * - * @param rightOff an offset into <code>right</code>, specifying the - * index where the start point’s <i>x</i> coordinate will be - * stored. - */ - public static void subdivide(double[] src, int srcOff, double[] left, - int leftOff, double[] right, int rightOff) - { - double x1; - double y1; - double xc; - double yc; - double x2; - double y2; - - x1 = src[srcOff]; - y1 = src[srcOff + 1]; - xc = src[srcOff + 2]; - yc = src[srcOff + 3]; - x2 = src[srcOff + 4]; - y2 = src[srcOff + 5]; - - if (left != null) - { - left[leftOff] = x1; - left[leftOff + 1] = y1; - } - - if (right != null) - { - right[rightOff + 4] = x2; - right[rightOff + 5] = y2; - } - - x1 = (x1 + xc) / 2; - x2 = (xc + x2) / 2; - xc = (x1 + x2) / 2; - y1 = (y1 + yc) / 2; - y2 = (y2 + yc) / 2; - yc = (y1 + y2) / 2; - - if (left != null) - { - left[leftOff + 2] = x1; - left[leftOff + 3] = y1; - left[leftOff + 4] = xc; - left[leftOff + 5] = yc; - } - - if (right != null) - { - right[rightOff] = xc; - right[rightOff + 1] = yc; - right[rightOff + 2] = x2; - right[rightOff + 3] = y2; - } - } - - /** - * Finds the non-complex roots of a quadratic equation, placing the - * results into the same array as the equation coefficients. The - * following equation is being solved: - * - * <blockquote><code>eqn[2]</code> · <i>x</i><sup>2</sup> - * + <code>eqn[1]</code> · <i>x</i> - * + <code>eqn[0]</code> - * = 0 - * </blockquote> - * - * <p>For some background about solving quadratic equations, see the - * article <a href= - * "http://planetmath.org/encyclopedia/QuadraticFormula.html" - * >“Quadratic Formula”</a> in <a href= - * "http://planetmath.org/">PlanetMath</a>. For an extensive library - * of numerical algorithms written in the C programming language, - * see the <a href="http://www.gnu.org/software/gsl/">GNU Scientific - * Library</a>. - * - * @see #solveQuadratic(double[], double[]) - * @see CubicCurve2D#solveCubic(double[], double[]) - * - * @param eqn an array with the coefficients of the equation. When - * this procedure has returned, <code>eqn</code> will contain the - * non-complex solutions of the equation, in no particular order. - * - * @return the number of non-complex solutions. A result of 0 - * indicates that the equation has no non-complex solutions. A - * result of -1 indicates that the equation is constant (i.e., - * always or never zero). - * - * @author Brian Gough (bjg@network-theory.com) - * (original C implementation in the <a href= - * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>) - * - * @author Sascha Brawer (brawer@dandelis.ch) - * (adaptation to Java) - */ - public static int solveQuadratic(double[] eqn) - { - return solveQuadratic(eqn, eqn); - } - - /** - * Finds the non-complex roots of a quadratic equation. The - * following equation is being solved: - * - * <blockquote><code>eqn[2]</code> · <i>x</i><sup>2</sup> - * + <code>eqn[1]</code> · <i>x</i> - * + <code>eqn[0]</code> - * = 0 - * </blockquote> - * - * <p>For some background about solving quadratic equations, see the - * article <a href= - * "http://planetmath.org/encyclopedia/QuadraticFormula.html" - * >“Quadratic Formula”</a> in <a href= - * "http://planetmath.org/">PlanetMath</a>. For an extensive library - * of numerical algorithms written in the C programming language, - * see the <a href="http://www.gnu.org/software/gsl/">GNU Scientific - * Library</a>. - * - * @see CubicCurve2D#solveCubic(double[],double[]) - * - * @param eqn an array with the coefficients of the equation. - * - * @param res an array into which the non-complex roots will be - * stored. The results may be in an arbitrary order. It is safe to - * pass the same array object reference for both <code>eqn</code> - * and <code>res</code>. - * - * @return the number of non-complex solutions. A result of 0 - * indicates that the equation has no non-complex solutions. A - * result of -1 indicates that the equation is constant (i.e., - * always or never zero). - * - * @author Brian Gough (bjg@network-theory.com) - * (original C implementation in the <a href= - * "http://www.gnu.org/software/gsl/">GNU Scientific Library</a>) - * - * @author Sascha Brawer (brawer@dandelis.ch) - * (adaptation to Java) - */ - public static int solveQuadratic(double[] eqn, double[] res) - { - // Taken from poly/solve_quadratic.c in the GNU Scientific Library - // (GSL), cvs revision 1.7 of 2003-07-26. For the original source, - // see http://www.gnu.org/software/gsl/ - // - // Brian Gough, the author of that code, has granted the - // permission to use it in GNU Classpath under the GNU Classpath - // license, and has assigned the copyright to the Free Software - // Foundation. - // - // The Java implementation is very similar to the GSL code, but - // not a strict one-to-one copy. For example, GSL would sort the - // result. - double a; - double b; - double c; - double disc; - - c = eqn[0]; - b = eqn[1]; - a = eqn[2]; - - // Check for linear or constant functions. This is not done by the - // GNU Scientific Library. Without this special check, we - // wouldn't return -1 for constant functions, and 2 instead of 1 - // for linear functions. - if (a == 0) - { - if (b == 0) - return -1; - - res[0] = -c / b; - return 1; - } - - disc = b * b - 4 * a * c; - - if (disc < 0) - return 0; - - if (disc == 0) - { - // The GNU Scientific Library returns two identical results here. - // We just return one. - res[0] = -0.5 * b / a; - return 1; - } - - // disc > 0 - if (b == 0) - { - double r; - - r = Math.abs(0.5 * Math.sqrt(disc) / a); - res[0] = -r; - res[1] = r; - } - else - { - double sgnb; - double temp; - - sgnb = (b > 0 ? 1 : -1); - temp = -0.5 * (b + sgnb * Math.sqrt(disc)); - - // The GNU Scientific Library sorts the result here. We don't. - res[0] = temp / a; - res[1] = c / temp; - } - return 2; - } - - /** - * Determines whether a point is inside the area bounded - * by the curve and the straight line connecting its end points. - * - * <p><img src="doc-files/QuadCurve2D-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 QuadCurve2D. - */ - public boolean contains(double x, double y) - { - if (! getBounds2D().contains(x, y)) - return false; - - return ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0); - } - - /** - * Determines whether a point is inside the area bounded - * by the curve and the straight line connecting its end points. - * - * <p><img src="doc-files/QuadCurve2D-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 QuadCurve2D. - */ - public boolean contains(Point2D p) - { - return contains(p.getX(), p.getY()); - } - - /** - * Determines whether any part of a rectangle is inside the area bounded - * by the curve and the straight line connecting its end points. - * - * <p><img src="doc-files/QuadCurve2D-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” in a CubicCurve2D. - */ - public boolean intersects(double x, double y, double w, double h) - { - if (! getBounds2D().contains(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 true; - - /* No intersections, is any point inside? */ - if ((getAxisIntersections(x, y, true, BIG_VALUE) & 1) != 0) - return true; - - return false; - } - - /** - * 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()); - } - - /** - * Determines whether a rectangle is entirely inside the area bounded - * by the curve and the straight line connecting its end points. - * - * <p><img src="doc-files/QuadCurve2D-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 QuadCurve2D. - * @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; - } - - /** - * Determines whether a Rectangle2D is entirely inside the area that is - * bounded by the curve and the straight line connecting its end points. - * @see #contains(double, double, 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 point. As the illustration - * below shows, the invisible control point may cause the bounds to - * be much larger than the area that is actually covered by the - * curve. - * - * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180" - * alt="An illustration of the bounds of a QuadCurve2D" /> - */ - 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) getCtrlX(); - coords[1] = (float) getCtrlY(); - coords[2] = (float) getX2(); - coords[3] = (float) getY2(); - result = SEG_QUADTO; - break; - default: - throw new NoSuchElementException("quad iterator out of bounds"); - } - if (at != null) - at.transform(coords, 0, coords, 0, 2); - 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] = getCtrlX(); - coords[1] = getCtrlY(); - coords[2] = getX2(); - coords[3] = getY2(); - result = SEG_QUADTO; - break; - default: - throw new NoSuchElementException("quad iterator out of bounds"); - } - if (at != null) - at.transform(coords, 0, coords, 0, 2); - return result; - } - }; - } - - public PathIterator getPathIterator(AffineTransform at, double flatness) - { - return new FlatteningPathIterator(getPathIterator(at), flatness); - } - - /** - * Creates 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 - * Return the number of curve/line intersections on a given axis - * extending from a certain point. useYaxis is true for using the Y axis, - * @param x x coordinate of the origin point - * @param y y coordinate of the origin point - * @param useYaxis axis to follow, 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/ - */ - private int getAxisIntersections(double x, double y, boolean useYaxis, - double distance) - { - int nCrossings = 0; - double a0; - double a1; - double a2; - double b0; - double b1; - double b2; - double[] r = new double[3]; - int nRoots; - - a0 = a2 = 0.0; - - if (useYaxis) - { - a0 = getY1() - y; - a1 = getCtrlY() - y; - a2 = getY2() - y; - b0 = getX1() - x; - b1 = getCtrlX() - x; - b2 = getX2() - x; - } - else - { - a0 = getX1() - x; - a1 = getCtrlX() - x; - a2 = getX2() - x; - b0 = getY1() - y; - b1 = getCtrlY() - y; - b2 = 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 || a2 == 0.0) - { - double small = getFlatness() * EPSILON; - if (a0 == 0.0) - a0 -= small; - - if (a2 == 0.0) - a2 -= small; - } - - r[0] = a0; - r[1] = 2 * (a1 - a0); - r[2] = (a2 - 2 * a1 + a0); - - nRoots = solveQuadratic(r); - for (int i = 0; i < nRoots; i++) - { - double t = r[i]; - if (t >= 0.0 && t <= 1.0) - { - double crossing = t * t * (b2 - 2 * b1 + b0) + 2 * t * (b1 - b0) - + b0; - /* single root is always doubly degenerate in quads */ - if (crossing > 0 && crossing < distance) - nCrossings += (nRoots == 1) ? 2 : 1; - } - } - - if (useYaxis) - { - if (Line2D.linesIntersect(b0, a0, b2, a2, EPSILON, 0.0, distance, 0.0)) - nCrossings++; - } - else - { - if (Line2D.linesIntersect(a0, b0, a2, b2, 0.0, EPSILON, 0.0, distance)) - nCrossings++; - } - - return (nCrossings); - } - - /** - * A two-dimensional curve that is parameterized with a quadratic - * function and stores coordinate values in double-precision - * floating-point format. - * - * @see QuadCurve2D.Float - * - * @author Eric Blake (ebb9@email.byu.edu) - * @author Sascha Brawer (brawer@dandelis.ch) - */ - public static class Double extends QuadCurve2D - { - /** - * 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 control point. - */ - public double ctrlx; - - /** - * The <i>y</i> coordinate of the curve’s control point. - */ - public double ctrly; - - /** - * 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 QuadCurve2D that stores its coordinate values - * in double-precision floating-point format. All points are - * initially at position (0, 0). - */ - public Double() - { - } - - /** - * Constructs a new QuadCurve2D that stores its coordinate values - * in double-precision floating-point format, specifying the - * initial position of each point. - * - * @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 cx the <i>x</i> coordinate of the curve’s control - * point. - * - * @param cy the <i>y</i> coordinate of the curve’s 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 cx, double cy, double x2, - double y2) - { - this.x1 = x1; - this.y1 = y1; - ctrlx = cx; - ctrly = cy; - 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 control - * point. - */ - public double getCtrlX() - { - return ctrlx; - } - - /** - * Returns the <i>y</i> coordinate of the curve’s control - * point. - */ - public double getCtrlY() - { - return ctrly; - } - - /** - * Returns the curve’s control point. - */ - public Point2D getCtrlPt() - { - return new Point2D.Double(ctrlx, ctrly); - } - - /** - * Returns the <i>x</i> coordinate of the curve’s end - * point. - */ - public double getX2() - { - return x2; - } - - /** - * Returns the <i>y</i> coordinate of the curve’s end - * point. - */ - public double getY2() - { - return y2; - } - - /** - * Returns the curve’s end point. - */ - public Point2D getP2() - { - return new Point2D.Double(x2, y2); - } - - /** - * Changes the geometry of the curve. - * - * @param x1 the <i>x</i> coordinate of the curve’s new - * start point. - * - * @param y1 the <i>y</i> coordinate of the curve’s new - * start point. - * - * @param cx the <i>x</i> coordinate of the curve’s new - * control point. - * - * @param cy the <i>y</i> coordinate of the curve’s new - * control point. - * - * @param x2 the <i>x</i> coordinate of the curve’s new - * end point. - * - * @param y2 the <i>y</i> coordinate of the curve’s new - * end point. - */ - public void setCurve(double x1, double y1, double cx, double cy, - double x2, double y2) - { - this.x1 = x1; - this.y1 = y1; - ctrlx = cx; - ctrly = cy; - this.x2 = x2; - this.y2 = y2; - } - - /** - * Determines the smallest rectangle that encloses the - * curve’s start, end and control point. As the - * illustration below shows, the invisible control point may cause - * the bounds to be much larger than the area that is actually - * covered by the curve. - * - * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180" - * alt="An illustration of the bounds of a QuadCurve2D" /> - */ - public Rectangle2D getBounds2D() - { - double nx1 = Math.min(Math.min(x1, ctrlx), x2); - double ny1 = Math.min(Math.min(y1, ctrly), y2); - double nx2 = Math.max(Math.max(x1, ctrlx), x2); - double ny2 = Math.max(Math.max(y1, ctrly), y2); - return new Rectangle2D.Double(nx1, ny1, nx2 - nx1, ny2 - ny1); - } - } - - /** - * A two-dimensional curve that is parameterized with a quadratic - * function and stores coordinate values in single-precision - * floating-point format. - * - * @see QuadCurve2D.Double - * - * @author Eric Blake (ebb9@email.byu.edu) - * @author Sascha Brawer (brawer@dandelis.ch) - */ - public static class Float extends QuadCurve2D - { - /** - * The <i>x</i> coordinate of the curve’s start point. - */ - public float x1; - - /** - * The <i>y</i> coordinate of the curve’s start point. - */ - public float y1; - - /** - * The <i>x</i> coordinate of the curve’s control point. - */ - public float ctrlx; - - /** - * The <i>y</i> coordinate of the curve’s control point. - */ - public float ctrly; - - /** - * The <i>x</i> coordinate of the curve’s end point. - */ - public float x2; - - /** - * The <i>y</i> coordinate of the curve’s end point. - */ - public float y2; - - /** - * Constructs a new QuadCurve2D that stores its coordinate values - * in single-precision floating-point format. All points are - * initially at position (0, 0). - */ - public Float() - { - } - - /** - * Constructs a new QuadCurve2D that stores its coordinate values - * in single-precision floating-point format, specifying the - * initial position of each point. - * - * @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 cx the <i>x</i> coordinate of the curve’s control - * point. - * - * @param cy the <i>y</i> coordinate of the curve’s 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 Float(float x1, float y1, float cx, float cy, float x2, float y2) - { - this.x1 = x1; - this.y1 = y1; - ctrlx = cx; - ctrly = cy; - 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.Float(x1, y1); - } - - /** - * Returns the <i>x</i> coordinate of the curve’s control - * point. - */ - public double getCtrlX() - { - return ctrlx; - } - - /** - * Returns the <i>y</i> coordinate of the curve’s control - * point. - */ - public double getCtrlY() - { - return ctrly; - } - - /** - * Returns the curve’s control point. - */ - public Point2D getCtrlPt() - { - return new Point2D.Float(ctrlx, ctrly); - } - - /** - * Returns the <i>x</i> coordinate of the curve’s end - * point. - */ - public double getX2() - { - return x2; - } - - /** - * Returns the <i>y</i> coordinate of the curve’s end - * point. - */ - public double getY2() - { - return y2; - } - - /** - * Returns the curve’s end point. - */ - public Point2D getP2() - { - return new Point2D.Float(x2, y2); - } - - /** - * Changes the geometry of the curve, specifying coordinate values - * as double-precision floating-point numbers. - * - * @param x1 the <i>x</i> coordinate of the curve’s new - * start point. - * - * @param y1 the <i>y</i> coordinate of the curve’s new - * start point. - * - * @param cx the <i>x</i> coordinate of the curve’s new - * control point. - * - * @param cy the <i>y</i> coordinate of the curve’s new - * control point. - * - * @param x2 the <i>x</i> coordinate of the curve’s new - * end point. - * - * @param y2 the <i>y</i> coordinate of the curve’s new - * end point. - */ - public void setCurve(double x1, double y1, double cx, double cy, - double x2, double y2) - { - this.x1 = (float) x1; - this.y1 = (float) y1; - ctrlx = (float) cx; - ctrly = (float) cy; - this.x2 = (float) x2; - this.y2 = (float) y2; - } - - /** - * Changes the geometry of the curve, specifying coordinate values - * as single-precision floating-point numbers. - * - * @param x1 the <i>x</i> coordinate of the curve’s new - * start point. - * - * @param y1 the <i>y</i> coordinate of the curve’s new - * start point. - * - * @param cx the <i>x</i> coordinate of the curve’s new - * control point. - * - * @param cy the <i>y</i> coordinate of the curve’s new - * control point. - * - * @param x2 the <i>x</i> coordinate of the curve’s new - * end point. - * - * @param y2 the <i>y</i> coordinate of the curve’s new - * end point. - */ - public void setCurve(float x1, float y1, float cx, float cy, float x2, - float y2) - { - this.x1 = x1; - this.y1 = y1; - ctrlx = cx; - ctrly = cy; - this.x2 = x2; - this.y2 = y2; - } - - /** - * Determines the smallest rectangle that encloses the - * curve’s start, end and control point. As the - * illustration below shows, the invisible control point may cause - * the bounds to be much larger than the area that is actually - * covered by the curve. - * - * <p><img src="doc-files/QuadCurve2D-2.png" width="350" height="180" - * alt="An illustration of the bounds of a QuadCurve2D" /> - */ - public Rectangle2D getBounds2D() - { - float nx1 = Math.min(Math.min(x1, ctrlx), x2); - float ny1 = Math.min(Math.min(y1, ctrly), y2); - float nx2 = Math.max(Math.max(x1, ctrlx), x2); - float ny2 = Math.max(Math.max(y1, ctrly), y2); - return new Rectangle2D.Float(nx1, ny1, nx2 - nx1, ny2 - ny1); - } - } -} diff --git a/libjava/classpath/java/awt/geom/Rectangle2D.java b/libjava/classpath/java/awt/geom/Rectangle2D.java deleted file mode 100644 index 6a255f9..0000000 --- a/libjava/classpath/java/awt/geom/Rectangle2D.java +++ /dev/null @@ -1,992 +0,0 @@ -/* Rectangle2D.java -- generic rectangles in 2-D space - Copyright (C) 2000, 2001, 2002, 2004 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.awt.geom; - -import java.util.NoSuchElementException; - -/** - * This class describes a rectangle by a point (x,y) and dimension (w x h). - * The actual storage is left up to subclasses. - * - * <p>It is valid for a rectangle to have negative width or height; but it - * is considered to have no area or internal points. Therefore, the behavior - * in methods like <code>contains</code> or <code>intersects</code> is - * undefined unless the rectangle has positive width and height. - * - * @author Tom Tromey (tromey@cygnus.com) - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @status updated to 1.4 - */ -public abstract class Rectangle2D extends RectangularShape -{ - /** - * The point lies left of the rectangle (p.x < r.x). - * - * @see #outcode(double, double) - */ - public static final int OUT_LEFT = 1; - - /** - * The point lies above the rectangle (p.y < r.y). - * - * @see #outcode(double, double) - */ - public static final int OUT_TOP = 2; - - /** - * The point lies right of the rectangle (p.x > r.maxX). - * - * @see #outcode(double, double) - */ - public static final int OUT_RIGHT = 4; - - /** - * The point lies below of the rectangle (p.y > r.maxY). - * - * @see #outcode(double, double) - */ - public static final int OUT_BOTTOM = 8; - - /** - * Default constructor. - */ - protected Rectangle2D() - { - } - - /** - * Set the bounding box of this rectangle. - * - * @param x the new X coordinate - * @param y the new Y coordinate - * @param w the new width - * @param h the new height - */ - public abstract void setRect(double x, double y, double w, double h); - - /** - * Set the bounding box of this rectangle from the given one. - * - * @param r rectangle to copy - * @throws NullPointerException if r is null - */ - public void setRect(Rectangle2D r) - { - setRect(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - /** - * Tests if the specified line intersects the interior of this rectangle. - * - * @param x1 the first x coordinate of line segment - * @param y1 the first y coordinate of line segment - * @param x2 the second x coordinate of line segment - * @param y2 the second y coordinate of line segment - * @return true if the line intersects the rectangle - */ - public boolean intersectsLine(double x1, double y1, double x2, double y2) - { - double x = getX(); - double y = getY(); - double w = getWidth(); - double h = getHeight(); - if (w <= 0 || h <= 0) - return false; - - if (x1 >= x && x1 <= x + w && y1 >= y && y1 <= y + h) - return true; - if (x2 >= x && x2 <= x + w && y2 >= y && y2 <= y + h) - return true; - - double x3 = x + w; - double y3 = y + h; - - return (Line2D.linesIntersect(x1, y1, x2, y2, x, y, x, y3) - || Line2D.linesIntersect(x1, y1, x2, y2, x, y3, x3, y3) - || Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x3, y) - || Line2D.linesIntersect(x1, y1, x2, y2, x3, y, x, y)); - } - - /** - * Tests if the specified line intersects the interior of this rectangle. - * - * @param l the line segment - * @return true if the line intersects the rectangle - * @throws NullPointerException if l is null - */ - public boolean intersectsLine(Line2D l) - { - return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2()); - } - - /** - * Determine where the point lies with respect to this rectangle. The - * result will be the binary OR of the appropriate bit masks. - * - * @param x the x coordinate to check - * @param y the y coordinate to check - * @return the binary OR of the result - * @see #OUT_LEFT - * @see #OUT_TOP - * @see #OUT_RIGHT - * @see #OUT_BOTTOM - */ - public abstract int outcode(double x, double y); - - /** - * Determine where the point lies with respect to this rectangle. The - * result will be the binary OR of the appropriate bit masks. - * - * @param p the point to check - * @return the binary OR of the result - * @throws NullPointerException if p is null - * @see #OUT_LEFT - * @see #OUT_TOP - * @see #OUT_RIGHT - * @see #OUT_BOTTOM - */ - public int outcode(Point2D p) - { - return outcode(p.getX(), p.getY()); - } - - /** - * Set the bounding box of this rectangle. - * - * @param x the new X coordinate - * @param y the new Y coordinate - * @param w the new width - * @param h the new height - */ - public void setFrame(double x, double y, double w, double h) - { - setRect(x, y, w, h); - } - - /** - * Returns the bounds of this rectangle. A pretty useless method, as this - * is already a rectangle. - * - * @return a copy of this rectangle - */ - public Rectangle2D getBounds2D() - { - return (Rectangle2D) clone(); - } - - /** - * Test if the given point is contained in the rectangle. - * - * @param x the x coordinate of the point - * @param y the y coordinate of the point - * @return true if (x,y) is in the rectangle - */ - public boolean contains(double x, double y) - { - double mx = getX(); - double my = getY(); - double w = getWidth(); - double h = getHeight(); - return w > 0 && h > 0 && x >= mx && x < mx + w && y >= my && y < my + h; - } - - /** - * Tests if the given rectangle intersects this one. In other words, test if - * the two rectangles share at least one internal point. - * - * @param x the x coordinate of the other rectangle - * @param y the y coordinate of the other rectangle - * @param w the width of the other rectangle - * @param h the height of the other rectangle - * @return true if the rectangles intersect - */ - public boolean intersects(double x, double y, double w, double h) - { - double mx = getX(); - double my = getY(); - double mw = getWidth(); - double mh = getHeight(); - return w > 0 && h > 0 && mw > 0 && mh > 0 - && x < mx + mw && x + w > mx && y < my + mh && y + h > my; - } - - /** - * Tests if this rectangle contains the given one. In other words, test if - * this rectangle contains all points in the given one. - * - * @param x the x coordinate of the other rectangle - * @param y the y coordinate of the other rectangle - * @param w the width of the other rectangle - * @param h the height of the other rectangle - * @return true if this rectangle contains the other - */ - public boolean contains(double x, double y, double w, double h) - { - double mx = getX(); - double my = getY(); - double mw = getWidth(); - double mh = getHeight(); - return w > 0 && h > 0 && mw > 0 && mh > 0 - && x >= mx && x + w <= mx + mw && y >= my && y + h <= my + mh; - } - - /** - * Return a new rectangle which is the intersection of this and the given - * one. The result will be empty if there is no intersection. - * - * @param r the rectangle to be intersected - * @return the intersection - * @throws NullPointerException if r is null - */ - public abstract Rectangle2D createIntersection(Rectangle2D r); - - /** - * Intersects a pair of rectangles, and places the result in the - * destination; this can be used to avoid object creation. This method - * even works when the destination is also a source, although you stand - * to lose the original data. - * - * @param src1 the first source - * @param src2 the second source - * @param dest the destination for the intersection - * @throws NullPointerException if any rectangle is null - */ - public static void intersect(Rectangle2D src1, Rectangle2D src2, - Rectangle2D dest) - { - double x = Math.max(src1.getX(), src2.getX()); - double y = Math.max(src1.getY(), src2.getY()); - double maxx = Math.min(src1.getMaxX(), src2.getMaxX()); - double maxy = Math.min(src1.getMaxY(), src2.getMaxY()); - dest.setRect(x, y, maxx - x, maxy - y); - } - - /** - * Return a new rectangle which is the union of this and the given one. - * - * @param r the rectangle to be merged - * @return the union - * @throws NullPointerException if r is null - */ - public abstract Rectangle2D createUnion(Rectangle2D r); - - /** - * Joins a pair of rectangles, and places the result in the destination; - * this can be used to avoid object creation. This method even works when - * the destination is also a source, although you stand to lose the - * original data. - * - * @param src1 the first source - * @param src2 the second source - * @param dest the destination for the union - * @throws NullPointerException if any rectangle is null - */ - public static void union(Rectangle2D src1, Rectangle2D src2, - Rectangle2D dest) - { - double x = Math.min(src1.getX(), src2.getX()); - double y = Math.min(src1.getY(), src2.getY()); - double maxx = Math.max(src1.getMaxX(), src2.getMaxX()); - double maxy = Math.max(src1.getMaxY(), src2.getMaxY()); - dest.setRect(x, y, maxx - x, maxy - y); - } - - /** - * Modifies this rectangle so that it represents the smallest rectangle - * that contains both the existing rectangle and the specified point. - * However, if the point falls on one of the two borders which are not - * inside the rectangle, a subsequent call to <code>contains</code> may - * return false. - * - * @param newx the X coordinate of the point to add to this rectangle - * @param newy the Y coordinate of the point to add to this rectangle - */ - public void add(double newx, double newy) - { - double minx = Math.min(getX(), newx); - double maxx = Math.max(getMaxX(), newx); - double miny = Math.min(getY(), newy); - double maxy = Math.max(getMaxY(), newy); - setRect(minx, miny, maxx - minx, maxy - miny); - } - - /** - * Modifies this rectangle so that it represents the smallest rectangle - * that contains both the existing rectangle and the specified point. - * However, if the point falls on one of the two borders which are not - * inside the rectangle, a subsequent call to <code>contains</code> may - * return false. - * - * @param p the point to add to this rectangle - * @throws NullPointerException if p is null - */ - public void add(Point2D p) - { - add(p.getX(), p.getY()); - } - - /** - * Modifies this rectangle so that it represents the smallest rectangle - * that contains both the existing rectangle and the specified rectangle. - * - * @param r the rectangle to add to this rectangle - * @throws NullPointerException if r is null - * @see #union(Rectangle2D, Rectangle2D, Rectangle2D) - */ - public void add(Rectangle2D r) - { - union(this, r, this); - } - - /** - * Return an iterator along the shape boundary. If the optional transform - * is provided, the iterator is transformed accordingly. Each call returns - * a new object, independent from others in use. This iterator is thread - * safe; modifications to the rectangle do not affect the results of this - * path instance. - * - * @param at an optional transform to apply to the iterator - * @return a new iterator over the boundary - * @since 1.2 - */ - public PathIterator getPathIterator(final AffineTransform at) - { - final double minx = getX(); - final double miny = getY(); - final double maxx = minx + getWidth(); - final double maxy = miny + getHeight(); - return new PathIterator() - { - /** Current coordinate. */ - private int current = (maxx <= minx && maxy <= miny) ? 6 : 0; - - public int getWindingRule() - { - // A test program showed that Sun J2SE 1.3.1 and 1.4.1_01 - // return WIND_NON_ZERO paths. While this does not really - // make any difference for rectangles (because they are not - // self-intersecting), it seems appropriate to behave - // identically. - - return WIND_NON_ZERO; - } - - public boolean isDone() - { - return current > 5; - } - - public void next() - { - current++; - } - - public int currentSegment(float[] coords) - { - switch (current) - { - case 1: - coords[0] = (float) maxx; - coords[1] = (float) miny; - break; - case 2: - coords[0] = (float) maxx; - coords[1] = (float) maxy; - break; - case 3: - coords[0] = (float) minx; - coords[1] = (float) maxy; - break; - case 0: - case 4: - coords[0] = (float) minx; - coords[1] = (float) miny; - break; - case 5: - return SEG_CLOSE; - default: - throw new NoSuchElementException("rect iterator out of bounds"); - } - if (at != null) - at.transform(coords, 0, coords, 0, 1); - return current == 0 ? SEG_MOVETO : SEG_LINETO; - } - - public int currentSegment(double[] coords) - { - switch (current) - { - case 1: - coords[0] = maxx; - coords[1] = miny; - break; - case 2: - coords[0] = maxx; - coords[1] = maxy; - break; - case 3: - coords[0] = minx; - coords[1] = maxy; - break; - case 0: - case 4: - coords[0] = minx; - coords[1] = miny; - break; - case 5: - return SEG_CLOSE; - default: - throw new NoSuchElementException("rect iterator out of bounds"); - } - if (at != null) - at.transform(coords, 0, coords, 0, 1); - return current == 0 ? SEG_MOVETO : SEG_LINETO; - } - }; - } - - /** - * Return an iterator along the shape boundary. If the optional transform - * is provided, the iterator is transformed accordingly. Each call returns - * a new object, independent from others in use. This iterator is thread - * safe; modifications to the rectangle do not affect the results of this - * path instance. As the rectangle is already flat, the flatness parameter - * is ignored. - * - * @param at an optional transform to apply to the iterator - * @param flatness the maximum distance for deviation from the real boundary - * @return a new iterator over the boundary - * @since 1.2 - */ - public PathIterator getPathIterator(AffineTransform at, double flatness) - { - return getPathIterator(at); - } - - /** - * Return the hashcode for this rectangle. The formula is not documented, but - * appears to be the same as: - * <pre> - * long l = Double.doubleToLongBits(getX()) - * + 37 * Double.doubleToLongBits(getY()) - * + 43 * Double.doubleToLongBits(getWidth()) - * + 47 * Double.doubleToLongBits(getHeight()); - * return (int) ((l >> 32) ^ l); - * </pre> - * - * @return the hashcode - */ - public int hashCode() - { - // Talk about a fun time reverse engineering this one! - long l = java.lang.Double.doubleToLongBits(getX()) - + 37 * java.lang.Double.doubleToLongBits(getY()) - + 43 * java.lang.Double.doubleToLongBits(getWidth()) - + 47 * java.lang.Double.doubleToLongBits(getHeight()); - return (int) ((l >> 32) ^ l); - } - - /** - * Tests this rectangle for equality against the specified object. This - * will be true if an only if the specified object is an instance of - * Rectangle2D with the same coordinates and dimensions. - * - * @param obj the object to test against for equality - * @return true if the specified object is equal to this one - */ - public boolean equals(Object obj) - { - if (! (obj instanceof Rectangle2D)) - return false; - Rectangle2D r = (Rectangle2D) obj; - return r.getX() == getX() && r.getY() == getY() - && r.getWidth() == getWidth() && r.getHeight() == getHeight(); - } - - /** - * This class defines a rectangle in <code>double</code> precision. - * - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @status updated to 1.4 - */ - public static class Double extends Rectangle2D - { - /** The x coordinate of the lower left corner. */ - public double x; - - /** The y coordinate of the lower left corner. */ - public double y; - - /** The width of the rectangle. */ - public double width; - - /** The height of the rectangle. */ - public double height; - - /** - * Create a rectangle at (0,0) with width 0 and height 0. - */ - public Double() - { - } - - /** - * Create a rectangle with the given values. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - */ - public Double(double x, double y, double w, double h) - { - this.x = x; - this.y = y; - width = w; - height = h; - } - - /** - * Return the X coordinate. - * - * @return the value of x - */ - public double getX() - { - return x; - } - - /** - * Return the Y coordinate. - * - * @return the value of y - */ - public double getY() - { - return y; - } - - /** - * Return the width. - * - * @return the value of width - */ - public double getWidth() - { - return width; - } - - /** - * Return the height. - * - * @return the value of height - */ - public double getHeight() - { - return height; - } - - /** - * Test if the rectangle is empty. - * - * @return true if width or height is not positive - */ - public boolean isEmpty() - { - return width <= 0 || height <= 0; - } - - /** - * Set the contents of this rectangle to those specified. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - */ - public void setRect(double x, double y, double w, double h) - { - this.x = x; - this.y = y; - width = w; - height = h; - } - - /** - * Set the contents of this rectangle to those specified. - * - * @param r the rectangle to copy - * @throws NullPointerException if r is null - */ - public void setRect(Rectangle2D r) - { - x = r.getX(); - y = r.getY(); - width = r.getWidth(); - height = r.getHeight(); - } - - /** - * Determine where the point lies with respect to this rectangle. The - * result will be the binary OR of the appropriate bit masks. - * - * @param x the x coordinate to check - * @param y the y coordinate to check - * @return the binary OR of the result - * @see #OUT_LEFT - * @see #OUT_TOP - * @see #OUT_RIGHT - * @see #OUT_BOTTOM - * @since 1.2 - */ - public int outcode(double x, double y) - { - int result = 0; - if (width <= 0) - result |= OUT_LEFT | OUT_RIGHT; - else if (x < this.x) - result |= OUT_LEFT; - else if (x > this.x + width) - result |= OUT_RIGHT; - if (height <= 0) - result |= OUT_BOTTOM | OUT_TOP; - else if (y < this.y) // Remember that +y heads top-to-bottom. - result |= OUT_TOP; - else if (y > this.y + height) - result |= OUT_BOTTOM; - return result; - } - - /** - * Returns the bounds of this rectangle. A pretty useless method, as this - * is already a rectangle. - * - * @return a copy of this rectangle - */ - public Rectangle2D getBounds2D() - { - return new Double(x, y, width, height); - } - - /** - * Return a new rectangle which is the intersection of this and the given - * one. The result will be empty if there is no intersection. - * - * @param r the rectangle to be intersected - * @return the intersection - * @throws NullPointerException if r is null - */ - public Rectangle2D createIntersection(Rectangle2D r) - { - Double res = new Double(); - intersect(this, r, res); - return res; - } - - /** - * Return a new rectangle which is the union of this and the given one. - * - * @param r the rectangle to be merged - * @return the union - * @throws NullPointerException if r is null - */ - public Rectangle2D createUnion(Rectangle2D r) - { - Double res = new Double(); - union(this, r, res); - return res; - } - - /** - * Returns a string representation of this rectangle. This is in the form - * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width - * + ",h=" + height + ']'</code>. - * - * @return a string representation of this rectangle - */ - public String toString() - { - return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width - + ",h=" + height + ']'; - } - } - - /** - * This class defines a rectangle in <code>float</code> precision. - * - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @status updated to 1.4 - */ - public static class Float extends Rectangle2D - { - /** The x coordinate of the lower left corner. */ - public float x; - - /** The y coordinate of the lower left corner. */ - public float y; - - /** The width of the rectangle. */ - public float width; - - /** The height of the rectangle. */ - public float height; - - /** - * Create a rectangle at (0,0) with width 0 and height 0. - */ - public Float() - { - } - - /** - * Create a rectangle with the given values. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - */ - public Float(float x, float y, float w, float h) - { - this.x = x; - this.y = y; - width = w; - height = h; - } - - /** - * Create a rectangle with the given values. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - */ - Float(double x, double y, double w, double h) - { - this.x = (float) x; - this.y = (float) y; - width = (float) w; - height = (float) h; - } - - /** - * Return the X coordinate. - * - * @return the value of x - */ - public double getX() - { - return x; - } - - /** - * Return the Y coordinate. - * - * @return the value of y - */ - public double getY() - { - return y; - } - - /** - * Return the width. - * - * @return the value of width - */ - public double getWidth() - { - return width; - } - - /** - * Return the height. - * - * @return the value of height - */ - public double getHeight() - { - return height; - } - - /** - * Test if the rectangle is empty. - * - * @return true if width or height is not positive - */ - public boolean isEmpty() - { - return width <= 0 || height <= 0; - } - - /** - * Set the contents of this rectangle to those specified. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - */ - public void setRect(float x, float y, float w, float h) - { - this.x = x; - this.y = y; - width = w; - height = h; - } - - /** - * Set the contents of this rectangle to those specified. - * - * @param x the x coordinate - * @param y the y coordinate - * @param w the width - * @param h the height - */ - public void setRect(double x, double y, double w, double h) - { - this.x = (float) x; - this.y = (float) y; - width = (float) w; - height = (float) h; - } - - /** - * Set the contents of this rectangle to those specified. - * - * @param r the rectangle to copy - * @throws NullPointerException if r is null - */ - public void setRect(Rectangle2D r) - { - x = (float) r.getX(); - y = (float) r.getY(); - width = (float) r.getWidth(); - height = (float) r.getHeight(); - } - - /** - * Determine where the point lies with respect to this rectangle. The - * result will be the binary OR of the appropriate bit masks. - * - * @param x the x coordinate to check - * @param y the y coordinate to check - * @return the binary OR of the result - * @see #OUT_LEFT - * @see #OUT_TOP - * @see #OUT_RIGHT - * @see #OUT_BOTTOM - * @since 1.2 - */ - public int outcode(double x, double y) - { - int result = 0; - if (width <= 0) - result |= OUT_LEFT | OUT_RIGHT; - else if (x < this.x) - result |= OUT_LEFT; - else if (x > this.x + width) - result |= OUT_RIGHT; - if (height <= 0) - result |= OUT_BOTTOM | OUT_TOP; - else if (y < this.y) // Remember that +y heads top-to-bottom. - result |= OUT_TOP; - else if (y > this.y + height) - result |= OUT_BOTTOM; - return result; - } - - /** - * Returns the bounds of this rectangle. A pretty useless method, as this - * is already a rectangle. - * - * @return a copy of this rectangle - */ - public Rectangle2D getBounds2D() - { - return new Float(x, y, width, height); - } - - /** - * Return a new rectangle which is the intersection of this and the given - * one. The result will be empty if there is no intersection. - * - * @param r the rectangle to be intersected - * @return the intersection - * @throws NullPointerException if r is null - */ - public Rectangle2D createIntersection(Rectangle2D r) - { - Float res = new Float(); - intersect(this, r, res); - return res; - } - - /** - * Return a new rectangle which is the union of this and the given one. - * - * @param r the rectangle to be merged - * @return the union - * @throws NullPointerException if r is null - */ - public Rectangle2D createUnion(Rectangle2D r) - { - Float res = new Float(); - union(this, r, res); - return res; - } - - /** - * Returns a string representation of this rectangle. This is in the form - * <code>getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width - * + ",h=" + height + ']'</code>. - * - * @return a string representation of this rectangle - */ - public String toString() - { - return getClass().getName() + "[x=" + x + ",y=" + y + ",w=" + width - + ",h=" + height + ']'; - } - } -} diff --git a/libjava/classpath/java/awt/geom/RectangularShape.java b/libjava/classpath/java/awt/geom/RectangularShape.java deleted file mode 100644 index 68bc451..0000000 --- a/libjava/classpath/java/awt/geom/RectangularShape.java +++ /dev/null @@ -1,382 +0,0 @@ -/* RectangularShape.java -- a rectangular frame for several generic shapes - Copyright (C) 2000, 2002 Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - - -package java.awt.geom; - -import java.awt.Rectangle; -import java.awt.Shape; - -/** - * This class provides a generic framework, and several helper methods, for - * subclasses which represent geometric objects inside a rectangular frame. - * This does not specify any geometry except for the bounding box. - * - * @author Tom Tromey (tromey@cygnus.com) - * @author Eric Blake (ebb9@email.byu.edu) - * @since 1.2 - * @see Arc2D - * @see Ellipse2D - * @see Rectangle2D - * @see RoundRectangle2D - * @status updated to 1.4 - */ -public abstract class RectangularShape implements Shape, Cloneable -{ - /** - * Default constructor. - */ - protected RectangularShape() - { - } - - /** - * Get the x coordinate of the upper-left corner of the framing rectangle. - * - * @return the x coordinate - */ - public abstract double getX(); - - /** - * Get the y coordinate of the upper-left corner of the framing rectangle. - * - * @return the y coordinate - */ - public abstract double getY(); - - /** - * Get the width of the framing rectangle. - * - * @return the width - */ - public abstract double getWidth(); - - /** - * Get the height of the framing rectangle. - * - * @return the height - */ - public abstract double getHeight(); - - /** - * Get the minimum x coordinate in the frame. This is misnamed, or else - * Sun has a bug, because the implementation returns getX() even when - * getWidth() is negative. - * - * @return the minimum x coordinate - */ - public double getMinX() - { - return getX(); - } - - /** - * Get the minimum y coordinate in the frame. This is misnamed, or else - * Sun has a bug, because the implementation returns getY() even when - * getHeight() is negative. - * - * @return the minimum y coordinate - */ - public double getMinY() - { - return getY(); - } - - /** - * Get the maximum x coordinate in the frame. This is misnamed, or else - * Sun has a bug, because the implementation returns getX()+getWidth() even - * when getWidth() is negative. - * - * @return the maximum x coordinate - */ - public double getMaxX() - { - return getX() + getWidth(); - } - - /** - * Get the maximum y coordinate in the frame. This is misnamed, or else - * Sun has a bug, because the implementation returns getY()+getHeight() even - * when getHeight() is negative. - * - * @return the maximum y coordinate - */ - public double getMaxY() - { - return getY() + getHeight(); - } - - /** - * Return the x coordinate of the center point of the framing rectangle. - * - * @return the central x coordinate - */ - public double getCenterX() - { - return getX() + getWidth() / 2; - } - - /** - * Return the y coordinate of the center point of the framing rectangle. - * - * @return the central y coordinate - */ - public double getCenterY() - { - return getY() + getHeight() / 2; - } - - /** - * Return the frame around this object. Note that this may be a looser - * bounding box than getBounds2D. - * - * @return the frame, in double precision - * @see #setFrame(double, double, double, double) - */ - public Rectangle2D getFrame() - { - return new Rectangle2D.Double(getX(), getY(), getWidth(), getHeight()); - } - - /** - * Test if the shape is empty, meaning that no points are inside it. - * - * @return true if the shape is empty - */ - public abstract boolean isEmpty(); - - /** - * Set the framing rectangle of this shape to the given coordinate and size. - * - * @param x the new x coordinate - * @param y the new y coordinate - * @param w the new width - * @param h the new height - * @see #getFrame() - */ - public abstract void setFrame(double x, double y, double w, double h); - - /** - * Set the framing rectangle of this shape to the given coordinate and size. - * - * @param p the new point - * @param d the new dimension - * @throws NullPointerException if p or d is null - * @see #getFrame() - */ - public void setFrame(Point2D p, Dimension2D d) - { - setFrame(p.getX(), p.getY(), d.getWidth(), d.getHeight()); - } - - /** - * Set the framing rectangle of this shape to the given rectangle. - * - * @param r the new framing rectangle - * @throws NullPointerException if r is null - * @see #getFrame() - */ - public void setFrame(Rectangle2D r) - { - setFrame(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - /** - * Set the framing rectangle of this shape using two points on a diagonal. - * The area will be positive. - * - * @param x1 the first x coordinate - * @param y1 the first y coordinate - * @param x2 the second x coordinate - * @param y2 the second y coordinate - */ - public void setFrameFromDiagonal(double x1, double y1, double x2, double y2) - { - if (x1 > x2) - { - double t = x2; - x2 = x1; - x1 = t; - } - if (y1 > y2) - { - double t = y2; - y2 = y1; - y1 = t; - } - setFrame(x1, y1, x2 - x1, y2 - y1); - } - - /** - * Set the framing rectangle of this shape using two points on a diagonal. - * The area will be positive. - * - * @param p1 the first point - * @param p2 the second point - * @throws NullPointerException if either point is null - */ - public void setFrameFromDiagonal(Point2D p1, Point2D p2) - { - setFrameFromDiagonal(p1.getX(), p1.getY(), p2.getX(), p2.getY()); - } - - /** - * Set the framing rectangle of this shape using the center of the frame, - * and one of the four corners. The area will be positive. - * - * @param centerX the x coordinate at the center - * @param centerY the y coordinate at the center - * @param cornerX the x coordinate at a corner - * @param cornerY the y coordinate at a corner - */ - public void setFrameFromCenter(double centerX, double centerY, - double cornerX, double cornerY) - { - double halfw = Math.abs(cornerX - centerX); - double halfh = Math.abs(cornerY - centerY); - setFrame(centerX - halfw, centerY - halfh, halfw + halfw, halfh + halfh); - } - - /** - * Set the framing rectangle of this shape using the center of the frame, - * and one of the four corners. The area will be positive. - * - * @param center the center point - * @param corner a corner point - * @throws NullPointerException if either point is null - */ - public void setFrameFromCenter(Point2D center, Point2D corner) - { - setFrameFromCenter(center.getX(), center.getY(), - corner.getX(), corner.getY()); - } - - /** - * Tests if a point is inside the boundary of the shape. - * - * @param p the point to test - * @return true if the point is inside the shape - * @throws NullPointerException if p is null - * @see #contains(double, double) - */ - public boolean contains(Point2D p) - { - return contains(p.getX(), p.getY()); - } - - /** - * Tests if a rectangle and this shape share common internal points. - * - * @param r the rectangle to test - * @return true if the rectangle intersects this shpae - * @throws NullPointerException if r is null - * @see #intersects(double, double, double, double) - */ - public boolean intersects(Rectangle2D r) - { - return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - /** - * Tests if the shape completely contains the given rectangle. - * - * @param r the rectangle to test - * @return true if r is contained in this shape - * @throws NullPointerException if r is null - * @see #contains(double, double, double, double) - */ - public boolean contains(Rectangle2D r) - { - return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight()); - } - - /** - * Returns a bounding box for this shape, in integer format. Notice that you - * may get a tighter bound with getBounds2D. - * - * @return a bounding box - */ - public Rectangle getBounds() - { - double x = getX(); - double y = getY(); - double maxx = Math.ceil(x + getWidth()); - double maxy = Math.ceil(y + getHeight()); - x = Math.floor(x); - y = Math.floor(y); - return new Rectangle((int) x, (int) y, (int) (maxx - x), (int) (maxy - y)); - } - - /** - * Return an iterator along the shape boundary. If the optional transform - * is provided, the iterator is transformed accordingly. The path is - * flattened until all segments differ from the curve by at most the value - * of the flatness parameter, within the limits of the default interpolation - * recursion limit of 1024 segments between actual points. Each call - * returns a new object, independent from others in use. The result is - * threadsafe if and only if the iterator returned by - * {@link #getPathIterator(AffineTransform)} is as well. - * - * @param at an optional transform to apply to the iterator - * @param flatness the desired flatness - * @return a new iterator over the boundary - * @throws IllegalArgumentException if flatness is invalid - * @since 1.2 - */ - public PathIterator getPathIterator(AffineTransform at, double flatness) - { - return new FlatteningPathIterator(getPathIterator(at), flatness); - } - - /** - * Create a new shape of the same run-time type 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 - } - } -} // class RectangularShape diff --git a/libjava/classpath/java/awt/geom/RoundRectangle2D.java b/libjava/classpath/java/awt/geom/RoundRectangle2D.java deleted file mode 100644 index 19a7b42..0000000 --- a/libjava/classpath/java/awt/geom/RoundRectangle2D.java +++ /dev/null @@ -1,584 +0,0 @@ -/* RoundRectangle2D.java -- represents a rectangle with rounded corners - Copyright (C) 2000, 2002, 2003, 2004, 2006, Free Software Foundation - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. */ - -package java.awt.geom; - - - -/** This class implements a rectangle with rounded corners. - * @author Tom Tromey (tromey@cygnus.com) - * @date December 3, 2000 - */ -public abstract class RoundRectangle2D extends RectangularShape -{ - /** - * Return the arc height of this round rectangle. The arc height and width - * control the roundness of the corners of the rectangle. - * - * @return The arc height. - * - * @see #getArcWidth() - */ - public abstract double getArcHeight(); - - /** - * Return the arc width of this round rectangle. The arc width and height - * control the roundness of the corners of the rectangle. - * - * @return The arc width. - * - * @see #getArcHeight() - */ - public abstract double getArcWidth(); - - /** - * Set the values of this round rectangle. - * - * @param x The x coordinate - * @param y The y coordinate - * @param w The width - * @param h The height - * @param arcWidth The arc width - * @param arcHeight The arc height - */ - public abstract void setRoundRect(double x, double y, double w, double h, - double arcWidth, double arcHeight); - - /** - * Create a RoundRectangle2D. This is protected because this class - * is abstract and cannot be instantiated. - */ - protected RoundRectangle2D() - { - } - - /** - * Return true if this object contains the specified point. - * @param x The x coordinate - * @param y The y coordinate - */ - public boolean contains(double x, double y) - { - double mx = getX(); - double mw = getWidth(); - if (x < mx || x >= mx + mw) - return false; - double my = getY(); - double mh = getHeight(); - if (y < my || y >= my + mh) - return false; - - // Now check to see if the point is in range of an arc. - double dy = Math.min(Math.abs(my - y), Math.abs(my + mh - y)); - double dx = Math.min(Math.abs(mx - x), Math.abs(mx + mw - x)); - - // The arc dimensions are that of the corresponding ellipse - // thus a 90 degree segment is half of that. - double aw = getArcWidth() / 2.0; - double ah = getArcHeight() / 2.0; - if (dx > aw || dy > ah) - return true; - - // At this point DX represents the distance from the nearest edge - // of the rectangle. But we want to transform it to represent the - // scaled distance from the center of the ellipse that forms the - // arc. Hence this code: - dy = (ah - dy) / ah; - dx = (aw - dx) / aw; - - return dx * dx + dy * dy <= 1.0; - } - - /** - * Return true if this object contains the specified rectangle - * @param x The x coordinate - * @param y The y coordinate - * @param w The width - * @param h The height - */ - public boolean contains(double x, double y, double w, double h) - { - // We have to check all four points here (for ordinary rectangles - // we can just check opposing corners). - return (contains(x, y) && contains(x, y + h) && contains(x + w, y + h) - && contains(x + w, y)); - } - - /** - * Return a new path iterator which iterates over this rectangle. - * - * @param at An affine transform to apply to the object - */ - public PathIterator getPathIterator(final AffineTransform at) - { - double arcW = Math.min(getArcWidth(), getWidth()); - double arcH = Math.min(getArcHeight(), getHeight()); - - // check for special cases... - if (arcW <= 0 || arcH <= 0) - { - Rectangle2D r = new Rectangle2D.Double(getX(), getY(), getWidth(), - getHeight()); - return r.getPathIterator(at); - } - else if (arcW >= getWidth() && arcH >= getHeight()) - { - Ellipse2D e = new Ellipse2D.Double(getX(), getY(), getWidth(), - getHeight()); - return e.getPathIterator(at); - } - - // otherwise return the standard case... - return new PathIterator() - { - double x = getX(); - double y = getY(); - double w = getWidth(); - double h = getHeight(); - double arcW = Math.min(getArcWidth(), w); - double arcH = Math.min(getArcHeight(), h); - Arc2D.Double arc = new Arc2D.Double(); - PathIterator corner; - int step = -1; - - public int currentSegment(double[] coords) - { - if (corner != null) // steps 1, 3, 5 and 7 - { - int r = corner.currentSegment(coords); - if (r == SEG_MOVETO) - r = SEG_LINETO; - return r; - } - if (step == -1) - { - // move to the start position - coords[0] = x + w - arcW / 2; - coords[1] = y; - } - else if (step == 0) - { - // top line - coords[0] = x + arcW / 2; - coords[1] = y; - } - else if (step == 2) - { - // left line - coords[0] = x; - coords[1] = y + h - arcH / 2; - } - else if (step == 4) - { - // bottom line - coords[0] = x + w - arcW / 2; - coords[1] = y + h; - } - else if (step == 6) - { - // right line - coords[0] = x + w; - coords[1] = y + arcH / 2; - } - if (at != null) - at.transform(coords, 0, coords, 0, 1); - return step == -1 ? SEG_MOVETO : SEG_LINETO; - } - - public int currentSegment(float[] coords) { - if (corner != null) // steps 1, 3, 5 and 7 - { - int r = corner.currentSegment(coords); - if (r == SEG_MOVETO) - r = SEG_LINETO; - return r; - } - if (step == -1) - { - // move to the start position - coords[0] = (float) (x + w - arcW / 2); - coords[1] = (float) y; - } - else if (step == 0) - { - // top line - coords[0] = (float) (x + arcW / 2); - coords[1] = (float) y; - } - else if (step == 2) - { - // left line - coords[0] = (float) x; - coords[1] = (float) (y + h - arcH / 2); - } - else if (step == 4) - { - // bottom line - coords[0] = (float) (x + w - arcW / 2); - coords[1] = (float) (y + h); - } - else if (step == 6) - { - // right line - coords[0] = (float) (x + w); - coords[1] = (float) (y + arcH / 2); - } - if (at != null) - at.transform(coords, 0, coords, 0, 1); - return step == -1 ? SEG_MOVETO : SEG_LINETO; - } - - public int getWindingRule() { - return WIND_NON_ZERO; - } - - public boolean isDone() { - return step >= 8; - } - - public void next() - { - if (corner != null) - { - corner.next(); - if (corner.isDone()) - { - corner = null; - step++; - } - } - else - { - step++; - if (step == 1) - { - // create top left corner - arc.setArc(x, y, arcW, arcH, 90, 90, Arc2D.OPEN); - corner = arc.getPathIterator(at); - } - else if (step == 3) - { - // create bottom left corner - arc.setArc(x, y + h - arcH, arcW, arcH, 180, 90, - Arc2D.OPEN); - corner = arc.getPathIterator(at); - } - else if (step == 5) - { - // create bottom right corner - arc.setArc(x + w - arcW, y + h - arcH, arcW, arcH, 270, 90, - Arc2D.OPEN); - corner = arc.getPathIterator(at); - } - else if (step == 7) - { - // create top right corner - arc.setArc(x + w - arcW, y, arcW, arcH, 0, 90, Arc2D.OPEN); - corner = arc.getPathIterator(at); - } - } - } - }; - } - - /** - * Return true if the given rectangle intersects this shape. - * @param x The x coordinate - * @param y The y coordinate - * @param w The width - * @param h The height - */ - public boolean intersects(double x, double y, double w, double h) - { - // Check if any corner is within the rectangle - return (contains(x, y) || contains(x, y + h) || contains(x + w, y + h) - || contains(x + w, y)); - } - - /** - * Set the boundary of this round rectangle. - * @param x The x coordinate - * @param y The y coordinate - * @param w The width - * @param h The height - */ - public void setFrame(double x, double y, double w, double h) - { - // This is a bit lame. - setRoundRect(x, y, w, h, getArcWidth(), getArcHeight()); - } - - /** - * Set the values of this round rectangle to be the same as those - * of the argument. - * @param rr The round rectangle to copy - */ - public void setRoundRect(RoundRectangle2D rr) - { - setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(), - rr.getArcWidth(), rr.getArcHeight()); - } - - /** - * A subclass of RoundRectangle which keeps its parameters as - * doubles. - */ - public static class Double extends RoundRectangle2D - { - /** The height of the corner arc. */ - public double archeight; - - /** The width of the corner arc. */ - public double arcwidth; - - /** The x coordinate of this object. */ - public double x; - - /** The y coordinate of this object. */ - public double y; - - /** The width of this object. */ - public double width; - - /** The height of this object. */ - public double height; - - /** - * Construct a new instance, with all parameters set to 0. - */ - public Double() - { - } - - /** - * Construct a new instance with the given arguments. - * @param x The x coordinate - * @param y The y coordinate - * @param w The width - * @param h The height - * @param arcWidth The arc width - * @param arcHeight The arc height - */ - public Double(double x, double y, double w, double h, double arcWidth, - double arcHeight) - { - this.x = x; - this.y = y; - this.width = w; - this.height = h; - this.arcwidth = arcWidth; - this.archeight = arcHeight; - } - - public double getArcHeight() - { - return archeight; - } - - public double getArcWidth() - { - return arcwidth; - } - - public Rectangle2D getBounds2D() - { - return new Rectangle2D.Double(x, y, width, height); - } - - public double getX() - { - return x; - } - - public double getY() - { - return y; - } - - public double getWidth() - { - return width; - } - - public double getHeight() - { - return height; - } - - public boolean isEmpty() - { - return width <= 0 || height <= 0; - } - - public void setRoundRect(double x, double y, double w, double h, - double arcWidth, double arcHeight) - { - this.x = x; - this.y = y; - this.width = w; - this.height = h; - this.arcwidth = arcWidth; - this.archeight = arcHeight; - } - } // class Double - - /** - * A subclass of RoundRectangle which keeps its parameters as - * floats. - */ - public static class Float extends RoundRectangle2D - { - /** The height of the corner arc. */ - public float archeight; - - /** The width of the corner arc. */ - public float arcwidth; - - /** The x coordinate of this object. */ - public float x; - - /** The y coordinate of this object. */ - public float y; - - /** The width of this object. */ - public float width; - - /** The height of this object. */ - public float height; - - /** - * Construct a new instance, with all parameters set to 0. - */ - public Float() - { - } - - /** - * Construct a new instance with the given arguments. - * @param x The x coordinate - * @param y The y coordinate - * @param w The width - * @param h The height - * @param arcWidth The arc width - * @param arcHeight The arc height - */ - public Float(float x, float y, float w, float h, float arcWidth, - float arcHeight) - { - this.x = x; - this.y = y; - this.width = w; - this.height = h; - this.arcwidth = arcWidth; - this.archeight = arcHeight; - } - - public double getArcHeight() - { - return archeight; - } - - public double getArcWidth() - { - return arcwidth; - } - - public Rectangle2D getBounds2D() - { - return new Rectangle2D.Float(x, y, width, height); - } - - public double getX() - { - return x; - } - - public double getY() - { - return y; - } - - public double getWidth() - { - return width; - } - - public double getHeight() - { - return height; - } - - public boolean isEmpty() - { - return width <= 0 || height <= 0; - } - - /** - * Sets the dimensions for this rounded rectangle. - * - * @param x the x-coordinate of the top left corner. - * @param y the y-coordinate of the top left corner. - * @param w the width of the rectangle. - * @param h the height of the rectangle. - * @param arcWidth the arc width. - * @param arcHeight the arc height. - * - * @see #setRoundRect(double, double, double, double, double, double) - */ - public void setRoundRect(float x, float y, float w, float h, - float arcWidth, float arcHeight) - { - this.x = x; - this.y = y; - this.width = w; - this.height = h; - this.arcwidth = arcWidth; - this.archeight = arcHeight; - } - - public void setRoundRect(double x, double y, double w, double h, - double arcWidth, double arcHeight) - { - this.x = (float) x; - this.y = (float) y; - this.width = (float) w; - this.height = (float) h; - this.arcwidth = (float) arcWidth; - this.archeight = (float) arcHeight; - } - } // class Float -} // class RoundRectangle2D diff --git a/libjava/classpath/java/awt/geom/doc-files/Area-1.png b/libjava/classpath/java/awt/geom/doc-files/Area-1.png Binary files differdeleted file mode 100644 index 44650f2..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/Area-1.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png Binary files differdeleted file mode 100644 index 1784509..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-1.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png Binary files differdeleted file mode 100644 index 1ddae9f..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-2.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png Binary files differdeleted file mode 100644 index b200dad..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-3.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png Binary files differdeleted file mode 100644 index e57ffdc..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-4.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png b/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png Binary files differdeleted file mode 100644 index 701ab13..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/CubicCurve2D-5.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png b/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png Binary files differdeleted file mode 100644 index 8317db6..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/Ellipse-1.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html b/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html deleted file mode 100644 index 5a52d69..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/FlatteningPathIterator-1.html +++ /dev/null @@ -1,481 +0,0 @@ -<?xml version="1.0" encoding="US-ASCII"?> -<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" - "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> -<head> - <title>The GNU Implementation of java.awt.geom.FlatteningPathIterator</title> - <meta name="author" content="Sascha Brawer" /> - <style type="text/css"><!-- - td { white-space: nowrap; } - li { margin: 2mm 0; } - --></style> -</head> -<body> - -<h1>The GNU Implementation of FlatteningPathIterator</h1> - -<p><i><a href="http://www.dandelis.ch/people/brawer/">Sascha -Brawer</a>, November 2003</i></p> - -<p>This document describes the GNU implementation of the class -<code>java.awt.geom.FlatteningPathIterator</code>. It does -<em>not</em> describe how a programmer should use this class; please -refer to the generated API documentation for this purpose. Instead, it -is intended for maintenance programmers who want to understand the -implementation, for example because they want to extend the class or -fix a bug.</p> - - -<h2>Data Structures</h2> - -<p>The algorithm uses a stack. Its allocation is delayed to the time -when the source path iterator actually returns the first curved -segment (either <code>SEG_QUADTO</code> or <code>SEG_CUBICTO</code>). -If the input path does not contain any curved segments, the value of -the <code>stack</code> variable stays <code>null</code>. In this quite -common case, the memory consumption is minimal.</p> - -<dl><dt><code>stack</code></dt><dd>The variable <code>stack</code> is -a <code>double</code> array that holds the start, control and end -points of individual sub-segments.</dd> - -<dt><code>recLevel</code></dt><dd>The variable <code>recLevel</code> -holds how many recursive sub-divisions were needed to calculate a -segment. The original curve has recursion level 0. For each -sub-division, the corresponding recursion level is increased by -one.</dd> - -<dt><code>stackSize</code></dt><dd>Finally, the variable -<code>stackSize</code> indicates how many sub-segments are stored on -the stack.</dd></dl> - -<h2>Algorithm</h2> - -<p>The implementation separately processes each segment that the -base iterator returns.</p> - -<p>In the case of <code>SEG_CLOSE</code>, -<code>SEG_MOVETO</code> and <code>SEG_LINETO</code> segments, the -implementation simply hands the segment to the consumer, without actually -doing anything.</p> - -<p>Any <code>SEG_QUADTO</code> and <code>SEG_CUBICTO</code> segments -need to be flattened. Flattening is performed with a fixed-sized -stack, holding the coordinates of subdivided segments. When the base -iterator returns a <code>SEG_QUADTO</code> and -<code>SEG_CUBICTO</code> segments, it is recursively flattened as -follows:</p> - -<ol><li>Intialization: Allocate memory for the stack (unless a -sufficiently large stack has been allocated previously). Push the -original quadratic or cubic curve onto the stack. Mark that segment as -having a <code>recLevel</code> of zero.</li> - -<li>If the stack is empty, flattening the segment is complete, -and the next segment is fetched from the base iterator.</li> - -<li>If the stack is not empty, pop a curve segment from the -stack. - - <ul><li>If its <code>recLevel</code> exceeds the recursion limit, - hand the current segment to the consumer.</li> - - <li>Calculate the squared flatness of the segment. If it smaller - than <code>flatnessSq</code>, hand the current segment to the - consumer.</li> - - <li>Otherwise, split the segment in two halves. Push the right - half onto the stack. Then, push the left half onto the stack. - Continue with step two.</li></ul></li> -</ol> - -<p>The implementation is slightly complicated by the fact that -consumers <em>pull</em> the flattened segments from the -<code>FlatteningPathIterator</code>. This means that we actually -cannot “hand the curent segment over to the consumer.” -But the algorithm is easier to understand if one assumes a -<em>push</em> paradigm.</p> - - -<h2>Example</h2> - -<p>The following example shows how a -<code>FlatteningPathIterator</code> processes a -<code>SEG_QUADTO</code> segment. It is (arbitrarily) assumed that the -recursion limit was set to 2.</p> - -<blockquote> -<table border="1" cellspacing="0" cellpadding="8"> - <tr align="center" valign="baseline"> - <th></th><th>A</th><th>B</th><th>C</th> - <th>D</th><th>E</th><th>F</th><th>G</th><th>H</th> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[0]</code></th> - <td>—</td> - <td>—</td> - <td><i>S<sub>ll</sub>.x</i></td> - <td>—</td> - <td>—</td> - <td>—</td> - <td>—</td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[1]</code></th> - <td>—</td> - <td>—</td> - <td><i>S<sub>ll</sub>.y</i></td> - <td>—</td> - <td>—</td> - <td>—</td> - <td>—</td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[2]</code></th> - <td>—</td> - <td>—</td> - <td><i>C<sub>ll</sub>.x</i></td> - <td>—</td> - <td>—</td> - <td>—</td> - <td>—</td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[3]</code></th> - <td>—</td> - <td>—</td> - <td><i>C<sub>ll</sub>.y</i></td> - <td>—</td> - <td>—</td> - <td>—</td> - <td>—</td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[4]</code></th> - <td>—</td> - <td><i>S<sub>l</sub>.x</i></td> - <td><i>E<sub>ll</sub>.x</i> - = <i>S<sub>lr</sub>.x</i></td> - <td><i>S<sub>lr</sub>.x</i></td> - <td>—</td> - <td><i>S<sub>rl</sub>.x</i></td> - <td>—</td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[5]</code></th> - <td>—</td> - <td><i>S<sub>l</sub>.y</i></td> - <td><i>E<sub>ll</sub>.x</i> - = <i>S<sub>lr</sub>.y</i></td> - <td><i>S<sub>lr</sub>.y</i></td> - <td>—</td> - <td><i>S<sub>rl</sub>.y</i></td> - <td>—</td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[6]</code></th> - <td>—</td> - <td><i>C<sub>l</sub>.x</i></td> - <td><i>C<sub>lr</sub>.x</i></td> - <td><i>C<sub>lr</sub>.x</i></td> - <td>—</td> - <td><i>C<sub>rl</sub>.x</i></td> - <td>—</td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[7]</code></th> - <td>—</td> - <td><i>C<sub>l</sub>.y</i></td> - <td><i>C<sub>lr</sub>.y</i></td> - <td><i>C<sub>lr</sub>.y</i></td> - <td>—</td> - <td><i>C<sub>rl</sub>.y</i></td> - <td>—</td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[8]</code></th> - <td><i>S.x</i></td> - <td><i>E<sub>l</sub>.x</i> - = <i>S<sub>r</sub>.x</i></td> - <td><i>E<sub>lr</sub>.x</i> - = <i>S<sub>r</sub>.x</i></td> - <td><i>E<sub>lr</sub>.x</i> - = <i>S<sub>r</sub>.x</i></td> - <td><i>S<sub>r</sub>.x</i></td> - <td><i>E<sub>rl</sub>.x</i> - = <i>S<sub>rr</sub>.x</i></td> - <td><i>S<sub>rr</sub>.x</i></td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[9]</code></th> - <td><i>S.y</i></td> - <td><i>E<sub>l</sub>.y</i> - = <i>S<sub>r</sub>.y</i></td> - <td><i>E<sub>lr</sub>.y</i> - = <i>S<sub>r</sub>.y</i></td> - <td><i>E<sub>lr</sub>.y</i> - = <i>S<sub>r</sub>.y</i></td> - <td><i>S<sub>r</sub>.y</i></td> - <td><i>E<sub>rl</sub>.y</i> - = <i>S<sub>rr</sub>.y</i></td> - <td><i>S<sub>rr</sub>.y</i></td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[10]</code></th> - <td><i>C.x</i></td> - <td><i>C<sub>r</sub>.x</i></td> - <td><i>C<sub>r</sub>.x</i></td> - <td><i>C<sub>r</sub>.x</i></td> - <td><i>C<sub>r</sub>.x</i></td> - <td><i>C<sub>rr</sub>.x</i></td> - <td><i>C<sub>rr</sub>.x</i></td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[11]</code></th> - <td><i>C.y</i></td> - <td><i>C<sub>r</sub>.y</i></td> - <td><i>C<sub>r</sub>.y</i></td> - <td><i>C<sub>r</sub>.y</i></td> - <td><i>C<sub>r</sub>.y</i></td> - <td><i>C<sub>rr</sub>.y</i></td> - <td><i>C<sub>rr</sub>.y</i></td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[12]</code></th> - <td><i>E.x</i></td> - <td><i>E<sub>r</sub>.x</i></td> - <td><i>E<sub>r</sub>.x</i></td> - <td><i>E<sub>r</sub>.x</i></td> - <td><i>E<sub>r</sub>.x</i></td> - <td><i>E<sub>rr</sub>.x</i></td> - <td><i>E<sub>rr</sub>.x</i></td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stack[13]</code></th> - <td><i>E.y</i></td> - <td><i>E<sub>r</sub>.y</i></td> - <td><i>E<sub>r</sub>.y</i></td> - <td><i>E<sub>r</sub>.y</i></td> - <td><i>E<sub>r</sub>.y</i></td> - <td><i>E<sub>rr</sub>.y</i></td> - <td><i>E<sub>rr</sub>.x</i></td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>stackSize</code></th> - <td>1</td> - <td>2</td> - <td>3</td> - <td>2</td> - <td>1</td> - <td>2</td> - <td>1</td> - <td>0</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>recLevel[2]</code></th> - <td>—</td> - <td>—</td> - <td>2</td> - <td>—</td> - <td>—</td> - <td>—</td> - <td>—</td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>recLevel[1]</code></th> - <td>—</td> - <td>1</td> - <td>2</td> - <td>2</td> - <td>—</td> - <td>2</td> - <td>—</td> - <td>—</td> - </tr> - <tr align="center" valign="baseline"> - <th><code>recLevel[0]</code></th> - <td>0</td> - <td>1</td> - <td>1</td> - <td>1</td> - <td>1</td> - <td>2</td> - <td>2</td> - <td>—</td> - </tr> - </table> -</blockquote> - -<ol> - -<li>The data structures are initialized as follows. - -<ul><li>The segment’s end point <i>E</i>, control point -<i>C</i>, and start point <i>S</i> are pushed onto the stack.</li> - - <li>Currently, the curve in the stack would be approximated by one - single straight line segment (<i>S</i> – <i>E</i>). - Therefore, <code>stackSize</code> is set to 1.</li> - - <li>This single straight line segment is approximating the original - curve, which can be seen as the result of zero recursive - splits. Therefore, <code>recLevel[0]</code> is set to - zero.</li></ul> - -Column A shows the state after the initialization step.</li> - -<li>The algorithm proceeds by taking the topmost curve segment -(<i>S</i> – <i>C</i> – <i>E</i>) from the stack. - - <ul><li>The recursion level of this segment (stored in - <code>recLevel[0]</code>) is zero, which is smaller than - the limit 2.</li> - - <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code> - is called to calculate the squared flatness.</li> - - <li>For the sake of argument, we assume that the squared flatness is - exceeding the threshold stored in <code>flatnessSq</code>. Thus, the - curve segment <i>S</i> – <i>C</i> – <i>E</i> gets - subdivided into a left and a right half, namely - <i>S<sub>l</sub></i> – <i>C<sub>l</sub></i> – - <i>E<sub>l</sub></i> and <i>S<sub>r</sub></i> – - <i>C<sub>r</sub></i> – <i>E<sub>r</sub></i>. Both halves are - pushed onto the stack, so the left half is now on top. - - <br /> <br />The left half starts at the same point - as the original curve, so <i>S<sub>l</sub></i> has the same - coordinates as <i>S</i>. Similarly, the end point of the right - half and of the original curve are identical - (<i>E<sub>r</sub></i> = <i>E</i>). More interestingly, the left - half ends where the right half starts. Because - <i>E<sub>l</sub></i> = <i>S<sub>r</sub></i>, their coordinates need - to be stored only once, which amounts to saving 16 bytes (two - <code>double</code> values) for each iteration.</li></ul> - -Column B shows the state after the first iteration.</li> - -<li>Again, the topmost curve segment (<i>S<sub>l</sub></i> -– <i>C<sub>l</sub></i> – <i>E<sub>l</sub></i>) is -taken from the stack. - - <ul><li>The recursion level of this segment (stored in - <code>recLevel[1]</code>) is 1, which is smaller than - the limit 2.</li> - - <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code> - is called to calculate the squared flatness.</li> - - <li>Assuming that the segment is still not considered - flat enough, it gets subdivided into a left - (<i>S<sub>ll</sub></i> – <i>C<sub>ll</sub></i> – - <i>E<sub>ll</sub></i>) and a right (<i>S<sub>lr</sub></i> - – <i>C<sub>lr</sub></i> – <i>E<sub>lr</sub></i>) - half.</li></ul> - -Column C shows the state after the second iteration.</li> - -<li>The topmost curve segment (<i>S<sub>ll</sub></i> – -<i>C<sub>ll</sub></i> – <i>E<sub>ll</sub></i>) is popped from -the stack. - - <ul><li>The recursion level of this segment (stored in - <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than - the limit 2. Therefore, a <code>SEG_LINETO</code> (from - <i>S<sub>ll</sub></i> to <i>E<sub>ll</sub></i>) is passed to the - consumer.</li></ul> - - The new state is shown in column D.</li> - - -<li>The topmost curve segment (<i>S<sub>lr</sub></i> – -<i>C<sub>lr</sub></i> – <i>E<sub>lr</sub></i>) is popped from -the stack. - - <ul><li>The recursion level of this segment (stored in - <code>recLevel[1]</code>) is 2, which is <em>not</em> smaller than - the limit 2. Therefore, a <code>SEG_LINETO</code> (from - <i>S<sub>lr</sub></i> to <i>E<sub>lr</sub></i>) is passed to the - consumer.</li></ul> - - The new state is shown in column E.</li> - -<li>The algorithm proceeds by taking the topmost curve segment -(<i>S<sub>r</sub></i> – <i>C<sub>r</sub></i> – -<i>E<sub>r</sub></i>) from the stack. - - <ul><li>The recursion level of this segment (stored in - <code>recLevel[0]</code>) is 1, which is smaller than - the limit 2.</li> - - <li>The method <code>java.awt.geom.QuadCurve2D.getFlatnessSq</code> - is called to calculate the squared flatness.</li> - - <li>For the sake of argument, we again assume that the squared - flatness is exceeding the threshold stored in - <code>flatnessSq</code>. Thus, the curve segment - (<i>S<sub>r</sub></i> – <i>C<sub>r</sub></i> – - <i>E<sub>r</sub></i>) is subdivided into a left and a right half, - namely - <i>S<sub>rl</sub></i> – <i>C<sub>rl</sub></i> – - <i>E<sub>rl</sub></i> and <i>S<sub>rr</sub></i> – - <i>C<sub>rr</sub></i> – <i>E<sub>rr</sub></i>. Both halves - are pushed onto the stack.</li></ul> - - The new state is shown in column F.</li> - -<li>The topmost curve segment (<i>S<sub>rl</sub></i> – -<i>C<sub>rl</sub></i> – <i>E<sub>rl</sub></i>) is popped from -the stack. - - <ul><li>The recursion level of this segment (stored in - <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than - the limit 2. Therefore, a <code>SEG_LINETO</code> (from - <i>S<sub>rl</sub></i> to <i>E<sub>rl</sub></i>) is passed to the - consumer.</li></ul> - - The new state is shown in column G.</li> - -<li>The topmost curve segment (<i>S<sub>rr</sub></i> – -<i>C<sub>rr</sub></i> – <i>E<sub>rr</sub></i>) is popped from -the stack. - - <ul><li>The recursion level of this segment (stored in - <code>recLevel[2]</code>) is 2, which is <em>not</em> smaller than - the limit 2. Therefore, a <code>SEG_LINETO</code> (from - <i>S<sub>rr</sub></i> to <i>E<sub>rr</sub></i>) is passed to the - consumer.</li></ul> - - The new state is shown in column H.</li> - -<li>The stack is now empty. The FlatteningPathIterator will fetch the -next segment from the base iterator, and process it.</li> - -</ol> - -<p>In order to split the most recently pushed segment, the -<code>subdivideQuadratic()</code> method passes <code>stack</code> -directly to -<code>QuadCurve2D.subdivide(double[],int,double[],int,double[],int)</code>. -Because the stack grows towards the beginning of the array, no data -needs to be copied around: <code>subdivide</code> will directly store -the result into the stack, which will have the contents shown to the -right.</p> - -</body> -</html> diff --git a/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png b/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png Binary files differdeleted file mode 100644 index d1d75d5..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/GeneralPath-1.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png Binary files differdeleted file mode 100644 index 7c2ec0e..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-1.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png Binary files differdeleted file mode 100644 index 496180c..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-2.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png Binary files differdeleted file mode 100644 index a7557ba..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-3.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png Binary files differdeleted file mode 100644 index 835c064..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-4.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png b/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png Binary files differdeleted file mode 100644 index 72110cd..0000000 --- a/libjava/classpath/java/awt/geom/doc-files/QuadCurve2D-5.png +++ /dev/null diff --git a/libjava/classpath/java/awt/geom/package.html b/libjava/classpath/java/awt/geom/package.html deleted file mode 100644 index c8ee827..0000000 --- a/libjava/classpath/java/awt/geom/package.html +++ /dev/null @@ -1,46 +0,0 @@ -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> -<!-- package.html - describes classes in java.awt.geom package. - Copyright (C) 2002 Free Software Foundation, Inc. - -This file is part of GNU Classpath. - -GNU Classpath is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2, or (at your option) -any later version. - -GNU Classpath is distributed in the hope that it will be useful, but -WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -General Public License for more details. - -You should have received a copy of the GNU General Public License -along with GNU Classpath; see the file COPYING. If not, write to the -Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301 USA. - -Linking this library statically or dynamically with other modules is -making a combined work based on this library. Thus, the terms and -conditions of the GNU General Public License cover the whole -combination. - -As a special exception, the copyright holders of this library give you -permission to link this library with independent modules to produce an -executable, regardless of the license terms of these independent -modules, and to copy and distribute the resulting executable under -terms of your choice, provided that you also meet, for each linked -independent module, the terms and conditions of the license of that -module. An independent module is a module which is not derived from -or based on this library. If you modify this library, you may extend -this exception to your version of the library, but you are not -obligated to do so. If you do not wish to do so, delete this -exception statement from your version. --> - -<html> -<head><title>GNU Classpath - java.awt.geom</title></head> - -<body> -<p>Classes to represent 2D objects and different path transformations.</p> - -</body> -</html> |