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