919 lines
30 KiB
Java
919 lines
30 KiB
Java
/*
|
|
* 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.awt.Rectangle;
|
|
import java.awt.Shape;
|
|
import java.util.NoSuchElementException;
|
|
|
|
import org.apache.harmony.awt.gl.Crossing;
|
|
import org.apache.harmony.awt.internal.nls.Messages;
|
|
|
|
/**
|
|
* The Class QuadCurve2D is a Shape that represents a segment of a quadratic
|
|
* (Bezier) curve. The curved segment is determined by three points: a start
|
|
* point, an end point, and a control point. The line from the control point to
|
|
* the starting point gives the tangent to the curve at the starting point, and
|
|
* the line from the control point to the end point gives the tangent to the
|
|
* curve at the end point.
|
|
*
|
|
* @since Android 1.0
|
|
*/
|
|
public abstract class QuadCurve2D implements Shape, Cloneable {
|
|
|
|
/**
|
|
* The Class Float is the subclass of QuadCurve2D that has all of its data
|
|
* values stored with float-level precision.
|
|
*
|
|
* @since Android 1.0
|
|
*/
|
|
public static class Float extends QuadCurve2D {
|
|
|
|
/**
|
|
* The x coordinate of the starting point of the curved segment.
|
|
*/
|
|
public float x1;
|
|
|
|
/**
|
|
* The y coordinate of the starting point of the curved segment.
|
|
*/
|
|
public float y1;
|
|
|
|
/**
|
|
* The x coordinate of the control point.
|
|
*/
|
|
public float ctrlx;
|
|
|
|
/**
|
|
* The y coordinate of the control point.
|
|
*/
|
|
public float ctrly;
|
|
|
|
/**
|
|
* The x coordinate of the end point of the curved segment.
|
|
*/
|
|
public float x2;
|
|
|
|
/**
|
|
* The y coordinate of the end point of the curved segment.
|
|
*/
|
|
public float y2;
|
|
|
|
/**
|
|
* Instantiates a new float-valued QuadCurve2D with all coordinate
|
|
* values set to zero.
|
|
*/
|
|
public Float() {
|
|
}
|
|
|
|
/**
|
|
* Instantiates a new float-valued QuadCurve2D with the specified
|
|
* coordinate values.
|
|
*
|
|
* @param x1
|
|
* the x coordinate of the starting point of the curved
|
|
* segment.
|
|
* @param y1
|
|
* the y coordinate of the starting point of the curved
|
|
* segment.
|
|
* @param ctrlx
|
|
* the x coordinate of the control point.
|
|
* @param ctrly
|
|
* the y coordinate of the control point.
|
|
* @param x2
|
|
* the x coordinate of the end point of the curved segment.
|
|
* @param y2
|
|
* the y coordinate of the end point of the curved segment.
|
|
*/
|
|
public Float(float x1, float y1, float ctrlx, float ctrly, float x2, float y2) {
|
|
setCurve(x1, y1, ctrlx, ctrly, x2, y2);
|
|
}
|
|
|
|
@Override
|
|
public double getX1() {
|
|
return x1;
|
|
}
|
|
|
|
@Override
|
|
public double getY1() {
|
|
return y1;
|
|
}
|
|
|
|
@Override
|
|
public double getCtrlX() {
|
|
return ctrlx;
|
|
}
|
|
|
|
@Override
|
|
public double getCtrlY() {
|
|
return ctrly;
|
|
}
|
|
|
|
@Override
|
|
public double getX2() {
|
|
return x2;
|
|
}
|
|
|
|
@Override
|
|
public double getY2() {
|
|
return y2;
|
|
}
|
|
|
|
@Override
|
|
public Point2D getP1() {
|
|
return new Point2D.Float(x1, y1);
|
|
}
|
|
|
|
@Override
|
|
public Point2D getCtrlPt() {
|
|
return new Point2D.Float(ctrlx, ctrly);
|
|
}
|
|
|
|
@Override
|
|
public Point2D getP2() {
|
|
return new Point2D.Float(x2, y2);
|
|
}
|
|
|
|
@Override
|
|
public void setCurve(double x1, double y1, double ctrlx, double ctrly, double x2, double y2) {
|
|
this.x1 = (float)x1;
|
|
this.y1 = (float)y1;
|
|
this.ctrlx = (float)ctrlx;
|
|
this.ctrly = (float)ctrly;
|
|
this.x2 = (float)x2;
|
|
this.y2 = (float)y2;
|
|
}
|
|
|
|
/**
|
|
* Sets the data values of the curve.
|
|
*
|
|
* @param x1
|
|
* the x coordinate of the starting point of the curved
|
|
* segment.
|
|
* @param y1
|
|
* the y coordinate of the starting point of the curved
|
|
* segment.
|
|
* @param ctrlx
|
|
* the x coordinate of the control point.
|
|
* @param ctrly
|
|
* the y coordinate of the control point.
|
|
* @param x2
|
|
* the x coordinate of the end point of the curved segment.
|
|
* @param y2
|
|
* the y coordinate of the end point of the curved segment.
|
|
*/
|
|
public void setCurve(float x1, float y1, float ctrlx, float ctrly, float x2, float y2) {
|
|
this.x1 = x1;
|
|
this.y1 = y1;
|
|
this.ctrlx = ctrlx;
|
|
this.ctrly = ctrly;
|
|
this.x2 = x2;
|
|
this.y2 = y2;
|
|
}
|
|
|
|
public Rectangle2D getBounds2D() {
|
|
float rx0 = Math.min(Math.min(x1, x2), ctrlx);
|
|
float ry0 = Math.min(Math.min(y1, y2), ctrly);
|
|
float rx1 = Math.max(Math.max(x1, x2), ctrlx);
|
|
float ry1 = Math.max(Math.max(y1, y2), ctrly);
|
|
return new Rectangle2D.Float(rx0, ry0, rx1 - rx0, ry1 - ry0);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* The Class Double is the subclass of QuadCurve2D that has all of its data
|
|
* values stored with double-level precision.
|
|
*
|
|
* @since Android 1.0
|
|
*/
|
|
public static class Double extends QuadCurve2D {
|
|
|
|
/**
|
|
* The x coordinate of the starting point of the curved segment.
|
|
*/
|
|
public double x1;
|
|
|
|
/**
|
|
* The y coordinate of the starting point of the curved segment.
|
|
*/
|
|
public double y1;
|
|
|
|
/**
|
|
* The x coordinate of the control point.
|
|
*/
|
|
public double ctrlx;
|
|
|
|
/**
|
|
* The y coordinate of the control point.
|
|
*/
|
|
public double ctrly;
|
|
|
|
/**
|
|
* The x coordinate of the end point of the curved segment.
|
|
*/
|
|
public double x2;
|
|
|
|
/**
|
|
* The y coordinate of the end point of the curved segment.
|
|
*/
|
|
public double y2;
|
|
|
|
/**
|
|
* Instantiates a new double-valued QuadCurve2D with all coordinate
|
|
* values set to zero.
|
|
*/
|
|
public Double() {
|
|
}
|
|
|
|
/**
|
|
* Instantiates a new double-valued QuadCurve2D with the specified
|
|
* coordinate values.
|
|
*
|
|
* @param x1
|
|
* the x coordinate of the starting point of the curved
|
|
* segment.
|
|
* @param y1
|
|
* the y coordinate of the starting point of the curved
|
|
* segment.
|
|
* @param ctrlx
|
|
* the x coordinate of the control point.
|
|
* @param ctrly
|
|
* the y coordinate of the control point.
|
|
* @param x2
|
|
* the x coordinate of the end point of the curved segment.
|
|
* @param y2
|
|
* the y coordinate of the end point of the curved segment.
|
|
*/
|
|
public Double(double x1, double y1, double ctrlx, double ctrly, double x2, double y2) {
|
|
setCurve(x1, y1, ctrlx, ctrly, x2, y2);
|
|
}
|
|
|
|
@Override
|
|
public double getX1() {
|
|
return x1;
|
|
}
|
|
|
|
@Override
|
|
public double getY1() {
|
|
return y1;
|
|
}
|
|
|
|
@Override
|
|
public double getCtrlX() {
|
|
return ctrlx;
|
|
}
|
|
|
|
@Override
|
|
public double getCtrlY() {
|
|
return ctrly;
|
|
}
|
|
|
|
@Override
|
|
public double getX2() {
|
|
return x2;
|
|
}
|
|
|
|
@Override
|
|
public double getY2() {
|
|
return y2;
|
|
}
|
|
|
|
@Override
|
|
public Point2D getP1() {
|
|
return new Point2D.Double(x1, y1);
|
|
}
|
|
|
|
@Override
|
|
public Point2D getCtrlPt() {
|
|
return new Point2D.Double(ctrlx, ctrly);
|
|
}
|
|
|
|
@Override
|
|
public Point2D getP2() {
|
|
return new Point2D.Double(x2, y2);
|
|
}
|
|
|
|
@Override
|
|
public void setCurve(double x1, double y1, double ctrlx, double ctrly, double x2, double y2) {
|
|
this.x1 = x1;
|
|
this.y1 = y1;
|
|
this.ctrlx = ctrlx;
|
|
this.ctrly = ctrly;
|
|
this.x2 = x2;
|
|
this.y2 = y2;
|
|
}
|
|
|
|
public Rectangle2D getBounds2D() {
|
|
double rx0 = Math.min(Math.min(x1, x2), ctrlx);
|
|
double ry0 = Math.min(Math.min(y1, y2), ctrly);
|
|
double rx1 = Math.max(Math.max(x1, x2), ctrlx);
|
|
double ry1 = Math.max(Math.max(y1, y2), ctrly);
|
|
return new Rectangle2D.Double(rx0, ry0, rx1 - rx0, ry1 - ry0);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* QuadCurve2D path iterator
|
|
*/
|
|
/**
|
|
* The PathIterator for a Quad2D curve.
|
|
*/
|
|
class Iterator implements PathIterator {
|
|
|
|
/**
|
|
* The source QuadCurve2D object.
|
|
*/
|
|
QuadCurve2D c;
|
|
|
|
/**
|
|
* The path iterator transformation.
|
|
*/
|
|
AffineTransform t;
|
|
|
|
/**
|
|
* The current segment index.
|
|
*/
|
|
int index;
|
|
|
|
/**
|
|
* Constructs a new QuadCurve2D.Iterator for given curve and
|
|
* transformation
|
|
*
|
|
* @param q
|
|
* the source QuadCurve2D object.
|
|
* @param t
|
|
* the AffineTransform that acts on the coordinates before
|
|
* returning them (or null).
|
|
*/
|
|
Iterator(QuadCurve2D q, AffineTransform t) {
|
|
this.c = q;
|
|
this.t = t;
|
|
}
|
|
|
|
public int getWindingRule() {
|
|
return WIND_NON_ZERO;
|
|
}
|
|
|
|
public boolean isDone() {
|
|
return (index > 1);
|
|
}
|
|
|
|
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$
|
|
}
|
|
int type;
|
|
int count;
|
|
if (index == 0) {
|
|
type = SEG_MOVETO;
|
|
coords[0] = c.getX1();
|
|
coords[1] = c.getY1();
|
|
count = 1;
|
|
} else {
|
|
type = SEG_QUADTO;
|
|
coords[0] = c.getCtrlX();
|
|
coords[1] = c.getCtrlY();
|
|
coords[2] = c.getX2();
|
|
coords[3] = c.getY2();
|
|
count = 2;
|
|
}
|
|
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$
|
|
}
|
|
int type;
|
|
int count;
|
|
if (index == 0) {
|
|
type = SEG_MOVETO;
|
|
coords[0] = (float)c.getX1();
|
|
coords[1] = (float)c.getY1();
|
|
count = 1;
|
|
} else {
|
|
type = SEG_QUADTO;
|
|
coords[0] = (float)c.getCtrlX();
|
|
coords[1] = (float)c.getCtrlY();
|
|
coords[2] = (float)c.getX2();
|
|
coords[3] = (float)c.getY2();
|
|
count = 2;
|
|
}
|
|
if (t != null) {
|
|
t.transform(coords, 0, coords, 0, count);
|
|
}
|
|
return type;
|
|
}
|
|
|
|
}
|
|
|
|
/**
|
|
* Instantiates a new quadratic curve.
|
|
*/
|
|
protected QuadCurve2D() {
|
|
}
|
|
|
|
/**
|
|
* Gets the x coordinate of the starting point.
|
|
*
|
|
* @return the x coordinate of the starting point.
|
|
*/
|
|
public abstract double getX1();
|
|
|
|
/**
|
|
* Gets the y coordinate of the starting point.
|
|
*
|
|
* @return the y coordinate of the starting point.
|
|
*/
|
|
public abstract double getY1();
|
|
|
|
/**
|
|
* Gets the starting point.
|
|
*
|
|
* @return the starting point.
|
|
*/
|
|
public abstract Point2D getP1();
|
|
|
|
/**
|
|
* Gets the x coordinate of the control point.
|
|
*
|
|
* @return the x coordinate of the control point.
|
|
*/
|
|
public abstract double getCtrlX();
|
|
|
|
/**
|
|
* Gets the y coordinate of the control point.
|
|
*
|
|
* @return y coordinate of the control point.
|
|
*/
|
|
public abstract double getCtrlY();
|
|
|
|
/**
|
|
* Gets the control point.
|
|
*
|
|
* @return the control point.
|
|
*/
|
|
public abstract Point2D getCtrlPt();
|
|
|
|
/**
|
|
* Gets the x coordinate of the end point.
|
|
*
|
|
* @return the x coordinate of the end point.
|
|
*/
|
|
public abstract double getX2();
|
|
|
|
/**
|
|
* Gets the y coordinate of the end point.
|
|
*
|
|
* @return the y coordinate of the end point.
|
|
*/
|
|
public abstract double getY2();
|
|
|
|
/**
|
|
* Gets the end point.
|
|
*
|
|
* @return the end point.
|
|
*/
|
|
public abstract Point2D getP2();
|
|
|
|
/**
|
|
* Sets the data of the curve.
|
|
*
|
|
* @param x1
|
|
* the x coordinate of the starting point of the curved segment.
|
|
* @param y1
|
|
* the y coordinate of the starting point of the curved segment.
|
|
* @param ctrlx
|
|
* the x coordinate of the control point.
|
|
* @param ctrly
|
|
* the y coordinate of the control point.
|
|
* @param x2
|
|
* the x coordinate of the end point of the curved segment.
|
|
* @param y2
|
|
* the y coordinate of the end point of the curved segment.
|
|
*/
|
|
public abstract void setCurve(double x1, double y1, double ctrlx, double ctrly, double x2,
|
|
double y2);
|
|
|
|
/**
|
|
* Sets the data of the curve.
|
|
*
|
|
* @param p1
|
|
* the starting point of the curved segment.
|
|
* @param cp
|
|
* the control point.
|
|
* @param p2
|
|
* the end point of the curved segment.
|
|
* @throws NullPointerException
|
|
* if any of the three points is null.
|
|
*/
|
|
public void setCurve(Point2D p1, Point2D cp, Point2D p2) {
|
|
setCurve(p1.getX(), p1.getY(), cp.getX(), cp.getY(), p2.getX(), p2.getY());
|
|
}
|
|
|
|
/**
|
|
* Sets the data of the curve by reading the data from an array of values.
|
|
* The values are read in the same order as the arguments of the method
|
|
* {@link QuadCurve2D#setCurve(double, double, double, double, double, double)}
|
|
* .
|
|
*
|
|
* @param coords
|
|
* the array of values containing the new coordinates.
|
|
* @param offset
|
|
* the offset of the data to read within the array.
|
|
* @throws ArrayIndexOutOfBoundsException
|
|
* if {@code coords.length} < offset + 6.
|
|
* @throws NullPointerException
|
|
* if the coordinate array is null.
|
|
*/
|
|
public void setCurve(double[] coords, int offset) {
|
|
setCurve(coords[offset + 0], coords[offset + 1], coords[offset + 2], coords[offset + 3],
|
|
coords[offset + 4], coords[offset + 5]);
|
|
}
|
|
|
|
/**
|
|
* Sets the data of the curve by reading the data from an array of points.
|
|
* The values are read in the same order as the arguments of the method
|
|
* {@link QuadCurve2D#setCurve(Point2D, Point2D, Point2D)}.
|
|
*
|
|
* @param points
|
|
* the array of points containing the new coordinates.
|
|
* @param offset
|
|
* the offset of the data to read within the array.
|
|
* @throws ArrayIndexOutOfBoundsException
|
|
* if points.length < offset + 3.
|
|
* @throws NullPointerException
|
|
* if the point array is null.
|
|
*/
|
|
public void setCurve(Point2D[] points, int offset) {
|
|
setCurve(points[offset + 0].getX(), points[offset + 0].getY(), points[offset + 1].getX(),
|
|
points[offset + 1].getY(), points[offset + 2].getX(), points[offset + 2].getY());
|
|
}
|
|
|
|
/**
|
|
* Sets the data of the curve by copying it from another QuadCurve2D.
|
|
*
|
|
* @param curve
|
|
* the curve to copy the data points from.
|
|
* @throws NullPointerException
|
|
* if the curve is null.
|
|
*/
|
|
public void setCurve(QuadCurve2D curve) {
|
|
setCurve(curve.getX1(), curve.getY1(), curve.getCtrlX(), curve.getCtrlY(), curve.getX2(),
|
|
curve.getY2());
|
|
}
|
|
|
|
/**
|
|
* Gets the square of the distance from the control point to the straight
|
|
* line segment connecting the start point and the end point for this curve.
|
|
*
|
|
* @return the square of the distance from the control point to the straight
|
|
* line segment connecting the start point and the end point.
|
|
*/
|
|
public double getFlatnessSq() {
|
|
return Line2D.ptSegDistSq(getX1(), getY1(), getX2(), getY2(), getCtrlX(), getCtrlY());
|
|
}
|
|
|
|
/**
|
|
* Gets the square of the distance from the control point to the straight
|
|
* line segment connecting the start point and the end point.
|
|
*
|
|
* @param x1
|
|
* the x coordinate of the starting point of the curved segment.
|
|
* @param y1
|
|
* the y coordinate of the starting point of the curved segment.
|
|
* @param ctrlx
|
|
* the x coordinate of the control point.
|
|
* @param ctrly
|
|
* the y coordinate of the control point.
|
|
* @param x2
|
|
* the x coordinate of the end point of the curved segment.
|
|
* @param y2
|
|
* the y coordinate of the end point of the curved segment.
|
|
* @return the square of the distance from the control point to the straight
|
|
* line segment connecting the start point and the end point.
|
|
*/
|
|
public static double getFlatnessSq(double x1, double y1, double ctrlx, double ctrly, double x2,
|
|
double y2) {
|
|
return Line2D.ptSegDistSq(x1, y1, x2, y2, ctrlx, ctrly);
|
|
}
|
|
|
|
/**
|
|
* Gets the square of the distance from the control point to the straight
|
|
* line segment connecting the start point and the end point by reading the
|
|
* coordinates of the points from an array of values. The values are read in
|
|
* the same order as the arguments of the method
|
|
* {@link QuadCurve2D#getFlatnessSq(double, double, double, double, double, double)}
|
|
* .
|
|
*
|
|
* @param coords
|
|
* the array of points containing the coordinates to use for the
|
|
* calculation
|
|
* @param offset
|
|
* the offset of the data to read within the array
|
|
* @return the square of the distance from the control point to the straight
|
|
* line segment connecting the start point and the end point.
|
|
* @throws ArrayIndexOutOfBoundsException
|
|
* if {@code coords.length} < offset + 6.
|
|
* @throws NullPointerException
|
|
* if the coordinate array is null.
|
|
*/
|
|
public static double getFlatnessSq(double coords[], int offset) {
|
|
return Line2D.ptSegDistSq(coords[offset + 0], coords[offset + 1], coords[offset + 4],
|
|
coords[offset + 5], coords[offset + 2], coords[offset + 3]);
|
|
}
|
|
|
|
/**
|
|
* Gets the distance from the control point to the straight line segment
|
|
* connecting the start point and the end point of this QuadCurve2D.
|
|
*
|
|
* @return the the distance from the control point to the straight line
|
|
* segment connecting the start point and the end point of this
|
|
* QuadCurve2D.
|
|
*/
|
|
public double getFlatness() {
|
|
return Line2D.ptSegDist(getX1(), getY1(), getX2(), getY2(), getCtrlX(), getCtrlY());
|
|
}
|
|
|
|
/**
|
|
* Gets the distance from the control point to the straight line segment
|
|
* connecting the start point and the end point.
|
|
*
|
|
* @param x1
|
|
* the x coordinate of the starting point of the curved segment.
|
|
* @param y1
|
|
* the y coordinate of the starting point of the curved segment.
|
|
* @param ctrlx
|
|
* the x coordinate of the control point.
|
|
* @param ctrly
|
|
* the y coordinate of the control point.
|
|
* @param x2
|
|
* the x coordinate of the end point of the curved segment.
|
|
* @param y2
|
|
* the y coordinate of the end point of the curved segment.
|
|
* @return the the distance from the control point to the straight line
|
|
* segment connecting the start point and the end point.
|
|
*/
|
|
public static double getFlatness(double x1, double y1, double ctrlx, double ctrly, double x2,
|
|
double y2) {
|
|
return Line2D.ptSegDist(x1, y1, x2, y2, ctrlx, ctrly);
|
|
}
|
|
|
|
/**
|
|
* Gets the the distance from the control point to the straight line segment
|
|
* connecting the start point and the end point. The values are read in the
|
|
* same order as the arguments of the method
|
|
* {@link QuadCurve2D#getFlatness(double, double, double, double, double, double)}
|
|
* .
|
|
*
|
|
* @param coords
|
|
* the array of points containing the coordinates to use for the
|
|
* calculation.
|
|
* @param offset
|
|
* the offset of the data to read within the array.
|
|
* @return the the distance from the control point to the straight line
|
|
* segment connecting the start point and the end point.
|
|
* @throws ArrayIndexOutOfBoundsException
|
|
* if {code coords.length} < offset + 6.
|
|
* @throws NullPointerException
|
|
* if the coordinate array is null.
|
|
*/
|
|
public static double getFlatness(double coords[], int offset) {
|
|
return Line2D.ptSegDist(coords[offset + 0], coords[offset + 1], coords[offset + 4],
|
|
coords[offset + 5], coords[offset + 2], coords[offset + 3]);
|
|
}
|
|
|
|
/**
|
|
* Creates the data for two quadratic curves by dividing this curve in two.
|
|
* The division point is the point on the curve that is closest to this
|
|
* curve's control point. The data of this curve is left unchanged.
|
|
*
|
|
* @param left
|
|
* the QuadCurve2D where the left (start) segment's data is
|
|
* written.
|
|
* @param right
|
|
* the QuadCurve2D where the right (end) segment's data is
|
|
* written.
|
|
* @throws NullPointerException
|
|
* if either curve is null.
|
|
*/
|
|
public void subdivide(QuadCurve2D left, QuadCurve2D right) {
|
|
subdivide(this, left, right);
|
|
}
|
|
|
|
/**
|
|
* Creates the data for two quadratic curves by dividing a source curve in
|
|
* two. The division point is the point on the curve that is closest to the
|
|
* source curve's control point. The data of the source curve is left
|
|
* unchanged.
|
|
*
|
|
* @param src
|
|
* the curve that provides the initial data.
|
|
* @param left
|
|
* the QuadCurve2D where the left (start) segment's data is
|
|
* written.
|
|
* @param right
|
|
* the QuadCurve2D where the right (end) segment's data is
|
|
* written.
|
|
* @throws NullPointerException
|
|
* if one of the curves is null.
|
|
*/
|
|
public static void subdivide(QuadCurve2D src, QuadCurve2D left, QuadCurve2D right) {
|
|
double x1 = src.getX1();
|
|
double y1 = src.getY1();
|
|
double cx = src.getCtrlX();
|
|
double cy = src.getCtrlY();
|
|
double x2 = src.getX2();
|
|
double y2 = src.getY2();
|
|
double cx1 = (x1 + cx) / 2.0;
|
|
double cy1 = (y1 + cy) / 2.0;
|
|
double cx2 = (x2 + cx) / 2.0;
|
|
double cy2 = (y2 + cy) / 2.0;
|
|
cx = (cx1 + cx2) / 2.0;
|
|
cy = (cy1 + cy2) / 2.0;
|
|
if (left != null) {
|
|
left.setCurve(x1, y1, cx1, cy1, cx, cy);
|
|
}
|
|
if (right != null) {
|
|
right.setCurve(cx, cy, cx2, cy2, x2, y2);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates the data for two quadratic curves by dividing a source curve in
|
|
* two. The division point is the point on the curve that is closest to the
|
|
* source curve's control point. The data for the three curves is read and
|
|
* written from arrays of values in the usual order: x1, y1, cx, cy, x2, y2.
|
|
*
|
|
* @param src
|
|
* the array that gives the data values for the source curve.
|
|
* @param srcoff
|
|
* the offset in the src array to read the values from.
|
|
* @param left
|
|
* the array where the coordinates of the start curve should be
|
|
* written.
|
|
* @param leftOff
|
|
* the offset in the left array to start writing the values.
|
|
* @param right
|
|
* the array where the coordinates of the end curve should be
|
|
* written.
|
|
* @param rightOff
|
|
* the offset in the right array to start writing the values.
|
|
* @throws ArrayIndexOutOfBoundsException
|
|
* if {@code src.length} < srcoff + 6 or if {@code left.length}
|
|
* < leftOff + 6 or if {@code right.length} < rightOff + 6.
|
|
* @throws NullPointerException
|
|
* if one of the arrays is null.
|
|
*/
|
|
public static void subdivide(double src[], int srcoff, double left[], int leftOff,
|
|
double right[], int rightOff) {
|
|
double x1 = src[srcoff + 0];
|
|
double y1 = src[srcoff + 1];
|
|
double cx = src[srcoff + 2];
|
|
double cy = src[srcoff + 3];
|
|
double x2 = src[srcoff + 4];
|
|
double y2 = src[srcoff + 5];
|
|
double cx1 = (x1 + cx) / 2.0;
|
|
double cy1 = (y1 + cy) / 2.0;
|
|
double cx2 = (x2 + cx) / 2.0;
|
|
double cy2 = (y2 + cy) / 2.0;
|
|
cx = (cx1 + cx2) / 2.0;
|
|
cy = (cy1 + cy2) / 2.0;
|
|
if (left != null) {
|
|
left[leftOff + 0] = x1;
|
|
left[leftOff + 1] = y1;
|
|
left[leftOff + 2] = cx1;
|
|
left[leftOff + 3] = cy1;
|
|
left[leftOff + 4] = cx;
|
|
left[leftOff + 5] = cy;
|
|
}
|
|
if (right != null) {
|
|
right[rightOff + 0] = cx;
|
|
right[rightOff + 1] = cy;
|
|
right[rightOff + 2] = cx2;
|
|
right[rightOff + 3] = cy2;
|
|
right[rightOff + 4] = x2;
|
|
right[rightOff + 5] = y2;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Finds the roots of the quadratic polynomial. This is accomplished by
|
|
* finding the (real) values of x that solve the following equation:
|
|
* eqn[2]*x*x + eqn[1]*x + eqn[0] = 0. The solutions are written back into
|
|
* the array eqn starting from the index 0 in the array. The return value
|
|
* tells how many array elements have been changed by this method call.
|
|
*
|
|
* @param eqn
|
|
* an array containing the coefficients of the quadratic
|
|
* polynomial to solve.
|
|
* @return the number of roots of the quadratic polynomial.
|
|
* @throws ArrayIndexOutOfBoundsException
|
|
* if {@code eqn.length} < 3.
|
|
* @throws NullPointerException
|
|
* if the array is null.
|
|
*/
|
|
public static int solveQuadratic(double eqn[]) {
|
|
return solveQuadratic(eqn, eqn);
|
|
}
|
|
|
|
/**
|
|
* Finds the roots of the quadratic polynomial. This is accomplished by
|
|
* finding the (real) values of x that solve the following equation:
|
|
* eqn[2]*x*x + eqn[1]*x + eqn[0] = 0. The solutions are written into the
|
|
* array res starting from the index 0 in the array. The return value tells
|
|
* how many array elements have been written by this method call.
|
|
*
|
|
* @param eqn
|
|
* an array containing the coefficients of the quadratic
|
|
* polynomial to solve.
|
|
* @param res
|
|
* the array that this method writes the results into.
|
|
* @return the number of roots of the quadratic polynomial.
|
|
* @throws ArrayIndexOutOfBoundsException
|
|
* if {@code eqn.length} < 3 or if {@code res.length} is less
|
|
* than the number of roots.
|
|
* @throws NullPointerException
|
|
* if either array is null.
|
|
*/
|
|
public static int solveQuadratic(double eqn[], double res[]) {
|
|
return Crossing.solveQuad(eqn, res);
|
|
}
|
|
|
|
public boolean contains(double px, double py) {
|
|
return Crossing.isInsideEvenOdd(Crossing.crossShape(this, px, py));
|
|
}
|
|
|
|
public boolean contains(double rx, double ry, double rw, double rh) {
|
|
int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
|
|
return cross != Crossing.CROSSING && Crossing.isInsideEvenOdd(cross);
|
|
}
|
|
|
|
public boolean intersects(double rx, double ry, double rw, double rh) {
|
|
int cross = Crossing.intersectShape(this, rx, ry, rw, rh);
|
|
return cross == Crossing.CROSSING || Crossing.isInsideEvenOdd(cross);
|
|
}
|
|
|
|
public boolean contains(Point2D p) {
|
|
return contains(p.getX(), p.getY());
|
|
}
|
|
|
|
public boolean intersects(Rectangle2D r) {
|
|
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
|
}
|
|
|
|
public boolean contains(Rectangle2D r) {
|
|
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
|
}
|
|
|
|
public Rectangle getBounds() {
|
|
return getBounds2D().getBounds();
|
|
}
|
|
|
|
public PathIterator getPathIterator(AffineTransform t) {
|
|
return new Iterator(this, t);
|
|
}
|
|
|
|
public PathIterator getPathIterator(AffineTransform t, double flatness) {
|
|
return new FlatteningPathIterator(getPathIterator(t), flatness);
|
|
}
|
|
|
|
@Override
|
|
public Object clone() {
|
|
try {
|
|
return super.clone();
|
|
} catch (CloneNotSupportedException e) {
|
|
throw new InternalError();
|
|
}
|
|
}
|
|
|
|
}
|