Merge branch 'master' of https://source.jalview.org/git/jalviewjs.git
[jalviewjs.git] / src / javajs / util / M3.java
1 /*
2    Copyright (C) 1997,1998,1999
3    Kenji Hiranabe, Eiwa System Management, Inc.
4
5    This program is free software.
6    Implemented by Kenji Hiranabe(hiranabe@esm.co.jp),
7    conforming to the Java(TM) 3D API specification by Sun Microsystems.
8
9    Permission to use, copy, modify, distribute and sell this software
10    and its documentation for any purpose is hereby granted without fee,
11    provided that the above copyright notice appear in all copies and
12    that both that copyright notice and this permission notice appear
13    in supporting documentation. Kenji Hiranabe and Eiwa System Management,Inc.
14    makes no representations about the suitability of this software for any
15    purpose.  It is provided "AS IS" with NO WARRANTY.
16 */
17 package javajs.util;
18
19 import java.io.Serializable;
20
21
22
23 /**
24  * A single precision floating point 3 by 3 matrix.
25  * 
26  * @author Kenji hiranabe
27  * 
28  *         additions by Bob Hanson hansonr@stolaf.edu 9/30/2012 for unique
29  *         constructor and method names for the optimization of compiled
30  *         JavaScript using Java2Script
31  *         
32  *         
33  */
34 public class M3 extends M34 implements Serializable {
35
36   /**
37    * Constructs and initializes a Matrix3f to all zeros.
38    * @j2sIgnore
39    */
40   public M3() {
41   }
42
43   /**
44    * Constructs and initializes a Matrix3f from the specified 9 element array.
45    * this.m00 =v[0], this.m01=v[1], etc.
46    * 
47    * @param v
48    *        the array of length 9 containing in order
49    * @return m
50    */
51   public static M3 newA9(float[] v) {
52     M3 m = new M3();
53     m.setA(v);
54     return m;
55   }
56   
57   /**
58    * Constructs a new matrix with the same values as the Matrix3f parameter.
59    * 
60    * @param m1
61    *        The source matrix.
62    * @return m
63    */
64   public static M3 newM3(M3 m1) {
65     M3 m = new M3();
66     if (m1 == null) {
67       m.setScale(1);
68       return m;
69     }
70     m.m00 = m1.m00;
71     m.m01 = m1.m01;
72     m.m02 = m1.m02;
73
74     m.m10 = m1.m10;
75     m.m11 = m1.m11;
76     m.m12 = m1.m12;
77
78     m.m20 = m1.m20;
79     m.m21 = m1.m21;
80     m.m22 = m1.m22;
81     return m;
82   }
83
84   /**
85    * Sets this Matrix3f to a scalar * Identity.
86    * @param scale 
87    */
88   public void setScale(float scale) {
89     clear33();
90     m00 = m11 = m22 = scale;
91   }
92
93   /**
94    * Sets the value of this matrix to the double value of the Matrix3f argument.
95    * 
96    * @param m1
97    *        the matrix3f
98    */
99   public void setM3(M34 m1) {
100     setM33(m1);
101   }
102   /**
103    * Sets the values in this Matrix3f equal to the row-major array parameter
104    * (ie, the first four elements of the array will be copied into the first row
105    * of this matrix, etc.).
106    * 
107    * @param m
108    */
109   public void setA(float m[]) {
110     m00 = m[0];
111     m01 = m[1];
112     m02 = m[2];
113     m10 = m[3];
114     m11 = m[4];
115     m12 = m[5];
116     m20 = m[6];
117     m21 = m[7];
118     m22 = m[8];
119   }
120
121   /**
122    * Sets the specified element of this matrix3d to the value provided.
123    * 
124    * @param row
125    *        the row number to be modified (zero indexed)
126    * @param col
127    *        the column number to be modified (zero indexed)
128    * @param v
129    *        the new value
130    */
131   public void setElement(int row, int col, float v) {
132     set33(row, col, v);
133   }
134
135   /**
136    * Retrieves the value at the specified row and column of this matrix.
137    * 
138    * @param row
139    *        the row number to be retrieved (zero indexed)
140    * @param col
141    *        the column number to be retrieved (zero indexed)
142    * @return the value at the indexed element
143    */
144   public float getElement(int row, int col) {
145     return get33(row, col);
146   }
147
148   /**
149    * Sets the specified row of this matrix3d to the three values provided.
150    * 
151    * @param row
152    *        the row number to be modified (zero indexed)
153    * @param x
154    *        the first column element
155    * @param y
156    *        the second column element
157    * @param z
158    *        the third column element
159    */
160   public void setRow(int row, float x, float y, float z) {
161     switch (row) {
162     case 0:
163       m00 = x;
164       m01 = y;
165       m02 = z;
166       return;
167     case 1:
168       m10 = x;
169       m11 = y;
170       m12 = z;
171       return;
172     case 2:
173       m20 = x;
174       m21 = y;
175       m22 = z;
176       return;
177     default:
178       err();
179     }
180   }
181
182   /**
183    * Sets the specified row of this matrix3d to the Vector provided.
184    * 
185    * @param row
186    *        the row number to be modified (zero indexed)
187    * @param v
188    *        the replacement row
189    */
190   public void setRowV(int row, T3 v) {
191     switch (row) {
192     case 0:
193       m00 = v.x;
194       m01 = v.y;
195       m02 = v.z;
196       return;
197     case 1:
198       m10 = v.x;
199       m11 = v.y;
200       m12 = v.z;
201       return;
202     case 2:
203       m20 = v.x;
204       m21 = v.y;
205       m22 = v.z;
206       return;
207     default:
208       err();
209     }
210   }
211
212   /**
213    * Sets the specified row of this matrix3d to the four values provided.
214    * 
215    * @param row
216    *        the row number to be modified (zero indexed)
217    * @param v
218    *        the replacement row
219    */
220   public void setRowA(int row, float v[]) {
221     setRow33(row, v);
222   }
223
224   /**
225    * Copies the matrix values in the specified row into the array parameter.
226    * 
227    * @param row
228    *        the matrix row
229    * @param v
230    *        The array into which the matrix row values will be copied
231    */
232   @Override
233   public void getRow(int row, float v[]) {
234     getRow33(row, v);
235   }
236
237   /**
238    * Sets the specified column of this matrix3d to the three values provided.
239    * 
240    * @param column
241    *        the column number to be modified (zero indexed)
242    * @param x
243    *        the first row element
244    * @param y
245    *        the second row element
246    * @param z
247    *        the third row element
248    */
249   public void setColumn3(int column, float x, float y, float z) {
250     switch (column) {
251     case 0:
252       m00 = x;
253       m10 = y;
254       m20 = z;
255       break;
256     case 1:
257       m01 = x;
258       m11 = y;
259       m21 = z;
260       break;
261     case 2:
262       m02 = x;
263       m12 = y;
264       m22 = z;
265       break;
266     default:
267       err();
268     }
269   }
270
271   /**
272    * Sets the specified column of this matrix3d to the vector provided.
273    * 
274    * @param column
275    *        the column number to be modified (zero indexed)
276    * @param v
277    *        the replacement column
278    */
279   public void setColumnV(int column, T3 v) {
280     switch (column) {
281     case 0:
282       m00 = v.x;
283       m10 = v.y;
284       m20 = v.z;
285       break;
286     case 1:
287       m01 = v.x;
288       m11 = v.y;
289       m21 = v.z;
290       break;
291     case 2:
292       m02 = v.x;
293       m12 = v.y;
294       m22 = v.z;
295       break;
296     default:
297       err();
298     }
299   }
300
301   /**
302    * Copies the matrix values in the specified column into the vector parameter.
303    * 
304    * @param column
305    *        the matrix column
306    * @param v
307    *        The vector into which the matrix row values will be copied
308    */
309   public void getColumnV(int column, T3 v) {
310     switch (column) {
311     case 0:
312       v.x = m00;
313       v.y = m10;
314       v.z = m20;
315       break;
316     case 1:
317       v.x = m01;
318       v.y = m11;
319       v.z = m21;
320       break;
321     case 2:
322       v.x = m02;
323       v.y = m12;
324       v.z = m22;
325       break;
326     default:
327       err();
328     }
329   }
330
331   /**
332    * Sets the specified column of this matrix3d to the four values provided.
333    * 
334    * @param column
335    *        the column number to be modified (zero indexed)
336    * @param v
337    *        the replacement column
338    */
339   public void setColumnA(int column, float v[]) {
340     setColumn33(column, v);
341   }
342
343   /**
344    * Copies the matrix values in the specified column into the array parameter.
345    * 
346    * @param column
347    *        the matrix column
348    * @param v
349    *        The array into which the matrix row values will be copied
350    */
351   public void getColumn(int column, float v[]) {
352     getColumn33(column, v);
353   }
354
355   /**
356    * Sets the value of this matrix to sum of itself and matrix m1.
357    * 
358    * @param m1
359    *        the other matrix
360    */
361   public void add(M3 m1) {
362     add33(m1);
363   }
364
365   /**
366    * Sets the value of this matrix to the matrix difference of itself and matrix
367    * m1 (this = this - m1).
368    * 
369    * @param m1
370    *        the other matrix
371    */
372   public void sub(M3 m1) {
373     sub33(m1);
374   }
375
376   /**
377    * Sets the value of this matrix to its transpose.
378    */
379   public void transpose() {
380     transpose33();
381   }
382
383   /**
384    * Sets the value of this matrix to the transpose of the argument matrix
385    * 
386    * @param m1
387    *        the matrix to be transposed
388    */
389   public void transposeM(M3 m1) {
390     // alias-safe
391     setM33(m1);
392     transpose33();
393   }
394
395   /**
396    * Sets the value of this matrix to the matrix inverse of the passed matrix
397    * m1.
398    * 
399    * @param m1
400    *        the matrix to be inverted
401    */
402   public void invertM(M3 m1) {
403     setM33(m1);
404     invert();
405   }
406
407   /**
408    * Sets the value of this matrix to its inverse.
409    */
410   public void invert() {
411     double s = determinant3();
412     if (s == 0.0)
413       return;
414     s = 1 / s;
415     // alias-safe way.
416     set9(m11 * m22 - m12 * m21, m02 * m21 - m01 * m22, m01 * m12 - m02 * m11,
417         m12 * m20 - m10 * m22, m00 * m22 - m02 * m20, m02 * m10 - m00 * m12,
418         m10 * m21 - m11 * m20, m01 * m20 - m00 * m21, m00 * m11 - m01 * m10);
419     scale((float) s);
420   }
421
422   /**
423    * Sets the value of this matrix to a rotation matrix about the x axis by the
424    * passed angle.
425    * 
426    * @param angle
427    *        the angle to rotate about the X axis in radians
428    * @return this
429    */
430   public M3 setAsXRotation(float angle) {
431     setXRot(angle);
432     return this;
433   }
434   
435   /**
436    * Sets the value of this matrix to a rotation matrix about the y axis by the
437    * passed angle.
438    * 
439    * @param angle
440    *        the angle to rotate about the Y axis in radians
441    * @return this
442    */
443   public M3 setAsYRotation(float angle) {
444     setYRot(angle);
445     return this;
446   }
447
448   /**
449    * Sets the value of this matrix to a rotation matrix about the z axis by the
450    * passed angle.
451    * 
452    * @param angle
453    *        the angle to rotate about the Z axis in radians
454    * @return this
455    */
456   public M3 setAsZRotation(float angle) {
457     setZRot(angle);
458     return this;
459   }
460
461   /**
462    * Multiplies each element of this matrix by a scalar.
463    * 
464    * @param scalar
465    *        The scalar multiplier.
466    */
467   public void scale(float scalar) {
468     mul33(scalar);
469   }
470
471   /**
472    * Sets the value of this matrix to the result of multiplying itself with
473    * matrix m1.
474    * 
475    * @param m1
476    *        the other matrix
477    */
478   public void mul(M3 m1) {
479     mul2(this, m1);
480   }
481
482   /**
483    * Sets the value of this matrix to the result of multiplying the two argument
484    * matrices together.
485    * 
486    * @param m1
487    *        the first matrix
488    * @param m2
489    *        the second matrix
490    */
491   public void mul2(M3 m1, M3 m2) {
492     // alias-safe way.
493     set9(m1.m00 * m2.m00 + m1.m01 * m2.m10 + m1.m02 * m2.m20, m1.m00 * m2.m01
494         + m1.m01 * m2.m11 + m1.m02 * m2.m21, m1.m00 * m2.m02 + m1.m01 * m2.m12
495         + m1.m02 * m2.m22,
496
497     m1.m10 * m2.m00 + m1.m11 * m2.m10 + m1.m12 * m2.m20, m1.m10 * m2.m01
498         + m1.m11 * m2.m11 + m1.m12 * m2.m21, m1.m10 * m2.m02 + m1.m11 * m2.m12
499         + m1.m12 * m2.m22,
500
501     m1.m20 * m2.m00 + m1.m21 * m2.m10 + m1.m22 * m2.m20, m1.m20 * m2.m01
502         + m1.m21 * m2.m11 + m1.m22 * m2.m21, m1.m20 * m2.m02 + m1.m21 * m2.m12
503         + m1.m22 * m2.m22);
504   }
505
506   /**
507    * Returns true if the Object o is of type Matrix3f and all of the data
508    * members of t1 are equal to the corresponding data members in this Matrix3f.
509    * 
510    * @param o
511    *        the object with which the comparison is made.
512    */
513   @Override
514   public boolean equals(Object o) {
515     if (!(o instanceof M3))
516       return false;
517     M3 m = (M3) o;
518     return m00 == m.m00 && m01 == m.m01 && m02 == m.m02 && m10 == m.m10
519         && m11 == m.m11 && m12 == m.m12 && m20 == m.m20 && m21 == m.m21
520         && m22 == m.m22;
521   }
522
523   /**
524    * Returns a hash number based on the data values in this object. Two
525    * different Matrix3f objects with identical data values (ie, returns true for
526    * equals(Matrix3f) ) will return the same hash number. Two objects with
527    * different data members may return the same hash value, although this is not
528    * likely.
529    * 
530    * @return the integer hash value
531    */
532   @Override
533   public int hashCode() {
534     return T3.floatToIntBits0(m00) ^ T3.floatToIntBits0(m01)
535         ^ T3.floatToIntBits0(m02) ^ T3.floatToIntBits0(m10)
536         ^ T3.floatToIntBits0(m11) ^ T3.floatToIntBits0(m12)
537         ^ T3.floatToIntBits0(m20) ^ T3.floatToIntBits0(m21)
538         ^ T3.floatToIntBits0(m22);
539   }
540
541   /**
542    * Sets this matrix to all zeros.
543    */
544   public void setZero() {
545     clear33();
546   }
547
548   /**
549    * Sets 9 values
550    * 
551    * @param m00
552    * @param m01
553    * @param m02
554    * @param m10
555    * @param m11
556    * @param m12
557    * @param m20
558    * @param m21
559    * @param m22
560    */
561   private void set9(float m00, float m01, float m02, float m10, float m11,
562                    float m12, float m20, float m21, float m22) {
563     this.m00 = m00;
564     this.m01 = m01;
565     this.m02 = m02;
566     this.m10 = m10;
567     this.m11 = m11;
568     this.m12 = m12;
569     this.m20 = m20;
570     this.m21 = m21;
571     this.m22 = m22;
572   }
573
574   /**
575    * Returns a string that contains the values of this Matrix3f.
576    * 
577    * @return the String representation
578    */
579   @Override
580   public String toString() {
581     return "[\n  [" + m00 + "\t" + m01 + "\t" + m02 + "]" + "\n  [" + m10
582         + "\t" + m11 + "\t" + m12 + "]" + "\n  [" + m20 + "\t" + m21 + "\t"
583         + m22 + "] ]";
584   }
585
586   /**
587    * Sets the value of this matrix to the matrix conversion of the single
588    * precision axis and angle argument.
589    * 
590    * @param a
591    *        the axis and angle to be converted
592    * @return this
593    */
594   public M3 setAA(A4 a) {
595     setAA33(a);
596     return this;
597   }
598
599   /**
600    * 3D ball rotation from dx dy in-plane mouse motion
601    * adapted from Andrew Hanson
602    * Computer Graphics beyond the Third Dimension:
603    * Geometry, Orientation Control, and Rendering for
604    * Graphics in Dimensions Greater than Three
605    * Course Notes for SIGGRAPH ’98
606    * http://www.cse.ohio-state.edu/~hwshen/888_su02/hanson_note.pdf
607    * 
608    * @param responseFactor Jmol uses 0.02 here
609    * @param dx
610    * @param dy
611    * @return true if successful; false if not;
612    */
613   public boolean setAsBallRotation(float responseFactor, float dx, float dy) {
614     float r = (float) Math.sqrt(dx * dx + dy * dy);
615     float th =  r * responseFactor;
616     if (th == 0) {
617       setScale(1);
618       return false;
619     }
620     float c = (float) Math.cos(th);
621     float s = (float) Math.sin(th);
622     float nx = -dy / r;
623     float ny = dx / r;
624     float c1 = c - 1;
625     m00 = 1 + c1 * nx * nx;
626     m01 = m10 = c1 * nx * ny;
627     m20 = -(m02 = s * nx);
628     m11 = 1 + c1 * ny * ny;
629     m21 = -(m12 = s * ny);
630     m22 = c;
631     return true;
632   }
633
634   public boolean isRotation() {
635     return (Math.abs(determinant3() - 1) < 0.001f);
636   }
637
638 }