/* file : AffineTransform3D.java
*
* Project : geometry
*
* ===========================================
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 2.1 of the License, or (at
* your option) any later version.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY, without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.
*
* See the GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library. if not, write to :
* The Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*
* Created on 27 nov. 2005
*
*/
package math.geom3d.transform;
import math.geom3d.Point3D;
import math.geom3d.Shape3D;
import math.geom3d.Vector3D;
/**
* @author dlegland
*/
public class AffineTransform3D implements Bijection3D {
// coefficients for x coordinate.
protected double m00, m01, m02, m03;
// coefficients for y coordinate.
protected double m10, m11, m12, m13;
// coefficients for y coordinate.
protected double m20, m21, m22, m23;
// ===================================================================
// public static methods
public final static AffineTransform3D createTranslation(Vector3D vec) {
return createTranslation(vec.getX(), vec.getY(), vec.getZ());
}
public final static AffineTransform3D createTranslation(double x, double y,
double z) {
return new AffineTransform3D(1, 0, 0, x, 0, 1, 0, y, 0, 0, 1, z);
}
public final static AffineTransform3D createRotationOx(double theta) {
double cot = Math.cos(theta);
double sit = Math.sin(theta);
return new AffineTransform3D(1, 0, 0, 0, 0, cot, -sit, 0, 0, sit, cot,
0);
}
public final static AffineTransform3D createRotationOy(double theta) {
double cot = Math.cos(theta);
double sit = Math.sin(theta);
return new AffineTransform3D(cot, 0, sit, 0, 0, 1, 0, 0, -sit, 0, cot,
0);
}
public final static AffineTransform3D createRotationOz(double theta) {
double cot = Math.cos(theta);
double sit = Math.sin(theta);
return new AffineTransform3D(cot, -sit, 0, 0, sit, cot, 0, 0, 0, 0, 1,
0);
}
public final static AffineTransform3D createScaling(double s) {
return createScaling(s, s, s);
}
public final static AffineTransform3D createScaling(double sx, double sy, double sz) {
return new AffineTransform3D(sx, 0, 0, 0, 0, sy, 0, 0, 0, 0, sz, 0);
}
// ===================================================================
// constructors
/** Creates a new affine transform3D set to identity */
public AffineTransform3D() {
// init to identity matrix
m00 = m11 = m22 = 1;
m01 = m02 = m03 = 0;
m10 = m12 = m13 = 0;
m20 = m21 = m23 = 0;
}
public AffineTransform3D(double[] coefs) {
if (coefs.length==9) {
m00 = coefs[0];
m01 = coefs[1];
m02 = coefs[2];
m10 = coefs[3];
m11 = coefs[4];
m12 = coefs[5];
m20 = coefs[6];
m21 = coefs[7];
m22 = coefs[8];
} else if (coefs.length==12) {
m00 = coefs[0];
m01 = coefs[1];
m02 = coefs[2];
m03 = coefs[3];
m10 = coefs[4];
m11 = coefs[5];
m12 = coefs[6];
m13 = coefs[7];
m20 = coefs[8];
m21 = coefs[9];
m22 = coefs[10];
m23 = coefs[11];
}
}
public AffineTransform3D(double xx, double yx, double zx, double tx,
double xy, double yy, double zy, double ty, double xz, double yz,
double zz, double tz) {
m00 = xx;
m01 = yx;
m02 = zx;
m03 = tx;
m10 = xy;
m11 = yy;
m12 = zy;
m13 = ty;
m20 = xz;
m21 = yz;
m22 = zz;
m23 = tz;
}
// ===================================================================
// accessors
public boolean isIdentity() {
if (m00!=1)
return false;
if (m11!=1)
return false;
if (m22!=0)
return false;
if (m01!=0)
return false;
if (m02!=0)
return false;
if (m03!=0)
return false;
if (m10!=0)
return false;
if (m12!=0)
return false;
if (m13!=0)
return false;
if (m20!=0)
return false;
if (m21!=0)
return false;
if (m23!=0)
return false;
return true;
}
/**
* Returns the affine coefficients of the transform. Result is an array of
* 12 double.
*/
public double[] coefficients() {
double[] tab = { m00, m01, m02, m03, m10, m11, m12, m13, m20, m21, m22, m23 };
return tab;
}
/**
* Computes the determinant of this transform. Can be zero.
*
* @return the determinant of the transform.
*/
private double determinant() {
return m00 * (m11 * m22 - m12 * m21) - m01 * (m10 * m22 - m20 * m12)
+ m02 * (m10 * m21 - m20 * m11);
}
/**
* Computes the inverse affine transform.
*/
public AffineTransform3D inverse() {
double det = this.determinant();
return new AffineTransform3D(
(m11 * m22 - m21 * m12) / det,
(m21 * m01 - m01 * m22) / det,
(m01 * m12 - m11 * m02) / det,
(m01 * (m22 * m13 - m12 * m23) + m02 * (m11 * m23 - m21 * m13)
- m03 * (m11 * m22 - m21 * m12)) / det,
(m20 * m12 - m10 * m22) / det,
(m00 * m22 - m20 * m02) / det,
(m10 * m02 - m00 * m12) / det,
(m00 * (m12 * m23 - m22 * m13) - m02 * (m10 * m23 - m20 * m13)
+ m03 * (m10 * m22 - m20 * m12)) / det,
(m10 * m21 - m20 * m11) / det,
(m20 * m01 - m00 * m21) / det,
(m00 * m11 - m10 * m01) / det,
(m00 * (m21 * m13 - m11 * m23) + m01 * (m10 * m23 - m20 * m13)
- m03 * (m10 * m21 - m20 * m11)) / det);
}
// ===================================================================
// general methods
/**
* Combines this transform with another AffineTransform.
*/
public void transform(AffineTransform3D trans) {
double n00 = m00 * trans.m00 + m10 * trans.m01;
double n10 = m00 * trans.m10 + m10 * trans.m11;
double n01 = m01 * trans.m00 + m11 * trans.m01;
double n11 = m01 * trans.m10 + m11 * trans.m11;
double n02 = m02 * trans.m00 + m12 * trans.m01 + trans.m02;
double n12 = m02 * trans.m10 + m12 * trans.m11 + trans.m12;
m00 = n00;
m01 = n01;
m02 = n02;
m10 = n10;
m11 = n11;
m12 = n12;
}
/**
* Combines this transform with another AffineTransform.
*/
public void preConcatenate(AffineTransform3D trans) {
double n00 = trans.m00 * m00 + trans.m10 * m01;
double n10 = trans.m00 * m10 + trans.m10 * m11;
double n01 = trans.m01 * m00 + trans.m11 * m01;
double n11 = trans.m01 * m10 + trans.m11 * m11;
double n02 = trans.m02 * m00 + trans.m12 * m01 + m02;
double n12 = trans.m02 * m10 + trans.m12 * m11 + m12;
m00 = n00;
m01 = n01;
m02 = n02;
m10 = n10;
m11 = n11;
m12 = n12;
}
/**
* Transforms the input point array, stores the result in the pre-allocated
* array, and returns a pointer to the result array.
* A new array is created if res is null or has length smaller
* than of src.
*/
public Point3D[] transformPoints(Point3D[] src, Point3D[] dst) {
// Check validity of result array
if (dst == null || dst.length < src.length)
dst = new Point3D[src.length];
// transform each input point
for (int i = 0; i < src.length; i++) {
dst[i] = new Point3D(
src[i].getX() * m00 + src[i].getY() * m01 + src[i].getZ() * m02 + m03,
src[i].getX() * m10 + src[i].getY() * m11 + src[i].getZ() * m12 + m13,
src[i].getX() * m20 + src[i].getY() * m21 + src[i].getZ() * m22 + m23);
}
return dst;
}
/**
* Transforms the input point.
*/
public Point3D transformPoint(Point3D src) {
return new Point3D(
src.getX() * m00 + src.getY() * m01 + src.getZ() * m02 + m03,
src.getX() * m10 + src.getY() * m11 + src.getZ() * m12 + m13,
src.getX() * m20 + src.getY() * m21 + src.getZ() * m22 + m23);
}
/**
* Compares two transforms. Returns true if all inner fields are equal up to
* the precision given by Shape3D.ACCURACY.
*/
@Override
public boolean equals(Object obj) {
if (!(obj instanceof AffineTransform3D))
return false;
double tab[] = ((AffineTransform3D) obj).coefficients();
if (Math.abs(tab[0] - m00) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[1] - m01) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[2] - m02) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[3] - m03) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[4] - m10) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[5] - m11) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[6] - m12) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[7] - m13) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[8] - m20) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[9] - m21) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[10] - m22) > Shape3D.ACCURACY)
return false;
if (Math.abs(tab[11] - m23) > Shape3D.ACCURACY)
return false;
return true;
}
}
Ads help maintain this website.