// $Id: Algebra.java,v 1.7 2007/05/23 05:04:10 Sasha Buzko Exp $ // // Copyright (c) 2000-2004 San Diego Supercomputer Center (SDSC), // a facility operated by the University of California, // San Diego (UCSD), San Diego, California, USA. // // Users and possessors of this source code are hereby granted a // nonexclusive, royalty-free copyright and design patent license to // use this code in individual software. License is not granted for // commercial resale, in whole or in part, without prior written // permission from SDSC. This source is provided "AS IS" without express // or implied warranty of any kind. // // For further information, please see: http://mbt.sdsc.edu // // History: // $Log: Algebra.java,v $ // Revision 1.7 2007/05/23 05:04:10 Sasha Buzko // *** empty log message *** // // Revision 1.6 2007/03/13 04:33:59 Sasha Buzko // *** empty log message *** // // Revision 1.5 2006/09/12 04:21:15 Sasha Buzko // *** empty log message *** // // Revision 1.4 2006/08/24 21:10:11 Sasha Buzko // *** empty log message *** // // Revision 1.3 2006/08/11 16:44:50 Sasha Buzko // *** empty log message *** // // Revision 1.2 2006/07/25 04:08:04 Sasha Buzko // *** empty log message *** // // Revision 1.1 2006/05/20 17:02:03 Sasha Buzko // Updated version // // Revision 1.2 2006/05/17 07:06:17 Sasha Buzko // *** empty log message *** // // Revision 1.1 2006/04/30 20:13:59 Sasha Buzko // New version of the app // // Revision 1.1 2006/04/15 19:42:27 Sasha Buzko // Initial commit // // Revision 1.12 2006/04/05 18:47:18 Administrator // *** empty log message *** // // Revision 1.11 2006/02/24 22:26:53 Administrator // *** empty log message *** // // Revision 1.10 2006/01/18 06:23:12 Administrator // *** empty log message *** // // Revision 1.9 2006/01/06 00:40:25 Administrator // *** empty log message *** // // Revision 1.8 2005/12/31 00:55:25 Administrator // *** empty log message *** // // Revision 1.7 2005/12/25 04:44:46 Administrator // *** empty log message *** // // Revision 1.6 2005/12/12 05:05:57 Administrator // *** empty log message *** // // Revision 1.5 2005/11/30 06:07:27 Administrator // *** empty log message *** // // Revision 1.4 2005/11/28 06:40:38 Administrator // *** empty log message *** // // Revision 1.3 2005/11/22 07:11:31 Administrator // *** empty log message *** // // Revision 1.2 2005/11/17 06:40:49 Administrator // *** empty log message *** // // Revision 1.1 2005/11/13 04:35:05 Administrator // *** empty log message *** // // Revision 1.1 2004/02/05 18:33:31 moreland // First version. // // Revision 1.0 2004/02/04 18:06:54 moreland // First version. // package edu.sdsc.mbt.util; //import javax.vecmath.Point3d; import edu.sdsc.mbt.*; import edu.sdsc.mbt.viewers.StructureViewerImpl.vec.Vec3d; import edu.sdsc.mbt.viewers.StructureViewerImpl.vec.Vec3f; /** * This class provides a number of algebreic methods for computing * various distances and angles between 3D virtex coordinates (double[3]). *

