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