Converted the float bits to double since they've substantially evolved.

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