Converted the float bits to double since they've substantially evolved.
This commit is contained in:
@@ -13,39 +13,37 @@ import java.util.NoSuchElementException;
|
||||
public abstract class AbstractArc extends RectangularShape implements IArc
|
||||
{
|
||||
@Override // from interface IArc
|
||||
public Point getStartPoint () {
|
||||
return getStartPoint(new Point());
|
||||
public Point startPoint () {
|
||||
return startPoint(new Point());
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public Point getStartPoint (Point target) {
|
||||
double a = Math.toRadians(getAngleStart());
|
||||
target.setLocation(getX() + (1f + Math.cos(a)) * getWidth() / 2f,
|
||||
getY() + (1f - Math.sin(a)) * getHeight() / 2f);
|
||||
return target;
|
||||
public Point startPoint (Point target) {
|
||||
double a = Math.toRadians(angleStart());
|
||||
return target.set(x() + (1f + Math.cos(a)) * width() / 2f,
|
||||
y() + (1f - Math.sin(a)) * height() / 2f);
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public Point getEndPoint () {
|
||||
return getEndPoint(new Point());
|
||||
public Point endPoint () {
|
||||
return endPoint(new Point());
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public Point getEndPoint (Point target) {
|
||||
double a = Math.toRadians(getAngleStart() + getAngleExtent());
|
||||
target.setLocation(getX() + (1f + Math.cos(a)) * getWidth() / 2f,
|
||||
getY() + (1f - Math.sin(a)) * getHeight() / 2f);
|
||||
return target;
|
||||
public Point endPoint (Point target) {
|
||||
double a = Math.toRadians(angleStart() + angleExtent());
|
||||
return target.set(x() + (1f + Math.cos(a)) * width() / 2f,
|
||||
y() + (1f - Math.sin(a)) * height() / 2f);
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public boolean containsAngle (double angle) {
|
||||
double extent = getAngleExtent();
|
||||
double extent = angleExtent();
|
||||
if (extent >= 360f) {
|
||||
return true;
|
||||
}
|
||||
angle = getNormAngle(angle);
|
||||
double a1 = getNormAngle(getAngleStart());
|
||||
angle = normAngle(angle);
|
||||
double a1 = normAngle(angleStart());
|
||||
double a2 = a1 + extent;
|
||||
if (a2 > 360f) {
|
||||
return angle >= a1 || angle <= a2 - 360f;
|
||||
@@ -58,41 +56,41 @@ public abstract class AbstractArc extends RectangularShape implements IArc
|
||||
|
||||
@Override // from interface IArc
|
||||
public Arc clone () {
|
||||
return new Arc(getX(), getY(), getWidth(), getHeight(), getAngleStart(), getAngleExtent(),
|
||||
getArcType());
|
||||
return new Arc(x(), y(), width(), height(), angleStart(), angleExtent(),
|
||||
arcType());
|
||||
}
|
||||
|
||||
@Override // from RectangularShape
|
||||
public boolean isEmpty () {
|
||||
return getArcType() == OPEN || super.isEmpty();
|
||||
return arcType() == OPEN || super.isEmpty();
|
||||
}
|
||||
|
||||
@Override // from RectangularShape
|
||||
public boolean contains (double px, double py) {
|
||||
// normalize point
|
||||
double nx = (px - getX()) / getWidth() - 0.5f;
|
||||
double ny = (py - getY()) / getHeight() - 0.5f;
|
||||
double nx = (px - x()) / width() - 0.5f;
|
||||
double ny = (py - y()) / height() - 0.5f;
|
||||
if ((nx * nx + ny * ny) > 0.25) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double extent = getAngleExtent();
|
||||
double extent = angleExtent();
|
||||
double absExtent = Math.abs(extent);
|
||||
if (absExtent >= 360f) {
|
||||
return true;
|
||||
}
|
||||
|
||||
boolean containsAngle = containsAngle(Math.toDegrees(-Math.atan2(ny, nx)));
|
||||
if (getArcType() == PIE) {
|
||||
if (arcType() == PIE) {
|
||||
return containsAngle;
|
||||
}
|
||||
if (absExtent <= 180f && !containsAngle) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Line l = new Line(getStartPoint(), getEndPoint());
|
||||
Line l = new Line(startPoint(), endPoint());
|
||||
int ccw1 = l.relativeCCW(px, py);
|
||||
int ccw2 = l.relativeCCW(getCenterX(), getCenterY());
|
||||
int ccw2 = l.relativeCCW(centerX(), centerY());
|
||||
return ccw1 == 0 || ccw2 == 0 || ((ccw1 + ccw2) == 0 ^ absExtent > 180f);
|
||||
}
|
||||
|
||||
@@ -103,20 +101,20 @@ public abstract class AbstractArc extends RectangularShape implements IArc
|
||||
return false;
|
||||
}
|
||||
|
||||
double absExtent = Math.abs(getAngleExtent());
|
||||
if (getArcType() != PIE || absExtent <= 180f || absExtent >= 360f) {
|
||||
double absExtent = Math.abs(angleExtent());
|
||||
if (arcType() != PIE || absExtent <= 180f || absExtent >= 360f) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Rectangle r = new Rectangle(rx, ry, rw, rh);
|
||||
double cx = getCenterX(), cy = getCenterY();
|
||||
double cx = centerX(), cy = centerY();
|
||||
if (r.contains(cx, cy)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Point p1 = getStartPoint(), p2 = getEndPoint();
|
||||
return !r.intersectsLine(cx, cy, p1.getX(), p1.getY()) &&
|
||||
!r.intersectsLine(cx, cy, p2.getX(), p2.getY());
|
||||
Point p1 = startPoint(), p2 = endPoint();
|
||||
return !r.intersectsLine(cx, cy, p1.x(), p1.y()) &&
|
||||
!r.intersectsLine(cx, cy, p2.x(), p2.y());
|
||||
}
|
||||
|
||||
@Override // from RectangularShape
|
||||
@@ -131,22 +129,22 @@ public abstract class AbstractArc extends RectangularShape implements IArc
|
||||
return true;
|
||||
}
|
||||
|
||||
double cx = getCenterX(), cy = getCenterY();
|
||||
Point p1 = getStartPoint(), p2 = getEndPoint();
|
||||
double cx = centerX(), cy = centerY();
|
||||
Point p1 = startPoint(), p2 = endPoint();
|
||||
|
||||
// check: does rectangle contain arc's points
|
||||
Rectangle r = new Rectangle(rx, ry, rw, rh);
|
||||
if (r.contains(p1) || r.contains(p2) || (getArcType() == PIE && r.contains(cx, cy))) {
|
||||
if (r.contains(p1) || r.contains(p2) || (arcType() == PIE && r.contains(cx, cy))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getArcType() == PIE) {
|
||||
if (r.intersectsLine(p1.getX(), p1.getY(), cx, cy) ||
|
||||
r.intersectsLine(p2.getX(), p2.getY(), cx, cy)) {
|
||||
if (arcType() == PIE) {
|
||||
if (r.intersectsLine(p1.x(), p1.y(), cx, cy) ||
|
||||
r.intersectsLine(p2.x(), p2.y(), cx, cy)) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (r.intersectsLine(p1.getX(), p1.getY(), p2.getX(), p2.getY())) {
|
||||
if (r.intersectsLine(p1.x(), p1.y(), p2.x(), p2.y())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -158,27 +156,27 @@ public abstract class AbstractArc extends RectangularShape implements IArc
|
||||
}
|
||||
|
||||
@Override // from RectangularShape
|
||||
public Rectangle getBounds (Rectangle target) {
|
||||
public Rectangle bounds (Rectangle target) {
|
||||
if (isEmpty()) {
|
||||
target.setBounds(getX(), getY(), getWidth(), getHeight());
|
||||
target.setBounds(x(), y(), width(), height());
|
||||
return target;
|
||||
}
|
||||
|
||||
double rx1 = getX();
|
||||
double ry1 = getY();
|
||||
double rx2 = rx1 + getWidth();
|
||||
double ry2 = ry1 + getHeight();
|
||||
double rx1 = x();
|
||||
double ry1 = y();
|
||||
double rx2 = rx1 + width();
|
||||
double ry2 = ry1 + height();
|
||||
|
||||
Point p1 = getStartPoint(), p2 = getEndPoint();
|
||||
Point p1 = startPoint(), p2 = endPoint();
|
||||
|
||||
double bx1 = containsAngle(180f) ? rx1 : Math.min(p1.getX(), p2.getX());
|
||||
double by1 = containsAngle(90f) ? ry1 : Math.min(p1.getY(), p2.getY());
|
||||
double bx2 = containsAngle(0f) ? rx2 : Math.max(p1.getX(), p2.getX());
|
||||
double by2 = containsAngle(270f) ? ry2 : Math.max(p1.getY(), p2.getY());
|
||||
double bx1 = containsAngle(180f) ? rx1 : Math.min(p1.x(), p2.x());
|
||||
double by1 = containsAngle(90f) ? ry1 : Math.min(p1.y(), p2.y());
|
||||
double bx2 = containsAngle(0f) ? rx2 : Math.max(p1.x(), p2.x());
|
||||
double by2 = containsAngle(270f) ? ry2 : Math.max(p1.y(), p2.y());
|
||||
|
||||
if (getArcType() == PIE) {
|
||||
double cx = getCenterX();
|
||||
double cy = getCenterY();
|
||||
if (arcType() == PIE) {
|
||||
double cx = centerX();
|
||||
double cy = centerY();
|
||||
bx1 = Math.min(bx1, cx);
|
||||
by1 = Math.min(by1, cy);
|
||||
bx2 = Math.max(bx2, cx);
|
||||
@@ -189,12 +187,12 @@ public abstract class AbstractArc extends RectangularShape implements IArc
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform at) {
|
||||
public PathIterator pathIterator (Transform at) {
|
||||
return new Iterator(this, at);
|
||||
}
|
||||
|
||||
/** Returns a normalized angle (bound between 0 and 360 degrees). */
|
||||
protected double getNormAngle (double angle) {
|
||||
protected double normAngle (double angle) {
|
||||
return angle - Math.floor(angle / 360f) * 360f;
|
||||
}
|
||||
|
||||
@@ -223,7 +221,7 @@ public abstract class AbstractArc extends RectangularShape implements IArc
|
||||
private int type;
|
||||
|
||||
/** The path iterator transformation */
|
||||
private AffineTransform t;
|
||||
private Transform t;
|
||||
|
||||
/** The current segment index */
|
||||
private int index;
|
||||
@@ -259,14 +257,14 @@ public abstract class AbstractArc extends RectangularShape implements IArc
|
||||
/** The y coordinate of the first path point (MOVE_TO) */
|
||||
private double my;
|
||||
|
||||
Iterator (IArc a, AffineTransform t) {
|
||||
this.width = a.getWidth() / 2f;
|
||||
this.height = a.getHeight() / 2f;
|
||||
this.x = a.getX() + width;
|
||||
this.y = a.getY() + height;
|
||||
this.angle = -Math.toRadians(a.getAngleStart());
|
||||
this.extent = -a.getAngleExtent();
|
||||
this.type = a.getArcType();
|
||||
Iterator (IArc a, Transform t) {
|
||||
this.width = a.width() / 2f;
|
||||
this.height = a.height() / 2f;
|
||||
this.x = a.x() + width;
|
||||
this.y = a.y() + height;
|
||||
this.angle = -Math.toRadians(a.angleStart());
|
||||
this.extent = -a.angleExtent();
|
||||
this.type = a.arcType();
|
||||
this.t = t;
|
||||
|
||||
if (width < 0 || height < 0) {
|
||||
@@ -298,7 +296,7 @@ public abstract class AbstractArc extends RectangularShape implements IArc
|
||||
}
|
||||
}
|
||||
|
||||
@Override public int getWindingRule () {
|
||||
@Override public int windingRule () {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,35 +13,35 @@ import java.util.NoSuchElementException;
|
||||
public abstract class AbstractCubicCurve implements ICubicCurve
|
||||
{
|
||||
@Override // from interface ICubicCurve
|
||||
public Point getP1 () {
|
||||
return new Point(getX1(), getY1());
|
||||
public Point p1 () {
|
||||
return new Point(x1(), y1());
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public Point getCtrlP1 () {
|
||||
return new Point(getCtrlX1(), getCtrlY1());
|
||||
public Point ctrlP1 () {
|
||||
return new Point(ctrlX1(), ctrlY1());
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public Point getCtrlP2 () {
|
||||
return new Point(getCtrlX2(), getCtrlY2());
|
||||
public Point ctrlP2 () {
|
||||
return new Point(ctrlX2(), ctrlY2());
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public Point getP2 () {
|
||||
return new Point(getX2(), getY2());
|
||||
public Point p2 () {
|
||||
return new Point(x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public double getFlatnessSq () {
|
||||
return CubicCurves.getFlatnessSq(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
|
||||
getCtrlX2(), getCtrlY2(), getX2(), getY2());
|
||||
public double flatnessSq () {
|
||||
return CubicCurves.flatnessSq(x1(), y1(), ctrlX1(), ctrlY1(),
|
||||
ctrlX2(), ctrlY2(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public double getFlatness () {
|
||||
return CubicCurves.getFlatness(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
|
||||
getCtrlX2(), getCtrlY2(), getX2(), getY2());
|
||||
public double flatness () {
|
||||
return CubicCurves.flatness(x1(), y1(), ctrlX1(), ctrlY1(),
|
||||
ctrlX2(), ctrlY2(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
@@ -51,8 +51,8 @@ public abstract class AbstractCubicCurve implements ICubicCurve
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public CubicCurve clone () {
|
||||
return new CubicCurve(getX1(), getY1(), getCtrlX1(), getCtrlY1(),
|
||||
getCtrlX2(), getCtrlY2(), getX2(), getY2());
|
||||
return new CubicCurve(x1(), y1(), ctrlX1(), ctrlY1(),
|
||||
ctrlX2(), ctrlY2(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
@@ -73,12 +73,12 @@ public abstract class AbstractCubicCurve implements ICubicCurve
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (IPoint p) {
|
||||
return contains(p.getX(), p.getY());
|
||||
return contains(p.x(), p.y());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (IRectangle r) {
|
||||
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
return contains(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
@@ -89,19 +89,19 @@ public abstract class AbstractCubicCurve implements ICubicCurve
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean intersects (IRectangle r) {
|
||||
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
return intersects(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds () {
|
||||
return getBounds(new Rectangle());
|
||||
public Rectangle bounds () {
|
||||
return bounds(new Rectangle());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds (Rectangle target) {
|
||||
double x1 = getX1(), y1 = getY1(), x2 = getX2(), y2 = getY2();
|
||||
double ctrlx1 = getCtrlX1(), ctrly1 = getCtrlY1();
|
||||
double ctrlx2 = getCtrlX2(), ctrly2 = getCtrlY2();
|
||||
public Rectangle bounds (Rectangle target) {
|
||||
double x1 = x1(), y1 = y1(), x2 = x2(), y2 = y2();
|
||||
double ctrlx1 = ctrlX1(), ctrly1 = ctrlY1();
|
||||
double ctrlx2 = ctrlX2(), ctrly2 = ctrlY2();
|
||||
double rx1 = Math.min(Math.min(x1, x2), Math.min(ctrlx1, ctrlx2));
|
||||
double ry1 = Math.min(Math.min(y1, y2), Math.min(ctrly1, ctrly2));
|
||||
double rx2 = Math.max(Math.max(x1, x2), Math.max(ctrlx1, ctrlx2));
|
||||
@@ -111,28 +111,28 @@ public abstract class AbstractCubicCurve implements ICubicCurve
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform t) {
|
||||
public PathIterator pathIterator (Transform t) {
|
||||
return new Iterator(this, t);
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform at, double flatness) {
|
||||
return new FlatteningPathIterator(getPathIterator(at), flatness);
|
||||
public PathIterator pathIterator (Transform at, double flatness) {
|
||||
return new FlatteningPathIterator(pathIterator(at), flatness);
|
||||
}
|
||||
|
||||
/** An iterator over an {@link ICubicCurve}. */
|
||||
protected static class Iterator implements PathIterator
|
||||
{
|
||||
private ICubicCurve c;
|
||||
private AffineTransform t;
|
||||
private Transform t;
|
||||
private int index;
|
||||
|
||||
Iterator (ICubicCurve c, AffineTransform t) {
|
||||
Iterator (ICubicCurve c, Transform t) {
|
||||
this.c = c;
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
@Override public int getWindingRule () {
|
||||
@Override public int windingRule () {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
@@ -152,17 +152,17 @@ public abstract class AbstractCubicCurve implements ICubicCurve
|
||||
int count;
|
||||
if (index == 0) {
|
||||
type = SEG_MOVETO;
|
||||
coords[0] = c.getX1();
|
||||
coords[1] = c.getY1();
|
||||
coords[0] = c.x1();
|
||||
coords[1] = c.y1();
|
||||
count = 1;
|
||||
} else {
|
||||
type = SEG_CUBICTO;
|
||||
coords[0] = c.getCtrlX1();
|
||||
coords[1] = c.getCtrlY1();
|
||||
coords[2] = c.getCtrlX2();
|
||||
coords[3] = c.getCtrlY2();
|
||||
coords[4] = c.getX2();
|
||||
coords[5] = c.getY2();
|
||||
coords[0] = c.ctrlX1();
|
||||
coords[1] = c.ctrlY1();
|
||||
coords[2] = c.ctrlX2();
|
||||
coords[3] = c.ctrlY2();
|
||||
coords[4] = c.x2();
|
||||
coords[5] = c.y2();
|
||||
count = 3;
|
||||
}
|
||||
if (t != null) {
|
||||
|
||||
@@ -19,9 +19,7 @@ public abstract class AbstractDimension implements IDimension
|
||||
|
||||
@Override
|
||||
public int hashCode () {
|
||||
long bits = Platform.hashCode(getWidth());
|
||||
bits += Platform.hashCode(getHeight()) * 37;
|
||||
return (((int) bits) ^ ((int) (bits >> 32)));
|
||||
return Platform.hashCode(width()) ^ Platform.hashCode(height());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,13 +29,13 @@ public abstract class AbstractDimension implements IDimension
|
||||
}
|
||||
if (obj instanceof AbstractDimension) {
|
||||
AbstractDimension d = (AbstractDimension)obj;
|
||||
return (d.getWidth() == getWidth() && d.getHeight() == getHeight());
|
||||
return (d.width() == width() && d.height() == height());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return Dimensions.dimenToString(getWidth(), getHeight());
|
||||
return Dimensions.dimenToString(width(), height());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,14 @@ public abstract class AbstractEllipse extends RectangularShape implements IEllip
|
||||
{
|
||||
@Override // from IEllipse
|
||||
public Ellipse clone () {
|
||||
return new Ellipse(getX(), getY(), getWidth(), getHeight());
|
||||
return new Ellipse(x(), y(), width(), height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (double px, double py) {
|
||||
if (isEmpty()) return false;
|
||||
double a = (px - getX()) / getWidth() - 0.5f;
|
||||
double b = (py - getY()) / getHeight() - 0.5f;
|
||||
double a = (px - x()) / width() - 0.5f;
|
||||
double b = (py - y()) / height() - 0.5f;
|
||||
return a * a + b * b < 0.25f;
|
||||
}
|
||||
|
||||
@@ -35,8 +35,8 @@ public abstract class AbstractEllipse extends RectangularShape implements IEllip
|
||||
@Override // from interface IShape
|
||||
public boolean intersects (double rx, double ry, double rw, double rh) {
|
||||
if (isEmpty() || rw <= 0f || rh <= 0f) return false;
|
||||
double cx = getX() + getWidth() / 2f;
|
||||
double cy = getY() + getHeight() / 2f;
|
||||
double cx = x() + width() / 2f;
|
||||
double cy = y() + height() / 2f;
|
||||
double rx1 = rx, ry1 = ry, rx2 = rx + rw, ry2 = ry + rh;
|
||||
double nx = cx < rx1 ? rx1 : (cx > rx2 ? rx2 : cx);
|
||||
double ny = cy < ry1 ? ry1 : (cy > ry2 ? ry2 : cy);
|
||||
@@ -44,7 +44,7 @@ public abstract class AbstractEllipse extends RectangularShape implements IEllip
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform at) {
|
||||
public PathIterator pathIterator (Transform at) {
|
||||
return new Iterator(this, at);
|
||||
}
|
||||
|
||||
@@ -52,21 +52,21 @@ public abstract class AbstractEllipse extends RectangularShape implements IEllip
|
||||
protected static class Iterator implements PathIterator
|
||||
{
|
||||
private final double x, y, width, height;
|
||||
private final AffineTransform t;
|
||||
private final Transform t;
|
||||
private int index;
|
||||
|
||||
Iterator (IEllipse e, AffineTransform t) {
|
||||
this.x = e.getX();
|
||||
this.y = e.getY();
|
||||
this.width = e.getWidth();
|
||||
this.height = e.getHeight();
|
||||
Iterator (IEllipse e, Transform t) {
|
||||
this.x = e.x();
|
||||
this.y = e.y();
|
||||
this.width = e.width();
|
||||
this.height = e.height();
|
||||
this.t = t;
|
||||
if (width < 0f || height < 0f) {
|
||||
index = 6;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public int getWindingRule () {
|
||||
@Override public int windingRule () {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,80 +13,78 @@ import java.util.NoSuchElementException;
|
||||
public abstract class AbstractLine implements ILine
|
||||
{
|
||||
@Override // from interface ILine
|
||||
public Point getP1 () {
|
||||
return getP1(new Point());
|
||||
public Point p1 () {
|
||||
return p1(new Point());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public Point getP1 (Point target) {
|
||||
target.setLocation(getX1(), getY1());
|
||||
return target;
|
||||
public Point p1 (Point target) {
|
||||
return target.set(x1(), y1());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public Point getP2 () {
|
||||
return getP2(new Point());
|
||||
public Point p2 () {
|
||||
return p2(new Point());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public Point getP2 (Point target) {
|
||||
target.setLocation(getX2(), getY2());
|
||||
return target;
|
||||
public Point p2 (Point target) {
|
||||
return target.set(x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double pointLineDistSq (double px, double py) {
|
||||
return Lines.pointLineDistSq(px, py, getX1(), getY1(), getX2(), getY2());
|
||||
return Lines.pointLineDistSq(px, py, x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double pointLineDistSq (IPoint p) {
|
||||
return Lines.pointLineDistSq(p.getX(), p.getY(), getX1(), getY1(), getX2(), getY2());
|
||||
return Lines.pointLineDistSq(p.x(), p.y(), x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double pointLineDist (double px, double py) {
|
||||
return Lines.pointLineDist(px, py, getX1(), getY1(), getX2(), getY2());
|
||||
return Lines.pointLineDist(px, py, x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double pointLineDist (IPoint p) {
|
||||
return Lines.pointLineDist(p.getX(), p.getY(), getX1(), getY1(), getX2(), getY2());
|
||||
return Lines.pointLineDist(p.x(), p.y(), x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double pointSegDistSq (double px, double py) {
|
||||
return Lines.pointSegDistSq(px, py, getX1(), getY1(), getX2(), getY2());
|
||||
return Lines.pointSegDistSq(px, py, x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double pointSegDistSq (IPoint p) {
|
||||
return Lines.pointSegDistSq(p.getX(), p.getY(), getX1(), getY1(), getX2(), getY2());
|
||||
return Lines.pointSegDistSq(p.x(), p.y(), x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double pointSegDist (double px, double py) {
|
||||
return Lines.pointSegDist(px, py, getX1(), getY1(), getX2(), getY2());
|
||||
return Lines.pointSegDist(px, py, x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double pointSegDist (IPoint p) {
|
||||
return Lines.pointSegDist(p.getX(), p.getY(), getX1(), getY1(), getX2(), getY2());
|
||||
return Lines.pointSegDist(p.x(), p.y(), x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public int relativeCCW (double px, double py) {
|
||||
return Lines.relativeCCW(px, py, getX1(), getY1(), getX2(), getY2());
|
||||
return Lines.relativeCCW(px, py, x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public int relativeCCW (IPoint p) {
|
||||
return Lines.relativeCCW(p.getX(), p.getY(), getX1(), getY1(), getX2(), getY2());
|
||||
return Lines.relativeCCW(p.x(), p.y(), x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public Line clone () {
|
||||
return new Line(getX1(), getY1(), getX2(), getY2());
|
||||
return new Line(x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
@@ -116,7 +114,7 @@ public abstract class AbstractLine implements ILine
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean intersects (double rx, double ry, double rw, double rh) {
|
||||
return Lines.lineIntersectsRect(getX1(), getY1(), getX2(), getY2(), rx, ry, rw, rh);
|
||||
return Lines.lineIntersectsRect(x1(), y1(), x2(), y2(), rx, ry, rw, rh);
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
@@ -125,13 +123,13 @@ public abstract class AbstractLine implements ILine
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds () {
|
||||
return getBounds(new Rectangle());
|
||||
public Rectangle bounds () {
|
||||
return bounds(new Rectangle());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds (Rectangle target) {
|
||||
double x1 = getX1(), x2 = getX2(), y1 = getY1(), y2 = getY2();
|
||||
public Rectangle bounds (Rectangle target) {
|
||||
double x1 = x1(), x2 = x2(), y1 = y1(), y2 = y2();
|
||||
double rx, ry, rw, rh;
|
||||
if (x1 < x2) {
|
||||
rx = x1;
|
||||
@@ -152,12 +150,12 @@ public abstract class AbstractLine implements ILine
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform at) {
|
||||
public PathIterator pathIterator (Transform at) {
|
||||
return new Iterator(this, at);
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform at, double flatness) {
|
||||
public PathIterator pathIterator (Transform at, double flatness) {
|
||||
return new Iterator(this, at);
|
||||
}
|
||||
|
||||
@@ -165,18 +163,18 @@ public abstract class AbstractLine implements ILine
|
||||
protected static class Iterator implements PathIterator
|
||||
{
|
||||
private double x1, y1, x2, y2;
|
||||
private AffineTransform t;
|
||||
private Transform t;
|
||||
private int index;
|
||||
|
||||
Iterator (ILine l, AffineTransform at) {
|
||||
this.x1 = l.getX1();
|
||||
this.y1 = l.getY1();
|
||||
this.x2 = l.getX2();
|
||||
this.y2 = l.getY2();
|
||||
Iterator (ILine l, Transform at) {
|
||||
this.x1 = l.x1();
|
||||
this.y1 = l.y1();
|
||||
this.x2 = l.x2();
|
||||
this.y2 = l.y2();
|
||||
this.t = at;
|
||||
}
|
||||
|
||||
@Override public int getWindingRule () {
|
||||
@Override public int windingRule () {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
|
||||
@@ -12,27 +12,59 @@ import pythagoras.util.Platform;
|
||||
*/
|
||||
public abstract class AbstractPoint implements IPoint
|
||||
{
|
||||
@Override // from interface IPoint
|
||||
@Override // from IPoint
|
||||
public double distanceSq (double px, double py) {
|
||||
return Points.distanceSq(getX(), getY(), px, py);
|
||||
return Points.distanceSq(x(), y(), px, py);
|
||||
}
|
||||
|
||||
@Override // from interface IPoint
|
||||
@Override // from IPoint
|
||||
public double distanceSq (IPoint p) {
|
||||
return Points.distanceSq(getX(), getY(), p.getX(), p.getY());
|
||||
return Points.distanceSq(x(), y(), p.x(), p.y());
|
||||
}
|
||||
|
||||
@Override // from interface IPoint
|
||||
@Override // from IPoint
|
||||
public double distance (double px, double py) {
|
||||
return Points.distance(getX(), getY(), px, py);
|
||||
return Points.distance(x(), y(), px, py);
|
||||
}
|
||||
|
||||
@Override // from interface IPoint
|
||||
@Override // from IPoint
|
||||
public double distance (IPoint p) {
|
||||
return Points.distance(getX(), getY(), p.getX(), p.getY());
|
||||
return Points.distance(x(), y(), p.x(), p.y());
|
||||
}
|
||||
|
||||
@Override // from interface IPoint
|
||||
@Override // from IPoint
|
||||
public Point mult (double s) {
|
||||
return mult(s, new Point());
|
||||
}
|
||||
|
||||
@Override // from IPoint
|
||||
public Point mult (double s, Point result) {
|
||||
return result.set(x() * s, y() * s);
|
||||
}
|
||||
|
||||
@Override // from IPoint
|
||||
public Point add (double x, double y) {
|
||||
return new Point(x() + x, y() + y);
|
||||
}
|
||||
|
||||
@Override // from IPoint
|
||||
public Point add (double x, double y, Point result) {
|
||||
return result.set(x() + x, y() + y);
|
||||
}
|
||||
|
||||
@Override // from IPoint
|
||||
public Point rotate (double angle) {
|
||||
return rotate(angle, new Point());
|
||||
}
|
||||
|
||||
@Override // from IPoint
|
||||
public Point rotate (double angle, Point result) {
|
||||
double x = x(), y = y();
|
||||
double sina = Math.sin(angle), cosa = Math.cos(angle);
|
||||
return result.set(x*cosa - y*sina, x*sina + y*cosa);
|
||||
}
|
||||
|
||||
@Override // from IPoint
|
||||
public Point clone () {
|
||||
return new Point(this);
|
||||
}
|
||||
@@ -44,18 +76,18 @@ public abstract class AbstractPoint implements IPoint
|
||||
}
|
||||
if (obj instanceof AbstractPoint) {
|
||||
AbstractPoint p = (AbstractPoint)obj;
|
||||
return getX() == p.getX() && getY() == p.getY();
|
||||
return x() == p.x() && y() == p.y();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode () {
|
||||
return Platform.hashCode(getX()) ^ Platform.hashCode(getY());
|
||||
return Platform.hashCode(x()) ^ Platform.hashCode(y());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return Points.pointToString(getX(), getY());
|
||||
return Points.pointToString(x(), y());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,28 +13,28 @@ import java.util.NoSuchElementException;
|
||||
public abstract class AbstractQuadCurve implements IQuadCurve
|
||||
{
|
||||
@Override // from interface IQuadCurve
|
||||
public Point getP1 () {
|
||||
return new Point(getX1(), getY1());
|
||||
public Point p1 () {
|
||||
return new Point(x1(), y1());
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public Point getCtrlP () {
|
||||
return new Point(getCtrlX(), getCtrlY());
|
||||
public Point ctrlP () {
|
||||
return new Point(ctrlX(), ctrlY());
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public Point getP2 () {
|
||||
return new Point(getX2(), getY2());
|
||||
public Point p2 () {
|
||||
return new Point(x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public double getFlatnessSq () {
|
||||
return Lines.pointSegDistSq(getCtrlX(), getCtrlY(), getX1(), getY1(), getX2(), getY2());
|
||||
public double flatnessSq () {
|
||||
return Lines.pointSegDistSq(ctrlX(), ctrlY(), x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public double getFlatness () {
|
||||
return Lines.pointSegDist(getCtrlX(), getCtrlY(), getX1(), getY1(), getX2(), getY2());
|
||||
public double flatness () {
|
||||
return Lines.pointSegDist(ctrlX(), ctrlY(), x1(), y1(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
@@ -44,7 +44,7 @@ public abstract class AbstractQuadCurve implements IQuadCurve
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public QuadCurve clone () {
|
||||
return new QuadCurve(getX1(), getY1(), getCtrlX(), getCtrlY(), getX2(), getY2());
|
||||
return new QuadCurve(x1(), y1(), ctrlX(), ctrlY(), x2(), y2());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
@@ -65,12 +65,12 @@ public abstract class AbstractQuadCurve implements IQuadCurve
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (IPoint p) {
|
||||
return contains(p.getX(), p.getY());
|
||||
return contains(p.x(), p.y());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (IRectangle r) {
|
||||
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
return contains(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
@@ -81,18 +81,18 @@ public abstract class AbstractQuadCurve implements IQuadCurve
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean intersects (IRectangle r) {
|
||||
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
return intersects(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds () {
|
||||
return getBounds(new Rectangle());
|
||||
public Rectangle bounds () {
|
||||
return bounds(new Rectangle());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds (Rectangle target) {
|
||||
double x1 = getX1(), y1 = getY1(), x2 = getX2(), y2 = getY2();
|
||||
double ctrlx = getCtrlX(), ctrly = getCtrlY();
|
||||
public Rectangle bounds (Rectangle target) {
|
||||
double x1 = x1(), y1 = y1(), x2 = x2(), y2 = y2();
|
||||
double ctrlx = ctrlX(), ctrly = ctrlY();
|
||||
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);
|
||||
@@ -102,28 +102,28 @@ public abstract class AbstractQuadCurve implements IQuadCurve
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform t) {
|
||||
public PathIterator pathIterator (Transform t) {
|
||||
return new Iterator(this, t);
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform t, double flatness) {
|
||||
return new FlatteningPathIterator(getPathIterator(t), flatness);
|
||||
public PathIterator pathIterator (Transform t, double flatness) {
|
||||
return new FlatteningPathIterator(pathIterator(t), flatness);
|
||||
}
|
||||
|
||||
/** An iterator over an {@link IQuadCurve}. */
|
||||
protected static class Iterator implements PathIterator
|
||||
{
|
||||
private IQuadCurve c;
|
||||
private AffineTransform t;
|
||||
private Transform t;
|
||||
private int index;
|
||||
|
||||
Iterator (IQuadCurve q, AffineTransform t) {
|
||||
Iterator (IQuadCurve q, Transform t) {
|
||||
this.c = q;
|
||||
this.t = t;
|
||||
}
|
||||
|
||||
@Override public int getWindingRule () {
|
||||
@Override public int windingRule () {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
@@ -143,15 +143,15 @@ public abstract class AbstractQuadCurve implements IQuadCurve
|
||||
int count;
|
||||
if (index == 0) {
|
||||
type = SEG_MOVETO;
|
||||
coords[0] = c.getX1();
|
||||
coords[1] = c.getY1();
|
||||
coords[0] = c.x1();
|
||||
coords[1] = c.y1();
|
||||
count = 1;
|
||||
} else {
|
||||
type = SEG_QUADTO;
|
||||
coords[0] = c.getCtrlX();
|
||||
coords[1] = c.getCtrlY();
|
||||
coords[2] = c.getX2();
|
||||
coords[3] = c.getY2();
|
||||
coords[0] = c.ctrlX();
|
||||
coords[1] = c.ctrlY();
|
||||
coords[2] = c.x2();
|
||||
coords[3] = c.y2();
|
||||
count = 2;
|
||||
}
|
||||
if (t != null) {
|
||||
|
||||
@@ -15,39 +15,38 @@ import pythagoras.util.Platform;
|
||||
public abstract class AbstractRectangle extends RectangularShape implements IRectangle
|
||||
{
|
||||
@Override // from interface IRectangle
|
||||
public Point getLocation () {
|
||||
return getLocation(new Point());
|
||||
public Point location () {
|
||||
return location(new Point());
|
||||
}
|
||||
|
||||
@Override // from interface IRectangle
|
||||
public Point getLocation (Point target) {
|
||||
target.setLocation(getX(), getY());
|
||||
return target;
|
||||
public Point location (Point target) {
|
||||
return target.set(x(), y());
|
||||
}
|
||||
|
||||
@Override // from interface IRectangle
|
||||
public Dimension getSize () {
|
||||
return getSize(new Dimension());
|
||||
public Dimension size () {
|
||||
return size(new Dimension());
|
||||
}
|
||||
|
||||
@Override // from interface IRectangle
|
||||
public Dimension getSize (Dimension target) {
|
||||
target.setSize(getWidth(), getHeight());
|
||||
public Dimension size (Dimension target) {
|
||||
target.setSize(width(), height());
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangle
|
||||
public Rectangle intersection (double rx, double ry, double rw, double rh) {
|
||||
double x1 = Math.max(getX(), rx);
|
||||
double y1 = Math.max(getY(), ry);
|
||||
double x2 = Math.min(getMaxX(), rx + rw);
|
||||
double y2 = Math.min(getMaxY(), ry + rh);
|
||||
double x1 = Math.max(x(), rx);
|
||||
double y1 = Math.max(y(), ry);
|
||||
double x2 = Math.min(maxX(), rx + rw);
|
||||
double y2 = Math.min(maxY(), ry + rh);
|
||||
return new Rectangle(x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
|
||||
@Override // from interface IRectangle
|
||||
public Rectangle intersection (IRectangle r) {
|
||||
return intersection(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
return intersection(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
@Override // from interface IRectangle
|
||||
@@ -59,31 +58,31 @@ public abstract class AbstractRectangle extends RectangularShape implements IRec
|
||||
|
||||
@Override // from interface IRectangle
|
||||
public boolean intersectsLine (double x1, double y1, double x2, double y2) {
|
||||
return Lines.lineIntersectsRect(x1, y1, x2, y2, getX(), getY(), getWidth(), getHeight());
|
||||
return Lines.lineIntersectsRect(x1, y1, x2, y2, x(), y(), width(), height());
|
||||
}
|
||||
|
||||
@Override // from interface IRectangle
|
||||
public boolean intersectsLine (ILine l) {
|
||||
return intersectsLine(l.getX1(), l.getY1(), l.getX2(), l.getY2());
|
||||
return intersectsLine(l.x1(), l.y1(), l.x2(), l.y2());
|
||||
}
|
||||
|
||||
@Override // from interface IRectangle
|
||||
public int outcode (double px, double py) {
|
||||
int code = 0;
|
||||
|
||||
if (getWidth() <= 0) {
|
||||
if (width() <= 0) {
|
||||
code |= OUT_LEFT | OUT_RIGHT;
|
||||
} else if (px < getX()) {
|
||||
} else if (px < x()) {
|
||||
code |= OUT_LEFT;
|
||||
} else if (px > getMaxX()) {
|
||||
} else if (px > maxX()) {
|
||||
code |= OUT_RIGHT;
|
||||
}
|
||||
|
||||
if (getHeight() <= 0) {
|
||||
if (height() <= 0) {
|
||||
code |= OUT_TOP | OUT_BOTTOM;
|
||||
} else if (py < getY()) {
|
||||
} else if (py < y()) {
|
||||
code |= OUT_TOP;
|
||||
} else if (py > getMaxY()) {
|
||||
} else if (py > maxY()) {
|
||||
code |= OUT_BOTTOM;
|
||||
}
|
||||
|
||||
@@ -92,7 +91,7 @@ public abstract class AbstractRectangle extends RectangularShape implements IRec
|
||||
|
||||
@Override // from interface IRectangle
|
||||
public int outcode (IPoint p) {
|
||||
return outcode(p.getX(), p.getY());
|
||||
return outcode(p.x(), p.y());
|
||||
}
|
||||
|
||||
@Override // from interface IRectangle
|
||||
@@ -104,19 +103,19 @@ public abstract class AbstractRectangle extends RectangularShape implements IRec
|
||||
public boolean contains (double px, double py) {
|
||||
if (isEmpty()) return false;
|
||||
|
||||
double x = getX(), y = getY();
|
||||
double x = x(), y = y();
|
||||
if (px < x || py < y) return false;
|
||||
|
||||
px -= x;
|
||||
py -= y;
|
||||
return px < getWidth() && py < getHeight();
|
||||
return px < width() && py < height();
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (double rx, double ry, double rw, double rh) {
|
||||
if (isEmpty()) return false;
|
||||
|
||||
double x1 = getX(), y1 = getY(), x2 = x1 + getWidth(), y2 = y1 + getHeight();
|
||||
double x1 = x(), y1 = y(), x2 = x1 + width(), y2 = y1 + height();
|
||||
return (x1 <= rx) && (rx + rw <= x2) && (y1 <= ry) && (ry + rh <= y2);
|
||||
}
|
||||
|
||||
@@ -124,17 +123,17 @@ public abstract class AbstractRectangle extends RectangularShape implements IRec
|
||||
public boolean intersects (double rx, double ry, double rw, double rh) {
|
||||
if (isEmpty()) return false;
|
||||
|
||||
double x1 = getX(), y1 = getY(), x2 = x1 + getWidth(), y2 = y1 + getHeight();
|
||||
double x1 = x(), y1 = y(), x2 = x1 + width(), y2 = y1 + height();
|
||||
return (rx + rw > x1) && (rx < x2) && (ry + rh > y1) && (ry < y2);
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform t) {
|
||||
public PathIterator pathIterator (Transform t) {
|
||||
return new Iterator(this, t);
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform t, double flatness) {
|
||||
public PathIterator pathIterator (Transform t, double flatness) {
|
||||
return new Iterator(this, t);
|
||||
}
|
||||
|
||||
@@ -145,45 +144,45 @@ public abstract class AbstractRectangle extends RectangularShape implements IRec
|
||||
}
|
||||
if (obj instanceof AbstractRectangle) {
|
||||
AbstractRectangle r = (AbstractRectangle)obj;
|
||||
return r.getX() == getX() && r.getY() == getY() &&
|
||||
r.getWidth() == getWidth() && r.getHeight() == getHeight();
|
||||
return r.x() == x() && r.y() == y() &&
|
||||
r.width() == width() && r.height() == height();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override // from Object
|
||||
public int hashCode () {
|
||||
return Platform.hashCode(getX()) ^ Platform.hashCode(getY()) ^
|
||||
Platform.hashCode(getWidth()) ^ Platform.hashCode(getHeight());
|
||||
return Platform.hashCode(x()) ^ Platform.hashCode(y()) ^
|
||||
Platform.hashCode(width()) ^ Platform.hashCode(height());
|
||||
}
|
||||
|
||||
@Override // from Object
|
||||
public String toString () {
|
||||
return Dimensions.dimenToString(getWidth(), getHeight()) +
|
||||
Points.pointToString(getX(), getY());
|
||||
return Dimensions.dimenToString(width(), height()) +
|
||||
Points.pointToString(x(), y());
|
||||
}
|
||||
|
||||
/** An iterator over an {@link IRectangle}. */
|
||||
protected static class Iterator implements PathIterator
|
||||
{
|
||||
private double x, y, width, height;
|
||||
private AffineTransform t;
|
||||
private Transform t;
|
||||
|
||||
/** The current segment index. */
|
||||
private int index;
|
||||
|
||||
Iterator (IRectangle r, AffineTransform at) {
|
||||
this.x = r.getX();
|
||||
this.y = r.getY();
|
||||
this.width = r.getWidth();
|
||||
this.height = r.getHeight();
|
||||
Iterator (IRectangle r, Transform at) {
|
||||
this.x = r.x();
|
||||
this.y = r.y();
|
||||
this.width = r.width();
|
||||
this.height = r.height();
|
||||
this.t = at;
|
||||
if (width < 0f || height < 0f) {
|
||||
index = 6;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public int getWindingRule () {
|
||||
@Override public int windingRule () {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,21 +14,21 @@ public abstract class AbstractRoundRectangle extends RectangularShape implements
|
||||
{
|
||||
@Override // from interface IRoundRectangle
|
||||
public RoundRectangle clone () {
|
||||
return new RoundRectangle(getX(), getY(), getWidth(), getHeight(),
|
||||
getArcWidth(), getArcHeight());
|
||||
return new RoundRectangle(x(), y(), width(), height(),
|
||||
arcWidth(), arcHeight());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (double px, double py) {
|
||||
if (isEmpty()) return false;
|
||||
|
||||
double rx1 = getX(), ry1 = getY();
|
||||
double rx2 = rx1 + getWidth(), ry2 = ry1 + getHeight();
|
||||
double rx1 = x(), ry1 = y();
|
||||
double rx2 = rx1 + width(), ry2 = ry1 + height();
|
||||
if (px < rx1 || px >= rx2 || py < ry1 || py >= ry2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
double aw = getArcWidth() / 2f, ah = getArcHeight() / 2f;
|
||||
double aw = arcWidth() / 2f, ah = arcHeight() / 2f;
|
||||
double cx, cy;
|
||||
if (px < rx1 + aw) {
|
||||
cx = rx1 + aw;
|
||||
@@ -62,7 +62,7 @@ public abstract class AbstractRoundRectangle extends RectangularShape implements
|
||||
public boolean intersects (double rx, double ry, double rw, double rh) {
|
||||
if (isEmpty() || rw <= 0f || rh <= 0f) return false;
|
||||
|
||||
double x1 = getX(), y1 = getY(), x2 = x1 + getWidth(), y2 = y1 + getHeight();
|
||||
double x1 = x(), y1 = y(), x2 = x1 + width(), y2 = y1 + height();
|
||||
double rx1 = rx, ry1 = ry, rx2 = rx + rw, ry2 = ry + rh;
|
||||
if (rx2 < x1 || x2 < rx1 || ry2 < y1 || y2 < ry1) {
|
||||
return false;
|
||||
@@ -75,7 +75,7 @@ public abstract class AbstractRoundRectangle extends RectangularShape implements
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform at) {
|
||||
public PathIterator pathIterator (Transform at) {
|
||||
return new Iterator(this, at);
|
||||
}
|
||||
|
||||
@@ -83,23 +83,23 @@ public abstract class AbstractRoundRectangle extends RectangularShape implements
|
||||
protected static class Iterator implements PathIterator
|
||||
{
|
||||
private final double x, y, width, height, aw, ah;
|
||||
private final AffineTransform t;
|
||||
private final Transform t;
|
||||
private int index;
|
||||
|
||||
Iterator (IRoundRectangle rr, AffineTransform at) {
|
||||
this.x = rr.getX();
|
||||
this.y = rr.getY();
|
||||
this.width = rr.getWidth();
|
||||
this.height = rr.getHeight();
|
||||
this.aw = Math.min(width, rr.getArcWidth());
|
||||
this.ah = Math.min(height, rr.getArcHeight());
|
||||
Iterator (IRoundRectangle rr, Transform at) {
|
||||
this.x = rr.x();
|
||||
this.y = rr.y();
|
||||
this.width = rr.width();
|
||||
this.height = rr.height();
|
||||
this.aw = Math.min(width, rr.arcWidth());
|
||||
this.ah = Math.min(height, rr.arcHeight());
|
||||
this.t = at;
|
||||
if (width < 0f || height < 0f || aw < 0f || ah < 0f) {
|
||||
index = POINTS.length;
|
||||
}
|
||||
}
|
||||
|
||||
@Override public int getWindingRule () {
|
||||
@Override public int windingRule () {
|
||||
return WIND_NON_ZERO;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* Implements some code shared by the various {@link Transform} implementations.
|
||||
*/
|
||||
public abstract class AbstractTransform implements Transform
|
||||
{
|
||||
@Override // from Transform
|
||||
public Vector scale () {
|
||||
return new Vector(scaleX(), scaleY());
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Vector translation () {
|
||||
return new Vector(tx(), ty());
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setUniformScale (double scale) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setScale (double scaleX, double scaleY) {
|
||||
setScaleX(scaleX);
|
||||
setScaleY(scaleY);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setScaleX (double scaleX) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setScaleY (double scaleY) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setRotation (double angle) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTranslation (double tx, double ty) {
|
||||
setTx(tx);
|
||||
setTy(ty);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform uniformScale (double scale) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform scale (double scaleX, double scaleY) {
|
||||
scaleX(scaleX);
|
||||
scaleY(scaleY);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform scaleX (double scaleX) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform scaleY (double scaleY) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform rotate (double angle) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translate (double tx, double ty) {
|
||||
translateX(tx);
|
||||
translateY(ty);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translateX (double tx) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translateY (double ty) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTx (double tx) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTy (double ty) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTransform (double m00, double m01, double m10, double m11, double tx, double ty) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public abstract Transform clone ();
|
||||
}
|
||||
@@ -0,0 +1,198 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
import pythagoras.util.Platform;
|
||||
|
||||
/**
|
||||
* Provides most of the implementation of {@link IVector}, obtaining only x and y from the derived
|
||||
* class.
|
||||
*/
|
||||
public abstract class AbstractVector implements IVector
|
||||
{
|
||||
@Override // from interface IVector
|
||||
public double dot (IVector other) {
|
||||
return x()*other.x() + y()*other.y();
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector negate () {
|
||||
return negate(new Vector());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector negate (Vector result) {
|
||||
return result.set(-x(), -y());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector normalize () {
|
||||
return normalize(new Vector());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector normalize (Vector result) {
|
||||
return mult(1f / length(), result);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double angle (IVector other) {
|
||||
double cos = dot(other) / (length() * other.length());
|
||||
return cos >= 1f ? 0f : Math.acos(cos);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double direction (IVector other) {
|
||||
return Math.atan2(other.y() - y(), other.x() - x());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double length () {
|
||||
return Math.sqrt(lengthSq());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double lengthSq () {
|
||||
double x = x(), y = y();
|
||||
return (x*x + y*y);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double distance (IVector other) {
|
||||
return Math.sqrt(distanceSq(other));
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public double distanceSq (IVector other) {
|
||||
double dx = x() - other.x(), dy = y() - other.y();
|
||||
return dx*dx + dy*dy;
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector mult (double v) {
|
||||
return mult(v, new Vector());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector mult (double v, Vector result) {
|
||||
return result.set(x()*v, y()*v);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector mult (IVector other) {
|
||||
return mult(other, new Vector());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector mult (IVector other, Vector result) {
|
||||
return result.set(x()*other.x(), y()*other.y());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector add (IVector other) {
|
||||
return add(other, new Vector());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector add (IVector other, Vector result) {
|
||||
return add(other.x(), other.y(), result);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector subtract (IVector other) {
|
||||
return subtract(other, new Vector());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector subtract (IVector other, Vector result) {
|
||||
return add(-other.x(), -other.y(), result);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector add (double x, double y) {
|
||||
return add(x, y, new Vector());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector add (double x, double y, Vector result) {
|
||||
return result.set(x() + x, y() + y);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector addScaled (IVector other, double v) {
|
||||
return addScaled(other, v, new Vector());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector addScaled (IVector other, double v, Vector result) {
|
||||
return result.set(x() + other.x()*v, y() + other.y()*v);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector rotate (double angle) {
|
||||
return rotate(angle, new Vector());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector rotate (double angle, Vector result) {
|
||||
double x = x(), y = y();
|
||||
double sina = Math.sin(angle), cosa = Math.cos(angle);
|
||||
return result.set(x*cosa - y*sina, x*sina + y*cosa);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector rotateAndAdd (double angle, IVector add, Vector result) {
|
||||
double x = x(), y = y();
|
||||
double sina = Math.sin(angle), cosa = Math.cos(angle);
|
||||
return result.set(x*cosa - y*sina + add.x(), x*sina + y*cosa + add.y());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector rotateScaleAndAdd (double angle, double scale, IVector add, Vector result) {
|
||||
double x = x(), y = y();
|
||||
double sina = Math.sin(angle), cosa = Math.cos(angle);
|
||||
return result.set((x*cosa - y*sina)*scale + add.x(),
|
||||
(x*sina + y*cosa)*scale + add.y());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector lerp (IVector other, double t) {
|
||||
return lerp(other, t, new Vector());
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector lerp (IVector other, double t, Vector result) {
|
||||
double x = x(), y = y();
|
||||
double dx = other.x() - x, dy = other.y() - y;
|
||||
return result.set(x + t*dx, y + t*dy);
|
||||
}
|
||||
|
||||
@Override // from interface IVector
|
||||
public Vector clone () {
|
||||
return new Vector(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals (Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof AbstractVector) {
|
||||
AbstractVector p = (AbstractVector)obj;
|
||||
return x() == p.x() && y() == p.y();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode () {
|
||||
return Platform.hashCode(x()) ^ Platform.hashCode(y());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return Vectors.vectorToString(x(), y());
|
||||
}
|
||||
}
|
||||
@@ -4,649 +4,350 @@
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import pythagoras.util.NoninvertibleTransformException;
|
||||
import pythagoras.util.Platform;
|
||||
|
||||
/**
|
||||
* Represents a 2D affine transform, which performs a linear mapping that preserves the
|
||||
* straightness and parallelness of lines.
|
||||
*
|
||||
* See http://download.oracle.com/javase/6/docs/api/java/awt/geom/AffineTransform.html
|
||||
* Implements an affine (3x2 matrix) transform. The transformation matrix has the form:
|
||||
* <pre>{@code
|
||||
* [ m00, m10, tx ]
|
||||
* [ m01, m11, ty ]
|
||||
* [ 0, 0, 1 ]
|
||||
* }</pre>
|
||||
*/
|
||||
public class AffineTransform implements Cloneable, Serializable
|
||||
public class AffineTransform extends AbstractTransform
|
||||
{
|
||||
public static final int TYPE_IDENTITY = 0;
|
||||
public static final int TYPE_TRANSLATION = 1;
|
||||
public static final int TYPE_UNIFORM_SCALE = 2;
|
||||
public static final int TYPE_GENERAL_SCALE = 4;
|
||||
public static final int TYPE_QUADRANT_ROTATION = 8;
|
||||
public static final int TYPE_GENERAL_ROTATION = 16;
|
||||
public static final int TYPE_GENERAL_TRANSFORM = 32;
|
||||
public static final int TYPE_FLIP = 64;
|
||||
public static final int TYPE_MASK_SCALE = TYPE_UNIFORM_SCALE | TYPE_GENERAL_SCALE;
|
||||
public static final int TYPE_MASK_ROTATION = TYPE_QUADRANT_ROTATION | TYPE_GENERAL_ROTATION;
|
||||
/** Identifies the affine transform in {@link #generality}. */
|
||||
public static final int GENERALITY = 4;
|
||||
|
||||
/**
|
||||
* Returns a transform that performs the specified translation.
|
||||
*/
|
||||
public static AffineTransform getTranslateInstance (double tx, double ty) {
|
||||
AffineTransform t = new AffineTransform();
|
||||
t.setToTranslation(tx, ty);
|
||||
return t;
|
||||
}
|
||||
/** The scale, rotation and shear components of this transform. */
|
||||
public double m00, m01, m10, m11;
|
||||
|
||||
/**
|
||||
* Returns a transform that performs the specified scale.
|
||||
*/
|
||||
public static AffineTransform getScaleInstance (double scx, double scY) {
|
||||
AffineTransform t = new AffineTransform();
|
||||
t.setToScale(scx, scY);
|
||||
return t;
|
||||
}
|
||||
/** The translation components of this transform. */
|
||||
public double tx, ty;
|
||||
|
||||
/**
|
||||
* Returns a transform that performs the specified shear.
|
||||
*/
|
||||
public static AffineTransform getShearInstance (double shx, double shy) {
|
||||
AffineTransform m = new AffineTransform();
|
||||
m.setToShear(shx, shy);
|
||||
return m;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a transform that performs the specified rotation.
|
||||
*/
|
||||
public static AffineTransform getRotateInstance (double angle) {
|
||||
AffineTransform t = new AffineTransform();
|
||||
t.setToRotation(angle);
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a transform that performs the specified rotation.
|
||||
*/
|
||||
public static AffineTransform getRotateInstance (double angle, double x, double y) {
|
||||
AffineTransform t = new AffineTransform();
|
||||
t.setToRotation(angle, x, y);
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs an identity transform.
|
||||
*/
|
||||
/** Creates an affine transform configured with the identity transform. */
|
||||
public AffineTransform () {
|
||||
setToIdentity();
|
||||
this(1, 0, 0, 1, 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a transform that is a copy of the supplied transform.
|
||||
*/
|
||||
public AffineTransform (AffineTransform t) {
|
||||
setTransform(t);
|
||||
/** Creates an affine transform from the supplied scale, rotation and translation. */
|
||||
public AffineTransform (double scale, double angle, double tx, double ty) {
|
||||
this(scale, scale, angle, tx, ty);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a transform with the specified transformation matrix.
|
||||
*/
|
||||
public AffineTransform (double m00, double m10, double m01, double m11,
|
||||
double m02, double m12) {
|
||||
setTransform(m00, m10, m01, m11, m02, m12);
|
||||
/** Creates an affine transform from the supplied scale, rotation and translation. */
|
||||
public AffineTransform (double scaleX, double scaleY, double angle, double tx, double ty) {
|
||||
double sina = Math.sin(angle), cosa = Math.cos(angle);
|
||||
this.m00 = cosa * scaleX; this.m01 = sina * scaleY;
|
||||
this.m10 = -sina * scaleX; this.m11 = cosa * scaleY;
|
||||
this.tx = tx; this.ty = ty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a transform with the specified transformation matrix.
|
||||
*
|
||||
* @param matrix either {@code [m00, m10, m01, m11]} or {@code [m00, m10, m01, m11, m02, m12]}.
|
||||
*/
|
||||
public AffineTransform (double[] matrix) {
|
||||
this.type = TYPE_UNKNOWN;
|
||||
m00 = matrix[0];
|
||||
m10 = matrix[1];
|
||||
m01 = matrix[2];
|
||||
m11 = matrix[3];
|
||||
if (matrix.length > 4) {
|
||||
m02 = matrix[4];
|
||||
m12 = matrix[5];
|
||||
}
|
||||
/** Creates an affine transform with the specified transform matrix. */
|
||||
public AffineTransform (double m00, double m01, double m10, double m11, double tx, double ty) {
|
||||
this.m00 = m00; this.m01 = m01;
|
||||
this.m10 = m10; this.m11 = m11;
|
||||
this.tx = tx; this.ty = ty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of this affine transform, which is a bitwise-or of the type flags
|
||||
* ({@link #TYPE_TRANSLATION}, etc.).
|
||||
*/
|
||||
public int getType () {
|
||||
if (type != TYPE_UNKNOWN) {
|
||||
return type;
|
||||
}
|
||||
|
||||
int type = 0;
|
||||
|
||||
if (m00 * m01 + m10 * m11 != 0) {
|
||||
type |= TYPE_GENERAL_TRANSFORM;
|
||||
return type;
|
||||
}
|
||||
|
||||
if (m02 != 0 || m12 != 0) {
|
||||
type |= TYPE_TRANSLATION;
|
||||
} else if (m00 == 1f && m11 == 1f && m01 == 0 && m10 == 0) {
|
||||
type = TYPE_IDENTITY;
|
||||
return type;
|
||||
}
|
||||
|
||||
if (m00 * m11 - m01 * m10 < 0) {
|
||||
type |= TYPE_FLIP;
|
||||
}
|
||||
|
||||
double dx = m00 * m00 + m10 * m10;
|
||||
double dy = m01 * m01 + m11 * m11;
|
||||
if (dx != dy) {
|
||||
type |= TYPE_GENERAL_SCALE;
|
||||
} else if (dx != 1f) {
|
||||
type |= TYPE_UNIFORM_SCALE;
|
||||
}
|
||||
|
||||
if ((m00 == 0 && m11 == 0) || (m10 == 0 && m01 == 0 && (m00 < 0 || m11 < 0))) {
|
||||
type |= TYPE_QUADRANT_ROTATION;
|
||||
} else if (m01 != 0 || m10 != 0) {
|
||||
type |= TYPE_GENERAL_ROTATION;
|
||||
}
|
||||
|
||||
return type;
|
||||
@Override // from Transform
|
||||
public double uniformScale () {
|
||||
// the square root of the signed area of the parallelogram spanned by the axis vectors
|
||||
double cp = m00*m11 - m01*m10;
|
||||
return (cp < 0f) ? -Math.sqrt(-cp) : Math.sqrt(cp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x-component of the scale vector.
|
||||
*/
|
||||
public double getScaleX () {
|
||||
return m00;
|
||||
@Override // from Transform
|
||||
public double scaleX () {
|
||||
return Math.sqrt(m00*m00 + m01*m01);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the y-component of the scale vector.
|
||||
*/
|
||||
public double getScaleY () {
|
||||
return m11;
|
||||
@Override // from Transform
|
||||
public double scaleY () {
|
||||
return Math.sqrt(m10*m10 + m11*m11);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the x-component of the shear vector.
|
||||
*/
|
||||
public double getShearX () {
|
||||
return m01;
|
||||
}
|
||||
@Override // from Transform
|
||||
public double rotation () {
|
||||
// use the iterative polar decomposition algorithm described by Ken Shoemake:
|
||||
// http://www.cs.wisc.edu/graphics/Courses/838-s2002/Papers/polar-decomp.pdf
|
||||
|
||||
/**
|
||||
* Returns the y-component of the shear vector.
|
||||
*/
|
||||
public double getShearY () {
|
||||
return m10;
|
||||
}
|
||||
// start with the contents of the upper 2x2 portion of the matrix
|
||||
double n00 = m00, n10 = m10;
|
||||
double n01 = m01, n11 = m11;
|
||||
for (int ii = 0; ii < 10; ii++) {
|
||||
// store the results of the previous iteration
|
||||
double o00 = n00, o10 = n10;
|
||||
double o01 = n01, o11 = n11;
|
||||
|
||||
/**
|
||||
* Returns the x-component of the translation vector.
|
||||
*/
|
||||
public double getTranslateX () {
|
||||
return m02;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the y-component of the translation vector.
|
||||
*/
|
||||
public double getTranslateY () {
|
||||
return m12;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this transform is the identity.
|
||||
*/
|
||||
public boolean isIdentity () {
|
||||
return getType() == TYPE_IDENTITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills in the supplied matrix with this transform's values.
|
||||
*
|
||||
* @param matrix either a length-4 or length-6 array.
|
||||
*/
|
||||
public void getMatrix (double[] matrix) {
|
||||
matrix[0] = m00;
|
||||
matrix[1] = m10;
|
||||
matrix[2] = m01;
|
||||
matrix[3] = m11;
|
||||
if (matrix.length > 4) {
|
||||
matrix[4] = m02;
|
||||
matrix[5] = m12;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the <a href="http://en.wikipedia.org/wiki/Determinant">determinant</a> of this
|
||||
* matrix.
|
||||
*/
|
||||
public double getDeterminant () {
|
||||
return m00 * m11 - m01 * m10;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this transform's values.
|
||||
*/
|
||||
public void setTransform (double m00, double m10, double m01, double m11,
|
||||
double m02, double m12) {
|
||||
this.type = TYPE_UNKNOWN;
|
||||
this.m00 = m00;
|
||||
this.m10 = m10;
|
||||
this.m01 = m01;
|
||||
this.m11 = m11;
|
||||
this.m02 = m02;
|
||||
this.m12 = m12;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this transform's values to be equal to those of the supplied transform.
|
||||
*/
|
||||
public void setTransform (AffineTransform t) {
|
||||
setTransform(t.m00, t.m10, t.m01, t.m11, t.m02, t.m12);
|
||||
type = t.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this transform to the identity transform. Any existing transform values are
|
||||
* overwritten.
|
||||
*/
|
||||
public void setToIdentity () {
|
||||
type = TYPE_IDENTITY;
|
||||
m00 = m11 = 1f;
|
||||
m10 = m01 = m02 = m12 = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this transform to a simple translation using the supplied values. Any existing
|
||||
* transform values are overwritten.
|
||||
*/
|
||||
public void setToTranslation (double tx, double ty) {
|
||||
m00 = m11 = 1f;
|
||||
m01 = m10 = 0;
|
||||
m02 = tx;
|
||||
m12 = ty;
|
||||
if (tx == 0 && ty == 0) {
|
||||
type = TYPE_IDENTITY;
|
||||
} else {
|
||||
type = TYPE_TRANSLATION;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this transform to a simple scale using the supplied values. Any existing transform
|
||||
* values are overwritten.
|
||||
*/
|
||||
public void setToScale (double scx, double scy) {
|
||||
m00 = scx;
|
||||
m11 = scy;
|
||||
m10 = m01 = m02 = m12 = 0;
|
||||
if (scx != 1f || scy != 1f) {
|
||||
type = TYPE_UNKNOWN;
|
||||
} else {
|
||||
type = TYPE_IDENTITY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this transform to a simple shear using the supplied values. Any existing transform
|
||||
* values are overwritten.
|
||||
*/
|
||||
public void setToShear (double shx, double shy) {
|
||||
m00 = m11 = 1f;
|
||||
m02 = m12 = 0;
|
||||
m01 = shx;
|
||||
m10 = shy;
|
||||
if (shx != 0 || shy != 0) {
|
||||
type = TYPE_UNKNOWN;
|
||||
} else {
|
||||
type = TYPE_IDENTITY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this transform to a simple rotation using the supplied values. Any existing transform
|
||||
* values are overwritten.
|
||||
*
|
||||
* @param angle the angle of rotation (in radians).
|
||||
*/
|
||||
public void setToRotation (double angle) {
|
||||
double sin = Math.sin(angle);
|
||||
double cos = Math.cos(angle);
|
||||
if (Math.abs(cos) < ZERO) {
|
||||
cos = 0;
|
||||
sin = sin > 0 ? 1f : -1f;
|
||||
} else if (Math.abs(sin) < ZERO) {
|
||||
sin = 0;
|
||||
cos = cos > 0 ? 1f : -1f;
|
||||
}
|
||||
m00 = m11 = cos;
|
||||
m01 = -sin;
|
||||
m10 = sin;
|
||||
m02 = m12 = 0;
|
||||
type = TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets this transform to a simple rotation using the supplied values. Any existing transform
|
||||
* values are overwritten.
|
||||
*
|
||||
* @param angle the angle of rotation (in radians).
|
||||
* @param px the x-coordinate of the point around which to rotate.
|
||||
* @param py the y-coordinate of the point around which to rotate.
|
||||
*/
|
||||
public void setToRotation (double angle, double px, double py) {
|
||||
setToRotation(angle);
|
||||
m02 = px * (1f - m00) + py * m10;
|
||||
m12 = py * (1f - m00) - px * m10;
|
||||
type = TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates the specified translation to this transform.
|
||||
*/
|
||||
public void translate (double tx, double ty) {
|
||||
concatenate(getTranslateInstance(tx, ty));
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates the specified scale to this transform.
|
||||
*/
|
||||
public void scale (double scx, double scy) {
|
||||
concatenate(getScaleInstance(scx, scy));
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates the specified shear to this transform.
|
||||
*/
|
||||
public void shear (double shx, double shy) {
|
||||
concatenate(getShearInstance(shx, shy));
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates the specified rotation to this transform.
|
||||
*/
|
||||
public void rotate (double angle) {
|
||||
concatenate(getRotateInstance(angle));
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates the specified rotation to this transform.
|
||||
*/
|
||||
public void rotate (double angle, double px, double py) {
|
||||
concatenate(getRotateInstance(angle, px, py));
|
||||
}
|
||||
|
||||
/**
|
||||
* Concatenates the specified transform to this transform.
|
||||
*/
|
||||
public void concatenate (AffineTransform t) {
|
||||
multiply(t, this, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-concatenates the specified transform to this transform.
|
||||
*/
|
||||
public void preConcatenate (AffineTransform t) {
|
||||
multiply(this, t, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the inverse of this transform and stores it in the supplied target.
|
||||
*
|
||||
* @return the supplied target.
|
||||
* @throws NoninvertibleTransformException if this transform cannot be inverted.
|
||||
*/
|
||||
public AffineTransform createInverse (AffineTransform target)
|
||||
throws NoninvertibleTransformException {
|
||||
double det = getDeterminant();
|
||||
if (Math.abs(det) < ZERO) {
|
||||
throw new NoninvertibleTransformException("Determinant is zero");
|
||||
}
|
||||
target.setTransform(m11 / det, // m00
|
||||
-m10 / det, // m10
|
||||
-m01 / det, // m01
|
||||
m00 / det, // m11
|
||||
(m01 * m12 - m11 * m02) / det, // m02
|
||||
(m10 * m02 - m00 * m12) / det); // m12
|
||||
return target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes and returns the inverse of this transform.
|
||||
*
|
||||
* @return the supplied target.
|
||||
* @throws NoninvertibleTransformException if this transform cannot be inverted.
|
||||
*/
|
||||
public AffineTransform createInverse () throws NoninvertibleTransformException {
|
||||
return createInverse(new AffineTransform());
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the supplied point using this transform's matrix.
|
||||
*
|
||||
* @param src the point to be transformed.
|
||||
* @param dst the point in which to store the transformed values, if null a new instance will
|
||||
* be created. May be {@code src}.
|
||||
* @return the supplied (or created) destination point.
|
||||
*/
|
||||
public Point transform (IPoint src, Point dst) {
|
||||
if (dst == null) {
|
||||
dst = new Point();
|
||||
}
|
||||
|
||||
double x = src.getX(), y = src.getY();
|
||||
dst.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12);
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the supplied points using this transform's matrix.
|
||||
*
|
||||
* @param src the points to be transformed.
|
||||
* @param srcOff the offset into the {@code src} array at which to start.
|
||||
* @param dst the points into which to store the transformed points. May be {@code src}.
|
||||
* @param dstOff the offset into the {@code dst} array at which to start.
|
||||
* @param length the number of points to transform.
|
||||
*/
|
||||
public void transform (IPoint[] src, int srcOff, Point[] dst, int dstOff, int length) {
|
||||
while (--length >= 0) {
|
||||
IPoint srcPoint = src[srcOff++];
|
||||
double x = srcPoint.getX();
|
||||
double y = srcPoint.getY();
|
||||
Point dstPoint = dst[dstOff];
|
||||
if (dstPoint == null) {
|
||||
dstPoint = new Point();
|
||||
// compute average of the matrix with its inverse transpose
|
||||
double det = o00*o11 - o10*o01;
|
||||
if (Math.abs(det) == 0f) {
|
||||
// determinant is zero; matrix is not invertible
|
||||
throw new NoninvertibleTransformException(this.toString());
|
||||
}
|
||||
dstPoint.setLocation(x * m00 + y * m01 + m02, x * m10 + y * m11 + m12);
|
||||
dst[dstOff++] = dstPoint;
|
||||
double hrdet = 0.5f / det;
|
||||
n00 = +o11 * hrdet + o00*0.5f;
|
||||
n10 = -o01 * hrdet + o10*0.5f;
|
||||
|
||||
n01 = -o10 * hrdet + o01*0.5f;
|
||||
n11 = +o00 * hrdet + o11*0.5f;
|
||||
|
||||
// compute the difference; if it's small enough, we're done
|
||||
double d00 = n00 - o00, d10 = n10 - o10;
|
||||
double d01 = n01 - o01, d11 = n11 - o11;
|
||||
if (d00*d00 + d10*d10 + d01*d01 + d11*d11 < MathUtil.EPSILON) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// now that we have a nice orthogonal matrix, we can extract the rotation
|
||||
return Math.atan2(n01, n00);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double tx () {
|
||||
return this.tx;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double ty () {
|
||||
return this.ty;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setUniformScale (double scale) {
|
||||
return setScale(scale, scale);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setScaleX (double scaleX) {
|
||||
// normalize the scale to 1, then re-apply
|
||||
double osx = scaleX();
|
||||
m00 /= osx; m01 /= osx;
|
||||
m00 *= scaleX; m01 *= scaleX;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setScaleY (double scaleY) {
|
||||
// normalize the scale to 1, then re-apply
|
||||
double osy = scaleY();
|
||||
m10 /= osy; m11 /= osy;
|
||||
m10 *= scaleY; m11 *= scaleY;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setRotation (double angle) {
|
||||
// extract the scale, then reapply rotation and scale together
|
||||
double sx = scaleX(), sy = scaleY();
|
||||
double sina = Math.sin(angle), cosa = Math.cos(angle);
|
||||
m00 = cosa * sx; m01 = sina * sx;
|
||||
m10 = -sina * sy; m11 = cosa * sy;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTranslation (double tx, double ty) {
|
||||
this.tx = tx;
|
||||
this.ty = ty;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTx (double tx) {
|
||||
this.tx = tx;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTy (double ty) {
|
||||
this.ty = ty;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTransform (double m00, double m01, double m10, double m11, double tx, double ty) {
|
||||
this.m00 = m00;
|
||||
this.m01 = m01;
|
||||
this.m10 = m10;
|
||||
this.m11 = m11;
|
||||
this.tx = tx;
|
||||
this.ty = ty;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform uniformScale (double scale) {
|
||||
return scale(scale, scale);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform scaleX (double scaleX) {
|
||||
m00 *= scaleX;
|
||||
m01 *= scaleX;
|
||||
tx *= scaleX;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform scaleY (double scaleY) {
|
||||
m10 *= scaleY;
|
||||
m11 *= scaleY;
|
||||
ty *= scaleY;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform rotate (double angle) {
|
||||
double sina = Math.sin(angle), cosa = Math.cos(angle);
|
||||
return Transforms.multiply(cosa, sina, -sina, cosa, 0, 0, this, this);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translate (double tx, double ty) {
|
||||
return Transforms.multiply(this, 1, 0, 0, 1, tx, ty, this);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translateX (double tx) {
|
||||
return Transforms.multiply(this, 1, 0, 0, 1, tx, 0, this);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translateY (double ty) {
|
||||
return Transforms.multiply(this, 1, 0, 0, 1, 0, ty, this);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform invert () {
|
||||
// compute the determinant, storing the subdeterminants for later use
|
||||
double det = m00*m11 - m10*m01;
|
||||
if (Math.abs(det) == 0f) {
|
||||
// determinant is zero; matrix is not invertible
|
||||
throw new NoninvertibleTransformException(this.toString());
|
||||
}
|
||||
double rdet = 1f / det;
|
||||
return new AffineTransform(
|
||||
+m11 * rdet, -m10 * rdet,
|
||||
-m01 * rdet, +m00 * rdet,
|
||||
(m10*ty - m11*tx) * rdet, (m01*tx - m00*ty) * rdet);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform concatenate (Transform other) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.preConcatenate(this);
|
||||
}
|
||||
if (other instanceof AffineTransform) {
|
||||
return Transforms.multiply(this, (AffineTransform)other, new AffineTransform());
|
||||
} else {
|
||||
AffineTransform oaff = new AffineTransform(other);
|
||||
return Transforms.multiply(this, oaff, oaff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the supplied points using this transform's matrix.
|
||||
*
|
||||
* @param src the points to be transformed (as {@code [x, y, x, y, ...]}).
|
||||
* @param srcOff the offset into the {@code src} array at which to start.
|
||||
* @param dst the points into which to store the transformed points. May be {@code src}.
|
||||
* @param dstOff the offset into the {@code dst} array at which to start.
|
||||
* @param length the number of points to transform.
|
||||
*/
|
||||
public void transform (double[] src, int srcOff, double[] dst, int dstOff, int length) {
|
||||
int step = 2;
|
||||
if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) {
|
||||
srcOff = srcOff + length * 2 - 2;
|
||||
dstOff = dstOff + length * 2 - 2;
|
||||
step = -2;
|
||||
@Override // from Transform
|
||||
public Transform preConcatenate (Transform other) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.concatenate(this);
|
||||
}
|
||||
while (--length >= 0) {
|
||||
double x = src[srcOff + 0];
|
||||
double y = src[srcOff + 1];
|
||||
dst[dstOff + 0] = (x * m00 + y * m01 + m02);
|
||||
dst[dstOff + 1] = (x * m10 + y * m11 + m12);
|
||||
srcOff += step;
|
||||
dstOff += step;
|
||||
if (other instanceof AffineTransform) {
|
||||
return Transforms.multiply((AffineTransform)other, this, new AffineTransform());
|
||||
} else {
|
||||
AffineTransform oaff = new AffineTransform(other);
|
||||
return Transforms.multiply(oaff, this, oaff);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the supplied relative distance vector (ignores the translation component).
|
||||
*
|
||||
* @param src the point to be transformed.
|
||||
* @param dst the point in which to store the transformed values, if null a new instance will
|
||||
* be created. May be {@code src}.
|
||||
* @return the supplied (or created) destination point.
|
||||
*/
|
||||
public Point deltaTransform (IPoint src, Point dst) {
|
||||
if (dst == null) {
|
||||
dst = new Point();
|
||||
@Override // from Transform
|
||||
public Transform lerp (Transform other, double t) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.lerp(this, -t); // TODO: is this correct?
|
||||
}
|
||||
double x = src.getX(), y = src.getY();
|
||||
dst.setLocation(x * m00 + y * m01, x * m10 + y * m11);
|
||||
return dst;
|
||||
|
||||
AffineTransform ot = (other instanceof AffineTransform) ?
|
||||
(AffineTransform)other : new AffineTransform(other);
|
||||
return new AffineTransform(
|
||||
m00 + t*(ot.m00 - m00), m01 + t*(ot.m01 - m01),
|
||||
m10 + t*(ot.m10 - m10), m11 + t*(ot.m11 - m11),
|
||||
tx + t*(ot.tx - tx ), ty + t*(ot.ty - ty ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the supplied relative distance vectors using this transform's matrix (ignores the
|
||||
* translation component).
|
||||
*
|
||||
* @param src the points to be transformed (as {@code [x, y, x, y, ...]}).
|
||||
* @param srcOff the offset into the {@code src} array at which to start.
|
||||
* @param dst the points into which to store the transformed points. May be {@code src}.
|
||||
* @param dstOff the offset into the {@code dst} array at which to start.
|
||||
* @param length the number of points to transform.
|
||||
*/
|
||||
public void deltaTransform (double[] src, int srcOff, double[] dst, int dstOff, int length) {
|
||||
while (--length >= 0) {
|
||||
@Override // from Transform
|
||||
public Point transform (IPoint p, Point into) {
|
||||
double x = p.x(), y = p.y();
|
||||
return into.set(m00*x + m10*y + tx, m01*x + m11*y + ty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public void transform (IPoint[] src, int srcOff, Point[] dst, int dstOff, int count) {
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
transform(src[srcOff++], dst[dstOff++]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public void transform (double[] src, int srcOff, double[] dst, int dstOff, int count) {
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
double x = src[srcOff++], y = src[srcOff++];
|
||||
dst[dstOff++] = x * m00 + y * m01;
|
||||
dst[dstOff++] = x * m10 + y * m11;
|
||||
dst[dstOff++] = m00*x + m10*y + tx;
|
||||
dst[dstOff++] = m01*x + m11*y + ty;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the supplied point using the inverse of this transform's matrix.
|
||||
*
|
||||
* @param src the point to be transformed.
|
||||
* @param dst the point in which to store the transformed values, if null a new instance will
|
||||
* be created. May be {@code src}.
|
||||
* @return the supplied (or created) destination point.
|
||||
*/
|
||||
public Point inverseTransform (IPoint src, Point dst) throws NoninvertibleTransformException {
|
||||
double det = getDeterminant();
|
||||
if (Math.abs(det) < ZERO) {
|
||||
throw new NoninvertibleTransformException("Determinant is zero");
|
||||
@Override // from Transform
|
||||
public Point inverseTransform (IPoint p, Point into) {
|
||||
double x = p.x() - tx, y = p.y() - ty;
|
||||
double det = m00 * m11 - m01 * m10;
|
||||
if (Math.abs(det) == 0f) {
|
||||
// determinant is zero; matrix is not invertible
|
||||
throw new NoninvertibleTransformException(this.toString());
|
||||
}
|
||||
if (dst == null) {
|
||||
dst = new Point();
|
||||
}
|
||||
double x = src.getX() - m02, y = src.getY() - m12;
|
||||
dst.setLocation((x * m11 - y * m01) / det, (y * m00 - x * m10) / det);
|
||||
return dst;
|
||||
double rdet = 1 / det;
|
||||
return into.set((x * m11 - y * m10) * rdet,
|
||||
(y * m00 - x * m01) * rdet);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the supplied points using the inverse of this transform's matrix.
|
||||
*
|
||||
* @param src the points to be transformed (as {@code [x, y, x, y, ...]}).
|
||||
* @param srcOff the offset into the {@code src} array at which to start.
|
||||
* @param dst the points into which to store the transformed points. May be {@code src}.
|
||||
* @param dstOff the offset into the {@code dst} array at which to start.
|
||||
* @param length the number of points to transform.
|
||||
*/
|
||||
public void inverseTransform (double[] src, int srcOff, double[] dst, int dstOff, int length)
|
||||
throws NoninvertibleTransformException {
|
||||
double det = getDeterminant();
|
||||
if (Math.abs(det) < ZERO) {
|
||||
throw new NoninvertibleTransformException("Determinant is zero");
|
||||
}
|
||||
while (--length >= 0) {
|
||||
double x = src[srcOff++] - m02, y = src[srcOff++] - m12;
|
||||
dst[dstOff++] = (x * m11 - y * m01) / det;
|
||||
dst[dstOff++] = (y * m00 - x * m10) / det;
|
||||
}
|
||||
@Override // from Transform
|
||||
public Vector transform (IVector v, Vector into) {
|
||||
double x = v.x(), y = v.y();
|
||||
return into.set(m00*x + m10*y, m01*x + m11*y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and returns a new shape that is the supplied shape transformed by this transform's
|
||||
* matrix.
|
||||
*/
|
||||
public IShape createTransformedShape (IShape src) {
|
||||
if (src == null) {
|
||||
return null;
|
||||
@Override // from Transform
|
||||
public Vector inverseTransform (IVector v, Vector into) {
|
||||
double x = v.x(), y = v.y();
|
||||
double det = m00 * m11 - m01 * m10;
|
||||
if (Math.abs(det) == 0f) {
|
||||
// determinant is zero; matrix is not invertible
|
||||
throw new NoninvertibleTransformException(this.toString());
|
||||
}
|
||||
if (src instanceof Path) {
|
||||
return ((Path)src).createTransformedShape(this);
|
||||
}
|
||||
PathIterator path = src.getPathIterator(this);
|
||||
Path dst = new Path(path.getWindingRule());
|
||||
dst.append(path, false);
|
||||
return dst;
|
||||
double rdet = 1 / det;
|
||||
return into.set((x * m11 - y * m10) * rdet,
|
||||
(y * m00 - x * m01) * rdet);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform clone () {
|
||||
return new AffineTransform(m00, m01, m10, m11, tx, ty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public int generality () {
|
||||
return GENERALITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return getClass().getName() +
|
||||
"[[" + m00 + ", " + m01 + ", " + m02 + "], [" + m10 + ", " + m11 + ", " + m12 + "]]";
|
||||
return "affine [" + MathUtil.toString(m00) + " " + MathUtil.toString(m01) + " " +
|
||||
MathUtil.toString(m10) + " " + MathUtil.toString(m11) + " " + translation() + "]";
|
||||
}
|
||||
|
||||
// @Override // can't declare @Override due to GWT
|
||||
public AffineTransform clone () {
|
||||
return new AffineTransform(this);
|
||||
// we don't publicize this because it might encourage someone to do something stupid like
|
||||
// create a new AffineTransform from another AffineTransform using this instead of clone()
|
||||
protected AffineTransform (Transform other) {
|
||||
this(other.scaleX(), other.scaleY(), other.rotation(),
|
||||
other.tx(), other.ty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode () {
|
||||
return Platform.hashCode(m00) ^ Platform.hashCode(m01) ^ Platform.hashCode(m02) ^
|
||||
Platform.hashCode(m10) ^ Platform.hashCode(m11) ^ Platform.hashCode(m12);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals (Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
if (obj instanceof AffineTransform) {
|
||||
AffineTransform t = (AffineTransform)obj;
|
||||
return m00 == t.m00 && m01 == t.m01 && m02 == t.m02 &&
|
||||
m10 == t.m10 && m11 == t.m11 && m12 == t.m12;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies two transforms, storing the result in the target transform.
|
||||
* @return the supplied target transform.
|
||||
*/
|
||||
protected static AffineTransform multiply (AffineTransform t1, AffineTransform t2,
|
||||
AffineTransform into) {
|
||||
into.setTransform(t1.m00 * t2.m00 + t1.m10 * t2.m01, // m00
|
||||
t1.m00 * t2.m10 + t1.m10 * t2.m11, // m01
|
||||
t1.m01 * t2.m00 + t1.m11 * t2.m01, // m10
|
||||
t1.m01 * t2.m10 + t1.m11 * t2.m11, // m11
|
||||
t1.m02 * t2.m00 + t1.m12 * t2.m01 + t2.m02, // m02
|
||||
t1.m02 * t2.m10 + t1.m12 * t2.m11 + t2.m12); // m12
|
||||
return into;
|
||||
}
|
||||
|
||||
// the values of transformation matrix
|
||||
private double m00;
|
||||
private double m10;
|
||||
private double m01;
|
||||
private double m11;
|
||||
private double m02;
|
||||
private double m12;
|
||||
|
||||
/** The transformation {@code type}. */
|
||||
private transient int type;
|
||||
|
||||
/** An initial type value. */
|
||||
private static final int TYPE_UNKNOWN = -1;
|
||||
|
||||
/** The min value equivalent to zero. An absolute value < ZERO is considered to be zero. */
|
||||
private static final double ZERO = 1E-10f;
|
||||
}
|
||||
|
||||
@@ -47,8 +47,7 @@ public class Arc extends AbstractArc implements Serializable
|
||||
* Creates an arc of the specified type with the specified framing rectangle, starting angle
|
||||
* and angular extent.
|
||||
*/
|
||||
public Arc (double x, double y, double width, double height,
|
||||
double start, double extent, int type) {
|
||||
public Arc (double x, double y, double width, double height, double start, double extent, int type) {
|
||||
setArc(x, y, width, height, start, extent, type);
|
||||
}
|
||||
|
||||
@@ -57,42 +56,42 @@ public class Arc extends AbstractArc implements Serializable
|
||||
* angular extent.
|
||||
*/
|
||||
public Arc (IRectangle bounds, double start, double extent, int type) {
|
||||
setArc(bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(),
|
||||
setArc(bounds.x(), bounds.y(), bounds.width(), bounds.height(),
|
||||
start, extent, type);
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public int getArcType () {
|
||||
public int arcType () {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public double getX () {
|
||||
public double x () {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public double getY () {
|
||||
public double y () {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public double getWidth () {
|
||||
public double width () {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public double getHeight () {
|
||||
public double height () {
|
||||
return height;
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public double getAngleStart () {
|
||||
public double angleStart () {
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override // from interface IArc
|
||||
public double getAngleExtent () {
|
||||
public double angleExtent () {
|
||||
return extent;
|
||||
}
|
||||
|
||||
@@ -140,7 +139,7 @@ public class Arc extends AbstractArc implements Serializable
|
||||
* values.
|
||||
*/
|
||||
public void setArc (IPoint point, IDimension size, double start, double extent, int type) {
|
||||
setArc(point.getX(), point.getY(), size.getWidth(), size.getHeight(), start, extent, type);
|
||||
setArc(point.x(), point.y(), size.width(), size.height(), start, extent, type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,7 +147,7 @@ public class Arc extends AbstractArc implements Serializable
|
||||
* values.
|
||||
*/
|
||||
public void setArc (IRectangle rect, double start, double extent, int type) {
|
||||
setArc(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight(), start, extent, type);
|
||||
setArc(rect.x(), rect.y(), rect.width(), rect.height(), start, extent, type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,8 +155,8 @@ public class Arc extends AbstractArc implements Serializable
|
||||
* the supplied arc.
|
||||
*/
|
||||
public void setArc (IArc arc) {
|
||||
setArc(arc.getX(), arc.getY(), arc.getWidth(), arc.getHeight(), arc.getAngleStart(),
|
||||
arc.getAngleExtent(), arc.getArcType());
|
||||
setArc(arc.x(), arc.y(), arc.width(), arc.height(), arc.angleStart(),
|
||||
arc.angleExtent(), arc.arcType());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -175,16 +174,16 @@ public class Arc extends AbstractArc implements Serializable
|
||||
*/
|
||||
public void setArcByTangent (IPoint p1, IPoint p2, IPoint p3, double radius) {
|
||||
// use simple geometric calculations of arc center, radius and angles by tangents
|
||||
double a1 = -Math.atan2(p1.getY() - p2.getY(), p1.getX() - p2.getX());
|
||||
double a2 = -Math.atan2(p3.getY() - p2.getY(), p3.getX() - p2.getX());
|
||||
double a1 = -Math.atan2(p1.y() - p2.y(), p1.x() - p2.x());
|
||||
double a2 = -Math.atan2(p3.y() - p2.y(), p3.x() - p2.x());
|
||||
double am = (a1 + a2) / 2f;
|
||||
double ah = a1 - am;
|
||||
double d = radius / Math.abs(Math.sin(ah));
|
||||
double x = p2.getX() + d * Math.cos(am);
|
||||
double y = p2.getY() - d * Math.sin(am);
|
||||
double x = p2.x() + d * Math.cos(am);
|
||||
double y = p2.y() - d * Math.sin(am);
|
||||
ah = ah >= 0f ? Math.PI * 1.5f - ah : Math.PI * 0.5f - ah;
|
||||
a1 = getNormAngle(Math.toDegrees(am - ah));
|
||||
a2 = getNormAngle(Math.toDegrees(am + ah));
|
||||
a1 = normAngle(Math.toDegrees(am - ah));
|
||||
a2 = normAngle(Math.toDegrees(am + ah));
|
||||
double delta = a2 - a1;
|
||||
if (delta <= 0f) {
|
||||
delta += 360f;
|
||||
@@ -197,8 +196,8 @@ public class Arc extends AbstractArc implements Serializable
|
||||
* the center of this arc.
|
||||
*/
|
||||
public void setAngleStart (IPoint point) {
|
||||
double angle = Math.atan2(point.getY() - getCenterY(), point.getX() - getCenterX());
|
||||
setAngleStart(getNormAngle(-Math.toDegrees(angle)));
|
||||
double angle = Math.atan2(point.y() - centerY(), point.x() - centerX());
|
||||
setAngleStart(normAngle(-Math.toDegrees(angle)));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -209,10 +208,10 @@ public class Arc extends AbstractArc implements Serializable
|
||||
* counterclockwise from the first point around to the second point.
|
||||
*/
|
||||
public void setAngles (double x1, double y1, double x2, double y2) {
|
||||
double cx = getCenterX();
|
||||
double cy = getCenterY();
|
||||
double a1 = getNormAngle(-Math.toDegrees(Math.atan2(y1 - cy, x1 - cx)));
|
||||
double a2 = getNormAngle(-Math.toDegrees(Math.atan2(y2 - cy, x2 - cx)));
|
||||
double cx = centerX();
|
||||
double cy = centerY();
|
||||
double a1 = normAngle(-Math.toDegrees(Math.atan2(y1 - cy, x1 - cx)));
|
||||
double a2 = normAngle(-Math.toDegrees(Math.atan2(y2 - cy, x2 - cx)));
|
||||
a2 -= a1;
|
||||
if (a2 <= 0f) {
|
||||
a2 += 360f;
|
||||
@@ -229,12 +228,12 @@ public class Arc extends AbstractArc implements Serializable
|
||||
* counterclockwise from the first point around to the second point.
|
||||
*/
|
||||
public void setAngles (IPoint p1, IPoint p2) {
|
||||
setAngles(p1.getX(), p1.getY(), p2.getX(), p2.getY());
|
||||
setAngles(p1.x(), p1.y(), p2.x(), p2.y());
|
||||
}
|
||||
|
||||
@Override // from RectangularShape
|
||||
public void setFrame (double x, double y, double width, double height) {
|
||||
setArc(x, y, width, height, getAngleStart(), getAngleExtent(), type);
|
||||
setArc(x, y, width, height, angleStart(), angleExtent(), type);
|
||||
}
|
||||
|
||||
private int type;
|
||||
|
||||
@@ -30,7 +30,7 @@ public class Area implements IShape, Cloneable
|
||||
int rulesIndex = 0;
|
||||
int coordsIndex = 0;
|
||||
|
||||
for (PathIterator pi = s.getPathIterator(null); !pi.isDone(); pi.next()) {
|
||||
for (PathIterator pi = s.pathIterator(null); !pi.isDone(); pi.next()) {
|
||||
coords = adjustSize(coords, coordsIndex + 6);
|
||||
rules = adjustSize(rules, rulesIndex + 1);
|
||||
offsets = adjustSize(offsets, rulesIndex + 1);
|
||||
@@ -112,15 +112,15 @@ public class Area implements IShape, Cloneable
|
||||
/**
|
||||
* Transforms this area with the supplied transform.
|
||||
*/
|
||||
public void transform (AffineTransform t) {
|
||||
copy(new Area(t.createTransformedShape(this)), this);
|
||||
public void transform (Transform t) {
|
||||
copy(new Area(Transforms.createTransformedShape(t, this)), this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new area equal to this area transformed by the supplied transform.
|
||||
*/
|
||||
public Area createTransformedArea (AffineTransform t) {
|
||||
return new Area(t.createTransformedShape(this));
|
||||
public Area createTransformedArea (Transform t) {
|
||||
return new Area(Transforms.createTransformedShape(t, this));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,7 +140,7 @@ public class Area implements IShape, Cloneable
|
||||
addCurvePolygon(area);
|
||||
}
|
||||
|
||||
if (getAreaBoundsSquare() < GeometryUtil.EPSILON) {
|
||||
if (areaBoundsSquare() < GeometryUtil.EPSILON) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
@@ -162,7 +162,7 @@ public class Area implements IShape, Cloneable
|
||||
intersectCurvePolygon(area);
|
||||
}
|
||||
|
||||
if (getAreaBoundsSquare() < GeometryUtil.EPSILON) {
|
||||
if (areaBoundsSquare() < GeometryUtil.EPSILON) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
@@ -181,7 +181,7 @@ public class Area implements IShape, Cloneable
|
||||
subtractCurvePolygon(area);
|
||||
}
|
||||
|
||||
if (getAreaBoundsSquare() < GeometryUtil.EPSILON) {
|
||||
if (areaBoundsSquare() < GeometryUtil.EPSILON) {
|
||||
reset();
|
||||
}
|
||||
}
|
||||
@@ -209,25 +209,25 @@ public class Area implements IShape, Cloneable
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (double x, double y, double width, double height) {
|
||||
int crossCount = Crossing.intersectPath(getPathIterator(null), x, y, width, height);
|
||||
int crossCount = Crossing.intersectPath(pathIterator(null), x, y, width, height);
|
||||
return crossCount != Crossing.CROSSING && Crossing.isInsideEvenOdd(crossCount);
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (IPoint p) {
|
||||
return contains(p.getX(), p.getY());
|
||||
return contains(p.x(), p.y());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (IRectangle r) {
|
||||
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
return contains(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean intersects (double x, double y, double width, double height) {
|
||||
if ((width <= 0f) || (height <= 0f)) {
|
||||
return false;
|
||||
} else if (!getBounds().intersects(x, y, width, height)) {
|
||||
} else if (!bounds().intersects(x, y, width, height)) {
|
||||
return false;
|
||||
}
|
||||
int crossCount = Crossing.intersectShape(this, x, y, width, height);
|
||||
@@ -236,16 +236,16 @@ public class Area implements IShape, Cloneable
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean intersects (IRectangle r) {
|
||||
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
return intersects(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds () {
|
||||
return getBounds(new Rectangle());
|
||||
public Rectangle bounds () {
|
||||
return bounds(new Rectangle());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds (Rectangle target) {
|
||||
public Rectangle bounds (Rectangle target) {
|
||||
double maxX = coords[0], maxY = coords[1];
|
||||
double minX = coords[0], minY = coords[1];
|
||||
for (int i = 0; i < coordsSize;) {
|
||||
@@ -258,13 +258,13 @@ public class Area implements IShape, Cloneable
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform t) {
|
||||
public PathIterator pathIterator (Transform t) {
|
||||
return new AreaPathIterator(t);
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform t, double flatness) {
|
||||
return new FlatteningPathIterator(getPathIterator(t), flatness);
|
||||
public PathIterator pathIterator (Transform t, double flatness) {
|
||||
return new FlatteningPathIterator(pathIterator(t), flatness);
|
||||
}
|
||||
|
||||
@Override // from Object
|
||||
@@ -296,9 +296,9 @@ public class Area implements IShape, Cloneable
|
||||
IntersectPoint[] intersectPoints = crossHelper.findCrossing();
|
||||
|
||||
if (intersectPoints.length == 0) {
|
||||
if (area.contains(getBounds())) {
|
||||
if (area.contains(bounds())) {
|
||||
copy(area, this);
|
||||
} else if (!contains(area.getBounds())) {
|
||||
} else if (!contains(area.bounds())) {
|
||||
coords = adjustSize(coords, coordsSize + area.coordsSize);
|
||||
System.arraycopy(area.coords, 0, coords, coordsSize, area.coordsSize);
|
||||
coordsSize += area.coordsSize;
|
||||
@@ -324,9 +324,9 @@ public class Area implements IShape, Cloneable
|
||||
resultOffsets[resultRulesPos++] = resultCoordPos;
|
||||
|
||||
do {
|
||||
resultCoords[resultCoordPos++] = point.getX();
|
||||
resultCoords[resultCoordPos++] = point.getY();
|
||||
int curIndex = point.getEndIndex(true);
|
||||
resultCoords[resultCoordPos++] = point.x();
|
||||
resultCoords[resultCoordPos++] = point.y();
|
||||
int curIndex = point.endIndex(true);
|
||||
if (curIndex < 0) {
|
||||
isCurrentArea = !isCurrentArea;
|
||||
} else if (area.containsExact(coords[2 * curIndex], coords[2 * curIndex + 1]) > 0) {
|
||||
@@ -335,13 +335,13 @@ public class Area implements IShape, Cloneable
|
||||
isCurrentArea = true;
|
||||
}
|
||||
|
||||
IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
IntersectPoint nextPoint = nextIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
double[] coords = (isCurrentArea) ? this.coords : area.coords;
|
||||
int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
|
||||
int[] rules = (isCurrentArea) ? this.rules : area.rules;
|
||||
int offset = point.getRuleIndex(isCurrentArea);
|
||||
int offset = point.ruleIndex(isCurrentArea);
|
||||
boolean isCopyUntilZero = false;
|
||||
if ((point.getRuleIndex(isCurrentArea) > nextPoint.getRuleIndex(isCurrentArea))) {
|
||||
if ((point.ruleIndex(isCurrentArea) > nextPoint.ruleIndex(isCurrentArea))) {
|
||||
int rulesSize = (isCurrentArea) ? this.rulesSize : area.rulesSize;
|
||||
resultCoordPos = includeCoordsAndRules(offset + 1, rulesSize, rules, offsets,
|
||||
resultRules, resultOffsets, resultCoords, coords, resultRulesPos,
|
||||
@@ -351,7 +351,7 @@ public class Area implements IShape, Cloneable
|
||||
isCopyUntilZero = true;
|
||||
}
|
||||
|
||||
int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
|
||||
int length = nextPoint.ruleIndex(isCurrentArea) - offset + 1;
|
||||
if (isCopyUntilZero) {
|
||||
offset = 0;
|
||||
}
|
||||
@@ -379,9 +379,9 @@ public class Area implements IShape, Cloneable
|
||||
IntersectPoint[] intersectPoints = crossHelper.findCrossing();
|
||||
|
||||
if (intersectPoints.length == 0) {
|
||||
if (area.contains(getBounds())) {
|
||||
if (area.contains(bounds())) {
|
||||
copy(area, this);
|
||||
} else if (!contains(area.getBounds())) {
|
||||
} else if (!contains(area.bounds())) {
|
||||
coords = adjustSize(coords, coordsSize + area.coordsSize);
|
||||
System.arraycopy(area.coords, 0, coords, coordsSize, area.coordsSize);
|
||||
coordsSize += area.coordsSize;
|
||||
@@ -406,11 +406,11 @@ public class Area implements IShape, Cloneable
|
||||
resultOffsets[resultRulesPos++] = resultCoordPos;
|
||||
|
||||
do {
|
||||
resultCoords[resultCoordPos++] = point.getX();
|
||||
resultCoords[resultCoordPos++] = point.getY();
|
||||
resultCoords[resultCoordPos++] = point.x();
|
||||
resultCoords[resultCoordPos++] = point.y();
|
||||
resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
|
||||
resultOffsets[resultRulesPos++] = resultCoordPos - 2;
|
||||
int curIndex = point.getEndIndex(true);
|
||||
int curIndex = point.endIndex(true);
|
||||
if (curIndex < 0) {
|
||||
isCurrentArea = !isCurrentArea;
|
||||
} else if (area.containsExact(coords[2 * curIndex], coords[2 * curIndex + 1]) > 0) {
|
||||
@@ -419,11 +419,11 @@ public class Area implements IShape, Cloneable
|
||||
isCurrentArea = true;
|
||||
}
|
||||
|
||||
IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
IntersectPoint nextPoint = nextIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
double[] coords = (isCurrentArea) ? this.coords : area.coords;
|
||||
int offset = 2 * point.getEndIndex(isCurrentArea);
|
||||
int offset = 2 * point.endIndex(isCurrentArea);
|
||||
if ((offset >= 0) &&
|
||||
(nextPoint.getBegIndex(isCurrentArea) < point.getEndIndex(isCurrentArea))) {
|
||||
(nextPoint.begIndex(isCurrentArea) < point.endIndex(isCurrentArea))) {
|
||||
int coordSize = (isCurrentArea) ? this.coordsSize : area.coordsSize;
|
||||
int length = coordSize - offset;
|
||||
System.arraycopy(coords, offset, resultCoords, resultCoordPos, length);
|
||||
@@ -438,7 +438,7 @@ public class Area implements IShape, Cloneable
|
||||
}
|
||||
|
||||
if (offset >= 0) {
|
||||
int length = 2 * nextPoint.getBegIndex(isCurrentArea) - offset + 2;
|
||||
int length = 2 * nextPoint.begIndex(isCurrentArea) - offset + 2;
|
||||
System.arraycopy(coords, offset, resultCoords, resultCoordPos, length);
|
||||
|
||||
for (int i = 0; i < length / 2; i++) {
|
||||
@@ -469,9 +469,9 @@ public class Area implements IShape, Cloneable
|
||||
new int[][] { offsets, area.offsets });
|
||||
IntersectPoint[] intersectPoints = crossHelper.findCrossing();
|
||||
if (intersectPoints.length == 0) {
|
||||
if (contains(area.getBounds())) {
|
||||
if (contains(area.bounds())) {
|
||||
copy(area, this);
|
||||
} else if (!area.contains(getBounds())) {
|
||||
} else if (!area.contains(bounds())) {
|
||||
reset();
|
||||
}
|
||||
return;
|
||||
@@ -490,10 +490,10 @@ public class Area implements IShape, Cloneable
|
||||
resultOffsets[resultRulesPos++] = resultCoordPos;
|
||||
|
||||
do {
|
||||
resultCoords[resultCoordPos++] = point.getX();
|
||||
resultCoords[resultCoordPos++] = point.getY();
|
||||
resultCoords[resultCoordPos++] = point.x();
|
||||
resultCoords[resultCoordPos++] = point.y();
|
||||
|
||||
int curIndex = point.getEndIndex(true);
|
||||
int curIndex = point.endIndex(true);
|
||||
if ((curIndex < 0) ||
|
||||
(area.containsExact(coords[2 * curIndex], coords[2 * curIndex + 1]) == 0)) {
|
||||
isCurrentArea = !isCurrentArea;
|
||||
@@ -503,14 +503,14 @@ public class Area implements IShape, Cloneable
|
||||
isCurrentArea = false;
|
||||
}
|
||||
|
||||
nextPoint = getNextIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
nextPoint = nextIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
double[] coords = (isCurrentArea) ? this.coords : area.coords;
|
||||
int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
|
||||
int[] rules = (isCurrentArea) ? this.rules : area.rules;
|
||||
int offset = point.getRuleIndex(isCurrentArea);
|
||||
int offset = point.ruleIndex(isCurrentArea);
|
||||
boolean isCopyUntilZero = false;
|
||||
|
||||
if (point.getRuleIndex(isCurrentArea) > nextPoint.getRuleIndex(isCurrentArea)) {
|
||||
if (point.ruleIndex(isCurrentArea) > nextPoint.ruleIndex(isCurrentArea)) {
|
||||
int rulesSize = (isCurrentArea) ? this.rulesSize : area.rulesSize;
|
||||
resultCoordPos = includeCoordsAndRules(
|
||||
offset + 1, rulesSize, rules, offsets, resultRules, resultOffsets,
|
||||
@@ -521,17 +521,17 @@ public class Area implements IShape, Cloneable
|
||||
isCopyUntilZero = true;
|
||||
}
|
||||
|
||||
int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
|
||||
int length = nextPoint.ruleIndex(isCurrentArea) - offset + 1;
|
||||
|
||||
if (isCopyUntilZero) {
|
||||
offset = 0;
|
||||
isCopyUntilZero = false;
|
||||
}
|
||||
if ((length == offset) &&
|
||||
(nextPoint.getRule(isCurrentArea) != PathIterator.SEG_LINETO) &&
|
||||
(nextPoint.getRule(isCurrentArea) != PathIterator.SEG_CLOSE) &&
|
||||
(point.getRule(isCurrentArea) != PathIterator.SEG_LINETO) &&
|
||||
(point.getRule(isCurrentArea) != PathIterator.SEG_CLOSE)) {
|
||||
(nextPoint.rule(isCurrentArea) != PathIterator.SEG_LINETO) &&
|
||||
(nextPoint.rule(isCurrentArea) != PathIterator.SEG_CLOSE) &&
|
||||
(point.rule(isCurrentArea) != PathIterator.SEG_LINETO) &&
|
||||
(point.rule(isCurrentArea) != PathIterator.SEG_CLOSE)) {
|
||||
isCopyUntilZero = true;
|
||||
length++;
|
||||
}
|
||||
@@ -548,8 +548,8 @@ public class Area implements IShape, Cloneable
|
||||
if (resultRules[resultRulesPos - 1] == PathIterator.SEG_LINETO) {
|
||||
resultRules[resultRulesPos - 1] = PathIterator.SEG_CLOSE;
|
||||
} else {
|
||||
resultCoords[resultCoordPos++] = nextPoint.getX();
|
||||
resultCoords[resultCoordPos++] = nextPoint.getY();
|
||||
resultCoords[resultCoordPos++] = nextPoint.x();
|
||||
resultCoords[resultCoordPos++] = nextPoint.y();
|
||||
resultRules[resultRulesPos++] = PathIterator.SEG_CLOSE;
|
||||
}
|
||||
|
||||
@@ -567,9 +567,9 @@ public class Area implements IShape, Cloneable
|
||||
new int[] { coordsSize, area.coordsSize });
|
||||
IntersectPoint[] intersectPoints = crossHelper.findCrossing();
|
||||
if (intersectPoints.length == 0) {
|
||||
if (contains(area.getBounds())) {
|
||||
if (contains(area.bounds())) {
|
||||
copy(area, this);
|
||||
} else if (!area.contains(getBounds())) {
|
||||
} else if (!area.contains(bounds())) {
|
||||
reset();
|
||||
}
|
||||
return;
|
||||
@@ -587,11 +587,11 @@ public class Area implements IShape, Cloneable
|
||||
resultOffsets[resultRulesPos++] = resultCoordPos;
|
||||
|
||||
do {
|
||||
resultCoords[resultCoordPos++] = point.getX();
|
||||
resultCoords[resultCoordPos++] = point.getY();
|
||||
resultCoords[resultCoordPos++] = point.x();
|
||||
resultCoords[resultCoordPos++] = point.y();
|
||||
resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
|
||||
resultOffsets[resultRulesPos++] = resultCoordPos - 2;
|
||||
int curIndex = point.getEndIndex(true);
|
||||
int curIndex = point.endIndex(true);
|
||||
|
||||
if ((curIndex < 0) ||
|
||||
(area.containsExact(coords[2 * curIndex], coords[2 * curIndex + 1]) == 0)) {
|
||||
@@ -602,11 +602,11 @@ public class Area implements IShape, Cloneable
|
||||
isCurrentArea = false;
|
||||
}
|
||||
|
||||
IntersectPoint nextPoint = getNextIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
IntersectPoint nextPoint = nextIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
double[] coords = (isCurrentArea) ? this.coords : area.coords;
|
||||
int offset = 2 * point.getEndIndex(isCurrentArea);
|
||||
int offset = 2 * point.endIndex(isCurrentArea);
|
||||
if ((offset >= 0) &&
|
||||
(nextPoint.getBegIndex(isCurrentArea) < point.getEndIndex(isCurrentArea))) {
|
||||
(nextPoint.begIndex(isCurrentArea) < point.endIndex(isCurrentArea))) {
|
||||
int coordSize = (isCurrentArea) ? this.coordsSize : area.coordsSize;
|
||||
int length = coordSize - offset;
|
||||
System.arraycopy(coords, offset, resultCoords, resultCoordPos, length);
|
||||
@@ -621,7 +621,7 @@ public class Area implements IShape, Cloneable
|
||||
}
|
||||
|
||||
if (offset >= 0) {
|
||||
int length = 2 * nextPoint.getBegIndex(isCurrentArea) - offset + 2;
|
||||
int length = 2 * nextPoint.begIndex(isCurrentArea) - offset + 2;
|
||||
System.arraycopy(coords, offset, resultCoords, resultCoordPos, length);
|
||||
|
||||
for (int i = 0; i < length / 2; i++) {
|
||||
@@ -651,7 +651,7 @@ public class Area implements IShape, Cloneable
|
||||
new int[] { rulesSize, area.rulesSize },
|
||||
new int[][] { offsets, area.offsets });
|
||||
IntersectPoint[] intersectPoints = crossHelper.findCrossing();
|
||||
if (intersectPoints.length == 0 && contains(area.getBounds())) {
|
||||
if (intersectPoints.length == 0 && contains(area.bounds())) {
|
||||
copy(area, this);
|
||||
return;
|
||||
}
|
||||
@@ -668,9 +668,9 @@ public class Area implements IShape, Cloneable
|
||||
resultOffsets[resultRulesPos++] = resultCoordPos;
|
||||
|
||||
do {
|
||||
resultCoords[resultCoordPos++] = point.getX();
|
||||
resultCoords[resultCoordPos++] = point.getY();
|
||||
int curIndex = offsets[point.getRuleIndex(true)] % coordsSize;
|
||||
resultCoords[resultCoordPos++] = point.x();
|
||||
resultCoords[resultCoordPos++] = point.y();
|
||||
int curIndex = offsets[point.ruleIndex(true)] % coordsSize;
|
||||
if (area.containsExact(coords[curIndex], coords[curIndex + 1]) == 0) {
|
||||
isCurrentArea = !isCurrentArea;
|
||||
} else if (area.containsExact(coords[curIndex], coords[curIndex + 1]) > 0) {
|
||||
@@ -680,19 +680,19 @@ public class Area implements IShape, Cloneable
|
||||
}
|
||||
|
||||
IntersectPoint nextPoint = (isCurrentArea) ?
|
||||
getNextIntersectPoint(intersectPoints, point, isCurrentArea) :
|
||||
getPrevIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
nextIntersectPoint(intersectPoints, point, isCurrentArea) :
|
||||
prevIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
double[] coords = (isCurrentArea) ? this.coords : area.coords;
|
||||
int[] offsets = (isCurrentArea) ? this.offsets : area.offsets;
|
||||
int[] rules = (isCurrentArea) ? this.rules : area.rules;
|
||||
int offset = (isCurrentArea) ? point.getRuleIndex(isCurrentArea) :
|
||||
nextPoint.getRuleIndex(isCurrentArea);
|
||||
int offset = (isCurrentArea) ? point.ruleIndex(isCurrentArea) :
|
||||
nextPoint.ruleIndex(isCurrentArea);
|
||||
boolean isCopyUntilZero = false;
|
||||
|
||||
if (((isCurrentArea) &&
|
||||
(point.getRuleIndex(isCurrentArea) > nextPoint.getRuleIndex(isCurrentArea))) ||
|
||||
(point.ruleIndex(isCurrentArea) > nextPoint.ruleIndex(isCurrentArea))) ||
|
||||
((!isCurrentArea) &&
|
||||
(nextPoint.getRuleIndex(isCurrentArea) > nextPoint.getRuleIndex(isCurrentArea)))) {
|
||||
(nextPoint.ruleIndex(isCurrentArea) > nextPoint.ruleIndex(isCurrentArea)))) {
|
||||
int rulesSize = (isCurrentArea) ? this.rulesSize : area.rulesSize;
|
||||
resultCoordPos = includeCoordsAndRules(
|
||||
offset + 1, rulesSize, rules, offsets, resultRules, resultOffsets, resultCoords,
|
||||
@@ -702,7 +702,7 @@ public class Area implements IShape, Cloneable
|
||||
isCopyUntilZero = true;
|
||||
}
|
||||
|
||||
int length = nextPoint.getRuleIndex(isCurrentArea) - offset + 1;
|
||||
int length = nextPoint.ruleIndex(isCurrentArea) - offset + 1;
|
||||
|
||||
if (isCopyUntilZero) {
|
||||
offset = 0;
|
||||
@@ -740,7 +740,7 @@ public class Area implements IShape, Cloneable
|
||||
new int[] { coordsSize, area.coordsSize });
|
||||
IntersectPoint[] intersectPoints = crossHelper.findCrossing();
|
||||
if (intersectPoints.length == 0) {
|
||||
if (contains(area.getBounds())) {
|
||||
if (contains(area.bounds())) {
|
||||
copy(area, this);
|
||||
return;
|
||||
}
|
||||
@@ -763,18 +763,18 @@ public class Area implements IShape, Cloneable
|
||||
resultOffsets[resultRulesPos++] = resultCoordPos;
|
||||
|
||||
do {
|
||||
resultCoords[resultCoordPos++] = point.getX();
|
||||
resultCoords[resultCoordPos++] = point.getY();
|
||||
resultCoords[resultCoordPos++] = point.x();
|
||||
resultCoords[resultCoordPos++] = point.y();
|
||||
resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
|
||||
resultOffsets[resultRulesPos++] = resultCoordPos - 2;
|
||||
int curIndex = point.getEndIndex(true);
|
||||
int curIndex = point.endIndex(true);
|
||||
|
||||
if ((curIndex < 0) ||
|
||||
(area.isVertex(coords[2 * curIndex], coords[2 * curIndex + 1]) &&
|
||||
crossHelper.containsPoint(new double[] { coords[2 * curIndex],
|
||||
coords[2 * curIndex + 1] }) &&
|
||||
(coords[2 * curIndex] != point.getX() ||
|
||||
coords[2 * curIndex + 1] != point.getY()))) {
|
||||
(coords[2 * curIndex] != point.x() ||
|
||||
coords[2 * curIndex + 1] != point.y()))) {
|
||||
isCurrentArea = !isCurrentArea;
|
||||
} else if (area.containsExact(coords[2 * curIndex], coords[2 * curIndex + 1]) > 0) {
|
||||
isCurrentArea = false;
|
||||
@@ -793,18 +793,18 @@ public class Area implements IShape, Cloneable
|
||||
}
|
||||
|
||||
IntersectPoint nextPoint = (isCurrentArea) ?
|
||||
getNextIntersectPoint(intersectPoints, point, isCurrentArea) :
|
||||
getPrevIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
nextIntersectPoint(intersectPoints, point, isCurrentArea) :
|
||||
prevIntersectPoint(intersectPoints, point, isCurrentArea);
|
||||
double[] coords = (isCurrentArea) ? this.coords : area.coords;
|
||||
|
||||
int offset = (isCurrentArea) ? 2 * point.getEndIndex(isCurrentArea) :
|
||||
2 * nextPoint.getEndIndex(isCurrentArea);
|
||||
int offset = (isCurrentArea) ? 2 * point.endIndex(isCurrentArea) :
|
||||
2 * nextPoint.endIndex(isCurrentArea);
|
||||
|
||||
if ((offset > 0) &&
|
||||
(((isCurrentArea) &&
|
||||
(nextPoint.getBegIndex(isCurrentArea) < point.getEndIndex(isCurrentArea))) ||
|
||||
(nextPoint.begIndex(isCurrentArea) < point.endIndex(isCurrentArea))) ||
|
||||
((!isCurrentArea) &&
|
||||
(nextPoint.getEndIndex(isCurrentArea) < nextPoint.getBegIndex(isCurrentArea))))) {
|
||||
(nextPoint.endIndex(isCurrentArea) < nextPoint.begIndex(isCurrentArea))))) {
|
||||
|
||||
int coordSize = (isCurrentArea) ? this.coordsSize : area.coordsSize;
|
||||
int length = coordSize - offset;
|
||||
@@ -829,8 +829,8 @@ public class Area implements IShape, Cloneable
|
||||
|
||||
if (offset >= 0) {
|
||||
int length = (isCurrentArea) ?
|
||||
2 * nextPoint.getBegIndex(isCurrentArea) - offset + 2 :
|
||||
2 * point.getBegIndex(isCurrentArea) - offset + 2;
|
||||
2 * nextPoint.begIndex(isCurrentArea) - offset + 2 :
|
||||
2 * point.begIndex(isCurrentArea) - offset + 2;
|
||||
|
||||
if (isCurrentArea) {
|
||||
System.arraycopy(coords, offset, resultCoords, resultCoordPos, length);
|
||||
@@ -861,10 +861,10 @@ public class Area implements IShape, Cloneable
|
||||
rulesSize = resultRulesPos;
|
||||
}
|
||||
|
||||
private IntersectPoint getNextIntersectPoint (IntersectPoint[] iPoints,
|
||||
private IntersectPoint nextIntersectPoint (IntersectPoint[] iPoints,
|
||||
IntersectPoint isectPoint,
|
||||
boolean isCurrentArea) {
|
||||
int endIndex = isectPoint.getEndIndex(isCurrentArea);
|
||||
int endIndex = isectPoint.endIndex(isCurrentArea);
|
||||
if (endIndex < 0) {
|
||||
return iPoints[Math.abs(endIndex) - 1];
|
||||
}
|
||||
@@ -872,11 +872,11 @@ public class Area implements IShape, Cloneable
|
||||
IntersectPoint firstIsectPoint = null;
|
||||
IntersectPoint nextIsectPoint = null;
|
||||
for (IntersectPoint point : iPoints) {
|
||||
int begIndex = point.getBegIndex(isCurrentArea);
|
||||
int begIndex = point.begIndex(isCurrentArea);
|
||||
if (begIndex >= 0) {
|
||||
if (firstIsectPoint == null) {
|
||||
firstIsectPoint = point;
|
||||
} else if (begIndex < firstIsectPoint.getBegIndex(isCurrentArea)) {
|
||||
} else if (begIndex < firstIsectPoint.begIndex(isCurrentArea)) {
|
||||
firstIsectPoint = point;
|
||||
}
|
||||
}
|
||||
@@ -884,7 +884,7 @@ public class Area implements IShape, Cloneable
|
||||
if (endIndex <= begIndex) {
|
||||
if (nextIsectPoint == null) {
|
||||
nextIsectPoint = point;
|
||||
} else if (begIndex < nextIsectPoint.getBegIndex(isCurrentArea)) {
|
||||
} else if (begIndex < nextIsectPoint.begIndex(isCurrentArea)) {
|
||||
nextIsectPoint = point;
|
||||
}
|
||||
}
|
||||
@@ -893,10 +893,10 @@ public class Area implements IShape, Cloneable
|
||||
return (nextIsectPoint != null) ? nextIsectPoint : firstIsectPoint;
|
||||
}
|
||||
|
||||
private IntersectPoint getPrevIntersectPoint (IntersectPoint[] iPoints,
|
||||
private IntersectPoint prevIntersectPoint (IntersectPoint[] iPoints,
|
||||
IntersectPoint isectPoint,
|
||||
boolean isCurrentArea) {
|
||||
int begIndex = isectPoint.getBegIndex(isCurrentArea);
|
||||
int begIndex = isectPoint.begIndex(isCurrentArea);
|
||||
if (begIndex < 0) {
|
||||
return iPoints[Math.abs(begIndex) - 1];
|
||||
}
|
||||
@@ -904,11 +904,11 @@ public class Area implements IShape, Cloneable
|
||||
IntersectPoint firstIsectPoint = null;
|
||||
IntersectPoint predIsectPoint = null;
|
||||
for (IntersectPoint point : iPoints) {
|
||||
int endIndex = point.getEndIndex(isCurrentArea);
|
||||
int endIndex = point.endIndex(isCurrentArea);
|
||||
if (endIndex >= 0) {
|
||||
if (firstIsectPoint == null) {
|
||||
firstIsectPoint = point;
|
||||
} else if (endIndex < firstIsectPoint.getEndIndex(isCurrentArea)) {
|
||||
} else if (endIndex < firstIsectPoint.endIndex(isCurrentArea)) {
|
||||
firstIsectPoint = point;
|
||||
}
|
||||
}
|
||||
@@ -916,7 +916,7 @@ public class Area implements IShape, Cloneable
|
||||
if (endIndex <= begIndex) {
|
||||
if (predIsectPoint == null) {
|
||||
predIsectPoint = point;
|
||||
} else if (endIndex > predIsectPoint.getEndIndex(isCurrentArea)) {
|
||||
} else if (endIndex > predIsectPoint.endIndex(isCurrentArea)) {
|
||||
predIsectPoint = point;
|
||||
}
|
||||
}
|
||||
@@ -976,7 +976,7 @@ public class Area implements IShape, Cloneable
|
||||
resultRules[resultRulesPos] = PathIterator.SEG_LINETO;
|
||||
resultOffsets[resultRulesPos++] = resultCoordPos + 2;
|
||||
boolean isLeft = CrossingHelper.compare(
|
||||
coords[index], coords[index + 1], point.getX(), point.getY()) > 0;
|
||||
coords[index], coords[index + 1], point.x(), point.y()) > 0;
|
||||
if (way || !isLeft) {
|
||||
temp[coordsCount++] = coords[index];
|
||||
temp[coordsCount++] = coords[index + 1];
|
||||
@@ -990,13 +990,13 @@ public class Area implements IShape, Cloneable
|
||||
coords[index - 2], coords[index - 1],
|
||||
coords[index], coords[index + 1], coords[index + 2], coords[index + 3] };
|
||||
isLeft = CrossingHelper.compare(
|
||||
coords[index - 2], coords[index - 1], point.getX(), point.getY()) > 0;
|
||||
coords[index - 2], coords[index - 1], point.x(), point.y()) > 0;
|
||||
|
||||
if ((!additional) && (operation == 0 || operation == 2)) {
|
||||
isLeft = !isLeft;
|
||||
way = false;
|
||||
}
|
||||
GeometryUtil.subQuad(coefs, point.getParam(isCurrentArea), isLeft);
|
||||
GeometryUtil.subQuad(coefs, point.param(isCurrentArea), isLeft);
|
||||
|
||||
if (way || isLeft) {
|
||||
temp[coordsCount++] = coefs[2];
|
||||
@@ -1014,8 +1014,8 @@ public class Area implements IShape, Cloneable
|
||||
coords[index + 1], coords[index + 2], coords[index + 3],
|
||||
coords[index + 4], coords[index + 5] };
|
||||
isLeft = CrossingHelper.compare(
|
||||
coords[index - 2], coords[index - 1], point.getX(), point.getY()) > 0;
|
||||
GeometryUtil.subCubic(coefs, point.getParam(isCurrentArea), !isLeft);
|
||||
coords[index - 2], coords[index - 1], point.x(), point.y()) > 0;
|
||||
GeometryUtil.subCubic(coefs, point.param(isCurrentArea), !isLeft);
|
||||
|
||||
if (isLeft) {
|
||||
System.arraycopy(coefs, 2, temp, coordsCount, 6);
|
||||
@@ -1048,7 +1048,7 @@ public class Area implements IShape, Cloneable
|
||||
}
|
||||
|
||||
private int containsExact (double x, double y) {
|
||||
PathIterator pi = getPathIterator(null);
|
||||
PathIterator pi = pathIterator(null);
|
||||
int crossCount = Crossing.crossPath(pi, x, y);
|
||||
if (Crossing.isInsideEvenOdd(crossCount)) {
|
||||
return 1;
|
||||
@@ -1062,7 +1062,7 @@ public class Area implements IShape, Cloneable
|
||||
double moveX = -1;
|
||||
double moveY = -1;
|
||||
|
||||
for (pi = getPathIterator(null); !pi.isDone(); pi.next()) {
|
||||
for (pi = pathIterator(null); !pi.isDone(); pi.next()) {
|
||||
rule = pi.currentSegment(segmentCoords);
|
||||
switch (rule) {
|
||||
case PathIterator.SEG_MOVETO:
|
||||
@@ -1123,9 +1123,9 @@ public class Area implements IShape, Cloneable
|
||||
}
|
||||
}
|
||||
|
||||
private double getAreaBoundsSquare () {
|
||||
Rectangle bounds = getBounds();
|
||||
return bounds.getHeight() * bounds.getWidth();
|
||||
private double areaBoundsSquare () {
|
||||
Rectangle bounds = bounds();
|
||||
return bounds.height() * bounds.width();
|
||||
}
|
||||
|
||||
private boolean isVertex (double x, double y) {
|
||||
@@ -1159,15 +1159,15 @@ public class Area implements IShape, Cloneable
|
||||
// the internal class implements PathIterator
|
||||
private class AreaPathIterator implements PathIterator
|
||||
{
|
||||
private final AffineTransform transform;
|
||||
private final Transform transform;
|
||||
private int curRuleIndex = 0;
|
||||
private int curCoordIndex = 0;
|
||||
|
||||
AreaPathIterator (AffineTransform t) {
|
||||
AreaPathIterator (Transform t) {
|
||||
this.transform = t;
|
||||
}
|
||||
|
||||
@Override public int getWindingRule () {
|
||||
@Override public int windingRule () {
|
||||
return WIND_EVEN_ODD;
|
||||
}
|
||||
|
||||
|
||||
@@ -472,10 +472,10 @@ class Crossing
|
||||
* Returns how many times a ray from point (x,y) crosses a shape.
|
||||
*/
|
||||
public static int crossShape (IShape s, double x, double y) {
|
||||
if (!s.getBounds().contains(x, y)) {
|
||||
if (!s.bounds().contains(x, y)) {
|
||||
return 0;
|
||||
}
|
||||
return crossPath(s.getPathIterator(null), x, y);
|
||||
return crossPath(s.pathIterator(null), x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -759,10 +759,10 @@ class Crossing
|
||||
* Returns how many times rectangle stripe cross shape or the are intersect
|
||||
*/
|
||||
public static int intersectShape (IShape s, double x, double y, double w, double h) {
|
||||
if (!s.getBounds().intersects(x, y, w, h)) {
|
||||
if (!s.bounds().intersects(x, y, w, h)) {
|
||||
return 0;
|
||||
}
|
||||
return intersectPath(s.getPathIterator(null), x, y, w, h);
|
||||
return intersectPath(s.pathIterator(null), x, y, w, h);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -177,8 +177,8 @@ class CrossingHelper
|
||||
IntersectPoint ip;
|
||||
for (Iterator<IntersectPoint> i = isectPoints.iterator(); i.hasNext();) {
|
||||
ip = i.next();
|
||||
if ((initBegin == ip.getBegIndex(true)) && (initEnd == ip.getEndIndex(true))) {
|
||||
if (compare(ip.getX(), ip.getY(), point[0], point[1]) > 0) {
|
||||
if ((initBegin == ip.begIndex(true)) && (initEnd == ip.endIndex(true))) {
|
||||
if (compare(ip.x(), ip.y(), point[0], point[1]) > 0) {
|
||||
initEnd = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setBegIndex1(-(isectPoints.size() + 1));
|
||||
} else {
|
||||
@@ -187,8 +187,8 @@ class CrossingHelper
|
||||
}
|
||||
}
|
||||
|
||||
if ((addBegin == ip.getBegIndex(false)) && (addEnd == ip.getEndIndex(false))) {
|
||||
if (compare(ip.getX(), ip.getY(), point[0], point[1]) > 0) {
|
||||
if ((addBegin == ip.begIndex(false)) && (addEnd == ip.endIndex(false))) {
|
||||
if (compare(ip.x(), ip.y(), point[0], point[1]) > 0) {
|
||||
addEnd = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setBegIndex2(-(isectPoints.size() + 1));
|
||||
} else {
|
||||
@@ -256,7 +256,7 @@ class CrossingHelper
|
||||
IntersectPoint ipoint;
|
||||
for (Iterator<IntersectPoint> i = isectPoints.iterator(); i.hasNext();) {
|
||||
ipoint = i.next();
|
||||
if (ipoint.getX() == point[0] && ipoint.getY() == point[1]) {
|
||||
if (ipoint.x() == point[0] && ipoint.y() == point[1]) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,8 +68,8 @@ public class CubicCurve extends AbstractCubicCurve implements Serializable
|
||||
* Configures the start, control and end points for this curve.
|
||||
*/
|
||||
public void setCurve (IPoint p1, IPoint cp1, IPoint cp2, IPoint p2) {
|
||||
setCurve(p1.getX(), p1.getY(), cp1.getX(), cp1.getY(),
|
||||
cp2.getX(), cp2.getY(), p2.getX(), p2.getY());
|
||||
setCurve(p1.x(), p1.y(), cp1.x(), cp1.y(),
|
||||
cp2.x(), cp2.y(), p2.x(), p2.y());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,10 +86,10 @@ public class CubicCurve extends AbstractCubicCurve implements Serializable
|
||||
* specified offset in the {@code points} array.
|
||||
*/
|
||||
public void setCurve (IPoint[] 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(),
|
||||
points[offset + 3].getX(), points[offset + 3].getY());
|
||||
setCurve(points[offset + 0].x(), points[offset + 0].y(),
|
||||
points[offset + 1].x(), points[offset + 1].y(),
|
||||
points[offset + 2].x(), points[offset + 2].y(),
|
||||
points[offset + 3].x(), points[offset + 3].y());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,47 +97,47 @@ public class CubicCurve extends AbstractCubicCurve implements Serializable
|
||||
* curve.
|
||||
*/
|
||||
public void setCurve (ICubicCurve curve) {
|
||||
setCurve(curve.getX1(), curve.getY1(), curve.getCtrlX1(), curve.getCtrlY1(),
|
||||
curve.getCtrlX2(), curve.getCtrlY2(), curve.getX2(), curve.getY2());
|
||||
setCurve(curve.x1(), curve.y1(), curve.ctrlX1(), curve.ctrlY1(),
|
||||
curve.ctrlX2(), curve.ctrlY2(), curve.x2(), curve.y2());
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public double getX1 () {
|
||||
public double x1 () {
|
||||
return x1;
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public double getY1 () {
|
||||
public double y1 () {
|
||||
return y1;
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public double getCtrlX1 () {
|
||||
public double ctrlX1 () {
|
||||
return ctrlx1;
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public double getCtrlY1 () {
|
||||
public double ctrlY1 () {
|
||||
return ctrly1;
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public double getCtrlX2 () {
|
||||
public double ctrlX2 () {
|
||||
return ctrlx2;
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public double getCtrlY2 () {
|
||||
public double ctrlY2 () {
|
||||
return ctrly2;
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public double getX2 () {
|
||||
public double x2 () {
|
||||
return x2;
|
||||
}
|
||||
|
||||
@Override // from interface ICubicCurve
|
||||
public double getY2 () {
|
||||
public double y2 () {
|
||||
return y2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,34 +9,34 @@ package pythagoras.d;
|
||||
*/
|
||||
public class CubicCurves
|
||||
{
|
||||
public static double getFlatnessSq (double x1, double y1, double ctrlx1, double ctrly1,
|
||||
public static double flatnessSq (double x1, double y1, double ctrlx1, double ctrly1,
|
||||
double ctrlx2, double ctrly2, double x2, double y2) {
|
||||
return Math.max(Lines.pointSegDistSq(ctrlx1, ctrly1, x1, y1, x2, y2),
|
||||
Lines.pointSegDistSq(ctrlx2, ctrly2, x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
public static double getFlatnessSq (double[] coords, int offset) {
|
||||
return getFlatnessSq(coords[offset + 0], coords[offset + 1], coords[offset + 2],
|
||||
public static double flatnessSq (double[] coords, int offset) {
|
||||
return flatnessSq(coords[offset + 0], coords[offset + 1], coords[offset + 2],
|
||||
coords[offset + 3], coords[offset + 4], coords[offset + 5],
|
||||
coords[offset + 6], coords[offset + 7]);
|
||||
}
|
||||
|
||||
public static double getFlatness (double x1, double y1, double ctrlx1, double ctrly1,
|
||||
public static double flatness (double x1, double y1, double ctrlx1, double ctrly1,
|
||||
double ctrlx2, double ctrly2, double x2, double y2) {
|
||||
return Math.sqrt(getFlatnessSq(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2));
|
||||
return Math.sqrt(flatnessSq(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2));
|
||||
}
|
||||
|
||||
public static double getFlatness (double[] coords, int offset) {
|
||||
return getFlatness(coords[offset + 0], coords[offset + 1], coords[offset + 2],
|
||||
public static double flatness (double[] coords, int offset) {
|
||||
return flatness(coords[offset + 0], coords[offset + 1], coords[offset + 2],
|
||||
coords[offset + 3], coords[offset + 4], coords[offset + 5],
|
||||
coords[offset + 6], coords[offset + 7]);
|
||||
}
|
||||
|
||||
public static void subdivide (ICubicCurve src, CubicCurve left, CubicCurve right) {
|
||||
double x1 = src.getX1(), y1 = src.getY1();
|
||||
double cx1 = src.getCtrlX1(), cy1 = src.getCtrlY1();
|
||||
double cx2 = src.getCtrlX2(), cy2 = src.getCtrlY2();
|
||||
double x2 = src.getX2(), y2 = src.getY2();
|
||||
double x1 = src.x1(), y1 = src.y1();
|
||||
double cx1 = src.ctrlX1(), cy1 = src.ctrlY1();
|
||||
double cx2 = src.ctrlX2(), cy2 = src.ctrlY2();
|
||||
double x2 = src.x2(), y2 = src.y2();
|
||||
double cx = (cx1 + cx2) / 2f, cy = (cy1 + cy2) / 2f;
|
||||
cx1 = (x1 + cx1) / 2f;
|
||||
cy1 = (y1 + cy1) / 2f;
|
||||
|
||||
@@ -43,11 +43,11 @@ class CurveCrossingHelper
|
||||
|
||||
for (int i = 0; i < rulesSizes[0]; i++) {
|
||||
rule1 = rules[0][i];
|
||||
endIndex1 = getCurrentEdge(0, i, edge1, mp1, cp1);
|
||||
endIndex1 = currentEdge(0, i, edge1, mp1, cp1);
|
||||
for (int j = 0; j < rulesSizes[1]; j++) {
|
||||
ipCount = 0;
|
||||
rule2 = rules[1][j];
|
||||
endIndex2 = getCurrentEdge(1, j, edge2, mp2, cp2);
|
||||
endIndex2 = currentEdge(1, j, edge2, mp2, cp2);
|
||||
if (((rule1 == PathIterator.SEG_LINETO) || (rule1 == PathIterator.SEG_CLOSE)) &&
|
||||
((rule2 == PathIterator.SEG_LINETO) || (rule2 == PathIterator.SEG_CLOSE))) {
|
||||
ipCount = GeometryUtil.intersectLinesWithParams(
|
||||
@@ -167,9 +167,9 @@ class CurveCrossingHelper
|
||||
for (Iterator<IntersectPoint> iter = isectPoints.iterator();
|
||||
iter.hasNext();) {
|
||||
ip = iter.next();
|
||||
if ((begIndex1 == ip.getBegIndex(true)) &&
|
||||
(endIndex1 == ip.getEndIndex(true))) {
|
||||
if (ip.getParam(true) > params[2 * k]) {
|
||||
if ((begIndex1 == ip.begIndex(true)) &&
|
||||
(endIndex1 == ip.endIndex(true))) {
|
||||
if (ip.param(true) > params[2 * k]) {
|
||||
endIndex1 = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setBegIndex1(-(isectPoints.size() + 1));
|
||||
} else {
|
||||
@@ -178,9 +178,9 @@ class CurveCrossingHelper
|
||||
}
|
||||
}
|
||||
|
||||
if ((begIndex2 == ip.getBegIndex(false)) &&
|
||||
(endIndex2 == ip.getEndIndex(false))) {
|
||||
if (ip.getParam(false) > params[2 * k + 1]) {
|
||||
if ((begIndex2 == ip.begIndex(false)) &&
|
||||
(endIndex2 == ip.endIndex(false))) {
|
||||
if (ip.param(false) > params[2 * k + 1]) {
|
||||
endIndex2 = -(isectPoints.indexOf(ip) + 1);
|
||||
ip.setBegIndex2(-(isectPoints.size() + 1));
|
||||
} else {
|
||||
@@ -209,7 +209,7 @@ class CurveCrossingHelper
|
||||
return isectPoints.toArray(new IntersectPoint[isectPoints.size()]);
|
||||
}
|
||||
|
||||
private int getCurrentEdge (int areaIndex, int index, double[] c, double[] mp, double[] cp) {
|
||||
private int currentEdge (int areaIndex, int index, double[] c, double[] mp, double[] cp) {
|
||||
int endIndex = 0;
|
||||
|
||||
switch (rules[areaIndex][index]) {
|
||||
@@ -263,8 +263,8 @@ class CurveCrossingHelper
|
||||
IntersectPoint ipoint;
|
||||
for (Iterator<IntersectPoint> i = isectPoints.iterator(); i.hasNext();) {
|
||||
ipoint = i.next();
|
||||
if ((Math.abs(ipoint.getX() - x) < Math.pow(10, -6)) &&
|
||||
(Math.abs(ipoint.getY() - y) < Math.pow(10, -6))) {
|
||||
if ((Math.abs(ipoint.x() - x) < Math.pow(10, -6)) &&
|
||||
(Math.abs(ipoint.y() - y) < Math.pow(10, -6))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ public class Dimension extends AbstractDimension implements Serializable
|
||||
* Creates a dimension with width and height equal to the supplied dimension.
|
||||
*/
|
||||
public Dimension (IDimension d) {
|
||||
this(d.getWidth(), d.getHeight());
|
||||
this(d.width(), d.height());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -50,16 +50,16 @@ public class Dimension extends AbstractDimension implements Serializable
|
||||
* Sets the magnitudes of this dimension to be equal to the supplied dimension.
|
||||
*/
|
||||
public void setSize (IDimension d) {
|
||||
setSize(d.getWidth(), d.getHeight());
|
||||
setSize(d.width(), d.height());
|
||||
}
|
||||
|
||||
@Override // from interface IDimension
|
||||
public double getWidth () {
|
||||
public double width () {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override // from interface IDimension
|
||||
public double getHeight () {
|
||||
public double height () {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,22 +37,22 @@ public class Ellipse extends AbstractEllipse implements Serializable
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getX () {
|
||||
public double x () {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getY () {
|
||||
public double y () {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getWidth () {
|
||||
public double width () {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getHeight () {
|
||||
public double height () {
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,18 +34,18 @@ class FlatteningPathIterator implements PathIterator
|
||||
this.bufIndex = bufSize;
|
||||
}
|
||||
|
||||
public double getFlatness () {
|
||||
public double flatness () {
|
||||
return flatness;
|
||||
}
|
||||
|
||||
public int getRecursionLimit () {
|
||||
public int recursionLimit () {
|
||||
return bufLimit;
|
||||
}
|
||||
|
||||
@Override
|
||||
// from interface PathIterator
|
||||
public int getWindingRule () {
|
||||
return p.getWindingRule();
|
||||
public int windingRule () {
|
||||
return p.windingRule();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -81,7 +81,7 @@ class FlatteningPathIterator implements PathIterator
|
||||
}
|
||||
|
||||
/** Calculates flat path points for the current segment of the source shape. Line segment is
|
||||
* flat by itself. Flatness of quad and cubic curves are evaluated by the getFlatnessSq()
|
||||
* flat by itself. Flatness of quad and cubic curves are evaluated by the flatnessSq()
|
||||
* method. Curves are subdivided until current flatness is bigger than user defined value and
|
||||
* subdivision limit isn't exhausted. Single source segments are translated to a series of
|
||||
* buffer points. The smaller the flatness the bigger the series. Every currentSegment() call
|
||||
@@ -109,7 +109,7 @@ class FlatteningPathIterator implements PathIterator
|
||||
}
|
||||
|
||||
while (bufSubdiv < bufLimit) {
|
||||
if (QuadCurves.getFlatnessSq(buf, bufIndex) < flatness2) {
|
||||
if (QuadCurves.flatnessSq(buf, bufIndex) < flatness2) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ class FlatteningPathIterator implements PathIterator
|
||||
}
|
||||
|
||||
while (bufSubdiv < bufLimit) {
|
||||
if (CubicCurves.getFlatnessSq(buf, bufIndex) < flatness2) {
|
||||
if (CubicCurves.flatnessSq(buf, bufIndex) < flatness2) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,8 +46,8 @@ public class GeometryUtil
|
||||
*
|
||||
* @return 1 if two lines intersect in the defined interval, otherwise 0.
|
||||
*/
|
||||
public static int intersectLines (double x1, double y1, double x2, double y2,
|
||||
double x3, double y3, double x4, double y4, double[] point) {
|
||||
public static int intersectLines (double x1, double y1, double x2, double y2, double x3, double y3,
|
||||
double x4, double y4, double[] point) {
|
||||
double A1 = -(y2 - y1);
|
||||
double B1 = (x2 - x1);
|
||||
double C1 = x1 * y2 - x2 * y1;
|
||||
@@ -172,10 +172,9 @@ public class GeometryUtil
|
||||
*
|
||||
* @return the number of roots that lie in the interval.
|
||||
*/
|
||||
public static int intersectQuads (double x1, double y1, double x2, double y2,
|
||||
double x3, double y3,
|
||||
double qx1, double qy1, double qx2, double qy2,
|
||||
double qx3, double qy3, double[] params) {
|
||||
public static int intersectQuads (double x1, double y1, double x2, double y2, double x3, double y3,
|
||||
double qx1, double qy1, double qx2, double qy2, double qx3,
|
||||
double qy3, double[] params) {
|
||||
double[] initParams = new double[2];
|
||||
double[] xCoefs1 = new double[3];
|
||||
double[] yCoefs1 = new double[3];
|
||||
@@ -288,11 +287,10 @@ public class GeometryUtil
|
||||
*
|
||||
* @return the number of intersection points that lie in the interval.
|
||||
*/
|
||||
public static int intersectCubics (double x1, double y1, double x2, double y2,
|
||||
double x3, double y3, double x4, double y4,
|
||||
double cx1, double cy1, double cx2, double cy2,
|
||||
double cx3, double cy3, double cx4, double cy4,
|
||||
double[] params) {
|
||||
public static int intersectCubics (double x1, double y1, double x2, double y2, double x3, double y3,
|
||||
double x4, double y4, double cx1, double cy1,
|
||||
double cx2, double cy2, double cx3, double cy3,
|
||||
double cx4, double cy4, double[] params) {
|
||||
int quantity = 0;
|
||||
double[] initParams = new double[3];
|
||||
double[] xCoefs1 = new double[4];
|
||||
|
||||
@@ -22,31 +22,31 @@ public interface IArc extends IRectangularShape, Cloneable
|
||||
int PIE = 2;
|
||||
|
||||
/** Returns the type of this arc: {@link #OPEN}, etc. */
|
||||
int getArcType ();
|
||||
int arcType ();
|
||||
|
||||
/** Returns the starting angle of this arc. */
|
||||
double getAngleStart ();
|
||||
double angleStart ();
|
||||
|
||||
/** Returns the angular extent of this arc. */
|
||||
double getAngleExtent ();
|
||||
double angleExtent ();
|
||||
|
||||
/** Returns the intersection of the ray from the center (defined by the starting angle) and the
|
||||
* elliptical boundary of the arc. */
|
||||
Point getStartPoint ();
|
||||
Point startPoint ();
|
||||
|
||||
/** Writes the intersection of the ray from the center (defined by the starting angle) and the
|
||||
* elliptical boundary of the arc into {@code target}.
|
||||
* @return the supplied point. */
|
||||
Point getStartPoint (Point target);
|
||||
Point startPoint (Point target);
|
||||
|
||||
/** Returns the intersection of the ray from the center (defined by the starting angle plus the
|
||||
* angular extent of the arc) and the elliptical boundary of the arc. */
|
||||
Point getEndPoint ();
|
||||
Point endPoint ();
|
||||
|
||||
/** Writes the intersection of the ray from the center (defined by the starting angle plus the
|
||||
* angular extent of the arc) and the elliptical boundary of the arc into {@code target}.
|
||||
* @return the supplied point. */
|
||||
Point getEndPoint (Point target);
|
||||
Point endPoint (Point target);
|
||||
|
||||
/** Returns whether the specified angle is within the angular extents of this arc. */
|
||||
boolean containsAngle (double angle);
|
||||
|
||||
@@ -10,48 +10,48 @@ package pythagoras.d;
|
||||
public interface ICubicCurve extends IShape, Cloneable
|
||||
{
|
||||
/** Returns the x-coordinate of the start of this curve. */
|
||||
double getX1 ();
|
||||
double x1 ();
|
||||
|
||||
/** Returns the y-coordinate of the start of this curve. */
|
||||
double getY1 ();
|
||||
double y1 ();
|
||||
|
||||
/** Returns the x-coordinate of the first control point. */
|
||||
double getCtrlX1 ();
|
||||
double ctrlX1 ();
|
||||
|
||||
/** Returns the y-coordinate of the first control point. */
|
||||
double getCtrlY1 ();
|
||||
double ctrlY1 ();
|
||||
|
||||
/** Returns the x-coordinate of the second control point. */
|
||||
double getCtrlX2 ();
|
||||
double ctrlX2 ();
|
||||
|
||||
/** Returns the y-coordinate of the second control point. */
|
||||
double getCtrlY2 ();
|
||||
double ctrlY2 ();
|
||||
|
||||
/** Returns the x-coordinate of the end of this curve. */
|
||||
double getX2 ();
|
||||
double x2 ();
|
||||
|
||||
/** Returns the y-coordinate of the end of this curve. */
|
||||
double getY2 ();
|
||||
double y2 ();
|
||||
|
||||
/** Returns a copy of the starting point of this curve. */
|
||||
Point getP1 ();
|
||||
Point p1 ();
|
||||
|
||||
/** Returns a copy of the first control point of this curve. */
|
||||
Point getCtrlP1 ();
|
||||
Point ctrlP1 ();
|
||||
|
||||
/** Returns a copy of the second control point of this curve. */
|
||||
Point getCtrlP2 ();
|
||||
Point ctrlP2 ();
|
||||
|
||||
/** Returns a copy of the ending point of this curve. */
|
||||
Point getP2 ();
|
||||
Point p2 ();
|
||||
|
||||
/** Returns the square of the flatness (maximum distance of a control point from the line
|
||||
* connecting the end points) of this curve. */
|
||||
double getFlatnessSq ();
|
||||
double flatnessSq ();
|
||||
|
||||
/** Returns the flatness (maximum distance of a control point from the line connecting the end
|
||||
* points) of this curve. */
|
||||
double getFlatness ();
|
||||
double flatness ();
|
||||
|
||||
/** Subdivides this curve and stores the results into {@code left} and {@code right}. */
|
||||
void subdivide (CubicCurve left, CubicCurve right);
|
||||
|
||||
@@ -12,12 +12,12 @@ public interface IDimension extends Cloneable
|
||||
/**
|
||||
* Returns the magnitude in the x-dimension.
|
||||
*/
|
||||
double getWidth ();
|
||||
double width ();
|
||||
|
||||
/**
|
||||
* Returns the magnitude in the y-dimension.
|
||||
*/
|
||||
double getHeight ();
|
||||
double height ();
|
||||
|
||||
/**
|
||||
* Returns a mutable copy of this dimension.
|
||||
|
||||
@@ -10,30 +10,30 @@ package pythagoras.d;
|
||||
public interface ILine extends IShape, Cloneable
|
||||
{
|
||||
/** Returns the x-coordinate of the start of this line. */
|
||||
double getX1 ();
|
||||
double x1 ();
|
||||
|
||||
/** Returns the y-coordinate of the start of this line. */
|
||||
double getY1 ();
|
||||
double y1 ();
|
||||
|
||||
/** Returns the x-coordinate of the end of this line. */
|
||||
double getX2 ();
|
||||
double x2 ();
|
||||
|
||||
/** Returns the y-coordinate of the end of this line. */
|
||||
double getY2 ();
|
||||
double y2 ();
|
||||
|
||||
/** Returns a copy of the starting point of this line. */
|
||||
Point getP1 ();
|
||||
Point p1 ();
|
||||
|
||||
/** Initializes the supplied point with this line's starting point.
|
||||
* @return the supplied point. */
|
||||
Point getP1 (Point target);
|
||||
Point p1 (Point target);
|
||||
|
||||
/** Returns a copy of the ending point of this line. */
|
||||
Point getP2 ();
|
||||
Point p2 ();
|
||||
|
||||
/** Initializes the supplied point with this line's ending point.
|
||||
* @return the supplied point. */
|
||||
Point getP2 (Point target);
|
||||
Point p2 (Point target);
|
||||
|
||||
/** Returns the square of the distance from the specified point to the line defined by this
|
||||
* line segment. */
|
||||
|
||||
@@ -10,10 +10,10 @@ package pythagoras.d;
|
||||
public interface IPoint extends Cloneable
|
||||
{
|
||||
/** Returns this point's x-coordinate. */
|
||||
double getX ();
|
||||
double x ();
|
||||
|
||||
/** Returns this point's y-coordinate. */
|
||||
double getY ();
|
||||
double y ();
|
||||
|
||||
/** Returns the squared Euclidian distance between this point and the specified point. */
|
||||
double distanceSq (double px, double py);
|
||||
@@ -27,6 +27,31 @@ public interface IPoint extends Cloneable
|
||||
/** Returns the Euclidian distance between this point and the supplied point. */
|
||||
double distance (IPoint p);
|
||||
|
||||
/** Multiplies this point by a scale factor.
|
||||
* @return a new point containing the result. */
|
||||
Point mult (double s);
|
||||
|
||||
/** Multiplies this point by a scale factor and places the result in the supplied object.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Point mult (double s, Point result);
|
||||
|
||||
/** Translates this point by the specified offset.
|
||||
* @return a new point containing the result. */
|
||||
Point add (double x, double y);
|
||||
|
||||
/** Translates this point by the specified offset and stores the result in the object provided.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Point add (double x, double y, Point result);
|
||||
|
||||
/** Rotates this point around the origin by the specified angle.
|
||||
* @return a new point containing the result. */
|
||||
Point rotate (double angle);
|
||||
|
||||
/** Rotates this point around the origin by the specified angle, storing the result in the
|
||||
* point provided.
|
||||
* @return a reference to the result point, for chaining. */
|
||||
Point rotate (double angle, Point result);
|
||||
|
||||
/** Returns a mutable copy of this point. */
|
||||
Point clone ();
|
||||
}
|
||||
|
||||
@@ -10,39 +10,39 @@ package pythagoras.d;
|
||||
public interface IQuadCurve extends IShape, Cloneable
|
||||
{
|
||||
/** Returns the x-coordinate of the start of this curve. */
|
||||
double getX1 ();
|
||||
double x1 ();
|
||||
|
||||
/** Returns the y-coordinate of the start of this curve. */
|
||||
double getY1 ();
|
||||
double y1 ();
|
||||
|
||||
/** Returns the x-coordinate of the control point. */
|
||||
double getCtrlX ();
|
||||
double ctrlX ();
|
||||
|
||||
/** Returns the y-coordinate of the control point. */
|
||||
double getCtrlY ();
|
||||
double ctrlY ();
|
||||
|
||||
/** Returns the x-coordinate of the end of this curve. */
|
||||
double getX2 ();
|
||||
double x2 ();
|
||||
|
||||
/** Returns the y-coordinate of the end of this curve. */
|
||||
double getY2 ();
|
||||
double y2 ();
|
||||
|
||||
/** Returns a copy of the starting point of this curve. */
|
||||
Point getP1 ();
|
||||
Point p1 ();
|
||||
|
||||
/** Returns a copy of the control point of this curve. */
|
||||
Point getCtrlP ();
|
||||
Point ctrlP ();
|
||||
|
||||
/** Returns a copy of the ending point of this curve. */
|
||||
Point getP2 ();
|
||||
Point p2 ();
|
||||
|
||||
/** Returns the square of the flatness (maximum distance of a control point from the line
|
||||
* connecting the end points) of this curve. */
|
||||
double getFlatnessSq ();
|
||||
double flatnessSq ();
|
||||
|
||||
/** Returns the flatness (maximum distance of a control point from the line connecting the end
|
||||
* points) of this curve. */
|
||||
double getFlatness ();
|
||||
double flatness ();
|
||||
|
||||
/** Subdivides this curve and stores the results into {@code left} and {@code right}. */
|
||||
void subdivide (QuadCurve left, QuadCurve right);
|
||||
|
||||
@@ -24,18 +24,18 @@ public interface IRectangle extends IRectangularShape, Cloneable
|
||||
int OUT_BOTTOM = 8;
|
||||
|
||||
/** Returns a copy of this rectangle's upper-left corner. */
|
||||
Point getLocation ();
|
||||
Point location ();
|
||||
|
||||
/** Initializes the supplied point with this rectangle's upper-left corner.
|
||||
* @return the supplied point. */
|
||||
Point getLocation (Point target);
|
||||
Point location (Point target);
|
||||
|
||||
/** Returns a copy of this rectangle's size. */
|
||||
Dimension getSize ();
|
||||
Dimension size ();
|
||||
|
||||
/** Initializes the supplied dimension with this rectangle's size.
|
||||
* @return the supplied dimension. */
|
||||
Dimension getSize (Dimension target);
|
||||
Dimension size (Dimension target);
|
||||
|
||||
/** Returns the intersection of the specified rectangle and this rectangle (i.e. the largest
|
||||
* rectangle contained in both this and the specified rectangle). */
|
||||
|
||||
@@ -12,48 +12,48 @@ package pythagoras.d;
|
||||
public interface IRectangularShape extends IShape
|
||||
{
|
||||
/** Returns the x-coordinate of the upper-left corner of the framing rectangle. */
|
||||
double getX ();
|
||||
double x ();
|
||||
|
||||
/** Returns the y-coordinate of the upper-left corner of the framing rectangle. */
|
||||
double getY ();
|
||||
double y ();
|
||||
|
||||
/** Returns the width of the framing rectangle. */
|
||||
double getWidth ();
|
||||
double width ();
|
||||
|
||||
/** Returns the height of the framing rectangle. */
|
||||
double getHeight ();
|
||||
double height ();
|
||||
|
||||
/** Returns the minimum x,y-coordinate of the framing rectangle. */
|
||||
Point getMin ();
|
||||
Point min ();
|
||||
|
||||
/** Returns the minimum x-coordinate of the framing rectangle. */
|
||||
double getMinX ();
|
||||
double minX ();
|
||||
|
||||
/** Returns the minimum y-coordinate of the framing rectangle. */
|
||||
double getMinY ();
|
||||
double minY ();
|
||||
|
||||
/** Returns the maximum x,y-coordinate of the framing rectangle. */
|
||||
Point getMax ();
|
||||
Point max ();
|
||||
|
||||
/** Returns the maximum x-coordinate of the framing rectangle. */
|
||||
double getMaxX ();
|
||||
double maxX ();
|
||||
|
||||
/** Returns the maximum y-coordinate of the framing rectangle. */
|
||||
double getMaxY ();
|
||||
double maxY ();
|
||||
|
||||
/** Returns the center of the framing rectangle. */
|
||||
Point getCenter ();
|
||||
Point center ();
|
||||
|
||||
/** Returns the x-coordinate of the center of the framing rectangle. */
|
||||
double getCenterX ();
|
||||
double centerX ();
|
||||
|
||||
/** Returns the y-coordinate of the center of the framing rectangle. */
|
||||
double getCenterY ();
|
||||
double centerY ();
|
||||
|
||||
/** Returns a copy of this shape's framing rectangle. */
|
||||
Rectangle getFrame ();
|
||||
Rectangle frame ();
|
||||
|
||||
/** Initializes the supplied rectangle with this shape's framing rectangle.
|
||||
* @return the supplied rectangle. */
|
||||
Rectangle getFrame (Rectangle target);
|
||||
Rectangle frame (Rectangle target);
|
||||
}
|
||||
|
||||
@@ -10,10 +10,10 @@ package pythagoras.d;
|
||||
public interface IRoundRectangle extends IRectangularShape, Cloneable
|
||||
{
|
||||
/** Returns the width of the corner arc. */
|
||||
double getArcWidth ();
|
||||
double arcWidth ();
|
||||
|
||||
/** Returns the height of the corner arc. */
|
||||
double getArcHeight ();
|
||||
double arcHeight ();
|
||||
|
||||
/** Returns a mutable copy of this round rectangle. */
|
||||
RoundRectangle clone ();
|
||||
|
||||
@@ -31,18 +31,18 @@ public interface IShape
|
||||
boolean intersects (IRectangle r);
|
||||
|
||||
/** Returns a copy of the bounding rectangle for this shape. */
|
||||
Rectangle getBounds ();
|
||||
Rectangle bounds ();
|
||||
|
||||
/** Initializes the supplied rectangle with this shape's bounding rectangle.
|
||||
* @return the supplied rectangle. */
|
||||
Rectangle getBounds (Rectangle target);
|
||||
Rectangle bounds (Rectangle target);
|
||||
|
||||
/**
|
||||
* Returns an iterator over the path described by this shape.
|
||||
*
|
||||
* @param at if supplied, the points in the path are transformed using this.
|
||||
*/
|
||||
PathIterator getPathIterator (AffineTransform at);
|
||||
PathIterator pathIterator (Transform at);
|
||||
|
||||
/**
|
||||
* Returns an iterator over the path described by this shape.
|
||||
@@ -52,5 +52,5 @@ public interface IShape
|
||||
* distance the lines are allowed to deviate from the approximated curve, thus a higher
|
||||
* flatness value generally allows for a path with fewer segments.
|
||||
*/
|
||||
PathIterator getPathIterator (AffineTransform at, double flatness);
|
||||
PathIterator pathIterator (Transform at, double flatness);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,132 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* Provides read-only access to a {@link Vector}.
|
||||
*/
|
||||
public interface IVector
|
||||
{
|
||||
/** Returns the x-component of this vector. */
|
||||
double x ();
|
||||
|
||||
/** Returns the y-component of this vector. */
|
||||
double y ();
|
||||
|
||||
/** Computes and returns the dot product of this and the specified other vector. */
|
||||
double dot (IVector other);
|
||||
|
||||
/** Negates this vector.
|
||||
* @return a new vector containing the result. */
|
||||
Vector negate ();
|
||||
|
||||
/** Negates this vector, storing the result in the supplied object.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector negate (Vector result);
|
||||
|
||||
/** Normalizes this vector.
|
||||
* @return a new vector containing the result. */
|
||||
Vector normalize ();
|
||||
|
||||
/** Normalizes this vector, storing the result in the object supplied.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector normalize (Vector result);
|
||||
|
||||
/** Returns the angle between this vector and the specified other vector. */
|
||||
double angle (IVector other);
|
||||
|
||||
/** Returns the direction of a vector pointing from this point to the specified other point. */
|
||||
double direction (IVector other);
|
||||
|
||||
/** Returns the length of this vector. */
|
||||
double length ();
|
||||
|
||||
/** Returns the squared length of this vector. */
|
||||
double lengthSq ();
|
||||
|
||||
/** Returns the distance from this vector to the specified other vector. */
|
||||
double distance (IVector other);
|
||||
|
||||
/** Returns the squared distance from this vector to the specified other. */
|
||||
double distanceSq (IVector other);
|
||||
|
||||
/** Multiplies this vector by a scalar.
|
||||
* @return a new vector containing the result. */
|
||||
Vector mult (double v);
|
||||
|
||||
/** Multiplies this vector by a scalar and places the result in the supplied object.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector mult (double v, Vector result);
|
||||
|
||||
/** Multiplies this vector by another.
|
||||
* @return a new vector containing the result. */
|
||||
Vector mult (IVector other);
|
||||
|
||||
/** Multiplies this vector by another, storing the result in the object provided.
|
||||
* @return a reference to the result vector, for chaining. */
|
||||
Vector mult (IVector other, Vector result);
|
||||
|
||||
/** Adds a vector to this one.
|
||||
* @return a new vector containing the result. */
|
||||
Vector add (IVector other);
|
||||
|
||||
/** Adds a vector to this one, storing the result in the object provided.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector add (IVector other, Vector result);
|
||||
|
||||
/** Adds a vector to this one.
|
||||
* @return a new vector containing the result. */
|
||||
Vector add (double x, double y);
|
||||
|
||||
/** Adds a vector to this one and stores the result in the object provided.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector add (double x, double y, Vector result);
|
||||
|
||||
/** Adds a scaled vector to this one.
|
||||
* @return a new vector containing the result. */
|
||||
Vector addScaled (IVector other, double v);
|
||||
|
||||
/** Adds a scaled vector to this one and stores the result in the supplied vector.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector addScaled (IVector other, double v, Vector result);
|
||||
|
||||
/** Subtracts a vector from this one.
|
||||
* @return a new vector containing the result. */
|
||||
Vector subtract (IVector other);
|
||||
|
||||
/** Subtracts a vector from this one and places the result in the supplied object.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector subtract (IVector other, Vector result);
|
||||
|
||||
/** Rotates this vector by the specified angle.
|
||||
* @return a new vector containing the result. */
|
||||
Vector rotate (double angle);
|
||||
|
||||
/** Rotates this vector by the specified angle, storing the result in the vector provided.
|
||||
* @return a reference to the result vector, for chaining. */
|
||||
Vector rotate (double angle, Vector result);
|
||||
|
||||
/** Rotates this vector by the specified angle and adds another vector to it, placing the
|
||||
* result in the object provided.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector rotateAndAdd (double angle, IVector add, Vector result);
|
||||
|
||||
/** Rotates this vector by the specified angle, applies a uniform scale, and adds another
|
||||
* vector to it, placing the result in the object provided.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector rotateScaleAndAdd (double angle, double scale, IVector add, Vector result);
|
||||
|
||||
/** Linearly interpolates between this and the specified other vector by the supplied amount.
|
||||
* @return a new vector containing the result. */
|
||||
Vector lerp (IVector other, double t);
|
||||
|
||||
/** Linearly interpolates between this and the supplied other vector by the supplied amount,
|
||||
* storing the result in the supplied object.
|
||||
* @return a reference to the result, for chaining. */
|
||||
Vector lerp (IVector other, double t, Vector result);
|
||||
|
||||
/** Returns a mutable copy of this vector. */
|
||||
Vector clone ();
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* Implements the identity transform.
|
||||
*/
|
||||
public class IdentityTransform extends AbstractTransform
|
||||
{
|
||||
/** Identifies the identity transform in {@link #generality}. */
|
||||
public static final int GENERALITY = 0;
|
||||
|
||||
@Override // from Transform
|
||||
public double uniformScale () {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double scaleX () {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double scaleY () {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double rotation () {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double tx () {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double ty () {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform invert () {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform concatenate (Transform other) {
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform preConcatenate (Transform other) {
|
||||
return other;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform lerp (Transform other, double t) {
|
||||
throw new UnsupportedOperationException(); // TODO
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Point transform (IPoint p, Point into) {
|
||||
return into.set(p);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public void transform (IPoint[] src, int srcOff, Point[] dst, int dstOff, int count) {
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
transform(src[srcOff++], dst[dstOff++]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public void transform (double[] src, int srcOff, double[] dst, int dstOff, int count) {
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
dst[dstOff++] = src[srcOff++];
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Point inverseTransform (IPoint p, Point into) {
|
||||
return into.set(p);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Vector transform (IVector v, Vector into) {
|
||||
return into.set(v);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Vector inverseTransform (IVector v, Vector into) {
|
||||
return into.set(v);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform clone () {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public int generality () {
|
||||
return GENERALITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return "ident";
|
||||
}
|
||||
}
|
||||
@@ -36,31 +36,31 @@ class IntersectPoint
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
public int getBegIndex (boolean isCurrentArea) {
|
||||
public int begIndex (boolean isCurrentArea) {
|
||||
return isCurrentArea ? begIndex1 : begIndex2;
|
||||
}
|
||||
|
||||
public int getEndIndex (boolean isCurrentArea) {
|
||||
public int endIndex (boolean isCurrentArea) {
|
||||
return isCurrentArea ? endIndex1 : endIndex2;
|
||||
}
|
||||
|
||||
public int getRuleIndex (boolean isCurrentArea) {
|
||||
public int ruleIndex (boolean isCurrentArea) {
|
||||
return isCurrentArea ? ruleIndex1 : ruleIndex2;
|
||||
}
|
||||
|
||||
public double getParam (boolean isCurrentArea) {
|
||||
public double param (boolean isCurrentArea) {
|
||||
return isCurrentArea ? param1 : param2;
|
||||
}
|
||||
|
||||
public int getRule (boolean isCurrentArea) {
|
||||
public int rule (boolean isCurrentArea) {
|
||||
return isCurrentArea ? rule1 : rule2;
|
||||
}
|
||||
|
||||
public double getX () {
|
||||
public double x () {
|
||||
return x;
|
||||
}
|
||||
|
||||
public double getY () {
|
||||
public double y () {
|
||||
return y;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,26 +57,26 @@ public class Line extends AbstractLine implements Serializable
|
||||
* Sets the start and end of this line to the specified points.
|
||||
*/
|
||||
public void setLine (IPoint p1, IPoint p2) {
|
||||
setLine(p1.getX(), p1.getY(), p2.getY(), p2.getY());
|
||||
setLine(p1.x(), p1.y(), p2.y(), p2.y());
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double getX1 () {
|
||||
public double x1 () {
|
||||
return x1;
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double getY1 () {
|
||||
public double y1 () {
|
||||
return y1;
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double getX2 () {
|
||||
public double x2 () {
|
||||
return x2;
|
||||
}
|
||||
|
||||
@Override // from interface ILine
|
||||
public double getY2 () {
|
||||
public double y2 () {
|
||||
return y2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,8 +80,7 @@ public class Lines
|
||||
/**
|
||||
* Returns the distance from the specified point to the specified line.
|
||||
*/
|
||||
public static double pointLineDist (double px, double py,
|
||||
double x1, double y1, double x2, double y2) {
|
||||
public static double pointLineDist (double px, double py, double x1, double y1, double x2, double y2) {
|
||||
return Math.sqrt(pointLineDistSq(px, py, x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
@@ -119,8 +118,7 @@ public class Lines
|
||||
/**
|
||||
* Returns the distance between the specified point and the specified line segment.
|
||||
*/
|
||||
public static double pointSegDist (double px, double py,
|
||||
double x1, double y1, double x2, double y2) {
|
||||
public static double pointSegDist (double px, double py, double x1, double y1, double x2, double y2) {
|
||||
return Math.sqrt(pointSegDistSq(px, py, x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
@@ -130,8 +128,7 @@ public class Lines
|
||||
*
|
||||
* See http://download.oracle.com/javase/6/docs/api/java/awt/geom/Line2D.html
|
||||
*/
|
||||
public static int relativeCCW (double px, double py,
|
||||
double x1, double y1, double x2, double y2) {
|
||||
public static int relativeCCW (double px, double py, double x1, double y1, double x2, double y2) {
|
||||
// A = (x2-x1, y2-y1)
|
||||
// P = (px-x1, py-y1)
|
||||
x2 -= x1;
|
||||
|
||||
@@ -0,0 +1,230 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* Math utility methods.
|
||||
*/
|
||||
public class MathUtil
|
||||
{
|
||||
/** A small number. */
|
||||
public static final double EPSILON = 0.00001f;
|
||||
|
||||
/** The circle constant, Tau (τ) http://tauday.com/ */
|
||||
public static final double TAU = (Math.PI * 2);
|
||||
|
||||
/** Twice Pi. */
|
||||
public static final double TWO_PI = TAU;
|
||||
|
||||
/** Pi times one half. */
|
||||
public static final double HALF_PI = (Math.PI * 0.5);
|
||||
|
||||
/**
|
||||
* A cheaper version of {@link Math#round} that doesn't handle the special cases.
|
||||
*/
|
||||
public static int round (double v)
|
||||
{
|
||||
return (v < 0f) ? (int)(v - 0.5f) : (int)(v + 0.5f);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the floor of v as an integer without calling the relatively expensive
|
||||
* {@link Math#floor}.
|
||||
*/
|
||||
public static int ifloor (double v)
|
||||
{
|
||||
int iv = (int)v;
|
||||
return (v < 0f) ? ((iv == v || iv == Integer.MIN_VALUE) ? iv : (iv - 1)) : iv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the ceiling of v as an integer without calling the relatively expensive
|
||||
* {@link Math#ceil}.
|
||||
*/
|
||||
public static int iceil (double v)
|
||||
{
|
||||
int iv = (int)v;
|
||||
return (v > 0f) ? ((iv == v || iv == Integer.MAX_VALUE) ? iv : (iv + 1)) : iv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamps a value to the range [lower, upper].
|
||||
*/
|
||||
public static double clamp (double v, double lower, double upper)
|
||||
{
|
||||
return Math.min(Math.max(v, lower), upper);
|
||||
}
|
||||
|
||||
/**
|
||||
* Rounds a value to the nearest multiple of a target.
|
||||
*/
|
||||
public static double roundNearest (double v, double target)
|
||||
{
|
||||
target = Math.abs(target);
|
||||
if (v >= 0) {
|
||||
return target * Math.floor((v + 0.5f * target) / target);
|
||||
} else {
|
||||
return target * Math.ceil((v - 0.5f * target) / target);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the value supplied is in [lower, upper].
|
||||
*/
|
||||
public static boolean isWithin (double v, double lower, double upper)
|
||||
{
|
||||
return v >= lower && v <= upper;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random value according to the normal distribution with the provided mean and
|
||||
* standard deviation.
|
||||
*
|
||||
* @param normal a normally distributed random value.
|
||||
* @param mean the desired mean.
|
||||
* @param stddev the desired standard deviation.
|
||||
*/
|
||||
public static double normal (double normal, double mean, double stddev)
|
||||
{
|
||||
return stddev*normal + mean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a random value according to the exponential distribution with the provided mean.
|
||||
*
|
||||
* @param random a uniformly distributed random value.
|
||||
* @param mean the desired mean.
|
||||
*/
|
||||
public static double exponential (double random, double mean)
|
||||
{
|
||||
return -Math.log(1f - random) * mean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Linearly interpolates between two angles, taking the shortest path around the circle.
|
||||
* This assumes that both angles are in [-pi, +pi].
|
||||
*/
|
||||
public static double lerpa (double a1, double a2, double t)
|
||||
{
|
||||
double ma1 = mirrorAngle(a1), ma2 = mirrorAngle(a2);
|
||||
double d = Math.abs(a2 - a1), md = Math.abs(ma1 - ma2);
|
||||
return (d < md) ? lerp(a1, a2, t) : mirrorAngle(lerp(ma1, ma2, t));
|
||||
}
|
||||
|
||||
/**
|
||||
* Linearly interpolates between v1 and v2 by the parameter t.
|
||||
*/
|
||||
public static double lerp (double v1, double v2, double t)
|
||||
{
|
||||
return v1 + t*(v2 - v1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether two values are "close enough" to equal.
|
||||
*/
|
||||
public static boolean epsilonEquals (double v1, double v2)
|
||||
{
|
||||
return Math.abs(v1 - v2) < EPSILON;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (shortest) distance between two angles, assuming that both angles are in
|
||||
* [-pi, +pi].
|
||||
*/
|
||||
public static double angularDistance (double a1, double a2)
|
||||
{
|
||||
double ma1 = mirrorAngle(a1), ma2 = mirrorAngle(a2);
|
||||
return Math.min(Math.abs(a1 - a2), Math.abs(ma1 - ma2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the (shortest) difference between two angles, assuming that both angles are in
|
||||
* [-pi, +pi].
|
||||
*/
|
||||
public static double angularDifference (double a1, double a2)
|
||||
{
|
||||
double ma1 = mirrorAngle(a1), ma2 = mirrorAngle(a2);
|
||||
double diff = a1 - a2, mdiff = ma2 - ma1;
|
||||
return (Math.abs(diff) < Math.abs(mdiff)) ? diff : mdiff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an angle in the range [-pi, pi].
|
||||
*/
|
||||
public static double normalizeAngle (double a)
|
||||
{
|
||||
while (a < -Math.PI) {
|
||||
a += TWO_PI;
|
||||
}
|
||||
while (a > Math.PI) {
|
||||
a -= TWO_PI;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an angle in the range [0, 2pi].
|
||||
*/
|
||||
public static double normalizeAnglePositive (double a)
|
||||
{
|
||||
while (a < 0f) {
|
||||
a += TWO_PI;
|
||||
}
|
||||
while (a > TWO_PI) {
|
||||
a -= TWO_PI;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the mirror angle of the specified angle (assumed to be in [-pi, +pi]).
|
||||
*/
|
||||
public static double mirrorAngle (double a)
|
||||
{
|
||||
return (a > 0f ? Math.PI : -Math.PI) - a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the number of decimal places to show when formatting values. By default, they are
|
||||
* formatted to three decimal places.
|
||||
*/
|
||||
public static void setToStringDecimalPlaces (int places) {
|
||||
if (places < 0) throw new IllegalArgumentException("Decimal places must be >= 0.");
|
||||
TO_STRING_DECIMAL_PLACES = places;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the supplied doubleing point value, truncated to the currently configured number of
|
||||
* decimal places. The value is also always preceded by a sign (e.g. +1.0 or -0.5).
|
||||
*/
|
||||
public static String toString (double value)
|
||||
{
|
||||
StringBuilder buf = new StringBuilder();
|
||||
if (value >= 0) buf.append("+");
|
||||
else {
|
||||
buf.append("-");
|
||||
value = -value;
|
||||
}
|
||||
int ivalue = (int)value;
|
||||
buf.append(ivalue);
|
||||
if (TO_STRING_DECIMAL_PLACES > 0) {
|
||||
buf.append(".");
|
||||
for (int ii = 0; ii < TO_STRING_DECIMAL_PLACES; ii++) {
|
||||
value = (value - ivalue) * 10;
|
||||
ivalue = (int)value;
|
||||
buf.append(ivalue);
|
||||
}
|
||||
// trim trailing zeros
|
||||
for (int ii = 0; ii < TO_STRING_DECIMAL_PLACES-1; ii++) {
|
||||
if (buf.charAt(buf.length()-1) == '0') {
|
||||
buf.setLength(buf.length()-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
protected static int TO_STRING_DECIMAL_PLACES = 3;
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* Implements a uniform (translation, rotation, scaleX, scaleY) transform.
|
||||
*/
|
||||
public class NonUniformTransform extends AbstractTransform
|
||||
{
|
||||
/** Identifies the uniform transform in {@link #generality}. */
|
||||
public static final int GENERALITY = 3;
|
||||
|
||||
/** The scale components of this transform. */
|
||||
public double scaleX, scaleY;
|
||||
|
||||
/** The rotation component of this transform (in radians). */
|
||||
public double rotation;
|
||||
|
||||
/** The translation components of this transform. */
|
||||
public double tx, ty;
|
||||
|
||||
/** Creates a uniform transform with zero translation and rotation, and unit scale. */
|
||||
public NonUniformTransform () {
|
||||
this.scaleX = this.scaleY = 1;
|
||||
}
|
||||
|
||||
/** Creates a uniform transform with the specified translation, rotation and scale. */
|
||||
public NonUniformTransform (double scaleX, double scaleY, double rotation, double tx, double ty) {
|
||||
setScale(scaleX, scaleY);
|
||||
setRotation(rotation);
|
||||
setTranslation(tx, ty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double uniformScale () {
|
||||
return (scaleX + scaleY) / 2; // TODO: is this sane
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double scaleX () {
|
||||
return scaleX;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double scaleY () {
|
||||
return scaleY;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double rotation () {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double tx () {
|
||||
return tx;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double ty () {
|
||||
return ty;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setUniformScale (double scale) {
|
||||
setScaleX(scale);
|
||||
setScaleY(scale);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setScaleX (double scaleX) {
|
||||
if (scaleX == 0) throw new IllegalArgumentException("Scale (x) must not be zero.");
|
||||
this.scaleX = scaleX;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setScaleY (double scaleY) {
|
||||
if (scaleY == 0) throw new IllegalArgumentException("Scale (y) must not be zero.");
|
||||
this.scaleY = scaleY;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setRotation (double angle) {
|
||||
this.rotation = angle;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTx (double tx) {
|
||||
this.tx = tx;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTy (double ty) {
|
||||
this.ty = ty;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform uniformScale (double scale) {
|
||||
return scale(scale, scale);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform scaleX (double scaleX) {
|
||||
if (scaleX == 0) throw new IllegalArgumentException("Scale (x) must not be zero.");
|
||||
this.tx *= scaleX;
|
||||
this.scaleX *= scaleX;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform scaleY (double scaleY) {
|
||||
if (scaleY == 0) throw new IllegalArgumentException("Scale (y) must not be zero.");
|
||||
this.ty *= scaleX;
|
||||
this.scaleY *= scaleY;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform rotate (double angle) {
|
||||
double otx = this.tx, oty = this.ty;
|
||||
if (otx != 0 || oty != 0) {
|
||||
double sina = Math.sin(angle), cosa = Math.cos(angle);
|
||||
this.tx = otx*cosa - oty*sina;
|
||||
this.ty = otx*sina + oty*cosa;
|
||||
}
|
||||
this.rotation += angle;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translateX (double tx) {
|
||||
this.tx += tx;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translateY (double ty) {
|
||||
this.ty += ty;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform invert () {
|
||||
Vector iscale = new Vector(1f / scaleX, 1f / scaleY);
|
||||
Vector t = new Vector(tx, ty).negateLocal().rotateLocal(-rotation).multLocal(iscale);
|
||||
return new NonUniformTransform(iscale.x, iscale.y, -rotation, t.x, t.y);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform concatenate (Transform other) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.preConcatenate(this);
|
||||
}
|
||||
|
||||
double otx = other.tx(), oty = other.ty();
|
||||
double sina = Math.sin(rotation), cosa = Math.cos(rotation);
|
||||
double ntx = (otx*cosa - oty*sina) * scaleX + tx();
|
||||
double nty = (otx*sina + oty*cosa) * scaleY + ty();
|
||||
|
||||
double nrotation = MathUtil.normalizeAngle(rotation + other.rotation());
|
||||
double nscaleX = scaleX * other.scaleX();
|
||||
double nscaleY = scaleY * other.scaleY();
|
||||
return new NonUniformTransform(nscaleX, nscaleY, nrotation, ntx, nty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform preConcatenate (Transform other) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.concatenate(this);
|
||||
}
|
||||
|
||||
double tx = tx(), ty = ty();
|
||||
double sina = Math.sin(other.rotation()), cosa = Math.cos(other.rotation());
|
||||
double ntx = (tx*cosa - ty*sina) * other.scaleX() + other.tx();
|
||||
double nty = (tx*sina + ty*cosa) * other.scaleY() + other.ty();
|
||||
double nrotation = MathUtil.normalizeAngle(other.rotation() + rotation);
|
||||
double nscaleX = other.scaleX() * scaleX;
|
||||
double nscaleY = other.scaleY() * scaleY;
|
||||
return new NonUniformTransform(nscaleX, nscaleY, nrotation, ntx, nty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform lerp (Transform other, double t) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.lerp(this, -t); // TODO: is this correct?
|
||||
}
|
||||
|
||||
double ntx = MathUtil.lerpa(tx, other.tx(), t);
|
||||
double nty = MathUtil.lerpa(ty, other.ty(), t);
|
||||
double nrotation = MathUtil.lerpa(rotation, other.rotation(), t);
|
||||
double nscaleX = MathUtil.lerp(scaleX, other.scaleX(), t);
|
||||
double nscaleY = MathUtil.lerp(scaleY, other.scaleY(), t);
|
||||
return new NonUniformTransform(nscaleX, nscaleY, nrotation, ntx, nty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Point transform (IPoint p, Point into) {
|
||||
return Points.transform(p.x(), p.y(), scaleX, scaleY, rotation, tx, ty, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public void transform (IPoint[] src, int srcOff, Point[] dst, int dstOff, int count) {
|
||||
double sina = Math.sin(rotation), cosa = Math.cos(rotation);
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
IPoint s = src[srcOff++];
|
||||
Points.transform(s.x(), s.y(), scaleX, scaleY, sina, cosa, tx, ty, dst[dstOff++]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public void transform (double[] src, int srcOff, double[] dst, int dstOff, int count) {
|
||||
Point p = new Point();
|
||||
double sina = Math.sin(rotation), cosa = Math.cos(rotation);
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
Points.transform(src[srcOff++], src[srcOff++], scaleX, scaleY, sina, cosa, tx, ty, p);
|
||||
dst[dstOff++] = p.x;
|
||||
dst[dstOff++] = p.y;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Point inverseTransform (IPoint p, Point into) {
|
||||
return Points.inverseTransform(p.x(), p.y(), scaleX, scaleY, rotation, tx, ty, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Vector transform (IVector v, Vector into) {
|
||||
return Vectors.transform(v.x(), v.y(), scaleX, scaleY, rotation, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Vector inverseTransform (IVector v, Vector into) {
|
||||
return Vectors.inverseTransform(v.x(), v.y(), scaleX, scaleY, rotation, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform clone () {
|
||||
return new NonUniformTransform(scaleX, scaleY, rotation, tx, ty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public int generality () {
|
||||
return GENERALITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return "nonunif [scale=" + scale() + ", rot=" + rotation +
|
||||
", trans=" + translation() + "]";
|
||||
}
|
||||
}
|
||||
@@ -35,8 +35,8 @@ public final class Path implements IShape, Cloneable
|
||||
|
||||
public Path (IShape shape) {
|
||||
this(WIND_NON_ZERO, BUFFER_SIZE);
|
||||
PathIterator p = shape.getPathIterator(null);
|
||||
setWindingRule(p.getWindingRule());
|
||||
PathIterator p = shape.pathIterator(null);
|
||||
setWindingRule(p.windingRule());
|
||||
append(p, false);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public final class Path implements IShape, Cloneable
|
||||
this.rule = rule;
|
||||
}
|
||||
|
||||
public int getWindingRule () {
|
||||
public int windingRule () {
|
||||
return rule;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public final class Path implements IShape, Cloneable
|
||||
}
|
||||
|
||||
public void append (IShape shape, boolean connect) {
|
||||
PathIterator p = shape.getPathIterator(null);
|
||||
PathIterator p = shape.pathIterator(null);
|
||||
append(p, connect);
|
||||
}
|
||||
|
||||
@@ -135,7 +135,7 @@ public final class Path implements IShape, Cloneable
|
||||
}
|
||||
}
|
||||
|
||||
public Point getCurrentPoint () {
|
||||
public Point currentPoint () {
|
||||
if (typeSize == 0) {
|
||||
return null;
|
||||
}
|
||||
@@ -157,11 +157,11 @@ public final class Path implements IShape, Cloneable
|
||||
pointSize = 0;
|
||||
}
|
||||
|
||||
public void transform (AffineTransform t) {
|
||||
public void transform (Transform t) {
|
||||
t.transform(points, 0, points, 0, pointSize / 2);
|
||||
}
|
||||
|
||||
public IShape createTransformedShape (AffineTransform t) {
|
||||
public IShape createTransformedShape (Transform t) {
|
||||
Path p = clone();
|
||||
if (t != null) {
|
||||
p.transform(t);
|
||||
@@ -170,12 +170,12 @@ public final class Path implements IShape, Cloneable
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds () {
|
||||
return getBounds(new Rectangle());
|
||||
public Rectangle bounds () {
|
||||
return bounds(new Rectangle());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds (Rectangle target) {
|
||||
public Rectangle bounds (Rectangle target) {
|
||||
double rx1, ry1, rx2, ry2;
|
||||
if (pointSize == 0) {
|
||||
rx1 = ry1 = rx2 = ry2 = 0f;
|
||||
@@ -205,7 +205,7 @@ public final class Path implements IShape, Cloneable
|
||||
@Override // from interface IShape
|
||||
public boolean isEmpty () {
|
||||
// TODO: will this be insanely difficult to do correctly?
|
||||
return getBounds().isEmpty();
|
||||
return bounds().isEmpty();
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
@@ -227,27 +227,27 @@ public final class Path implements IShape, Cloneable
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (IPoint p) {
|
||||
return contains(p.getX(), p.getY());
|
||||
return contains(p.x(), p.y());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (IRectangle r) {
|
||||
return contains(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
return contains(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean intersects (IRectangle r) {
|
||||
return intersects(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
return intersects(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform t) {
|
||||
public PathIterator pathIterator (Transform t) {
|
||||
return new Iterator(this, t);
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform t, double flatness) {
|
||||
return new FlatteningPathIterator(getPathIterator(t), flatness);
|
||||
public PathIterator pathIterator (Transform t, double flatness) {
|
||||
return new FlatteningPathIterator(pathIterator(t), flatness);
|
||||
}
|
||||
|
||||
// @Override // can't declare @Override due to GWT
|
||||
@@ -309,19 +309,19 @@ public final class Path implements IShape, Cloneable
|
||||
private Path p;
|
||||
|
||||
/** The path iterator transformation. */
|
||||
private AffineTransform t;
|
||||
private Transform t;
|
||||
|
||||
Iterator (Path path) {
|
||||
this(path, null);
|
||||
}
|
||||
|
||||
Iterator (Path path, AffineTransform at) {
|
||||
Iterator (Path path, Transform at) {
|
||||
this.p = path;
|
||||
this.t = at;
|
||||
}
|
||||
|
||||
@Override public int getWindingRule () {
|
||||
return p.getWindingRule();
|
||||
@Override public int windingRule () {
|
||||
return p.windingRule();
|
||||
}
|
||||
|
||||
@Override public boolean isDone () {
|
||||
|
||||
@@ -36,7 +36,7 @@ public interface PathIterator
|
||||
/**
|
||||
* Returns the winding rule used to determine the interior of this path.
|
||||
*/
|
||||
int getWindingRule ();
|
||||
int windingRule ();
|
||||
|
||||
/**
|
||||
* Returns true if this path has no additional segments.
|
||||
|
||||
@@ -27,53 +27,55 @@ public class Point extends AbstractPoint implements Serializable
|
||||
* Constructs a point at the specified coordinates.
|
||||
*/
|
||||
public Point (double x, double y) {
|
||||
setLocation(x, y);
|
||||
set(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a point with coordinates equal to the supplied point.
|
||||
*/
|
||||
public Point (IPoint p) {
|
||||
setLocation(p.getX(), p.getY());
|
||||
set(p.x(), p.y());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the coordinates of this point to be equal to those of the supplied point.
|
||||
*/
|
||||
public void setLocation (IPoint p) {
|
||||
setLocation(p.getX(), p.getY());
|
||||
/** Sets the coordinates of this point to be equal to those of the supplied point.
|
||||
* @return a reference to this this, for chaining. */
|
||||
public Point set (IPoint p) {
|
||||
return set(p.x(), p.y());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the coordinates of this point to the supplied values.
|
||||
*/
|
||||
public void setLocation (double x, double y) {
|
||||
/** Sets the coordinates of this point to the supplied values.
|
||||
* @return a reference to this this, for chaining. */
|
||||
public Point set (double x, double y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* A synonym for {@link #setLocation}.
|
||||
*/
|
||||
public void move (double x, double y) {
|
||||
setLocation(x, y);
|
||||
/** Multiplies this point by a scale factor.
|
||||
* @return a a reference to this point, for chaining. */
|
||||
public Point multLocal (double s) {
|
||||
return mult(s, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translates this point by the specified offset.
|
||||
*/
|
||||
public void translate (double dx, double dy) {
|
||||
x += dx;
|
||||
y += dy;
|
||||
/** Translates this point by the specified offset.
|
||||
* @return a reference to this point, for chaining. */
|
||||
public Point addLocal (double dx, double dy) {
|
||||
return add(dx, dy, this);
|
||||
}
|
||||
|
||||
/** Rotates this point in-place by the specified angle.
|
||||
* @return a reference to this point, for chaining. */
|
||||
public Point rotateLocal (double angle) {
|
||||
return rotate(angle, this);
|
||||
}
|
||||
|
||||
@Override // from interface IPoint
|
||||
public double getX () {
|
||||
public double x () {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override // from interface IPoint
|
||||
public double getY () {
|
||||
public double y () {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ package pythagoras.d;
|
||||
*/
|
||||
public class Points
|
||||
{
|
||||
/** The point at the origin. */
|
||||
public static final IPoint ZERO = new Point(0f, 0f);
|
||||
|
||||
/**
|
||||
* Returns the squared Euclidean distance between the specified two points.
|
||||
*/
|
||||
@@ -25,16 +28,37 @@ public class Points
|
||||
return Math.sqrt(distanceSq(x1, y1, x2, y2));
|
||||
}
|
||||
|
||||
/** Transforms a point as specified, storing the result in the point provided.
|
||||
* @return a reference to the result point, for chaining. */
|
||||
public static Point transform (double x, double y, double sx, double sy, double rotation,
|
||||
double tx, double ty, Point result) {
|
||||
return transform(x, y, sx, sy, Math.sin(rotation), Math.cos(rotation), tx, ty,
|
||||
result);
|
||||
}
|
||||
|
||||
/** Transforms a point as specified, storing the result in the point provided.
|
||||
* @return a reference to the result point, for chaining. */
|
||||
public static Point transform (double x, double y, double sx, double sy, double sina, double cosa,
|
||||
double tx, double ty, Point result) {
|
||||
return result.set((x*cosa - y*sina) * sx + tx, (x*sina + y*cosa) * sy + ty);
|
||||
}
|
||||
|
||||
/** Inverse transforms a point as specified, storing the result in the point provided.
|
||||
* @return a reference to the result point, for chaining. */
|
||||
public static Point inverseTransform (double x, double y, double sx, double sy, double rotation,
|
||||
double tx, double ty, Point result) {
|
||||
x -= tx; y -= ty; // untranslate
|
||||
double sinnega = Math.sin(-rotation), cosnega = Math.cos(-rotation);
|
||||
double nx = (x * cosnega - y * sinnega); // unrotate
|
||||
double ny = (x * sinnega + y * cosnega);
|
||||
return result.set(nx / sx, ny / sy); // unscale
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string describing the supplied point, of the form <code>+x+y</code>,
|
||||
* <code>+x-y</code>, <code>-x-y</code>, etc.
|
||||
*/
|
||||
public static String pointToString (double x, double y) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
if (x >= 0) buf.append("+");
|
||||
buf.append(x);
|
||||
if (y >= 0) buf.append("+");
|
||||
buf.append(y);
|
||||
return buf.toString();
|
||||
return MathUtil.toString(x) + MathUtil.toString(y);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ public class QuadCurve extends AbstractQuadCurve implements Serializable
|
||||
* Configures the start, control, and end points for this curve.
|
||||
*/
|
||||
public void setCurve (IPoint p1, IPoint cp, IPoint p2) {
|
||||
setCurve(p1.getX(), p1.getY(), cp.getX(), cp.getY(), p2.getX(), p2.getY());
|
||||
setCurve(p1.x(), p1.y(), cp.x(), cp.y(), p2.x(), p2.y());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,9 +76,9 @@ public class QuadCurve extends AbstractQuadCurve implements Serializable
|
||||
* specified offset in the {@code points} array.
|
||||
*/
|
||||
public void setCurve (IPoint[] 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());
|
||||
setCurve(points[offset + 0].x(), points[offset + 0].y(),
|
||||
points[offset + 1].x(), points[offset + 1].y(),
|
||||
points[offset + 2].x(), points[offset + 2].y());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,37 +86,37 @@ public class QuadCurve extends AbstractQuadCurve implements Serializable
|
||||
* curve.
|
||||
*/
|
||||
public void setCurve (IQuadCurve curve) {
|
||||
setCurve(curve.getX1(), curve.getY1(), curve.getCtrlX(), curve.getCtrlY(),
|
||||
curve.getX2(), curve.getY2());
|
||||
setCurve(curve.x1(), curve.y1(), curve.ctrlX(), curve.ctrlY(),
|
||||
curve.x2(), curve.y2());
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public double getX1 () {
|
||||
public double x1 () {
|
||||
return x1;
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public double getY1 () {
|
||||
public double y1 () {
|
||||
return y1;
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public double getCtrlX () {
|
||||
public double ctrlX () {
|
||||
return ctrlx;
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public double getCtrlY () {
|
||||
public double ctrlY () {
|
||||
return ctrly;
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public double getX2 () {
|
||||
public double x2 () {
|
||||
return x2;
|
||||
}
|
||||
|
||||
@Override // from interface IQuadCurve
|
||||
public double getY2 () {
|
||||
public double y2 () {
|
||||
return y2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,35 +9,35 @@ package pythagoras.d;
|
||||
*/
|
||||
public class QuadCurves
|
||||
{
|
||||
public static double getFlatnessSq (double x1, double y1, double ctrlx, double ctrly,
|
||||
public static double flatnessSq (double x1, double y1, double ctrlx, double ctrly,
|
||||
double x2, double y2) {
|
||||
return Lines.pointSegDistSq(ctrlx, ctrly, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
public static double getFlatnessSq (double[] coords, int offset) {
|
||||
public static double flatnessSq (double[] coords, int offset) {
|
||||
return Lines.pointSegDistSq(coords[offset + 2], coords[offset + 3],
|
||||
coords[offset + 0], coords[offset + 1],
|
||||
coords[offset + 4], coords[offset + 5]);
|
||||
}
|
||||
|
||||
public static double getFlatness (double x1, double y1, double ctrlx, double ctrly,
|
||||
public static double flatness (double x1, double y1, double ctrlx, double ctrly,
|
||||
double x2, double y2) {
|
||||
return Lines.pointSegDist(ctrlx, ctrly, x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
public static double getFlatness (double[] coords, int offset) {
|
||||
public static double flatness (double[] coords, int offset) {
|
||||
return Lines.pointSegDist(coords[offset + 2], coords[offset + 3],
|
||||
coords[offset + 0], coords[offset + 1],
|
||||
coords[offset + 4], coords[offset + 5]);
|
||||
}
|
||||
|
||||
public static void subdivide (IQuadCurve src, QuadCurve left, QuadCurve 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 x1 = src.x1();
|
||||
double y1 = src.y1();
|
||||
double cx = src.ctrlX();
|
||||
double cy = src.ctrlY();
|
||||
double x2 = src.x2();
|
||||
double y2 = src.y2();
|
||||
double cx1 = (x1 + cx) / 2f;
|
||||
double cy1 = (y1 + cy) / 2f;
|
||||
double cx2 = (x2 + cx) / 2f;
|
||||
|
||||
@@ -33,14 +33,14 @@ public class Rectangle extends AbstractRectangle implements Serializable
|
||||
* Constructs a rectangle with the supplied upper-left corner and dimensions (0,0).
|
||||
*/
|
||||
public Rectangle (IPoint p) {
|
||||
setBounds(p.getX(), p.getY(), 0, 0);
|
||||
setBounds(p.x(), p.y(), 0, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a rectangle with upper-left corner at (0,) and the supplied dimensions.
|
||||
*/
|
||||
public Rectangle (IDimension d) {
|
||||
setBounds(0, 0, d.getWidth(), d.getHeight());
|
||||
setBounds(0, 0, d.width(), d.height());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -48,7 +48,7 @@ public class Rectangle extends AbstractRectangle implements Serializable
|
||||
* dimensions.
|
||||
*/
|
||||
public Rectangle (IPoint p, IDimension d) {
|
||||
setBounds(p.getX(), p.getY(), d.getWidth(), d.getHeight());
|
||||
setBounds(p.x(), p.y(), d.width(), d.height());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,7 +62,7 @@ public class Rectangle extends AbstractRectangle implements Serializable
|
||||
* Constructs a rectangle with bounds equal to the supplied rectangle.
|
||||
*/
|
||||
public Rectangle (IRectangle r) {
|
||||
setBounds(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
setBounds(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,7 +77,7 @@ public class Rectangle extends AbstractRectangle implements Serializable
|
||||
* Sets the upper-left corner of this rectangle to the supplied point.
|
||||
*/
|
||||
public void setLocation (IPoint p) {
|
||||
setLocation(p.getX(), p.getY());
|
||||
setLocation(p.x(), p.y());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +92,7 @@ public class Rectangle extends AbstractRectangle implements Serializable
|
||||
* Sets the size of this rectangle to the supplied dimensions.
|
||||
*/
|
||||
public void setSize (IDimension d) {
|
||||
setSize(d.getWidth(), d.getHeight());
|
||||
setSize(d.width(), d.height());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,7 +109,7 @@ public class Rectangle extends AbstractRectangle implements Serializable
|
||||
* Sets the bounds of this rectangle to those of the supplied rectangle.
|
||||
*/
|
||||
public void setBounds (IRectangle r) {
|
||||
setBounds(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
setBounds(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,37 +147,37 @@ public class Rectangle extends AbstractRectangle implements Serializable
|
||||
* Expands the bounds of this rectangle to contain the supplied point.
|
||||
*/
|
||||
public void add (IPoint p) {
|
||||
add(p.getX(), p.getY());
|
||||
add(p.x(), p.y());
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands the bounds of this rectangle to contain the supplied rectangle.
|
||||
*/
|
||||
public void add (IRectangle r) {
|
||||
double x1 = Math.min(x, r.getX());
|
||||
double x2 = Math.max(x + width, r.getX() + r.getWidth());
|
||||
double y1 = Math.min(y, r.getY());
|
||||
double y2 = Math.max(y + height, r.getY() + r.getHeight());
|
||||
double x1 = Math.min(x, r.x());
|
||||
double x2 = Math.max(x + width, r.x() + r.width());
|
||||
double y1 = Math.min(y, r.y());
|
||||
double y2 = Math.max(y + height, r.y() + r.height());
|
||||
setBounds(x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getX () {
|
||||
public double x () {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getY () {
|
||||
public double y () {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getWidth () {
|
||||
public double width () {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getHeight () {
|
||||
public double height () {
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@ public class Rectangles
|
||||
* Intersects the supplied two rectangles, writing the result into {@code dst}.
|
||||
*/
|
||||
public static void intersect (IRectangle src1, IRectangle src2, Rectangle dst) {
|
||||
double x1 = Math.max(src1.getMinX(), src2.getMinX());
|
||||
double y1 = Math.max(src1.getMinY(), src2.getMinY());
|
||||
double x2 = Math.min(src1.getMaxX(), src2.getMaxX());
|
||||
double y2 = Math.min(src1.getMaxY(), src2.getMaxY());
|
||||
double x1 = Math.max(src1.minX(), src2.minX());
|
||||
double y1 = Math.max(src1.minY(), src2.minY());
|
||||
double x2 = Math.min(src1.maxX(), src2.maxX());
|
||||
double y2 = Math.min(src1.maxY(), src2.maxY());
|
||||
dst.setBounds(x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ public class Rectangles
|
||||
* Unions the supplied two rectangles, writing the result into {@code dst}.
|
||||
*/
|
||||
public static void union (IRectangle src1, IRectangle src2, Rectangle dst) {
|
||||
double x1 = Math.min(src1.getMinX(), src2.getMinX());
|
||||
double y1 = Math.min(src1.getMinY(), src2.getMinY());
|
||||
double x2 = Math.max(src1.getMaxX(), src2.getMaxX());
|
||||
double y2 = Math.max(src1.getMaxY(), src2.getMaxY());
|
||||
double x1 = Math.min(src1.minX(), src2.minX());
|
||||
double y1 = Math.min(src1.minY(), src2.minY());
|
||||
double x2 = Math.max(src1.maxX(), src2.maxX());
|
||||
double y2 = Math.max(src1.maxY(), src2.maxY());
|
||||
dst.setBounds(x1, y1, x2 - x1, y2 - y1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ public abstract class RectangularShape implements IRectangularShape
|
||||
* Sets the location and size of the framing rectangle of this shape to the supplied values.
|
||||
*/
|
||||
public void setFrame (IPoint loc, IDimension size) {
|
||||
setFrame(loc.getX(), loc.getY(), size.getWidth(), size.getHeight());
|
||||
setFrame(loc.x(), loc.y(), size.width(), size.height());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -27,7 +27,7 @@ public abstract class RectangularShape implements IRectangularShape
|
||||
* supplied rectangle.
|
||||
*/
|
||||
public void setFrame (IRectangle r) {
|
||||
setFrame(r.getX(), r.getY(), r.getWidth(), r.getHeight());
|
||||
setFrame(r.x(), r.y(), r.width(), r.height());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,7 +58,7 @@ public abstract class RectangularShape implements IRectangularShape
|
||||
* diagonal line.
|
||||
*/
|
||||
public void setFrameFromDiagonal (IPoint p1, IPoint p2) {
|
||||
setFrameFromDiagonal(p1.getX(), p1.getY(), p2.getX(), p2.getY());
|
||||
setFrameFromDiagonal(p1.x(), p1.y(), p2.x(), p2.y());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,100 +77,100 @@ public abstract class RectangularShape implements IRectangularShape
|
||||
* center and corner points.
|
||||
*/
|
||||
public void setFrameFromCenter (IPoint center, IPoint corner) {
|
||||
setFrameFromCenter(center.getX(), center.getY(), corner.getX(), corner.getY());
|
||||
setFrameFromCenter(center.x(), center.y(), corner.x(), corner.y());
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public Point getMin ()
|
||||
public Point min ()
|
||||
{
|
||||
return new Point(getMinX(), getMinY());
|
||||
return new Point(minX(), minY());
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public double getMinX () {
|
||||
return getX();
|
||||
public double minX () {
|
||||
return x();
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public double getMinY () {
|
||||
return getY();
|
||||
public double minY () {
|
||||
return y();
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public Point getMax ()
|
||||
public Point max ()
|
||||
{
|
||||
return new Point(getMaxX(), getMaxY());
|
||||
return new Point(maxX(), maxY());
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public double getMaxX () {
|
||||
return getX() + getWidth();
|
||||
public double maxX () {
|
||||
return x() + width();
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public double getMaxY () {
|
||||
return getY() + getHeight();
|
||||
public double maxY () {
|
||||
return y() + height();
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public Point getCenter ()
|
||||
public Point center ()
|
||||
{
|
||||
return new Point(getCenterX(), getCenterY());
|
||||
return new Point(centerX(), centerY());
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public double getCenterX () {
|
||||
return getX() + getWidth() / 2;
|
||||
public double centerX () {
|
||||
return x() + width() / 2;
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public double getCenterY () {
|
||||
return getY() + getHeight() / 2;
|
||||
public double centerY () {
|
||||
return y() + height() / 2;
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public Rectangle getFrame () {
|
||||
return getBounds();
|
||||
public Rectangle frame () {
|
||||
return bounds();
|
||||
}
|
||||
|
||||
@Override // from IRectangularShape
|
||||
public Rectangle getFrame (Rectangle target) {
|
||||
return getBounds(target);
|
||||
public Rectangle frame (Rectangle target) {
|
||||
return bounds(target);
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean isEmpty () {
|
||||
return getWidth() <= 0 || getHeight() <= 0;
|
||||
return width() <= 0 || height() <= 0;
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (IPoint point) {
|
||||
return contains(point.getX(), point.getY());
|
||||
return contains(point.x(), point.y());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean contains (IRectangle rect) {
|
||||
return contains(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
|
||||
return contains(rect.x(), rect.y(), rect.width(), rect.height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public boolean intersects (IRectangle rect) {
|
||||
return intersects(rect.getX(), rect.getY(), rect.getWidth(), rect.getHeight());
|
||||
return intersects(rect.x(), rect.y(), rect.width(), rect.height());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds () {
|
||||
return getBounds(new Rectangle());
|
||||
public Rectangle bounds () {
|
||||
return bounds(new Rectangle());
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public Rectangle getBounds (Rectangle target) {
|
||||
target.setBounds(getX(), getY(), getWidth(), getHeight());
|
||||
public Rectangle bounds (Rectangle target) {
|
||||
target.setBounds(x(), y(), width(), height());
|
||||
return target;
|
||||
}
|
||||
|
||||
@Override // from interface IShape
|
||||
public PathIterator getPathIterator (AffineTransform t, double flatness) {
|
||||
return new FlatteningPathIterator(getPathIterator(t), flatness);
|
||||
public PathIterator pathIterator (Transform t, double flatness) {
|
||||
return new FlatteningPathIterator(pathIterator(t), flatness);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* Implements a rigid body (translation, rotation) transform.
|
||||
*/
|
||||
public class RigidTransform extends AbstractTransform
|
||||
{
|
||||
/** Identifies the rigid body transform in {@link #generality}. */
|
||||
public static final int GENERALITY = 1;
|
||||
|
||||
/** The rotation component of this transform (in radians). */
|
||||
public double rotation;
|
||||
|
||||
/** The translation components of this transform. */
|
||||
public double tx, ty;
|
||||
|
||||
/** Creates a rigid body transform with zero translation and rotation. */
|
||||
public RigidTransform () {
|
||||
}
|
||||
|
||||
/** Creates a rigid body transform with the specified translation and rotation. */
|
||||
public RigidTransform (double rotation, double tx, double ty) {
|
||||
setRotation(rotation);
|
||||
setTranslation(tx, ty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double uniformScale () {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double scaleX () {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double scaleY () {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double rotation () {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double tx () {
|
||||
return tx;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double ty () {
|
||||
return ty;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setRotation (double angle) {
|
||||
this.rotation = angle;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTx (double tx) {
|
||||
this.tx = tx;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTy (double ty) {
|
||||
this.ty = ty;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform rotate (double angle) {
|
||||
double otx = this.tx, oty = this.ty;
|
||||
if (otx != 0 || oty != 0) {
|
||||
double sina = Math.sin(angle), cosa = Math.cos(angle);
|
||||
this.tx = otx*cosa - oty*sina;
|
||||
this.ty = otx*sina + oty*cosa;
|
||||
}
|
||||
this.rotation += angle;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translateX (double tx) {
|
||||
this.tx += tx;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translateY (double ty) {
|
||||
this.ty += ty;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform invert () {
|
||||
Vector t = translation().negateLocal().rotateLocal(-rotation);
|
||||
return new RigidTransform(-rotation, t.x, t.y);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform concatenate (Transform other) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.preConcatenate(this);
|
||||
}
|
||||
|
||||
Vector nt = other.translation();
|
||||
nt.rotateAndAdd(rotation, translation(), nt);
|
||||
double nrotation = MathUtil.normalizeAngle(rotation + other.rotation());
|
||||
return new RigidTransform(nrotation, nt.x, nt.y);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform preConcatenate (Transform other) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.concatenate(this);
|
||||
}
|
||||
|
||||
Vector nt = translation();
|
||||
nt.rotateAndAdd(other.rotation(), other.translation(), nt);
|
||||
double nrotation = MathUtil.normalizeAngle(other.rotation() + rotation);
|
||||
return new RigidTransform(nrotation, nt.x, nt.y);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform lerp (Transform other, double t) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.lerp(this, -t); // TODO: is this correct?
|
||||
}
|
||||
Vector nt = translation().lerpLocal(other.translation(), t);
|
||||
return new RigidTransform(MathUtil.lerpa(rotation, other.rotation(), t), nt.x, nt.y);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Point transform (IPoint p, Point into) {
|
||||
return Points.transform(p.x(), p.y(), 1, 1, rotation, tx, ty, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public void transform (IPoint[] src, int srcOff, Point[] dst, int dstOff, int count) {
|
||||
double sina = Math.sin(rotation), cosa = Math.cos(rotation);
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
IPoint s = src[srcOff++];
|
||||
Points.transform(s.x(), s.y(), 1, 1, sina, cosa, tx, ty, dst[dstOff++]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public void transform (double[] src, int srcOff, double[] dst, int dstOff, int count) {
|
||||
Point p = new Point();
|
||||
double sina = Math.sin(rotation), cosa = Math.cos(rotation);
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
Points.transform(src[srcOff++], src[srcOff++], 1, 1, sina, cosa, tx, ty, p);
|
||||
dst[dstOff++] = p.x;
|
||||
dst[dstOff++] = p.y;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Point inverseTransform (IPoint p, Point into) {
|
||||
return Points.inverseTransform(p.x(), p.y(), 1, 1, rotation, tx, ty, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Vector transform (IVector v, Vector into) {
|
||||
return v.rotate(rotation, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Vector inverseTransform (IVector v, Vector into) {
|
||||
return v.rotate(-rotation, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform clone () {
|
||||
return new RigidTransform(rotation, tx, ty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public int generality () {
|
||||
return GENERALITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return "rigid [rot=" + rotation + ", trans=" + translation() + "]";
|
||||
}
|
||||
}
|
||||
@@ -61,37 +61,37 @@ public class RoundRectangle extends AbstractRoundRectangle implements Serializab
|
||||
* rectangle.
|
||||
*/
|
||||
public void setRoundRect (IRoundRectangle rr) {
|
||||
setRoundRect(rr.getX(), rr.getY(), rr.getWidth(), rr.getHeight(),
|
||||
rr.getArcWidth(), rr.getArcHeight());
|
||||
setRoundRect(rr.x(), rr.y(), rr.width(), rr.height(),
|
||||
rr.arcWidth(), rr.arcHeight());
|
||||
}
|
||||
|
||||
@Override // from interface IRoundRectangle
|
||||
public double getArcWidth () {
|
||||
public double arcWidth () {
|
||||
return arcwidth;
|
||||
}
|
||||
|
||||
@Override // from interface IRoundRectangle
|
||||
public double getArcHeight () {
|
||||
public double arcHeight () {
|
||||
return archeight;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getX () {
|
||||
public double x () {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getY () {
|
||||
public double y () {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getWidth () {
|
||||
public double width () {
|
||||
return width;
|
||||
}
|
||||
|
||||
@Override // from interface IRectangularShape
|
||||
public double getHeight () {
|
||||
public double height () {
|
||||
return height;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,196 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* Represents a geometric transform. Specialized implementations exist for identity, rigid body,
|
||||
* uniform, non-uniform, and affine transforms.
|
||||
*/
|
||||
public interface Transform
|
||||
{
|
||||
/** Returns the uniform scale applied by this transform. The uniform scale will be approximated
|
||||
* for non-uniform transforms. */
|
||||
double uniformScale ();
|
||||
|
||||
/** Returns the scale vector for this transform. */
|
||||
Vector scale ();
|
||||
|
||||
/** Returns the x-component of the scale applied by this transform. Note that this will be
|
||||
* extracted and therefore approximate for affine transforms. */
|
||||
double scaleX ();
|
||||
|
||||
/** Returns the y-component of the scale applied by this transform. Note that this will be
|
||||
* extracted and therefore approximate for affine transforms. */
|
||||
double scaleY ();
|
||||
|
||||
/** Returns the rotation applied by this transform. Note that the rotation is extracted and
|
||||
* therefore approximate for affine transforms.
|
||||
* @throws NoninvertibleTransformException if the transform is not invertible. */
|
||||
double rotation ();
|
||||
|
||||
/** Returns the translation vector for this transform. */
|
||||
Vector translation ();
|
||||
|
||||
/** Returns the x-coordinate of the translation component. */
|
||||
double tx ();
|
||||
|
||||
/** Returns the y-coordinate of the translation component. */
|
||||
double ty ();
|
||||
|
||||
/** Sets the uniform scale of this transform.
|
||||
* @return this instance, for chaining.
|
||||
* @throws IllegalArgumentException if the supplied scale is zero.
|
||||
* @throws UnsupportedOperationException if the transform is not uniform or greater. */
|
||||
Transform setUniformScale (double scale);
|
||||
|
||||
/** Sets the x and y scale of this transform.
|
||||
* @return this instance, for chaining.
|
||||
* @throws IllegalArgumentException if either supplied scale is zero.
|
||||
* @throws UnsupportedOperationException if the transform is not non-uniform or greater. */
|
||||
Transform setScale (double scaleX, double scaleY);
|
||||
|
||||
/** Sets the x scale of this transform.
|
||||
* @return this instance, for chaining.
|
||||
* @throws IllegalArgumentException if the supplied scale is zero.
|
||||
* @throws UnsupportedOperationException if the transform is not non-uniform or greater. */
|
||||
Transform setScaleX (double scaleX);
|
||||
|
||||
/** Sets the y scale of this transform.
|
||||
* @return this instance, for chaining.
|
||||
* @throws IllegalArgumentException if the supplied scale is zero.
|
||||
* @throws UnsupportedOperationException if the transform is not non-uniform or greater. */
|
||||
Transform setScaleY (double scaleY);
|
||||
|
||||
/** Sets the rotation component of this transform.
|
||||
* @return this instance, for chaining.
|
||||
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
|
||||
Transform setRotation (double angle);
|
||||
|
||||
/** Sets the translation component of this transform.
|
||||
* @return this instance, for chaining.
|
||||
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
|
||||
Transform setTranslation (double tx, double ty);
|
||||
|
||||
/** Sets the x-component of this transform's translation.
|
||||
* @return this instance, for chaining.
|
||||
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
|
||||
Transform setTx (double tx);
|
||||
|
||||
/** Sets the y-component of this transform's translation.
|
||||
* @return this instance, for chaining.
|
||||
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
|
||||
Transform setTy (double ty);
|
||||
|
||||
/** Sets the affine transform matrix.
|
||||
* @return this instance, for chaining.
|
||||
* @throws UnsupportedOperationException if the transform is not affine or greater. */
|
||||
Transform setTransform (double m00, double m01, double m10, double m11,
|
||||
double tx, double ty);
|
||||
|
||||
/** Scales this transform in a uniform manner by the specified amount.
|
||||
* @return this instance, for chaining.
|
||||
* @throws IllegalArgumentException if the supplied scale is zero.
|
||||
* @throws UnsupportedOperationException if the transform is not uniform or greater. */
|
||||
Transform uniformScale (double scale);
|
||||
|
||||
/** Scales this transform by the specified amount in the x and y dimensions.
|
||||
* @return this instance, for chaining.
|
||||
* @throws IllegalArgumentException if either supplied scale is zero.
|
||||
* @throws UnsupportedOperationException if the transform is not non-uniform or greater. */
|
||||
Transform scale (double scaleX, double scaleY);
|
||||
|
||||
/** Scales this transform by the specified amount in the x dimension.
|
||||
* @return this instance, for chaining.
|
||||
* @throws IllegalArgumentException if the supplied scale is zero.
|
||||
* @throws UnsupportedOperationException if the transform is not non-uniform or greater. */
|
||||
Transform scaleX (double scaleX);
|
||||
|
||||
/** Scales this transform by the specified amount in the y dimension.
|
||||
* @return this instance, for chaining.
|
||||
* @throws IllegalArgumentException if the supplied scale is zero.
|
||||
* @throws UnsupportedOperationException if the transform is not non-uniform or greater. */
|
||||
Transform scaleY (double scaleY);
|
||||
|
||||
/** Rotates this transform.
|
||||
* @return this instance, for chaining.
|
||||
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
|
||||
Transform rotate (double angle);
|
||||
|
||||
/** Translates this transform.
|
||||
* @return this instance, for chaining.
|
||||
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
|
||||
Transform translate (double tx, double ty);
|
||||
|
||||
/** Translates this transform in the x dimension.
|
||||
* @return this instance, for chaining.
|
||||
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
|
||||
Transform translateX (double tx);
|
||||
|
||||
/** Translates this transform in the y dimension.
|
||||
* @return this instance, for chaining.
|
||||
* @throws UnsupportedOperationException if the transform is not rigid body or greater. */
|
||||
Transform translateY (double ty);
|
||||
|
||||
/** Returns a new transform that represents the inverse of this transform.
|
||||
* @throws NoninvertibleTransformException if the transform is not invertible. */
|
||||
Transform invert ();
|
||||
|
||||
/** Returns a new transform comprised of the concatenation of {@code other} to this transform
|
||||
* (i.e. {@code this x other}). */
|
||||
Transform concatenate (Transform other);
|
||||
|
||||
/** Returns a new transform comprised of the concatenation of this transform to {@code other}
|
||||
* (i.e. {@code other x this}). */
|
||||
Transform preConcatenate (Transform other);
|
||||
|
||||
/** Returns a new transform comprised of the linear interpolation between this transform and
|
||||
* the specified other. */
|
||||
Transform lerp (Transform other, double t);
|
||||
|
||||
/** Transforms the supplied point, writing the result into {@code into}.
|
||||
* @param into a point into which to store the result, may be the same object as {@code p}.
|
||||
* @return {@code into} for chaining. */
|
||||
Point transform (IPoint p, Point into);
|
||||
|
||||
/** Transforms the supplied points.
|
||||
* @param src the points to be transformed.
|
||||
* @param srcOff the offset into the {@code src} array at which to start.
|
||||
* @param dst the points into which to store the transformed points. May be {@code src}.
|
||||
* @param dstOff the offset into the {@code dst} array at which to start.
|
||||
* @param count the number of points to transform. */
|
||||
void transform (IPoint[] src, int srcOff, Point[] dst, int dstOff, int count);
|
||||
|
||||
/** Transforms the supplied points.
|
||||
* @param src the points to be transformed (as {@code [x, y, x, y, ...]}).
|
||||
* @param srcOff the offset into the {@code src} array at which to start.
|
||||
* @param dst the points into which to store the transformed points. May be {@code src}.
|
||||
* @param dstOff the offset into the {@code dst} array at which to start.
|
||||
* @param count the number of points to transform. */
|
||||
void transform (double[] src, int srcOff, double[] dst, int dstOff, int count);
|
||||
|
||||
/** Inverse transforms the supplied point, writing the result into {@code into}.
|
||||
* @param into a point into which to store the result, may be the same object as {@code p}.
|
||||
* @return {@code into}, for chaining.
|
||||
* @throws NoninvertibleTransformException if the transform is not invertible. */
|
||||
Point inverseTransform (IPoint p, Point into);
|
||||
|
||||
/** Transforms the supplied vector, writing the result into {@code into}.
|
||||
* @param into a vector into which to store the result, may be the same object as {@code v}.
|
||||
* @return {@code into}, for chaining. */
|
||||
Vector transform (IVector v, Vector into);
|
||||
|
||||
/** Inverse transforms the supplied vector, writing the result into {@code into}.
|
||||
* @param into a vector into which to store the result, may be the same object as {@code v}.
|
||||
* @return {@code into}, for chaining.
|
||||
* @throws NoninvertibleTransformException if the transform is not invertible. */
|
||||
Vector inverseTransform (IVector v, Vector into);
|
||||
|
||||
/** Returns a clone of this transform. */
|
||||
Transform clone ();
|
||||
|
||||
/** Returns an integer that increases monotonically with the generality of the transform
|
||||
* implementation. Used internally when combining transforms. */
|
||||
int generality ();
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* {@link Transform} related utility methods.
|
||||
*/
|
||||
public class Transforms
|
||||
{
|
||||
/**
|
||||
* Creates and returns a new shape that is the supplied shape transformed by this transform's
|
||||
* matrix.
|
||||
*/
|
||||
public static IShape createTransformedShape (Transform t, IShape src) {
|
||||
if (src == null) {
|
||||
return null;
|
||||
}
|
||||
if (src instanceof Path) {
|
||||
return ((Path)src).createTransformedShape(t);
|
||||
}
|
||||
PathIterator path = src.pathIterator(t);
|
||||
Path dst = new Path(path.windingRule());
|
||||
dst.append(path, false);
|
||||
return dst;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the supplied two affine transforms, storing the result in {@code into}. {@code
|
||||
* into} may refer to the same instance as {@code a} or {@code b}.
|
||||
* @return {@code into} for chaining.
|
||||
*/
|
||||
public static AffineTransform multiply (
|
||||
AffineTransform a, AffineTransform b, AffineTransform into) {
|
||||
return multiply(a.m00, a.m01, a.m10, a.m11, a.tx, a.ty,
|
||||
b.m00, b.m01, b.m10, b.m11, b.tx, b.ty, into);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the supplied two affine transforms, storing the result in {@code into}. {@code
|
||||
* into} may refer to the same instance as {@code a}.
|
||||
* @return {@code into} for chaining.
|
||||
*/
|
||||
public static AffineTransform multiply (
|
||||
AffineTransform a, double m00, double m01, double m10, double m11, double tx, double ty,
|
||||
AffineTransform into) {
|
||||
return multiply(a.m00, a.m01, a.m10, a.m11, a.tx, a.ty,
|
||||
m00, m01, m10, m11, tx, ty, into);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the supplied two affine transforms, storing the result in {@code into}. {@code
|
||||
* into} may refer to the same instance as {@code b}.
|
||||
* @return {@code into} for chaining.
|
||||
*/
|
||||
public static AffineTransform multiply (
|
||||
double m00, double m01, double m10, double m11, double tx, double ty,
|
||||
AffineTransform b, AffineTransform into) {
|
||||
return multiply(m00, m01, m10, m11, tx, ty,
|
||||
b.m00, b.m01, b.m10, b.m11, b.tx, b.ty, into);
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies the supplied two affine transforms, storing the result in {@code into}.
|
||||
* @return {@code into} for chaining.
|
||||
*/
|
||||
public static AffineTransform multiply (
|
||||
double am00, double am01, double am10, double am11, double atx, double aty,
|
||||
double bm00, double bm01, double bm10, double bm11, double btx, double bty,
|
||||
AffineTransform into) {
|
||||
into.m00 = am00 * bm00 + am10 * bm01;
|
||||
into.m01 = am01 * bm00 + am11 * bm01;
|
||||
into.m10 = am00 * bm10 + am10 * bm11;
|
||||
into.m11 = am01 * bm10 + am11 * bm11;
|
||||
into.tx = am00 * btx + am10 * bty + atx;
|
||||
into.ty = am01 * btx + am11 * bty + aty;
|
||||
return into;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,225 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* Implements a uniform (translation, rotation, scale) transform.
|
||||
*/
|
||||
public class UniformTransform extends AbstractTransform
|
||||
{
|
||||
/** Identifies the uniform transform in {@link #generality}. */
|
||||
public static final int GENERALITY = 2;
|
||||
|
||||
/** The uniform scale component of this transform. */
|
||||
public double scale;
|
||||
|
||||
/** The rotation component of this transform (in radians). */
|
||||
public double rotation;
|
||||
|
||||
/** The translation components of this transform. */
|
||||
public double tx, ty;
|
||||
|
||||
/** Creates a uniform transform with zero translation and rotation, and unit scale. */
|
||||
public UniformTransform () {
|
||||
setUniformScale(1);
|
||||
}
|
||||
|
||||
/** Creates a uniform transform with the specified translation, rotation and scale. */
|
||||
public UniformTransform (double scale, double rotation, double tx, double ty) {
|
||||
setUniformScale(scale);
|
||||
setRotation(rotation);
|
||||
setTranslation(tx, ty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double uniformScale () {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double scaleX () {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double scaleY () {
|
||||
return scale;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double rotation () {
|
||||
return rotation;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double tx () {
|
||||
return tx;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public double ty () {
|
||||
return ty;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setUniformScale (double scale) {
|
||||
if (scale == 0) throw new IllegalArgumentException("Scale must be non-zero.");
|
||||
this.scale = scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setRotation (double angle) {
|
||||
this.rotation = angle;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTx (double tx) {
|
||||
this.tx = tx;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform setTy (double ty) {
|
||||
this.ty = ty;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform uniformScale (double scale) {
|
||||
if (scale == 0) throw new IllegalArgumentException("Scale must be non-zero.");
|
||||
this.tx *= scale;
|
||||
this.ty *= scale;
|
||||
this.scale *= scale;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform rotate (double angle) {
|
||||
double otx = this.tx, oty = this.ty;
|
||||
if (otx != 0 || oty != 0) {
|
||||
double sina = Math.sin(angle), cosa = Math.cos(angle);
|
||||
this.tx = otx*cosa - oty*sina;
|
||||
this.ty = otx*sina + oty*cosa;
|
||||
}
|
||||
this.rotation += angle;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translateX (double tx) {
|
||||
this.tx += tx;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform translateY (double ty) {
|
||||
this.ty += ty;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform invert () {
|
||||
double nscale = 1f / scale, nrotation = -rotation;
|
||||
Vector t = translation().negateLocal().rotateLocal(nrotation).multLocal(nscale);
|
||||
return new UniformTransform(nscale, nrotation, t.x, t.y);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform concatenate (Transform other) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.preConcatenate(this);
|
||||
}
|
||||
|
||||
Vector nt = other.translation();
|
||||
nt.rotateScaleAndAdd(rotation, scale, translation(), nt);
|
||||
double nrotation = MathUtil.normalizeAngle(rotation + other.rotation());
|
||||
double nscale = scale * other.uniformScale();
|
||||
return new UniformTransform(nscale, nrotation, nt.x, nt.y);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform preConcatenate (Transform other) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.concatenate(this);
|
||||
}
|
||||
|
||||
Vector nt = translation();
|
||||
nt.rotateScaleAndAdd(other.rotation(), other.uniformScale(),
|
||||
other.translation(), nt);
|
||||
double nrotation = MathUtil.normalizeAngle(other.rotation() + rotation);
|
||||
double nscale = other.uniformScale() * scale;
|
||||
return new UniformTransform(nscale, nrotation, nt.x, nt.y);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform lerp (Transform other, double t) {
|
||||
if (generality() < other.generality()) {
|
||||
return other.lerp(this, -t); // TODO: is this correct?
|
||||
}
|
||||
|
||||
Vector nt = translation().lerpLocal(other.translation(), t);
|
||||
double nrotation = MathUtil.lerpa(rotation, other.rotation(), t);
|
||||
double nscale = MathUtil.lerp(scale, other.uniformScale(), t);
|
||||
return new UniformTransform(nscale, nrotation, nt.x, nt.y);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Point transform (IPoint p, Point into) {
|
||||
return Points.transform(p.x(), p.y(), scale, scale, rotation, tx, ty, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public void transform (IPoint[] src, int srcOff, Point[] dst, int dstOff, int count) {
|
||||
double sina = Math.sin(rotation), cosa = Math.cos(rotation);
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
IPoint p = src[srcOff++];
|
||||
Points.transform(p.x(), p.y(), scale, scale, sina, cosa, tx, ty, dst[dstOff++]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public void transform (double[] src, int srcOff, double[] dst, int dstOff, int count) {
|
||||
Point p = new Point();
|
||||
double sina = Math.sin(rotation), cosa = Math.cos(rotation);
|
||||
for (int ii = 0; ii < count; ii++) {
|
||||
Points.transform(src[srcOff++], src[srcOff++], scale, scale, sina, cosa, tx, ty, p);
|
||||
dst[dstOff++] = p.x;
|
||||
dst[dstOff++] = p.y;
|
||||
}
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Point inverseTransform (IPoint p, Point into) {
|
||||
return Points.inverseTransform(p.x(), p.y(), scale, scale, rotation, tx, ty, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Vector transform (IVector v, Vector into) {
|
||||
return Vectors.transform(v.x(), v.y(), scale, scale, rotation, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Vector inverseTransform (IVector v, Vector into) {
|
||||
return Vectors.inverseTransform(v.x(), v.y(), scale, scale, rotation, into);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public Transform clone () {
|
||||
return new UniformTransform(scale, rotation, tx, ty);
|
||||
}
|
||||
|
||||
@Override // from Transform
|
||||
public int generality () {
|
||||
return GENERALITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString () {
|
||||
return "uniform [scale=" + scale + ", rot=" + rotation +
|
||||
", trans=" + translation() + "]";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* Represents a vector in a plane.
|
||||
*/
|
||||
public class Vector extends AbstractVector
|
||||
{
|
||||
/** The x-component of the vector. */
|
||||
public double x;
|
||||
|
||||
/** The y-component of the vector. */
|
||||
public double y;
|
||||
|
||||
/** Creates a vector with the specified x and y components. */
|
||||
public Vector (double x, double y) {
|
||||
set(x, y);
|
||||
}
|
||||
|
||||
/** Creates a vector equal to {@code other}. */
|
||||
public Vector (IVector other) {
|
||||
set(other);
|
||||
}
|
||||
|
||||
/** Creates a vector with zero x and y components. */
|
||||
public Vector () {
|
||||
}
|
||||
|
||||
/** Negates this vector in-place.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector negateLocal () {
|
||||
return negate(this);
|
||||
}
|
||||
|
||||
/** Normalizes this vector in-place.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector normalizeLocal () {
|
||||
return normalize(this);
|
||||
}
|
||||
|
||||
/** Multiplies this vector in-place by a scalar.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector multLocal (double v) {
|
||||
return mult(v, this);
|
||||
}
|
||||
|
||||
/** Multiplies this vector in-place by another.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector multLocal (IVector other) {
|
||||
return mult(other, this);
|
||||
}
|
||||
|
||||
/** Adds a vector in-place to this one.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector addLocal (IVector other) {
|
||||
return add(other, this);
|
||||
}
|
||||
|
||||
/** Subtracts a vector in-place from this one.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector subtractLocal (IVector other) {
|
||||
return subtract(other, this);
|
||||
}
|
||||
|
||||
/** Adds a vector in-place to this one.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector addLocal (double x, double y) {
|
||||
return add(x, y, this);
|
||||
}
|
||||
|
||||
/** Adds a scaled vector in-place to this one.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector addScaledLocal (IVector other, double v) {
|
||||
return addScaled(other, v, this);
|
||||
}
|
||||
|
||||
/** Rotates this vector in-place by the specified angle.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector rotateLocal (double angle) {
|
||||
return rotate(angle, this);
|
||||
}
|
||||
|
||||
/** Linearly interpolates between this and {@code other} in-place by the supplied amount.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector lerpLocal (IVector other, double t) {
|
||||
return lerp(other, t, this);
|
||||
}
|
||||
|
||||
/** Copies the elements of another vector.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector set (IVector other) {
|
||||
return set(other.x(), other.y());
|
||||
}
|
||||
|
||||
/** Copies the elements of an array.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector set (double[] values) {
|
||||
return set(values[0], values[1]);
|
||||
}
|
||||
|
||||
/** Sets all of the elements of the vector.
|
||||
* @return a reference to this vector, for chaining. */
|
||||
public Vector set (double x, double y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override // from AbstractVector
|
||||
public double x () {
|
||||
return x;
|
||||
}
|
||||
|
||||
@Override // from AbstractVector
|
||||
public double y () {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
//
|
||||
// Pythagoras - a collection of geometry classes
|
||||
// http://github.com/samskivert/pythagoras
|
||||
|
||||
package pythagoras.d;
|
||||
|
||||
/**
|
||||
* Vector-related utility methods.
|
||||
*/
|
||||
public class Vectors
|
||||
{
|
||||
/** A unit vector in the X+ direction. */
|
||||
public static final IVector UNIT_X = new Vector(1f, 0f);
|
||||
|
||||
/** A unit vector in the Y+ direction. */
|
||||
public static final IVector UNIT_Y = new Vector(0f, 1f);
|
||||
|
||||
/** The zero vector. */
|
||||
public static final IVector ZERO = new Vector(0f, 0f);
|
||||
|
||||
/** A vector containing the minimum doubleing point value for all components
|
||||
* (note: the components are -{@link Float#MAX_VALUE}, not {@link Float#MIN_VALUE}). */
|
||||
public static final IVector MIN_VALUE = new Vector(-Float.MAX_VALUE, -Float.MAX_VALUE);
|
||||
|
||||
/** A vector containing the maximum doubleing point value for all components. */
|
||||
public static final IVector MAX_VALUE = new Vector(Float.MAX_VALUE, Float.MAX_VALUE);
|
||||
|
||||
/**
|
||||
* Returns the magnitude of the specified vector.
|
||||
*/
|
||||
public static final double length (double x, double y) {
|
||||
return Math.sqrt(lengthSq(x, y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the square of the magnitude of the specified vector.
|
||||
*/
|
||||
public static final double lengthSq (double x, double y) {
|
||||
return (x*x + y*y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a point as specified, storing the result in the point provided.
|
||||
* @return a reference to the result vector, for chaining.
|
||||
*/
|
||||
public static Vector transform (double x, double y, double sx, double sy, double rotation,
|
||||
Vector result) {
|
||||
return transform(x, y, sx, sy, Math.sin(rotation), Math.cos(rotation), result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms a vector as specified, storing the result in the vector provided.
|
||||
* @return a reference to the result vector, for chaining.
|
||||
*/
|
||||
public static Vector transform (double x, double y, double sx, double sy, double sina, double cosa,
|
||||
Vector result) {
|
||||
return result.set((x*cosa - y*sina) * sx, (x*sina + y*cosa) * sy);
|
||||
}
|
||||
|
||||
/**
|
||||
* Inverse transforms a point as specified, storing the result in the point provided.
|
||||
* @return a reference to the result vector, for chaining.
|
||||
*/
|
||||
public static Vector inverseTransform (double x, double y, double sx, double sy, double rotation,
|
||||
Vector result) {
|
||||
double sinnega = Math.sin(-rotation), cosnega = Math.cos(-rotation);
|
||||
double nx = (x * cosnega - y * sinnega); // unrotate
|
||||
double ny = (x * sinnega + y * cosnega);
|
||||
return result.set(nx / sx, ny / sy); // unscale
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string describing the supplied vector, of the form <code>+x+y</code>,
|
||||
* <code>+x-y</code>, <code>-x-y</code>, etc.
|
||||
*/
|
||||
public static String vectorToString (double x, double y) {
|
||||
return MathUtil.toString(x) + MathUtil.toString(y);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user