diff --git a/src/main/java/pythagoras/d/AbstractArc.java b/src/main/java/pythagoras/d/AbstractArc.java index e1b1583..509414e 100644 --- a/src/main/java/pythagoras/d/AbstractArc.java +++ b/src/main/java/pythagoras/d/AbstractArc.java @@ -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; } diff --git a/src/main/java/pythagoras/d/AbstractCubicCurve.java b/src/main/java/pythagoras/d/AbstractCubicCurve.java index ab9ff64..34fe234 100644 --- a/src/main/java/pythagoras/d/AbstractCubicCurve.java +++ b/src/main/java/pythagoras/d/AbstractCubicCurve.java @@ -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) { diff --git a/src/main/java/pythagoras/d/AbstractDimension.java b/src/main/java/pythagoras/d/AbstractDimension.java index 3c12e43..d025361 100644 --- a/src/main/java/pythagoras/d/AbstractDimension.java +++ b/src/main/java/pythagoras/d/AbstractDimension.java @@ -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()); } } diff --git a/src/main/java/pythagoras/d/AbstractEllipse.java b/src/main/java/pythagoras/d/AbstractEllipse.java index bb3cb93..f0fa587 100644 --- a/src/main/java/pythagoras/d/AbstractEllipse.java +++ b/src/main/java/pythagoras/d/AbstractEllipse.java @@ -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; } diff --git a/src/main/java/pythagoras/d/AbstractLine.java b/src/main/java/pythagoras/d/AbstractLine.java index 1bb50db..038ef05 100644 --- a/src/main/java/pythagoras/d/AbstractLine.java +++ b/src/main/java/pythagoras/d/AbstractLine.java @@ -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; } diff --git a/src/main/java/pythagoras/d/AbstractPoint.java b/src/main/java/pythagoras/d/AbstractPoint.java index 116be02..0a96f42 100644 --- a/src/main/java/pythagoras/d/AbstractPoint.java +++ b/src/main/java/pythagoras/d/AbstractPoint.java @@ -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()); } } diff --git a/src/main/java/pythagoras/d/AbstractQuadCurve.java b/src/main/java/pythagoras/d/AbstractQuadCurve.java index 0769d84..816220c 100644 --- a/src/main/java/pythagoras/d/AbstractQuadCurve.java +++ b/src/main/java/pythagoras/d/AbstractQuadCurve.java @@ -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) { diff --git a/src/main/java/pythagoras/d/AbstractRectangle.java b/src/main/java/pythagoras/d/AbstractRectangle.java index de38ec9..1467650 100644 --- a/src/main/java/pythagoras/d/AbstractRectangle.java +++ b/src/main/java/pythagoras/d/AbstractRectangle.java @@ -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; } diff --git a/src/main/java/pythagoras/d/AbstractRoundRectangle.java b/src/main/java/pythagoras/d/AbstractRoundRectangle.java index 9bcb48c..05f7ba9 100644 --- a/src/main/java/pythagoras/d/AbstractRoundRectangle.java +++ b/src/main/java/pythagoras/d/AbstractRoundRectangle.java @@ -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; } diff --git a/src/main/java/pythagoras/d/AbstractTransform.java b/src/main/java/pythagoras/d/AbstractTransform.java new file mode 100644 index 0000000..fdb09e1 --- /dev/null +++ b/src/main/java/pythagoras/d/AbstractTransform.java @@ -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 (); +} diff --git a/src/main/java/pythagoras/d/AbstractVector.java b/src/main/java/pythagoras/d/AbstractVector.java new file mode 100644 index 0000000..2671081 --- /dev/null +++ b/src/main/java/pythagoras/d/AbstractVector.java @@ -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()); + } +} diff --git a/src/main/java/pythagoras/d/AffineTransform.java b/src/main/java/pythagoras/d/AffineTransform.java index 4b2a25d..04d966f 100644 --- a/src/main/java/pythagoras/d/AffineTransform.java +++ b/src/main/java/pythagoras/d/AffineTransform.java @@ -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: + *
{@code
+ * [ m00, m10, tx ]
+ * [ m01, m11, ty ]
+ * [ 0, 0, 1 ]
+ * }
*/
-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 determinant 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;
}
diff --git a/src/main/java/pythagoras/d/Arc.java b/src/main/java/pythagoras/d/Arc.java
index 1c55adf..115bbda 100644
--- a/src/main/java/pythagoras/d/Arc.java
+++ b/src/main/java/pythagoras/d/Arc.java
@@ -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;
diff --git a/src/main/java/pythagoras/d/Area.java b/src/main/java/pythagoras/d/Area.java
index 3ad915a..b1983d1 100644
--- a/src/main/java/pythagoras/d/Area.java
+++ b/src/main/java/pythagoras/d/Area.java
@@ -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;
}
diff --git a/src/main/java/pythagoras/d/Crossing.java b/src/main/java/pythagoras/d/Crossing.java
index f0d401a..08cf4d8 100644
--- a/src/main/java/pythagoras/d/Crossing.java
+++ b/src/main/java/pythagoras/d/Crossing.java
@@ -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);
}
/**
diff --git a/src/main/java/pythagoras/d/CrossingHelper.java b/src/main/java/pythagoras/d/CrossingHelper.java
index 25f9298..0c07c83 100644
--- a/src/main/java/pythagoras/d/CrossingHelper.java
+++ b/src/main/java/pythagoras/d/CrossingHelper.java
@@ -177,8 +177,8 @@ class CrossingHelper
IntersectPoint ip;
for (Iterator+x+y,
* +x-y, -x-y, 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);
}
}
diff --git a/src/main/java/pythagoras/d/QuadCurve.java b/src/main/java/pythagoras/d/QuadCurve.java
index f6e456d..bad9ed9 100644
--- a/src/main/java/pythagoras/d/QuadCurve.java
+++ b/src/main/java/pythagoras/d/QuadCurve.java
@@ -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;
}
}
diff --git a/src/main/java/pythagoras/d/QuadCurves.java b/src/main/java/pythagoras/d/QuadCurves.java
index 57b0a53..90c4d31 100644
--- a/src/main/java/pythagoras/d/QuadCurves.java
+++ b/src/main/java/pythagoras/d/QuadCurves.java
@@ -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;
diff --git a/src/main/java/pythagoras/d/Rectangle.java b/src/main/java/pythagoras/d/Rectangle.java
index 873ed19..fca1adf 100644
--- a/src/main/java/pythagoras/d/Rectangle.java
+++ b/src/main/java/pythagoras/d/Rectangle.java
@@ -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;
}
diff --git a/src/main/java/pythagoras/d/Rectangles.java b/src/main/java/pythagoras/d/Rectangles.java
index cc33c64..043770e 100644
--- a/src/main/java/pythagoras/d/Rectangles.java
+++ b/src/main/java/pythagoras/d/Rectangles.java
@@ -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);
}
}
diff --git a/src/main/java/pythagoras/d/RectangularShape.java b/src/main/java/pythagoras/d/RectangularShape.java
index 3e2951e..91e382c 100644
--- a/src/main/java/pythagoras/d/RectangularShape.java
+++ b/src/main/java/pythagoras/d/RectangularShape.java
@@ -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);
}
}
diff --git a/src/main/java/pythagoras/d/RigidTransform.java b/src/main/java/pythagoras/d/RigidTransform.java
new file mode 100644
index 0000000..e05b6da
--- /dev/null
+++ b/src/main/java/pythagoras/d/RigidTransform.java
@@ -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() + "]";
+ }
+}
diff --git a/src/main/java/pythagoras/d/RoundRectangle.java b/src/main/java/pythagoras/d/RoundRectangle.java
index fbdb2a5..c87db15 100644
--- a/src/main/java/pythagoras/d/RoundRectangle.java
+++ b/src/main/java/pythagoras/d/RoundRectangle.java
@@ -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;
}
diff --git a/src/main/java/pythagoras/d/Transform.java b/src/main/java/pythagoras/d/Transform.java
new file mode 100644
index 0000000..2e642d6
--- /dev/null
+++ b/src/main/java/pythagoras/d/Transform.java
@@ -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 ();
+}
diff --git a/src/main/java/pythagoras/d/Transforms.java b/src/main/java/pythagoras/d/Transforms.java
new file mode 100644
index 0000000..82649a9
--- /dev/null
+++ b/src/main/java/pythagoras/d/Transforms.java
@@ -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;
+ }
+}
diff --git a/src/main/java/pythagoras/d/UniformTransform.java b/src/main/java/pythagoras/d/UniformTransform.java
new file mode 100644
index 0000000..e6e5326
--- /dev/null
+++ b/src/main/java/pythagoras/d/UniformTransform.java
@@ -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() + "]";
+ }
+}
diff --git a/src/main/java/pythagoras/d/Vector.java b/src/main/java/pythagoras/d/Vector.java
new file mode 100644
index 0000000..a7bafe9
--- /dev/null
+++ b/src/main/java/pythagoras/d/Vector.java
@@ -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;
+ }
+}
diff --git a/src/main/java/pythagoras/d/Vectors.java b/src/main/java/pythagoras/d/Vectors.java
new file mode 100644
index 0000000..dcc661e
--- /dev/null
+++ b/src/main/java/pythagoras/d/Vectors.java
@@ -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 +x+y,
+ * +x-y, -x-y, etc.
+ */
+ public static String vectorToString (double x, double y) {
+ return MathUtil.toString(x) + MathUtil.toString(y);
+ }
+}