Numerous bits:

- nixed all transforms except identity and affine; the intermediate transforms
were more trouble than they were worth
- fixed bugs in AffineTransform.translate/scaleX/scaleY/rotate; aiya!
- replaced Transform.clone with Transform.copy; deprecated clone
- rewrote transform test in Scala and using Java AffineTransform as a
reference.
This commit is contained in:
Michael Bayne
2012-07-12 12:25:06 -07:00
parent 6d95f45603
commit 485abe95e6
16 changed files with 255 additions and 1871 deletions
@@ -112,6 +112,11 @@ public abstract class AbstractTransform implements Transform
throw new UnsupportedOperationException();
}
@Deprecated @Override // from Transform
public Transform clone () {
return copy();
}
@Override // from Transform
public abstract Transform clone ();
public abstract Transform copy ();
}
+10 -11
View File
@@ -189,26 +189,25 @@ public class AffineTransform extends AbstractTransform
return scale(scale, scale);
}
@Override // from Transform
public Transform scale (double scaleX, double scaleY) {
return Transforms.multiply(this, scaleX, 0, 0, scaleY, 0, 0, this);
}
@Override // from Transform
public Transform scaleX (double scaleX) {
m00 *= scaleX;
m01 *= scaleX;
tx *= scaleX;
return this;
return Transforms.multiply(this, scaleX, 0, 0, 1, 0, 0, this);
}
@Override // from Transform
public Transform scaleY (double scaleY) {
m10 *= scaleY;
m11 *= scaleY;
ty *= scaleY;
return this;
return Transforms.multiply(this, 1, 0, 0, scaleY, 0, 0, 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);
return Transforms.multiply(this, cosa, sina, -sina, cosa, 0, 0, this);
}
@Override // from Transform
@@ -342,7 +341,7 @@ public class AffineTransform extends AbstractTransform
}
@Override // from Transform
public Transform clone () {
public Transform copy () {
return new AffineTransform(m00, m01, m10, m11, tx, ty);
}
@@ -358,7 +357,7 @@ public class AffineTransform extends AbstractTransform
}
// 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()
// create a new AffineTransform from another AffineTransform using this instead of copy()
protected AffineTransform (Transform other) {
this(other.scaleX(), other.scaleY(), other.rotation(),
other.tx(), other.ty());
@@ -109,7 +109,7 @@ public class IdentityTransform extends AbstractTransform
}
@Override // from Transform
public Transform clone () {
public Transform copy () {
return this;
}
@@ -1,272 +0,0 @@
//
// 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 void get (double[] matrix) {
double sina = Math.sin(rotation), cosa = Math.cos(rotation);
matrix[0] = cosa * scaleX; matrix[1] = sina * scaleY;
matrix[2] = -sina * scaleX; matrix[3] = cosa * scaleY;
matrix[4] = tx; matrix[5] = 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).scaleLocal(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 transformPoint (IVector v, Vector into) {
return Vectors.transform(v.x(), v.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() + "]";
}
}
@@ -1,209 +0,0 @@
//
// 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 void get (double[] matrix) {
double sina = Math.sin(rotation), cosa = Math.cos(rotation);
matrix[0] = cosa; matrix[1] = sina;
matrix[2] = -sina; matrix[3] = cosa;
matrix[4] = tx; matrix[5] = 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 transformPoint (IVector v, Vector into) {
return Vectors.transform(v.x(), v.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() + "]";
}
}
+5 -2
View File
@@ -197,8 +197,11 @@ public interface Transform
* @throws NoninvertibleTransformException if the transform is not invertible. */
Vector inverseTransform (IVector v, Vector into);
/** Returns a clone of this transform. */
Transform clone ();
/** @deprecated Use {@link #copy}. */
@Deprecated Transform clone ();
/** Returns a copy of this transform. */
Transform copy ();
/** Returns an integer that increases monotonically with the generality of the transform
* implementation. Used internally when combining transforms. */
@@ -1,238 +0,0 @@
//
// 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 void get (double[] matrix) {
double sina = Math.sin(rotation), cosa = Math.cos(rotation);
matrix[0] = cosa * scale; matrix[1] = sina * scale;
matrix[2] = -sina * scale; matrix[3] = cosa * scale;
matrix[4] = tx; matrix[5] = 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).scaleLocal(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 transformPoint (IVector p, Vector into) {
return Vectors.transform(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() + "]";
}
}
@@ -112,6 +112,11 @@ public abstract class AbstractTransform implements Transform
throw new UnsupportedOperationException();
}
@Deprecated @Override // from Transform
public Transform clone () {
return copy();
}
@Override // from Transform
public abstract Transform clone ();
public abstract Transform copy ();
}
+10 -11
View File
@@ -189,26 +189,25 @@ public class AffineTransform extends AbstractTransform
return scale(scale, scale);
}
@Override // from Transform
public Transform scale (float scaleX, float scaleY) {
return Transforms.multiply(this, scaleX, 0, 0, scaleY, 0, 0, this);
}
@Override // from Transform
public Transform scaleX (float scaleX) {
m00 *= scaleX;
m01 *= scaleX;
tx *= scaleX;
return this;
return Transforms.multiply(this, scaleX, 0, 0, 1, 0, 0, this);
}
@Override // from Transform
public Transform scaleY (float scaleY) {
m10 *= scaleY;
m11 *= scaleY;
ty *= scaleY;
return this;
return Transforms.multiply(this, 1, 0, 0, scaleY, 0, 0, this);
}
@Override // from Transform
public Transform rotate (float angle) {
float sina = FloatMath.sin(angle), cosa = FloatMath.cos(angle);
return Transforms.multiply(cosa, sina, -sina, cosa, 0, 0, this, this);
return Transforms.multiply(this, cosa, sina, -sina, cosa, 0, 0, this);
}
@Override // from Transform
@@ -342,7 +341,7 @@ public class AffineTransform extends AbstractTransform
}
@Override // from Transform
public Transform clone () {
public Transform copy () {
return new AffineTransform(m00, m01, m10, m11, tx, ty);
}
@@ -358,7 +357,7 @@ public class AffineTransform extends AbstractTransform
}
// 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()
// create a new AffineTransform from another AffineTransform using this instead of copy()
protected AffineTransform (Transform other) {
this(other.scaleX(), other.scaleY(), other.rotation(),
other.tx(), other.ty());
@@ -109,7 +109,7 @@ public class IdentityTransform extends AbstractTransform
}
@Override // from Transform
public Transform clone () {
public Transform copy () {
return this;
}
@@ -1,272 +0,0 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* 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 float scaleX, scaleY;
/** The rotation component of this transform (in radians). */
public float rotation;
/** The translation components of this transform. */
public float 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 (float scaleX, float scaleY, float rotation, float tx, float ty) {
setScale(scaleX, scaleY);
setRotation(rotation);
setTranslation(tx, ty);
}
@Override // from Transform
public float uniformScale () {
return (scaleX + scaleY) / 2; // TODO: is this sane
}
@Override // from Transform
public float scaleX () {
return scaleX;
}
@Override // from Transform
public float scaleY () {
return scaleY;
}
@Override // from Transform
public float rotation () {
return rotation;
}
@Override // from Transform
public float tx () {
return tx;
}
@Override // from Transform
public float ty () {
return ty;
}
@Override // from Transform
public void get (float[] matrix) {
float sina = FloatMath.sin(rotation), cosa = FloatMath.cos(rotation);
matrix[0] = cosa * scaleX; matrix[1] = sina * scaleY;
matrix[2] = -sina * scaleX; matrix[3] = cosa * scaleY;
matrix[4] = tx; matrix[5] = ty;
}
@Override // from Transform
public Transform setUniformScale (float scale) {
setScaleX(scale);
setScaleY(scale);
return this;
}
@Override // from Transform
public Transform setScaleX (float scaleX) {
if (scaleX == 0) throw new IllegalArgumentException("Scale (x) must not be zero.");
this.scaleX = scaleX;
return this;
}
@Override // from Transform
public Transform setScaleY (float scaleY) {
if (scaleY == 0) throw new IllegalArgumentException("Scale (y) must not be zero.");
this.scaleY = scaleY;
return this;
}
@Override // from Transform
public Transform setRotation (float angle) {
this.rotation = angle;
return this;
}
@Override // from Transform
public Transform setTx (float tx) {
this.tx = tx;
return this;
}
@Override // from Transform
public Transform setTy (float ty) {
this.ty = ty;
return this;
}
@Override // from Transform
public Transform uniformScale (float scale) {
return scale(scale, scale);
}
@Override // from Transform
public Transform scaleX (float 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 (float 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 (float angle) {
float otx = this.tx, oty = this.ty;
if (otx != 0 || oty != 0) {
float sina = FloatMath.sin(angle), cosa = FloatMath.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 (float tx) {
this.tx += tx;
return this;
}
@Override // from Transform
public Transform translateY (float 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).scaleLocal(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);
}
float otx = other.tx(), oty = other.ty();
float sina = FloatMath.sin(rotation), cosa = FloatMath.cos(rotation);
float ntx = (otx*cosa - oty*sina) * scaleX + tx();
float nty = (otx*sina + oty*cosa) * scaleY + ty();
float nrotation = MathUtil.normalizeAngle(rotation + other.rotation());
float nscaleX = scaleX * other.scaleX();
float 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);
}
float tx = tx(), ty = ty();
float sina = FloatMath.sin(other.rotation()), cosa = FloatMath.cos(other.rotation());
float ntx = (tx*cosa - ty*sina) * other.scaleX() + other.tx();
float nty = (tx*sina + ty*cosa) * other.scaleY() + other.ty();
float nrotation = MathUtil.normalizeAngle(other.rotation() + rotation);
float nscaleX = other.scaleX() * scaleX;
float nscaleY = other.scaleY() * scaleY;
return new NonUniformTransform(nscaleX, nscaleY, nrotation, ntx, nty);
}
@Override // from Transform
public Transform lerp (Transform other, float t) {
if (generality() < other.generality()) {
return other.lerp(this, -t); // TODO: is this correct?
}
float ntx = MathUtil.lerpa(tx, other.tx(), t);
float nty = MathUtil.lerpa(ty, other.ty(), t);
float nrotation = MathUtil.lerpa(rotation, other.rotation(), t);
float nscaleX = MathUtil.lerp(scaleX, other.scaleX(), t);
float 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) {
float sina = FloatMath.sin(rotation), cosa = FloatMath.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 (float[] src, int srcOff, float[] dst, int dstOff, int count) {
Point p = new Point();
float sina = FloatMath.sin(rotation), cosa = FloatMath.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 transformPoint (IVector v, Vector into) {
return Vectors.transform(v.x(), v.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() + "]";
}
}
@@ -1,209 +0,0 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* 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 float rotation;
/** The translation components of this transform. */
public float 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 (float rotation, float tx, float ty) {
setRotation(rotation);
setTranslation(tx, ty);
}
@Override // from Transform
public float uniformScale () {
return 1;
}
@Override // from Transform
public float scaleX () {
return 1;
}
@Override // from Transform
public float scaleY () {
return 1;
}
@Override // from Transform
public float rotation () {
return rotation;
}
@Override // from Transform
public float tx () {
return tx;
}
@Override // from Transform
public float ty () {
return ty;
}
@Override // from Transform
public void get (float[] matrix) {
float sina = FloatMath.sin(rotation), cosa = FloatMath.cos(rotation);
matrix[0] = cosa; matrix[1] = sina;
matrix[2] = -sina; matrix[3] = cosa;
matrix[4] = tx; matrix[5] = ty;
}
@Override // from Transform
public Transform setRotation (float angle) {
this.rotation = angle;
return this;
}
@Override // from Transform
public Transform setTx (float tx) {
this.tx = tx;
return this;
}
@Override // from Transform
public Transform setTy (float ty) {
this.ty = ty;
return this;
}
@Override // from Transform
public Transform rotate (float angle) {
float otx = this.tx, oty = this.ty;
if (otx != 0 || oty != 0) {
float sina = FloatMath.sin(angle), cosa = FloatMath.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 (float tx) {
this.tx += tx;
return this;
}
@Override // from Transform
public Transform translateY (float 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);
float 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);
float nrotation = MathUtil.normalizeAngle(other.rotation() + rotation);
return new RigidTransform(nrotation, nt.x, nt.y);
}
@Override // from Transform
public Transform lerp (Transform other, float 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) {
float sina = FloatMath.sin(rotation), cosa = FloatMath.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 (float[] src, int srcOff, float[] dst, int dstOff, int count) {
Point p = new Point();
float sina = FloatMath.sin(rotation), cosa = FloatMath.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 transformPoint (IVector v, Vector into) {
return Vectors.transform(v.x(), v.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() + "]";
}
}
+5 -2
View File
@@ -197,8 +197,11 @@ public interface Transform
* @throws NoninvertibleTransformException if the transform is not invertible. */
Vector inverseTransform (IVector v, Vector into);
/** Returns a clone of this transform. */
Transform clone ();
/** @deprecated Use {@link #copy}. */
@Deprecated Transform clone ();
/** Returns a copy of this transform. */
Transform copy ();
/** Returns an integer that increases monotonically with the generality of the transform
* implementation. Used internally when combining transforms. */
@@ -1,238 +0,0 @@
//
// Pythagoras - a collection of geometry classes
// http://github.com/samskivert/pythagoras
package pythagoras.f;
/**
* 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 float scale;
/** The rotation component of this transform (in radians). */
public float rotation;
/** The translation components of this transform. */
public float 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 (float scale, float rotation, float tx, float ty) {
setUniformScale(scale);
setRotation(rotation);
setTranslation(tx, ty);
}
@Override // from Transform
public float uniformScale () {
return scale;
}
@Override // from Transform
public float scaleX () {
return scale;
}
@Override // from Transform
public float scaleY () {
return scale;
}
@Override // from Transform
public float rotation () {
return rotation;
}
@Override // from Transform
public float tx () {
return tx;
}
@Override // from Transform
public float ty () {
return ty;
}
@Override // from Transform
public void get (float[] matrix) {
float sina = FloatMath.sin(rotation), cosa = FloatMath.cos(rotation);
matrix[0] = cosa * scale; matrix[1] = sina * scale;
matrix[2] = -sina * scale; matrix[3] = cosa * scale;
matrix[4] = tx; matrix[5] = ty;
}
@Override // from Transform
public Transform setUniformScale (float scale) {
if (scale == 0) throw new IllegalArgumentException("Scale must be non-zero.");
this.scale = scale;
return this;
}
@Override // from Transform
public Transform setRotation (float angle) {
this.rotation = angle;
return this;
}
@Override // from Transform
public Transform setTx (float tx) {
this.tx = tx;
return this;
}
@Override // from Transform
public Transform setTy (float ty) {
this.ty = ty;
return this;
}
@Override // from Transform
public Transform uniformScale (float 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 (float angle) {
float otx = this.tx, oty = this.ty;
if (otx != 0 || oty != 0) {
float sina = FloatMath.sin(angle), cosa = FloatMath.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 (float tx) {
this.tx += tx;
return this;
}
@Override // from Transform
public Transform translateY (float ty) {
this.ty += ty;
return this;
}
@Override // from Transform
public Transform invert () {
float nscale = 1f / scale, nrotation = -rotation;
Vector t = translation().negateLocal().rotateLocal(nrotation).scaleLocal(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);
float nrotation = MathUtil.normalizeAngle(rotation + other.rotation());
float 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);
float nrotation = MathUtil.normalizeAngle(other.rotation() + rotation);
float nscale = other.uniformScale() * scale;
return new UniformTransform(nscale, nrotation, nt.x, nt.y);
}
@Override // from Transform
public Transform lerp (Transform other, float t) {
if (generality() < other.generality()) {
return other.lerp(this, -t); // TODO: is this correct?
}
Vector nt = translation().lerpLocal(other.translation(), t);
float nrotation = MathUtil.lerpa(rotation, other.rotation(), t);
float 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) {
float sina = FloatMath.sin(rotation), cosa = FloatMath.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 (float[] src, int srcOff, float[] dst, int dstOff, int count) {
Point p = new Point();
float sina = FloatMath.sin(rotation), cosa = FloatMath.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 transformPoint (IVector p, Vector into) {
return Vectors.transform(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() + "]";
}
}