Documented AffineTransform.

This commit is contained in:
Michael Bayne
2011-07-01 16:33:13 -07:00
parent 9d431ee9fd
commit fd11be72ee
2 changed files with 382 additions and 32 deletions
+192 -17
View File
@@ -28,19 +28,33 @@ public class AffineTransform implements Cloneable, Serializable
public static final int TYPE_MASK_SCALE = TYPE_UNIFORM_SCALE | TYPE_GENERAL_SCALE; 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; public static final int TYPE_MASK_ROTATION = TYPE_QUADRANT_ROTATION | TYPE_GENERAL_ROTATION;
/**
* Constructs an identity transform.
*/
public AffineTransform () { public AffineTransform () {
setToIdentity(); setToIdentity();
} }
/**
* Constructs a transform that is a copy of the supplied transform.
*/
public AffineTransform (AffineTransform t) { public AffineTransform (AffineTransform t) {
setTransform(t); setTransform(t);
} }
public AffineTransform (double m00, double m10, double m01, /**
double m11, double m02, double m12) { * 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); setTransform(m00, m10, m01, m11, m02, m12);
} }
/**
* 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) { public AffineTransform (double[] matrix) {
this.type = TYPE_UNKNOWN; this.type = TYPE_UNKNOWN;
m00 = matrix[0]; m00 = matrix[0];
@@ -53,21 +67,9 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/* /**
* Method returns type of affine transformation. * Returns the type of this affine transform, which is a bitwise-or of the type flags
* * ({@link #TYPE_TRANSLATION}, etc.).
* Transform matrix is m00 m01 m02 m10 m11 m12
*
* According analytic geometry new basis vectors are (m00, m01) and (m10,
* m11), translation vector is (m02, m12). Original basis vectors are (1, 0)
* and (0, 1). Type transformations classification: TYPE_IDENTITY - new
* basis equals original one and zero translation TYPE_TRANSLATION -
* translation vector isn't zero TYPE_UNIFORM_SCALE - vectors length of new
* basis equals TYPE_GENERAL_SCALE - vectors length of new basis doesn't
* equal TYPE_FLIP - new basis vector orientation differ from original one
* TYPE_QUADRANT_ROTATION - new basis is rotated by 90, 180, 270, or 360
* degrees TYPE_GENERAL_ROTATION - new basis is rotated by arbitrary angle
* TYPE_GENERAL_TRANSFORM - transformation can't be inversed
*/ */
public int getType () { public int getType () {
if (type != TYPE_UNKNOWN) { if (type != TYPE_UNKNOWN) {
@@ -109,34 +111,60 @@ public class AffineTransform implements Cloneable, Serializable
return type; return type;
} }
/**
* Returns the x-component of the scale vector.
*/
public double getScaleX () { public double getScaleX () {
return m00; return m00;
} }
/**
* Returns the y-component of the scale vector.
*/
public double getScaleY () { public double getScaleY () {
return m11; return m11;
} }
/**
* Returns the x-component of the shear vector.
*/
public double getShearX () { public double getShearX () {
return m01; return m01;
} }
/**
* Returns the y-component of the shear vector.
*/
public double getShearY () { public double getShearY () {
return m10; return m10;
} }
/**
* Returns the x-component of the translation vector.
*/
public double getTranslateX () { public double getTranslateX () {
return m02; return m02;
} }
/**
* Returns the y-component of the translation vector.
*/
public double getTranslateY () { public double getTranslateY () {
return m12; return m12;
} }
/**
* Returns true if this transform is the identity.
*/
public boolean isIdentity () { public boolean isIdentity () {
return getType() == TYPE_IDENTITY; 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) { public void getMatrix (double[] matrix) {
matrix[0] = m00; matrix[0] = m00;
matrix[1] = m10; matrix[1] = m10;
@@ -148,10 +176,17 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* Returns the <a href="http://en.wikipedia.org/wiki/Determinant">determinant</a> of this
* matrix.
*/
public double getDeterminant () { public double getDeterminant () {
return m00 * m11 - m01 * m10; return m00 * m11 - m01 * m10;
} }
/**
* Sets this transform's values.
*/
public void setTransform (double m00, double m10, double m01, double m11, public void setTransform (double m00, double m10, double m01, double m11,
double m02, double m12) { double m02, double m12) {
this.type = TYPE_UNKNOWN; this.type = TYPE_UNKNOWN;
@@ -163,17 +198,28 @@ public class AffineTransform implements Cloneable, Serializable
this.m12 = m12; this.m12 = m12;
} }
/**
* Sets this transform's values to be equal to those of the supplied transform.
*/
public void setTransform (AffineTransform t) { public void setTransform (AffineTransform t) {
setTransform(t.m00, t.m10, t.m01, t.m11, t.m02, t.m12); setTransform(t.m00, t.m10, t.m01, t.m11, t.m02, t.m12);
type = t.type; type = t.type;
} }
/**
* Sets this transform to the identity transform. Any existing transform values are
* overwritten.
*/
public void setToIdentity () { public void setToIdentity () {
type = TYPE_IDENTITY; type = TYPE_IDENTITY;
m00 = m11 = 1f; m00 = m11 = 1f;
m10 = m01 = m02 = m12 = 0; 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) { public void setToTranslation (double tx, double ty) {
m00 = m11 = 1f; m00 = m11 = 1f;
m01 = m10 = 0; m01 = m10 = 0;
@@ -186,6 +232,10 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* Sets this transform to a simple scale using the supplied values. Any existing transform
* values are overwritten.
*/
public void setToScale (double scx, double scy) { public void setToScale (double scx, double scy) {
m00 = scx; m00 = scx;
m11 = scy; m11 = scy;
@@ -197,6 +247,10 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* Sets this transform to a simple shear using the supplied values. Any existing transform
* values are overwritten.
*/
public void setToShear (double shx, double shy) { public void setToShear (double shx, double shy) {
m00 = m11 = 1f; m00 = m11 = 1f;
m02 = m12 = 0; m02 = m12 = 0;
@@ -209,6 +263,10 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* Sets this transform to a simple rotation using the supplied values. Any existing transform
* values are overwritten.
*/
public void setToRotation (double angle) { public void setToRotation (double angle) {
double sin = Math.sin(angle); double sin = Math.sin(angle);
double cos = Math.cos(angle); double cos = Math.cos(angle);
@@ -226,6 +284,10 @@ public class AffineTransform implements Cloneable, Serializable
type = TYPE_UNKNOWN; type = TYPE_UNKNOWN;
} }
/**
* Sets this transform to a simple rotation using the supplied values. Any existing transform
* values are overwritten.
*/
public void setToRotation (double angle, double px, double py) { public void setToRotation (double angle, double px, double py) {
setToRotation(angle); setToRotation(angle);
m02 = px * (1f - m00) + py * m10; m02 = px * (1f - m00) + py * m10;
@@ -233,64 +295,106 @@ public class AffineTransform implements Cloneable, Serializable
type = TYPE_UNKNOWN; type = TYPE_UNKNOWN;
} }
/**
* Returns a transform that performs the specified translation.
*/
public static AffineTransform getTranslateInstance (double tx, double ty) { public static AffineTransform getTranslateInstance (double tx, double ty) {
AffineTransform t = new AffineTransform(); AffineTransform t = new AffineTransform();
t.setToTranslation(tx, ty); t.setToTranslation(tx, ty);
return t; return t;
} }
/**
* Returns a transform that performs the specified scale.
*/
public static AffineTransform getScaleInstance (double scx, double scY) { public static AffineTransform getScaleInstance (double scx, double scY) {
AffineTransform t = new AffineTransform(); AffineTransform t = new AffineTransform();
t.setToScale(scx, scY); t.setToScale(scx, scY);
return t; return t;
} }
/**
* Returns a transform that performs the specified shear.
*/
public static AffineTransform getShearInstance (double shx, double shy) { public static AffineTransform getShearInstance (double shx, double shy) {
AffineTransform m = new AffineTransform(); AffineTransform m = new AffineTransform();
m.setToShear(shx, shy); m.setToShear(shx, shy);
return m; return m;
} }
/**
* Returns a transform that performs the specified rotation.
*/
public static AffineTransform getRotateInstance (double angle) { public static AffineTransform getRotateInstance (double angle) {
AffineTransform t = new AffineTransform(); AffineTransform t = new AffineTransform();
t.setToRotation(angle); t.setToRotation(angle);
return t; return t;
} }
/**
* Returns a transform that performs the specified rotation.
*/
public static AffineTransform getRotateInstance (double angle, double x, double y) { public static AffineTransform getRotateInstance (double angle, double x, double y) {
AffineTransform t = new AffineTransform(); AffineTransform t = new AffineTransform();
t.setToRotation(angle, x, y); t.setToRotation(angle, x, y);
return t; return t;
} }
/**
* Concatenates the specified translation to this transform.
*/
public void translate (double tx, double ty) { public void translate (double tx, double ty) {
concatenate(getTranslateInstance(tx, ty)); concatenate(getTranslateInstance(tx, ty));
} }
/**
* Concatenates the specified scale to this transform.
*/
public void scale (double scx, double scy) { public void scale (double scx, double scy) {
concatenate(getScaleInstance(scx, scy)); concatenate(getScaleInstance(scx, scy));
} }
/**
* Concatenates the specified shear to this transform.
*/
public void shear (double shx, double shy) { public void shear (double shx, double shy) {
concatenate(getShearInstance(shx, shy)); concatenate(getShearInstance(shx, shy));
} }
/**
* Concatenates the specified rotation to this transform.
*/
public void rotate (double angle) { public void rotate (double angle) {
concatenate(getRotateInstance(angle)); concatenate(getRotateInstance(angle));
} }
/**
* Concatenates the specified rotation to this transform.
*/
public void rotate (double angle, double px, double py) { public void rotate (double angle, double px, double py) {
concatenate(getRotateInstance(angle, px, py)); concatenate(getRotateInstance(angle, px, py));
} }
/**
* Concatenates the specified transform to this transform.
*/
public void concatenate (AffineTransform t) { public void concatenate (AffineTransform t) {
multiply(t, this, this); multiply(t, this, this);
} }
/**
* Pre-concatenates the specified transform to this transform.
*/
public void preConcatenate (AffineTransform t) { public void preConcatenate (AffineTransform t) {
multiply(this, t, this); 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) public AffineTransform createInverse (AffineTransform target)
throws NoninvertibleTransformException { throws NoninvertibleTransformException {
double det = getDeterminant(); double det = getDeterminant();
@@ -306,10 +410,24 @@ public class AffineTransform implements Cloneable, Serializable
return target; 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 { public AffineTransform createInverse () throws NoninvertibleTransformException {
return createInverse(new AffineTransform()); 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) { public Point transform (IPoint src, Point dst) {
if (dst == null) { if (dst == null) {
dst = new Point(); dst = new Point();
@@ -320,6 +438,15 @@ public class AffineTransform implements Cloneable, Serializable
return dst; 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) { public void transform (IPoint[] src, int srcOff, Point[] dst, int dstOff, int length) {
while (--length >= 0) { while (--length >= 0) {
IPoint srcPoint = src[srcOff++]; IPoint srcPoint = src[srcOff++];
@@ -334,6 +461,15 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* 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) { public void transform (double[] src, int srcOff, double[] dst, int dstOff, int length) {
int step = 2; int step = 2;
if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) { if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) {
@@ -351,6 +487,14 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* 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) { public Point deltaTransform (IPoint src, Point dst) {
if (dst == null) { if (dst == null) {
dst = new Point(); dst = new Point();
@@ -360,6 +504,16 @@ public class AffineTransform implements Cloneable, Serializable
return dst; return dst;
} }
/**
* 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) { public void deltaTransform (double[] src, int srcOff, double[] dst, int dstOff, int length) {
while (--length >= 0) { while (--length >= 0) {
double x = src[srcOff++], y = src[srcOff++]; double x = src[srcOff++], y = src[srcOff++];
@@ -368,6 +522,14 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* 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 { public Point inverseTransform (IPoint src, Point dst) throws NoninvertibleTransformException {
double det = getDeterminant(); double det = getDeterminant();
if (Math.abs(det) < ZERO) { if (Math.abs(det) < ZERO) {
@@ -381,6 +543,15 @@ public class AffineTransform implements Cloneable, Serializable
return dst; return dst;
} }
/**
* 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) public void inverseTransform (double[] src, int srcOff, double[] dst, int dstOff, int length)
throws NoninvertibleTransformException { throws NoninvertibleTransformException {
double det = getDeterminant(); double det = getDeterminant();
@@ -394,6 +565,10 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* Creates and returns a new shape that is the supplied shape transformed by this transform's
* matrix.
*/
public IShape createTransformedShape (IShape src) { public IShape createTransformedShape (IShape src) {
if (src == null) { if (src == null) {
return null; return null;
+190 -15
View File
@@ -28,18 +28,32 @@ public class AffineTransform implements Cloneable, Serializable
public static final int TYPE_MASK_SCALE = TYPE_UNIFORM_SCALE | TYPE_GENERAL_SCALE; 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; public static final int TYPE_MASK_ROTATION = TYPE_QUADRANT_ROTATION | TYPE_GENERAL_ROTATION;
/**
* Constructs an identity transform.
*/
public AffineTransform () { public AffineTransform () {
setToIdentity(); setToIdentity();
} }
/**
* Constructs a transform that is a copy of the supplied transform.
*/
public AffineTransform (AffineTransform t) { public AffineTransform (AffineTransform t) {
setTransform(t); setTransform(t);
} }
/**
* Constructs a transform with the specified transformation matrix.
*/
public AffineTransform (float m00, float m10, float m01, float m11, float m02, float m12) { public AffineTransform (float m00, float m10, float m01, float m11, float m02, float m12) {
setTransform(m00, m10, m01, m11, m02, m12); setTransform(m00, m10, m01, m11, m02, m12);
} }
/**
* 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 (float[] matrix) { public AffineTransform (float[] matrix) {
this.type = TYPE_UNKNOWN; this.type = TYPE_UNKNOWN;
m00 = matrix[0]; m00 = matrix[0];
@@ -52,21 +66,9 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/* /**
* Method returns type of affine transformation. * Returns the type of this affine transform, which is a bitwise-or of the type flags
* * ({@link #TYPE_TRANSLATION}, etc.).
* Transform matrix is m00 m01 m02 m10 m11 m12
*
* According analytic geometry new basis vectors are (m00, m01) and (m10,
* m11), translation vector is (m02, m12). Original basis vectors are (1, 0)
* and (0, 1). Type transformations classification: TYPE_IDENTITY - new
* basis equals original one and zero translation TYPE_TRANSLATION -
* translation vector isn't zero TYPE_UNIFORM_SCALE - vectors length of new
* basis equals TYPE_GENERAL_SCALE - vectors length of new basis doesn't
* equal TYPE_FLIP - new basis vector orientation differ from original one
* TYPE_QUADRANT_ROTATION - new basis is rotated by 90, 180, 270, or 360
* degrees TYPE_GENERAL_ROTATION - new basis is rotated by arbitrary angle
* TYPE_GENERAL_TRANSFORM - transformation can't be inversed
*/ */
public int getType () { public int getType () {
if (type != TYPE_UNKNOWN) { if (type != TYPE_UNKNOWN) {
@@ -108,34 +110,60 @@ public class AffineTransform implements Cloneable, Serializable
return type; return type;
} }
/**
* Returns the x-component of the scale vector.
*/
public float getScaleX () { public float getScaleX () {
return m00; return m00;
} }
/**
* Returns the y-component of the scale vector.
*/
public float getScaleY () { public float getScaleY () {
return m11; return m11;
} }
/**
* Returns the x-component of the shear vector.
*/
public float getShearX () { public float getShearX () {
return m01; return m01;
} }
/**
* Returns the y-component of the shear vector.
*/
public float getShearY () { public float getShearY () {
return m10; return m10;
} }
/**
* Returns the x-component of the translation vector.
*/
public float getTranslateX () { public float getTranslateX () {
return m02; return m02;
} }
/**
* Returns the y-component of the translation vector.
*/
public float getTranslateY () { public float getTranslateY () {
return m12; return m12;
} }
/**
* Returns true if this transform is the identity.
*/
public boolean isIdentity () { public boolean isIdentity () {
return getType() == TYPE_IDENTITY; 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 (float[] matrix) { public void getMatrix (float[] matrix) {
matrix[0] = m00; matrix[0] = m00;
matrix[1] = m10; matrix[1] = m10;
@@ -147,10 +175,17 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* Returns the <a href="http://en.wikipedia.org/wiki/Determinant">determinant</a> of this
* matrix.
*/
public float getDeterminant () { public float getDeterminant () {
return m00 * m11 - m01 * m10; return m00 * m11 - m01 * m10;
} }
/**
* Sets this transform's values.
*/
public void setTransform (float m00, float m10, float m01, float m11, float m02, float m12) { public void setTransform (float m00, float m10, float m01, float m11, float m02, float m12) {
this.type = TYPE_UNKNOWN; this.type = TYPE_UNKNOWN;
this.m00 = m00; this.m00 = m00;
@@ -161,17 +196,28 @@ public class AffineTransform implements Cloneable, Serializable
this.m12 = m12; this.m12 = m12;
} }
/**
* Sets this transform's values to be equal to those of the supplied transform.
*/
public void setTransform (AffineTransform t) { public void setTransform (AffineTransform t) {
setTransform(t.m00, t.m10, t.m01, t.m11, t.m02, t.m12); setTransform(t.m00, t.m10, t.m01, t.m11, t.m02, t.m12);
type = t.type; type = t.type;
} }
/**
* Sets this transform to the identity transform. Any existing transform values are
* overwritten.
*/
public void setToIdentity () { public void setToIdentity () {
type = TYPE_IDENTITY; type = TYPE_IDENTITY;
m00 = m11 = 1f; m00 = m11 = 1f;
m10 = m01 = m02 = m12 = 0; 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 (float tx, float ty) { public void setToTranslation (float tx, float ty) {
m00 = m11 = 1f; m00 = m11 = 1f;
m01 = m10 = 0; m01 = m10 = 0;
@@ -184,6 +230,10 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* Sets this transform to a simple scale using the supplied values. Any existing transform
* values are overwritten.
*/
public void setToScale (float scx, float scy) { public void setToScale (float scx, float scy) {
m00 = scx; m00 = scx;
m11 = scy; m11 = scy;
@@ -195,6 +245,10 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* Sets this transform to a simple shear using the supplied values. Any existing transform
* values are overwritten.
*/
public void setToShear (float shx, float shy) { public void setToShear (float shx, float shy) {
m00 = m11 = 1f; m00 = m11 = 1f;
m02 = m12 = 0; m02 = m12 = 0;
@@ -207,6 +261,10 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* Sets this transform to a simple rotation using the supplied values. Any existing transform
* values are overwritten.
*/
public void setToRotation (float angle) { public void setToRotation (float angle) {
float sin = (float)Math.sin(angle); float sin = (float)Math.sin(angle);
float cos = (float)Math.cos(angle); float cos = (float)Math.cos(angle);
@@ -224,6 +282,10 @@ public class AffineTransform implements Cloneable, Serializable
type = TYPE_UNKNOWN; type = TYPE_UNKNOWN;
} }
/**
* Sets this transform to a simple rotation using the supplied values. Any existing transform
* values are overwritten.
*/
public void setToRotation (float angle, float px, float py) { public void setToRotation (float angle, float px, float py) {
setToRotation(angle); setToRotation(angle);
m02 = px * (1f - m00) + py * m10; m02 = px * (1f - m00) + py * m10;
@@ -231,64 +293,106 @@ public class AffineTransform implements Cloneable, Serializable
type = TYPE_UNKNOWN; type = TYPE_UNKNOWN;
} }
/**
* Returns a transform that performs the specified translation.
*/
public static AffineTransform getTranslateInstance (float tx, float ty) { public static AffineTransform getTranslateInstance (float tx, float ty) {
AffineTransform t = new AffineTransform(); AffineTransform t = new AffineTransform();
t.setToTranslation(tx, ty); t.setToTranslation(tx, ty);
return t; return t;
} }
/**
* Returns a transform that performs the specified scale.
*/
public static AffineTransform getScaleInstance (float scx, float scY) { public static AffineTransform getScaleInstance (float scx, float scY) {
AffineTransform t = new AffineTransform(); AffineTransform t = new AffineTransform();
t.setToScale(scx, scY); t.setToScale(scx, scY);
return t; return t;
} }
/**
* Returns a transform that performs the specified shear.
*/
public static AffineTransform getShearInstance (float shx, float shy) { public static AffineTransform getShearInstance (float shx, float shy) {
AffineTransform m = new AffineTransform(); AffineTransform m = new AffineTransform();
m.setToShear(shx, shy); m.setToShear(shx, shy);
return m; return m;
} }
/**
* Returns a transform that performs the specified rotation.
*/
public static AffineTransform getRotateInstance (float angle) { public static AffineTransform getRotateInstance (float angle) {
AffineTransform t = new AffineTransform(); AffineTransform t = new AffineTransform();
t.setToRotation(angle); t.setToRotation(angle);
return t; return t;
} }
/**
* Returns a transform that performs the specified rotation.
*/
public static AffineTransform getRotateInstance (float angle, float x, float y) { public static AffineTransform getRotateInstance (float angle, float x, float y) {
AffineTransform t = new AffineTransform(); AffineTransform t = new AffineTransform();
t.setToRotation(angle, x, y); t.setToRotation(angle, x, y);
return t; return t;
} }
/**
* Concatenates the specified translation to this transform.
*/
public void translate (float tx, float ty) { public void translate (float tx, float ty) {
concatenate(getTranslateInstance(tx, ty)); concatenate(getTranslateInstance(tx, ty));
} }
/**
* Concatenates the specified scale to this transform.
*/
public void scale (float scx, float scy) { public void scale (float scx, float scy) {
concatenate(getScaleInstance(scx, scy)); concatenate(getScaleInstance(scx, scy));
} }
/**
* Concatenates the specified shear to this transform.
*/
public void shear (float shx, float shy) { public void shear (float shx, float shy) {
concatenate(getShearInstance(shx, shy)); concatenate(getShearInstance(shx, shy));
} }
/**
* Concatenates the specified rotation to this transform.
*/
public void rotate (float angle) { public void rotate (float angle) {
concatenate(getRotateInstance(angle)); concatenate(getRotateInstance(angle));
} }
/**
* Concatenates the specified rotation to this transform.
*/
public void rotate (float angle, float px, float py) { public void rotate (float angle, float px, float py) {
concatenate(getRotateInstance(angle, px, py)); concatenate(getRotateInstance(angle, px, py));
} }
/**
* Concatenates the specified transform to this transform.
*/
public void concatenate (AffineTransform t) { public void concatenate (AffineTransform t) {
multiply(t, this, this); multiply(t, this, this);
} }
/**
* Pre-concatenates the specified transform to this transform.
*/
public void preConcatenate (AffineTransform t) { public void preConcatenate (AffineTransform t) {
multiply(this, t, this); 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) public AffineTransform createInverse (AffineTransform target)
throws NoninvertibleTransformException { throws NoninvertibleTransformException {
float det = getDeterminant(); float det = getDeterminant();
@@ -304,10 +408,24 @@ public class AffineTransform implements Cloneable, Serializable
return target; 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 { public AffineTransform createInverse () throws NoninvertibleTransformException {
return createInverse(new AffineTransform()); 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) { public Point transform (IPoint src, Point dst) {
if (dst == null) { if (dst == null) {
dst = new Point(); dst = new Point();
@@ -318,6 +436,15 @@ public class AffineTransform implements Cloneable, Serializable
return dst; 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) { public void transform (IPoint[] src, int srcOff, Point[] dst, int dstOff, int length) {
while (--length >= 0) { while (--length >= 0) {
IPoint srcPoint = src[srcOff++]; IPoint srcPoint = src[srcOff++];
@@ -332,6 +459,15 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* 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 (float[] src, int srcOff, float[] dst, int dstOff, int length) { public void transform (float[] src, int srcOff, float[] dst, int dstOff, int length) {
int step = 2; int step = 2;
if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) { if (src == dst && srcOff < dstOff && dstOff < srcOff + length * 2) {
@@ -349,6 +485,14 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* 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) { public Point deltaTransform (IPoint src, Point dst) {
if (dst == null) { if (dst == null) {
dst = new Point(); dst = new Point();
@@ -358,6 +502,16 @@ public class AffineTransform implements Cloneable, Serializable
return dst; return dst;
} }
/**
* 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 (float[] src, int srcOff, float[] dst, int dstOff, int length) { public void deltaTransform (float[] src, int srcOff, float[] dst, int dstOff, int length) {
while (--length >= 0) { while (--length >= 0) {
float x = src[srcOff++], y = src[srcOff++]; float x = src[srcOff++], y = src[srcOff++];
@@ -366,6 +520,14 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* 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 { public Point inverseTransform (IPoint src, Point dst) throws NoninvertibleTransformException {
float det = getDeterminant(); float det = getDeterminant();
if (Math.abs(det) < ZERO) { if (Math.abs(det) < ZERO) {
@@ -379,6 +541,15 @@ public class AffineTransform implements Cloneable, Serializable
return dst; return dst;
} }
/**
* 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 (float[] src, int srcOff, float[] dst, int dstOff, int length) public void inverseTransform (float[] src, int srcOff, float[] dst, int dstOff, int length)
throws NoninvertibleTransformException { throws NoninvertibleTransformException {
float det = getDeterminant(); float det = getDeterminant();
@@ -392,6 +563,10 @@ public class AffineTransform implements Cloneable, Serializable
} }
} }
/**
* Creates and returns a new shape that is the supplied shape transformed by this transform's
* matrix.
*/
public IShape createTransformedShape (IShape src) { public IShape createTransformedShape (IShape src) {
if (src == null) { if (src == null) {
return null; return null;