2 * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
3 * Copyright (C) $$Year-Rel$$ The Jalview Authors
5 * This file is part of Jalview.
7 * Jalview is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation, either version 3
10 * of the License, or (at your option) any later version.
12 * Jalview is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty
14 * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
19 * The Jalview Authors are detailed in the 'AUTHORS' file.
23 import jalview.datamodel.Point;
25 import java.util.HashMap;
29 * Model for a 3x3 matrix which provides methods for rotation in 3-D space
31 public class RotatableMatrix
33 private static final int DIMS = 3;
36 * cache the most used rotations: +/- 1, 2, 3, 4 degrees around x or y axis
38 private static Map<Axis, Map<Float, float[][]>> cachedRotations;
42 cachedRotations = new HashMap<>();
43 for (Axis axis : Axis.values())
45 HashMap<Float, float[][]> map = new HashMap<>();
46 cachedRotations.put(axis, map);
47 for (int deg = 1; deg < 5; deg++)
49 float[][] rotation = getRotation(deg, axis);
50 map.put(Float.valueOf(deg), rotation);
51 rotation = getRotation(-deg, axis);
52 map.put(Float.valueOf(-deg), rotation);
65 * Constructor creates a new identity matrix (all values zero except for 1 on
68 public RotatableMatrix()
70 matrix = new float[DIMS][DIMS];
71 for (int j = 0; j < DIMS; j++)
78 * Sets the value at position (i, j) of the matrix
84 public void setValue(int i, int j, float value)
90 * Answers the value at position (i, j) of the matrix
96 public float getValue(int i, int j)
102 * Prints the matrix in rows of space-delimited values
107 matrix[0][0] + " " + matrix[0][1] + " " + matrix[0][2]);
110 matrix[1][0] + " " + matrix[1][1] + " " + matrix[1][2]);
113 matrix[2][0] + " " + matrix[2][1] + " " + matrix[2][2]);
117 * Rotates the matrix through the specified number of degrees around the
123 public void rotate(float degrees, Axis axis)
125 float[][] rot = getRotation(degrees, axis);
131 * Answers a matrix which, when it pre-multiplies another matrix, applies a
132 * rotation of the specified number of degrees around the specified axis
137 * @see https://en.wikipedia.org/wiki/Rotation_matrix#Basic_rotations
139 protected static float[][] getRotation(float degrees, Axis axis)
141 Float floatValue = Float.valueOf(degrees);
142 if (cachedRotations.get(axis).containsKey(floatValue))
144 // System.out.println("getRotation from cache: " + (int) degrees);
145 return cachedRotations.get(axis).get(floatValue);
148 float costheta = (float) Math.cos(degrees * Math.PI / 180f);
150 float sintheta = (float) Math.sin(degrees * Math.PI / 180f);
152 float[][] rot = new float[DIMS][DIMS];
158 rot[1][1] = costheta;
159 rot[1][2] = sintheta;
160 rot[2][1] = -sintheta;
161 rot[2][2] = costheta;
164 rot[0][0] = costheta;
165 rot[0][2] = -sintheta;
167 rot[2][0] = sintheta;
168 rot[2][2] = costheta;
171 rot[0][0] = costheta;
172 rot[0][1] = -sintheta;
173 rot[1][0] = sintheta;
174 rot[1][1] = costheta;
182 * Answers a new array of float values which is the result of pre-multiplying
183 * this matrix by the given vector. Each value of the result is the dot
184 * product of the vector with one column of this matrix. The matrix and input
185 * vector are not modified.
191 public float[] vectorMultiply(float[] vect)
193 float[] result = new float[DIMS];
195 for (int i = 0; i < DIMS; i++)
197 result[i] = (matrix[i][0] * vect[0]) + (matrix[i][1] * vect[1])
198 + (matrix[i][2] * vect[2]);
205 * Performs pre-multiplication of this matrix by the given one. Value (i, j)
206 * of the result is the dot product of the i'th row of <code>mat</code> with
207 * the j'th column of this matrix.
211 public void preMultiply(float[][] mat)
213 float[][] tmp = new float[DIMS][DIMS];
215 for (int i = 0; i < DIMS; i++)
217 for (int j = 0; j < DIMS; j++)
219 tmp[i][j] = (mat[i][0] * matrix[0][j]) + (mat[i][1] * matrix[1][j])
220 + (mat[i][2] * matrix[2][j]);
228 * Performs post-multiplication of this matrix by the given one. Value (i, j)
229 * of the result is the dot product of the i'th row of this matrix with the
230 * j'th column of <code>mat</code>.
234 public void postMultiply(float[][] mat)
236 float[][] tmp = new float[DIMS][DIMS];
238 for (int i = 0; i < DIMS; i++)
240 for (int j = 0; j < DIMS; j++)
242 tmp[i][j] = (matrix[i][0] * mat[0][j]) + (matrix[i][1] * mat[1][j])
243 + (matrix[i][2] * mat[2][j]);
256 public static void main(String[] args)
258 RotatableMatrix m = new RotatableMatrix();
280 RotatableMatrix n = new RotatableMatrix();
302 // m.postMultiply(n.matrix);
304 // m.rotate(45,'z',new RotatableMatrix(3,3));
305 float[] vect = new float[3];
313 vect = m.vectorMultiply(vect);
315 System.out.println(vect[0] + " " + vect[1] + " " + vect[2]);
319 * Performs a vector multiplication whose result is the Point representing the
320 * input point's value vector post-multiplied by this matrix.
325 public Point vectorMultiply(Point coord)
327 float[] v = vectorMultiply(new float[] { coord.x, coord.y, coord.z });
328 return new Point(v[0], v[1], v[2]);