/* * JBox2D - A Java Port of Erin Catto's Box2D * * JBox2D homepage: http://jbox2d.sourceforge.net/ * Box2D homepage: http://www.box2d.org * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ package org.jbox2d.common; /** * A 2x2 matrix class. * * @author ewjordan * */ public class Mat22 { public Vec2 col1, col2; /** Convert the matrix to printable format. */ public String toString() { String s = ""; s += "["+col1.x+","+col2.x+"]\n"; s += "["+col1.y+","+col2.y+"]"; return s; } /** Construct zero matrix. Note: this is NOT an identity matrix! */ public Mat22() { // optimised: create empty vectors instead of clone. col1 = new Vec2(); col2 = new Vec2(); //this(new Vec2(), new Vec2()); } /** * Create a matrix representing a rotation. * @param angle Rotation (in radians) that matrix represents. */ public Mat22(float angle) { // optimised: create empty vectors instead of clone. col1 = new Vec2(); col2 = new Vec2(); // this(); setAngle(angle); } /** * Create a matrix with given vectors as columns. * @param c1 Column 1 of matrix * @param c2 Column 2 of matrix */ public Mat22(Vec2 c1, Vec2 c2) { col1 = c1.clone(); col2 = c2.clone(); } /** * Create a matrix from four floats. * @param col1x * @param col2x * @param col1y * @param col2y */ public Mat22(float col1x, float col2x, float col1y, float col2y) { col1 = new Vec2(col1x, col1y); col2 = new Vec2(col2x, col2y); } /** * Set as a copy of another matrix. * @param m Matrix to copy */ public void set(Mat22 m) { col1.x = m.col1.x; col1.y = m.col1.y; col2.x = m.col2.x; col2.y = m.col2.y; } /** * Return a clone of this matrix. */ public Mat22 clone() { return new Mat22(this.col1.clone(), this.col2.clone()); } /** * Set as a matrix representing a rotation. * @param angle Rotation (in radians) that matrix represents. */ public void set(float angle) { float c = (float)Math.cos(angle), s = (float)Math.sin(angle); col1.x = c; col2.x = -s; col1.y = s; col2.y = c; } /** * Set as the identity matrix. */ public void setIdentity() { col1.x = 1.0f; col2.x = 0.0f; col1.y = 0.0f; col2.y = 1.0f; } /** * Set as the zero matrix. */ public void setZero() { col1.x = 0.0f; col2.x = 0.0f; col1.y = 0.0f; col2.y = 0.0f; } /** * Set as a matrix representing a rotation. * @param angle Rotation (in radians) that matrix represents. */ public void setAngle(float angle) { float c = (float) Math.cos(angle); float s = (float) Math.sin(angle); col1.x = c; col2.x = -s; col1.y = s; col2.y = c; } /** * Set by column vectors. * @param c1 Column 1 * @param c2 Column 2 */ public void set(Vec2 c1, Vec2 c2) { col1.x = c1.x; col2.x = c2.x; col1.y = c1.y; col2.y = c2.y; } /** Returns the inverted Mat22 - does NOT invert the matrix locally! */ public Mat22 invert() { float a = col1.x, b = col2.x, c = col1.y, d = col2.y; Mat22 B = new Mat22(); float det = a * d - b * c; // b2Assert(det != 0.0f); det = 1.0f / det; B.col1.x = det * d; B.col2.x = -det * b; B.col1.y = -det * c; B.col2.y = det * a; return B; } /** * Return the matrix composed of the absolute values of all elements. * @return Absolute value matrix */ public Mat22 abs() { return new Mat22(col1.abs(), col2.abs()); } /** * Return the matrix composed of the absolute values of all elements. * @return Absolute value matrix */ public static Mat22 abs(Mat22 R) { return R.abs(); } static final float ftiMul = 1f/65536f; static final float ftiMulL = 1f/(65536L*65536L); /** * Multiply a vector by this matrix. * @param v Vector to multiply by matrix. * @return Resulting vector */ public Vec2 mul_fixed(Vec2 v) { // fixed point version return new Vec2( ( (long)(col1.x*65536f) * (long)(v.x*65536f) + (long)(col2.x*65536f) * (long)(v.y*65536f) )*ftiMulL, ( (long)(col1.y*65536f) * (long)(v.x*65536f) + (long)(col2.y*65536f) * (long)(v.y*65536f) )*ftiMulL ); //return new Vec2(col1.x * v.x + col2.x * v.y, col1.y * v.x + col2.y // * v.y); } public Vec2 mul(Vec2 v) { return new Vec2(col1.x * v.x + col2.x * v.y, col1.y * v.x + col2.y * v.y); } /** * Multiply another matrix by this one (this one on left). * @param R * @return */ public Mat22 mul_fixed(Mat22 R) { Mat22 C = new Mat22(); // written out for efficiency (midp) // fixed point version C.col1.x = ( (long)(col1.x*65536f) * (long)(R.col1.x*65536f) + (long)(col2.x*65536f) * (long)(R.col1.y*65536f) )*ftiMulL; C.col1.y = ( (long)(col1.y*65536f) * (long)(R.col1.x*65536f) + (long)(col2.y*65536f) * (long)(R.col1.y*65536f) )*ftiMulL; C.col2.x = ( (long)(col1.x*65536f) * (long)(R.col2.x*65536f) + (long)(col2.x*65536f) * (long)(R.col2.y*65536f) )*ftiMulL; C.col2.y = ( (long)(col1.y*65536f) * (long)(R.col2.x*65536f) + (long)(col2.y*65536f) * (long)(R.col2.y*65536f) )*ftiMulL; //C.col1.x = col1.x * R.col1.x + col2.x * R.col1.y; //C.col1.y = col1.y * R.col1.x + col2.y * R.col1.y; //C.col2.x = col1.x * R.col2.x + col2.x * R.col2.y; //C.col2.y = col1.y * R.col2.x + col2.y * R.col2.y; //old code: C.set(this.mul(R.col1), this.mul(R.col2)); return C; } public Mat22 mul(Mat22 R) { Mat22 C = new Mat22(); // written out for efficiency (midp) C.col1.x = col1.x * R.col1.x + col2.x * R.col1.y; C.col1.y = col1.y * R.col1.x + col2.y * R.col1.y; C.col2.x = col1.x * R.col2.x + col2.x * R.col2.y; C.col2.y = col1.y * R.col2.x + col2.y * R.col2.y; //old code: C.set(this.mul(R.col1), this.mul(R.col2)); return C; } /** * Multiply another matrix by the transpose of this one (transpose of this one on left). * @param B * @return */ public Mat22 mulT(Mat22 B) { Vec2 c1 = new Vec2(Vec2.dot(this.col1, B.col1), Vec2.dot(this.col2, B.col1)); Vec2 c2 = new Vec2(Vec2.dot(this.col1, B.col2), Vec2.dot(this.col2, B.col2)); Mat22 C = new Mat22(); C.set(c1, c2); return C; } /** * Multiply a vector by the transpose of this matrix. * @param v * @return */ public Vec2 mulT(Vec2 v) { return new Vec2(Vec2.dot(v, col1), Vec2.dot(v, col2)); } /** * Add this matrix to B, return the result. * @param B * @return */ public Mat22 add(Mat22 B) { return new Mat22(col1.add(B.col1), col2.add(B.col2)); } /** * Add B to this matrix locally. * @param B * @return */ public Mat22 addLocal(Mat22 B) { col1.addLocal(B.col1); col2.addLocal(B.col2); return this; } /** * Solve A * x = b where A = this matrix. * @return The vector x that solves the above equation. */ public Vec2 solve(Vec2 b) { float a11 = col1.x, a12 = col2.x, a21 = col1.y, a22 = col2.y; float det = a11 * a22 - a12 * a21; //assert(det != 0.0f); det = 1.0f / det; Vec2 x = new Vec2( det * (a22 * b.x - a12 * b.y), det * (a11 * b.y - a21 * b.x) ); return x; } public static Vec2 mul(Mat22 R, Vec2 v) { return R.mul(v); } public static Mat22 mul(Mat22 A, Mat22 B){ return A.mul(B); } public static Vec2 mulT(Mat22 R, Vec2 v) { return R.mulT(v); } public static Mat22 mulT(Mat22 A, Mat22 B){ return A.mulT(B); } }