summaryrefslogtreecommitdiffstats
path: root/awt/java/awt/geom/Ellipse2D.java
diff options
context:
space:
mode:
Diffstat (limited to 'awt/java/awt/geom/Ellipse2D.java')
-rw-r--r--awt/java/awt/geom/Ellipse2D.java403
1 files changed, 403 insertions, 0 deletions
diff --git a/awt/java/awt/geom/Ellipse2D.java b/awt/java/awt/geom/Ellipse2D.java
new file mode 100644
index 0000000..33464af
--- /dev/null
+++ b/awt/java/awt/geom/Ellipse2D.java
@@ -0,0 +1,403 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @author Denis M. Kishenko
+ * @version $Revision$
+ */
+package java.awt.geom;
+
+import java.util.NoSuchElementException;
+
+import org.apache.harmony.awt.internal.nls.Messages;
+
+/**
+ * The Class Ellipse2D describes an ellipse defined by a rectangular
+ * area in which it is inscribed.
+ */
+public abstract class Ellipse2D extends RectangularShape {
+
+ /**
+ * The Class Float is the subclass of Ellipse2D that has all
+ * of its data values stored with float-level precision.
+ */
+ public static class Float extends Ellipse2D {
+
+ /** The x coordinate of the upper left corner of the ellipse's
+ * bounding rectangle. */
+ public float x;
+
+ /** The y coordinate of the upper left corner of the ellipse's
+ * bounding rectangle. */
+ public float y;
+
+ /** The width of the ellipse's bounding rectangle. */
+ public float width;
+
+ /** The height of the ellipse's bounding rectangle. */
+ public float height;
+
+ /**
+ * Instantiates a new float-valued Ellipse2D.
+ */
+ public Float() {
+ }
+
+ /**
+ * Instantiates a new float-valued Ellipse2D with the specified data.
+ *
+ * @param x the x coordinate of the upper left corner of the ellipse's
+ * bounding rectangle
+ * @param y the y coordinate of the upper left corner of the ellipse's
+ * bounding rectangle
+ * @param width the width of the ellipse's bounding rectangle
+ * @param height the height of the ellipse's bounding rectangle
+ */
+ public Float(float x, float y, float width, float height) {
+ setFrame(x, y, width, height);
+ }
+
+ @Override
+ public double getX() {
+ return x;
+ }
+
+ @Override
+ public double getY() {
+ return y;
+ }
+
+ @Override
+ public double getWidth() {
+ return width;
+ }
+
+ @Override
+ public double getHeight() {
+ return height;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return width <= 0.0 || height <= 0.0;
+ }
+
+ /**
+ * Sets the data of the ellipse's bounding rectangle.
+ *
+ * @param x the x coordinate of the upper left corner of the ellipse's
+ * bounding rectangle
+ * @param y the y coordinate of the upper left corner of the ellipse's
+ * bounding rectangle
+ * @param width the width of the ellipse's bounding rectangle
+ * @param height the height of the ellipse's bounding rectangle
+ */
+ public void setFrame(float x, float y, float width, float height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ @Override
+ public void setFrame(double x, double y, double width, double height) {
+ this.x = (float)x;
+ this.y = (float)y;
+ this.width = (float)width;
+ this.height = (float)height;
+ }
+
+ public Rectangle2D getBounds2D() {
+ return new Rectangle2D.Float(x, y, width, height);
+ }
+ }
+
+ /**
+ * The Class Double is the subclass of Ellipse2D that has all
+ * of its data values stored with double-level precision.
+ */
+ public static class Double extends Ellipse2D {
+
+ /** The x coordinate of the upper left corner of the ellipse's
+ * bounding rectangle. */
+ public double x;
+
+ /** The y coordinate of the upper left corner of the ellipse's
+ * bounding rectangle. */
+ public double y;
+
+ /** The width of the ellipse's bounding rectangle. */
+ public double width;
+
+ /** The height of the ellipse's bounding rectangle. */
+ public double height;
+
+ /**
+ * Instantiates a new double-valued Ellipse2D.
+ */
+ public Double() {
+ }
+
+ /**
+ * Instantiates a new double-valued Ellipse2D with the specified
+ * data.
+ *
+ * @param x the x coordinate of the upper left corner of the ellipse's
+ * bounding rectangle
+ * @param y the y coordinate of the upper left corner of the ellipse's
+ * bounding rectangle
+ * @param width the width of the ellipse's bounding rectangle
+ * @param height the height of the ellipse's bounding rectangle
+ */
+ public Double(double x, double y, double width, double height) {
+ setFrame(x, y, width, height);
+ }
+
+ @Override
+ public double getX() {
+ return x;
+ }
+
+ @Override
+ public double getY() {
+ return y;
+ }
+
+ @Override
+ public double getWidth() {
+ return width;
+ }
+
+ @Override
+ public double getHeight() {
+ return height;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return width <= 0.0 || height <= 0.0;
+ }
+
+ @Override
+ public void setFrame(double x, double y, double width, double height) {
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+
+ public Rectangle2D getBounds2D() {
+ return new Rectangle2D.Double(x, y, width, height);
+ }
+ }
+
+ /*
+ * Ellipse2D path iterator
+ */
+ /**
+ * The subclass of PathIterator to traverse an Ellipse2D.
+ */
+ class Iterator implements PathIterator {
+
+ /*
+ * Ellipse is subdivided into four quarters by x and y axis. Each part approximated by
+ * cubic Bezier curve. Arc in first quarter is started in (a, 0) and finished in (0, b) points.
+ * Control points for cubic curve wiil be (a, 0), (a, m), (n, b) and (0, b) where n and m are
+ * calculated based on requirement Bezier curve in point 0.5 should lay on the arc.
+ */
+
+ /** The coefficient to calculate control points of Bezier curves. */
+ final double u = 2.0 / 3.0 * (Math.sqrt(2.0) - 1.0);
+
+ /** The points coordinates calculation table. */
+ final double points[][] = {
+ { 1.0, 0.5 + u, 0.5 + u, 1.0, 0.5, 1.0 },
+ { 0.5 - u, 1.0, 0.0, 0.5 + u, 0.0, 0.5 },
+ { 0.0, 0.5 - u, 0.5 - u, 0.0, 0.5, 0.0 },
+ { 0.5 + u, 0.0, 1.0, 0.5 - u, 1.0, 0.5 }
+ };
+
+ /** The x coordinate of left-upper corner of the ellipse bounds. */
+ double x;
+
+ /** The y coordinate of left-upper corner of the ellipse bounds. */
+ double y;
+
+ /** The width of the ellipse bounds. */
+ double width;
+
+ /** The height of the ellipse bounds. */
+ double height;
+
+ /** The path iterator transformation. */
+ AffineTransform t;
+
+ /** The current segmenet index. */
+ int index;
+
+ /**
+ * Constructs a new Ellipse2D.Iterator for given ellipse and transformation
+ *
+ * @param e - the source Ellipse2D object
+ * @param t the t
+ */
+ Iterator(Ellipse2D e, AffineTransform t) {
+ this.x = e.getX();
+ this.y = e.getY();
+ this.width = e.getWidth();
+ this.height = e.getHeight();
+ this.t = t;
+ if (width < 0.0 || height < 0.0) {
+ index = 6;
+ }
+ }
+
+ public int getWindingRule() {
+ return WIND_NON_ZERO;
+ }
+
+ public boolean isDone() {
+ return index > 5;
+ }
+
+ public void next() {
+ index++;
+ }
+
+ public int currentSegment(double[] coords) {
+ if (isDone()) {
+ // awt.4B=Iterator out of bounds
+ throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+ }
+ if (index == 5) {
+ return SEG_CLOSE;
+ }
+ int type;
+ int count;
+ if (index == 0) {
+ type = SEG_MOVETO;
+ count = 1;
+ double p[] = points[3];
+ coords[0] = x + p[4] * width;
+ coords[1] = y + p[5] * height;
+ } else {
+ type = SEG_CUBICTO;
+ count = 3;
+ double p[] = points[index - 1];
+ int j = 0;
+ for (int i = 0; i < 3; i++) {
+ coords[j] = x + p[j++] * width;
+ coords[j] = y + p[j++] * height;
+ }
+ }
+ if (t != null) {
+ t.transform(coords, 0, coords, 0, count);
+ }
+ return type;
+ }
+
+ public int currentSegment(float[] coords) {
+ if (isDone()) {
+ // awt.4B=Iterator out of bounds
+ throw new NoSuchElementException(Messages.getString("awt.4B")); //$NON-NLS-1$
+ }
+ if (index == 5) {
+ return SEG_CLOSE;
+ }
+ int type;
+ int count;
+ if (index == 0) {
+ type = SEG_MOVETO;
+ count = 1;
+ double p[] = points[3];
+ coords[0] = (float)(x + p[4] * width);
+ coords[1] = (float)(y + p[5] * height);
+ } else {
+ type = SEG_CUBICTO;
+ count = 3;
+ int j = 0;
+ double p[] = points[index - 1];
+ for (int i = 0; i < 3; i++) {
+ coords[j] = (float)(x + p[j++] * width);
+ coords[j] = (float)(y + p[j++] * height);
+ }
+ }
+ if (t != null) {
+ t.transform(coords, 0, coords, 0, count);
+ }
+ return type;
+ }
+
+ }
+
+ /**
+ * Instantiates a new Ellipse2D.
+ */
+ protected Ellipse2D() {
+ }
+
+ public boolean contains(double px, double py) {
+ if (isEmpty()) {
+ return false;
+ }
+
+ double a = (px - getX()) / getWidth() - 0.5;
+ double b = (py - getY()) / getHeight() - 0.5;
+
+ return a * a + b * b < 0.25;
+ }
+
+ public boolean intersects(double rx, double ry, double rw, double rh) {
+ if (isEmpty() || rw <= 0.0 || rh <= 0.0) {
+ return false;
+ }
+
+ double cx = getX() + getWidth() / 2.0;
+ double cy = getY() + getHeight() / 2.0;
+
+ double rx1 = rx;
+ double ry1 = ry;
+ double rx2 = rx + rw;
+ double ry2 = ry + rh;
+
+ double nx = cx < rx1 ? rx1 : (cx > rx2 ? rx2 : cx);
+ double ny = cy < ry1 ? ry1 : (cy > ry2 ? ry2 : cy);
+
+ return contains(nx, ny);
+ }
+
+ public boolean contains(double rx, double ry, double rw, double rh) {
+ if (isEmpty() || rw <= 0.0 || rh <= 0.0) {
+ return false;
+ }
+
+ double rx1 = rx;
+ double ry1 = ry;
+ double rx2 = rx + rw;
+ double ry2 = ry + rh;
+
+ return
+ contains(rx1, ry1) &&
+ contains(rx2, ry1) &&
+ contains(rx2, ry2) &&
+ contains(rx1, ry2);
+ }
+
+ public PathIterator getPathIterator(AffineTransform at) {
+ return new Iterator(this, at);
+ }
+}
+