* @author John L. Moreland * @see edu.sdsc.mbt.Bond * @see edu.sdsc.mbt.util.BondFactory */ public class Algebra { public static final int X_AXIS = 0; public static final int Y_AXIS = 1; public static final int Z_AXIS = 2; /** * Compute the distance between two virtex coordinates. *

*

	 *  v1--v2
	 *  
* @param v1 First virtex coordinate as double[3]. * @param v2 Second virtex coordinate as double[3]. * @return the computed distence. */ public static double distance( double v1[], double v2[] ) { return Math.sqrt( (v2[0] - v1[0]) * (v2[0] - v1[0]) + (v2[1] - v1[1]) * (v2[1] - v1[1]) + (v2[2] - v1[2]) * (v2[2] - v1[2]) ); } /** * Calculate the angle formed by three virtex coordinates. *

*

	 *  v1  v3
	 *   \  /
	 *    v2
	 *  
*

* @param v1 An end virtex coordinate as double[3]. * @param v2 The middle virtex coordinate as double[3]. * @param v3 An end virtex coordinate as double[3]. * @return angle in degrees. */ public static double angle( double v1[], double v2[], double v3[] ) { // See: http://mathworld.wolfram.com/Line-LineAngle.html // Compute the numerator. double a = (v1[0] - v2[0]) * (v3[0] - v2[0]) + (v1[1] - v2[1]) * (v3[1] - v2[1]) + (v1[2] - v2[2]) * (v3[2] - v2[2]); // Compute the distance between v1 and v2. double b = Math.sqrt( (v1[0] - v2[0]) * (v1[0] - v2[0]) + (v1[1] - v2[1]) * (v1[1] - v2[1]) + (v1[2] - v2[2]) * (v1[2] - v2[2]) ); // Compute the distance between v3 and v2. double c = Math.sqrt( (v3[0] - v2[0]) * (v3[0] - v2[0]) + (v3[1] - v2[1]) * (v3[1] - v2[1]) + (v3[2] - v2[2]) * (v3[2] - v2[2]) ); // Calculate the angle between the two vectors. double cos = a / (b * c); double rad = Math.acos( cos ); double degrees = Math.toDegrees( rad ); return degrees; } /** * Calculate the dihedral angle defined by four virtex coordinates. *

*

	 *  v1     v4
	 *   \     /
	 *    v2--v3
	 *  
*

* @param v1 An end virtex coordinate as double[3]. * @param v2 An interior virtex coordinate as double[3]. * @param v3 An interior virtex coordinate as double[3]. * @param v4 An end virtex coordinate as double[3]. * @return dihedral angle in degrees. */ public static double dihedralAngle( double v1[], double v2[], double v3[], double v4[] ) { // See: http://mathworld.wolfram.com/DihedralAngle.html // Calculate the normal components for plane 1 (defined by v1-v2-v3). double a1 = (v3[1] - v2[1]) * (v1[2] - v2[2]) - (v1[1] - v2[1]) * (v3[2] - v2[2]); double b1 = (v1[0] - v2[0]) * (v3[2] - v2[2]) - (v3[0] - v2[0]) * (v1[2] - v2[2]); double c1 = (v3[0] - v2[0]) * (v1[1] - v2[1]) - (v1[0] - v2[0]) * (v3[1] - v2[1]); // Calculate the normal components for plane 2 (defined by v2-v3-v4). double a2 = (v3[1] - v2[1]) * (v4[2] - v2[2]) - (v4[1] - v2[1]) * (v3[2] - v2[2]); double b2 = (v4[0] - v2[0]) * (v3[2] - v2[2]) - (v3[0] - v2[0]) * (v4[2] - v2[2]); double c2 = (v3[0] - v2[0]) * (v4[1] - v2[1]) - (v4[0] - v2[0]) * (v3[1] - v2[1]); // Calculate the dihedral angle between the two plane's normals. double a = a1*a2 + b1*b2 + c1*c2; double b = Math.sqrt( a1*a1 + b1*b1 + c1*c1 ); double c = Math.sqrt( a2*a2 + b2*b2 + c2*c2 ); double cos = a / (b * c); double rad = Math.acos( cos ); double degrees = Math.toDegrees( rad ); //get the angle //first, compute the back bond normal double[] center = new double[]{ v2[0] - v3[0], v2[1] - v3[1], v2[2] - v3[2] }; double[] back = new double[]{ v4[0] - v3[0], v4[1] - v3[1], v4[2] - v3[2] }; double[] normal = Algebra.crossProduct(center, back); //compute the projection of the front bond to get the correct angle between the projection and //the normal: if the angle < 90, then the angle is positive double[] bond = new double[]{ v1[0] - v2[0], v1[1] - v2[1], v1[2] - v2[2] }; double[] cross = Algebra.crossProduct(center, bond); double[] projection = Algebra.crossProduct(cross, center); //now get the angle if (Algebra.getAngleBetweenVectors(projection, normal) > 90){ degrees = -degrees; } return degrees; } /** * Compute the midpoint between two points. */ public static Vec3d midpoint(Vec3d a, Vec3d b){ double x = a.value[0] + (b.value[0] - a.value[0])/2; double y = a.value[1] + (b.value[1] - a.value[1])/2; double z = a.value[2] + (b.value[2] - a.value[2])/2; return new Vec3d(x, y, z); } /** * Compute the distance between coordinates using double values */ public static double distance( Vec3d v1, Vec3d v2 ) { double dist = 0.0; dist += (v2.value[0] - v1.value[0])*(v2.value[0] - v1.value[0]); dist += (v2.value[1] - v1.value[1])*(v2.value[1] - v1.value[1]); dist += (v2.value[2] - v1.value[2])*(v2.value[2] - v1.value[2]); dist = Math.sqrt( dist ); return dist; } /** * Compute the distance between coordinates using float values */ public static float distance( Vec3f v1, Vec3f v2 ) { float dist = 0.0f; dist += (v2.value[0] - v1.value[0])*(v2.value[0] - v1.value[0]); dist += (v2.value[1] - v1.value[1])*(v2.value[1] - v1.value[1]); dist += (v2.value[2] - v1.value[2])*(v2.value[2] - v1.value[2]); dist = (float)Math.sqrt( dist ); return dist; } /** * Returns coordinates of the given Atom in 3d space. * @param atom * @return */ public static Vec3d getAtomCoordinates(Atom atom){ double x = atom.coordinate[0]; double y = atom.coordinate[1]; double z = atom.coordinate[2]; return new Vec3d(x, y, z); } /** * Calculates the angle formed by the three points. * @param v2 coordinates of the middle point * @param v1 coordinates of an end point * @param v3 coordinates of an end point * @return angle in degrees */ public static double getAngle(Vec3d v2, Vec3d v1, Vec3d v3){ //get the angle based on the coordinates of three points expressed in whole degrees //v1 is the central atom at the vertex double a = (v2.value[0] - v1.value[0])*(v3.value[0] - v1.value[0]) + (v2.value[1] - v1.value[1])*(v3.value[1] - v1.value[1]) + (v2.value[2] - v1.value[2])*(v3.value[2] - v1.value[2]); double b = Math.sqrt((v2.value[0] - v1.value[0])*(v2.value[0] - v1.value[0]) + (v2.value[1] - v1.value[1])*(v2.value[1] - v1.value[1]) + (v2.value[2] - v1.value[2])*(v2.value[2] - v1.value[2])); double c = Math.sqrt((v3.value[0] - v1.value[0])*(v3.value[0] - v1.value[0]) + (v3.value[1] - v1.value[1])*(v3.value[1] - v1.value[1]) + (v3.value[2] - v1.value[2])*(v3.value[2] - v1.value[2])); double cos = a/(b*c); double rad = Math.acos(cos); double degrees = Math.toDegrees(rad); return degrees; } /** * Calculates the dihedral angle defined by four points * @param v3 coordinates of an end point * @param v1 coordinates of the second point in the sequence * @param v2 coordinates of the third point * @param v4 coordinates of the other end point * @return */ public static double getDihedralAngle(Vec3d v3, Vec3d v1, Vec3d v2, Vec3d v4){ //calculate the components of normals to the planes double a1 = (v2.value[1] - v1.value[1])*(v3.value[2] - v1.value[2]) - (v3.value[1] - v1.value[1])*(v2.value[2] - v1.value[2]); double b1 = (v3.value[0] - v1.value[0])*(v2.value[2] - v1.value[2]) - (v2.value[0] - v1.value[0])*(v3.value[2] - v1.value[2]); double c1 = (v2.value[0] - v1.value[0])*(v3.value[1] - v1.value[1]) - (v3.value[0] - v1.value[0])*(v2.value[1] - v1.value[1]); double a2 = (v2.value[1] - v1.value[1])*(v4.value[2] - v1.value[2]) - (v4.value[1] - v1.value[1])*(v2.value[2] - v1.value[2]); double b2 = (v4.value[0] - v1.value[0])*(v2.value[2] - v1.value[2]) - (v2.value[0] - v1.value[0])*(v4.value[2] - v1.value[2]); double c2 = (v2.value[0] - v1.value[0])*(v4.value[1] - v1.value[1]) - (v4.value[0] - v1.value[0])*(v2.value[1] - v1.value[1]); double a = a1*a2 + b1*b2 + c1*c2; double b = Math.sqrt(a1*a1 + b1*b1 + c1*c1); double c = Math.sqrt(a2*a2 + b2*b2 + c2*c2); double cos = a/(b*c); double rad = Math.acos(cos); double degrees = Math.toDegrees(rad); return degrees; } /** * Compute the vector cross product between v1 and v2 storing the * output in result. *

* @param v1 First vector argument. * @param v2 Second vector argument. * @param result The vector in which the result will be stored. */ public static void crossProduct( double[] v1, double[] v2, double[] result ) { if ( v1.length != 3 ) throw new IllegalArgumentException( "v1.length != 3" ); if ( v2.length != 3 ) throw new IllegalArgumentException( "v2.length != 3" ); if ( result.length != 3 ) throw new IllegalArgumentException( "result.length != 3" ); if ( v1 == v2 ) throw new IllegalArgumentException( "v1 == v2" ); if ( result == v1 ) throw new IllegalArgumentException( "result == v1" ); if ( result == v2 ) throw new IllegalArgumentException( "result == v2" ); result[0] = + ( ( v1[1] * v2[2] ) - ( v2[1] * v1[2] ) ); result[1] = - ( ( v1[0] * v2[2] ) - ( v2[0] * v1[2] ) ); result[2] = + ( ( v1[0] * v2[1] ) - ( v2[0] * v1[1] ) ); } public static void crossProduct( float[] v1, float[] v2, float[] result ) { if ( v1.length != 3 ) throw new IllegalArgumentException( "v1.length != 3" ); if ( v2.length != 3 ) throw new IllegalArgumentException( "v2.length != 3" ); if ( result.length != 3 ) throw new IllegalArgumentException( "result.length != 3" ); if ( v1 == v2 ) throw new IllegalArgumentException( "v1 == v2" ); if ( result == v1 ) throw new IllegalArgumentException( "result == v1" ); if ( result == v2 ) throw new IllegalArgumentException( "result == v2" ); result[0] = + ( ( v1[1] * v2[2] ) - ( v2[1] * v1[2] ) ); result[1] = - ( ( v1[0] * v2[2] ) - ( v2[0] * v1[2] ) ); result[2] = + ( ( v1[0] * v2[1] ) - ( v2[0] * v1[1] ) ); } public static double[] crossProduct( double[] v1, double[] v2 ) { double[] result = new double[3]; if ( v1.length != 3 ) throw new IllegalArgumentException( "v1.length != 3" ); if ( v2.length != 3 ) throw new IllegalArgumentException( "v2.length != 3" ); result[0] = + ( ( v1[1] * v2[2] ) - ( v2[1] * v1[2] ) ); result[1] = - ( ( v1[0] * v2[2] ) - ( v2[0] * v1[2] ) ); result[2] = + ( ( v1[0] * v2[1] ) - ( v2[0] * v1[1] ) ); return result; } /** * Return the vector dot product between v1 and v2. *

* @param v1 First vector argument. * @param v2 Second vector argument. * @return The dot product value. */ public static double dotProduct( double[] v1, double[] v2 ) { if ( v1.length != v2.length ) throw new IllegalArgumentException( "v1.length != v2.length" ); double sumOfSquares = 0.0; for ( int i=0; i * @param inVector The input vector argument. * @param outVector The output vector. */ public static void normalizeVector( double[] inVector, double[] outVector ) { if ( inVector == null ) throw new NullPointerException( "null inVector" ); if ( outVector == null ) throw new NullPointerException( "null outVector" ); if ( inVector.length != outVector.length ) throw new IllegalArgumentException( "vector length mismatch" ); double length = vectorLength( inVector ); if ( length == 0.0 ) length = 1.0; for ( int i=0; i * @param vector The vector to be normalized in-place. */ public static void normalizeVector( double[] vector ) { normalizeVector( vector, vector ); } public static void normalizeVector( float[] vector ) { normalizeVector( vector, vector ); } public static void normalizeVector( float[] inVector, float[] outVector ) { if ( inVector == null ) throw new NullPointerException( "null inVector" ); if ( outVector == null ) throw new NullPointerException( "null outVector" ); if ( inVector.length != outVector.length ) throw new IllegalArgumentException( "vector length mismatch" ); float length = vectorLength( inVector ); if ( length == 0.0 ) length = 1.0f; for ( int i=0; i * @param vector The input vector. * @return The length of the input vector. */ public static double vectorLength( double[] vector ) { if ( vector == null ) throw new NullPointerException( "null vector" ); double sqSum = 0.0; for ( int i=0; i * @param angleAxis The angle-axis rotation vector. * @param point The point to be rotated in-place. */ public static void angleAxisRotate( double[] angleAxis, double[] point ) { if ( angleAxis == null ) throw new NullPointerException( "null angleAxis" ); if ( angleAxis.length < 4 ) throw new IllegalArgumentException( "angleAxis.length < 4" ); if ( point == null ) throw new NullPointerException( "null point" ); if ( point.length < 3 ) throw new IllegalArgumentException( "point.length < 3" ); final double matrix[] = new double[16]; rotationToMatrix( angleAxis, matrix ); matrixRotate( matrix, point ); } /** * Rotate the point by the given 16-element rotation matrix. *

* @param matrix The 16-element rotation matrix. * @param point The point to be rotated in-place. */ public static void matrixRotate( double[] matrix, double[] point ) { if ( matrix == null ) throw new NullPointerException( "null matrix" ); if ( matrix.length < 16 ) throw new IllegalArgumentException( "matrix.length < 16" ); if ( point == null ) throw new NullPointerException( "null point" ); if ( point.length < 3 ) throw new IllegalArgumentException( "point.length < 3" ); double[] m = matrix; double x = point[0]; double y = point[1]; double z = point[2]; double w = 1.0; point[0] = m[0]*x + m[1]*y + m[2]*z + m[3]*w; point[1] = m[4]*x + m[5]*y + m[6]*z + m[7]*w; point[2] = m[8]*x + m[9]*y + m[10]*z + m[11]*w; } /** * Convert the angle-axis {angle,x,y,z} rotation vector to a 16-element * rotation matrix. *

* @param rotation The angle-axis rotation vector. * @param matrix The resulting 16-element rotation matrix. */ public static void rotationToMatrix( double[] rotation, double[] matrix ) { if ( rotation == null ) throw new NullPointerException( "null rotation" ); if ( rotation.length < 4 ) throw new IllegalArgumentException( "rotation.length < 4" ); if ( matrix == null ) throw new NullPointerException( "null matrix" ); if ( matrix.length < 16 ) throw new IllegalArgumentException( "matrix.length < 16" ); // Make sure that the rotation vector is unit length. double len = Math.sqrt( rotation[1] * rotation[1] + rotation[2] * rotation[2] + rotation[3] * rotation[3] ); double norm = 1.0 / len; if ( norm == 0.0 ) norm = 1.0; double a = rotation[0]; double x = rotation[1] * norm; double y = rotation[2] * norm; double z = rotation[3] * norm; double c = Math.cos( a ); double s = Math.sin( a ); double t = 1.0 - c; matrix[0] = t*x*x + c; matrix[1] = t*x*y - s*z; matrix[2] = t*x*z + s*y; matrix[3] = 0.0; matrix[4] = t*x*y + s*z; matrix[5] = t*y*y + c; matrix[6] = t*y*z - s*x; matrix[7] = 0.0; matrix[8] = t*x*z - s*y; matrix[9] = t*y*z + s*x; matrix[10] = t*z*z + c; matrix[11] = 0.0; matrix[12] = 0.0; matrix[13] = 0.0; matrix[14] = 0.0; matrix[15] = 1.0; } /** * Calculate the position of the view point on Z axis, given the center of the * viewed structure and the required distance * @param target * @param distance * @return */ public static double[] getViewPoint(double[] target, double distance){ double result = target[2] + Math.sqrt(Math.pow(distance, 2) - Math.pow(target[0], 2) - Math.pow(target[1], 2) ); return new double[] { 0, 0, result }; } public static double[] multiplyMatrices(double[][] a, double[][] b){ double[] A = new double[16]; double[] B = new double[16]; A[0] = a[0][0]; A[1] = a[0][1]; A[2] = a[0][2]; A[3] = 0; A[4] = a[1][0]; A[5] = a[1][1]; A[6] = a[1][2]; A[7] = 0; A[8] = a[2][0]; A[9] = a[2][1]; A[10] = a[2][2]; A[11] = 0; A[12] = 0; A[13] = 0; A[14] = 0; A[15] = 1; B[0] = b[0][0]; B[1] = b[0][1]; B[2] = b[0][2]; B[3] = 0; B[4] = b[1][0]; B[5] = b[1][1]; B[6] = b[1][2]; B[7] = 0; B[8] = b[2][0]; B[9] = b[2][1]; B[10] = b[2][2]; B[11] = 0; B[12] = 0; B[13] = 0; B[14] = 0; B[15] = 1; return Algebra.multiplySquareMatrices(A, B); } /** * Calculate a product of two matrices and return the result * @param first multiplier * @param second multiplier matrix * @return result */ public static double[] multiplySquareMatrices(double[] a, double[] b){ if (a.length != b.length) throw new IllegalArgumentException("The matrices are not of equal size."); if (a.length != 16) throw new IllegalArgumentException("Matrix length must be 16."); double[] out = new double[16]; out[0] = a[0]*b[0] + a[4]*b[1] + a[8]*b[2] + a[12]*b[3]; out[1] = a[1]*b[0] + a[5]*b[1] + a[9]*b[2] + a[13]*b[3]; out[2] = a[2]*b[0] + a[6]*b[1] + a[10]*b[2] + a[14]*b[3]; out[3] = a[3]*b[0] + a[7]*b[1] + a[11]*b[2] + a[15]*b[3]; out[4] = a[0]*b[4] + a[4]*b[5] + a[8]*b[6] + a[12]*b[7]; out[5] = a[1]*b[4] + a[5]*b[5] + a[9]*b[6] + a[13]*b[7]; out[6] = a[2]*b[4] + a[6]*b[5] + a[10]*b[6] + a[14]*b[7]; out[7] = a[3]*b[4] + a[7]*b[5] + a[11]*b[6] + a[15]*b[7]; out[8] = a[0]*b[8] + a[4]*b[9] + a[8]*b[10] + a[12]*b[11]; out[9] = a[1]*b[8] + a[5]*b[9] + a[9]*b[10] + a[13]*b[11]; out[10] = a[2]*b[8] + a[6]*b[9] + a[10]*b[10] + a[14]*b[11]; out[11] = a[3]*b[8] + a[7]*b[9] + a[11]*b[10] + a[15]*b[11]; out[12] = a[0]*b[12] + a[4]*b[13] + a[8]*b[14] + a[12]*b[15]; out[13] = a[1]*b[12] + a[5]*b[13] + a[9]*b[14] + a[13]*b[15]; out[14] = a[2]*b[12] + a[6]*b[13] + a[10]*b[14] + a[14]*b[15]; out[15] = a[3]*b[12] + a[7]*b[13] + a[11]*b[14] + a[15]*b[15]; return out; } /** * This method solves a system of three equations with three unknowns and returns * an array of x,y,z values * @param system linear array of all 12 constituents: a1, b1, c1, d1, a2, b2.. etc * @return */ public static double[] solveSystemOfEquations(double[] system){ double[] out = new double[3]; double a1, b1, c1, d1, a2, b2, c2, d2, a3, b3, c3, d3; a1 = system[0]; b1 = system[1]; c1 = system[2]; d1 = system[3]; a2 = system[4]; b2 = system[5]; c2 = system[6]; d2 = system[7]; a3 = system[8]; b3 = system[9]; c3 = system[10]; d3 = system[11]; /* System.out.println("a1 = " + a1); System.out.println("b1 = " + b1); System.out.println("c1 = " + c1); System.out.println("d1 = " + d1); System.out.println("a2 = " + a2); System.out.println("b2 = " + b2); System.out.println("c2 = " + c2); System.out.println("d2 = " + d2); System.out.println("a3 = " + a3); System.out.println("b3 = " + b3); System.out.println("c3 = " + c3); System.out.println("d3 = " + d3); */ //solve the system using the matrix method double determinant = a1*b2*c3 - a1*b3*c2 + a2*b3*c1 - a2*b1*c3 + a3*b1*c2 - a3*b2*c1; if (determinant == 0) return null; //find x out[0] = (d1*b2*c3 - d1*b3*c2 + d2*b3*c1 - d2*b1*c3 + d3*b1*c2 - d3*b2*c1)/determinant; out[1] = (a1*d2*c3 - a1*d3*c2 + a2*d3*c1 - a2*d1*c3 + a3*d1*c2 - a3*d2*c1)/determinant; out[2] = (a1*b2*d3 - a1*b3*d2 + a2*b3*d1 - a2*b1*d3 + a3*b1*d2 - a3*b2*d1)/determinant; return out; } public static double getAngleBetweenVectors(double[] a, double[] b){ double[] ta = getNormalizedVector(a); double[] tb = getNormalizedVector(b); double cos = dotProduct(ta, tb)/(vectorLength(ta) * vectorLength(tb)); double angle = Math.acos(cos); return Math.toDegrees(angle); } public static double[] getVector(double[] start, double[] end){ double[] out = new double[3]; out[0] = end[0] - start[0]; out[1] = end[1] - start[1]; out[2] = end[2] - start[2]; return out; } public static double[] getNormalizedVector(double[] start, double[] end){ double[] out = new double[3]; out[0] = end[0] - start[0]; out[1] = end[1] - start[1]; out[2] = end[2] - start[2]; return Algebra.getNormalizedVector(out); } public static void main(String[] args){ /* double[] a = new double[]{ 1.5470, -0.0260 , -0.0000}; double[] b = new double[]{ 1.9350 , 1.4340, -0.0000}; double[] out = Algebra.getNormalizedVector(a, b); System.out.println(out[0] + "\t" + out[1] + "\t" + out[2]); */ double[][] a = new double[3][3]; a[0][0] = 1; a[1][0] = 1; a[2][0] = 0; a[0][1] = 1; a[1][1] = 2; a[2][1] = 0; a[0][2] = 1; a[1][2] = 2; a[2][2] = 1; double[][] res = Algebra.getInverseMatrix(a); for (int i = 0; i < 3; i++){ for (int j = 0; j < 3; j++){ System.out.println("res[" + i + "][" + j + "] = " + res[i][j]); } } } public static double[][] getInverseMatrix(double[][] a){ if (a[0].length != 3 || a[1].length != 3 || a[2].length != 3 || a.length != 3) return null; //compute determinant double det = a[0][0]*(a[1][1]*a[2][2] - a[2][1]*a[1][2]) - a[0][1]*(a[1][0]*a[2][2] - a[2][0]*a[1][2]) + a[0][2]*(a[1][0]*a[2][1] - a[2][0]*a[1][1]); System.out.println("det = " + det); double[][] out = new double[3][3]; //calculate the elements of the new matrix out[0][0] = (a[1][1]*a[2][2] - a[2][1]*a[1][2])/det; out[0][1] = -(a[1][0]*a[2][2] - a[2][0]*a[1][2])/det; out[0][2] = (a[1][0]*a[2][1] - a[2][0]*a[1][1])/det; out[1][0] = -(a[0][1]*a[2][2] - a[2][1]*a[0][2])/det; out[1][1] = (a[0][0]*a[2][2] - a[2][0]*a[0][2])/det; out[1][2] = -(a[0][0]*a[2][1] - a[2][0]*a[0][1])/det; out[2][0] = (a[0][1]*a[1][2] - a[1][1]*a[0][2])/det; out[2][1] = -(a[0][0]*a[1][2] - a[1][0]*a[0][2])/det; out[2][2] = (a[0][0]*a[1][1] - a[1][0]*a[0][1])/det; return out; } /** * Multiply a vector times a scalar. *

* @param vector The vector to be scaled in-place. */ public static void scalarMultiply( float[] vector, float scalar ) { for ( int i=0; i * @param vector The vector to be scaled in-place. */ public static void scalarMultiply( double[] vector, double scalar ) { for ( int i=0; i * @param vector1 The vector to be orthogonalized. * @param vector2 The reference vector for orthogonalization. * @throws NullPointerException for null vector. * @throws IllegalArgumentException for zero vector. */ public static void orthogonalize( float[] vector1, float[] vector2 ) { float v1Dotv2 = dotProduct( vector1, vector2 ); scalarMultiply( vector1, v1Dotv2 ); subtractVectors( vector1, vector2 ); normalizeVector( vector1 ); } /** * Subtract one vector from another. *

* @param vector1 The vector to be modified. * @param vector2 The vector to subtract. */ public static void subtractVectors( double[] vector1, double[] vector2 ) { if ( vector1 == null ) throw new NullPointerException( "null vector1" ); if ( vector2 == null ) throw new NullPointerException( "null vector2" ); if ( vector1.length != vector2.length ) throw new IllegalArgumentException( "vector length mismatch" ); for ( int i=0; i * @param vector1 The vector to be modified. * @param vector2 The vector to subtract. */ public static void subtractVectors( float[] vector1, float[] vector2 ) { if ( vector1 == null ) throw new NullPointerException( "null vector1" ); if ( vector2 == null ) throw new NullPointerException( "null vector2" ); if ( vector1.length != vector2.length ) throw new IllegalArgumentException( "vector length mismatch" ); for ( int i=0; i