1 module matrix_3x2d;
2 
3 import Math = math;
4 import MemUtil = mem_util;
5 
6 import matrix_2d;
7 import matrix_3d;
8 
9 import vector_2d;
10 import vector_3d;
11 
12 /*
13  * The MIT License
14  *
15  * Copyright (c) 2017-2021 DOML
16  $@#$!@ Translated by jordan4ibanez
17  *
18  * Permission is hereby granted, free of charge, to any person obtaining a copy
19  * of this software and associated documentation files (the "Software"), to deal
20  * in the Software without restriction, including without limitation the rights
21  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22  * copies of the Software, and to permit persons to whom the Software is
23  * furnished to do so, subject to the following conditions:
24  *
25  * The above copyright notice and this permission notice shall be included in
26  * all copies or substantial portions of the Software.
27  *
28  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
29  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
30  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
31  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
32  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
33  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
34  * THE SOFTWARE.
35  */
36 
37 /**
38  * Contains the definition of a 3x2 matrix of doubles, and associated functions to transform
39  * it. The matrix is column-major to match OpenGL's interpretation, and it looks like this:
40  * <p>
41  *      m00  m10  m20<br>
42  *      m01  m11  m21<br>
43  * 
44  * @author Kai Burjack
45  */
46 public struct Matrix3x2d {
47 
48     double m00 = 1.0;
49     double m01 = 0.0;
50     double m10 = 0.0;
51     
52     double m11 = 1.0;
53     double m20 = 0.0;
54     double m21 = 0.0;
55 
56     /**
57      * Create a new {@link Matrix3x2d} by setting its left 2x2 submatrix to the values of the given {@link Matrix2d}
58      * and the rest to identity.
59      *
60      * @param mat
61      *          the {@link Matrix2d}
62      */
63     this(Matrix2d mat) {
64         setMatrix2d(mat);
65     }
66 
67 
68     /**
69      * Create a new {@link Matrix3x2d} and make it a copy of the given matrix.
70      * 
71      * @param mat
72      *          the {@link Matrix3x2d} to copy the values from
73      */
74     this(Matrix3x2d mat) {
75         setMatrix3x2d(mat);
76     }
77 
78     /**
79      * Create a new 3x2 matrix using the supplied double values. The order of the parameter is column-major, 
80      * so the first two parameters specify the two elements of the first column.
81      * 
82      * @param m00
83      *          the value of m00
84      * @param m01
85      *          the value of m01
86      * @param m10
87      *          the value of m10
88      * @param m11
89      *          the value of m11
90      * @param m20
91      *          the value of m20
92      * @param m21
93      *          the value of m21
94      */
95     this(double m00, double m01,
96                       double m10, double m11,
97                       double m20, double m21) {
98         this.m00 = m00;
99         this.m01 = m01;
100         this.m10 = m10;
101         this.m11 = m11;
102         this.m20 = m20;
103         this.m21 = m21;
104     }
105 
106     /**
107      * Set the value of the matrix element at column 0 and row 0.
108      * 
109      * @param m00
110      *          the new value
111      * @return this
112      */
113     ref Matrix3x2d _m00(double m00) return {
114         this.m00 = m00;
115         return this;
116     }
117     /**
118      * Set the value of the matrix element at column 0 and row 1.
119      * 
120      * @param m01
121      *          the new value
122      * @return this
123      */
124     ref Matrix3x2d _m01(double m01) return {
125         this.m01 = m01;
126         return this;
127     }
128     /**
129      * Set the value of the matrix element at column 1 and row 0.
130      * 
131      * @param m10
132      *          the new value
133      * @return this
134      */
135     ref Matrix3x2d _m10(double m10) return {
136         this.m10 = m10;
137         return this;
138     }
139     /**
140      * Set the value of the matrix element at column 1 and row 1.
141      * 
142      * @param m11
143      *          the new value
144      * @return this
145      */
146     ref Matrix3x2d _m11(double m11) return {
147         this.m11 = m11;
148         return this;
149     }
150     /**
151      * Set the value of the matrix element at column 2 and row 0.
152      * 
153      * @param m20
154      *          the new value
155      * @return this
156      */
157     ref Matrix3x2d _m20(double m20) return {
158         this.m20 = m20;
159         return this;
160     }
161     /**
162      * Set the value of the matrix element at column 2 and row 1.
163      * 
164      * @param m21
165      *          the new value
166      * @return this
167      */
168     ref Matrix3x2d _m21(double m21) return {
169         this.m21 = m21;
170         return this;
171     }
172 
173     /**
174      * Set the elements of this matrix to the ones in <code>m</code>.
175      * 
176      * @param m
177      *          the matrix to copy the elements from
178      * @return this
179      */
180     ref public Matrix3x2d set(Matrix3x2d m) return {
181         setMatrix3x2d(m);
182         return this;
183     }
184     private void setMatrix3x2d(Matrix3x2d mat) {
185         m00 = mat.m00;
186         m01 = mat.m01;
187         m10 = mat.m10;
188         m11 = mat.m11;
189         m20 = mat.m20;
190         m21 = mat.m21;
191     }
192 
193     /**
194      * Set the left 2x2 submatrix of this {@link Matrix3x2d} to the given {@link Matrix2d} and don't change the other elements.
195      *
196      * @param m
197      *          the 2x2 matrix
198      * @return this
199      */
200     ref public Matrix3x2d set(Matrix2d m) return {
201         setMatrix2d(m);
202         return this;
203     }
204     private void setMatrix2d(Matrix2d mat) {
205         m00 = mat.m00;
206         m01 = mat.m01;
207         m10 = mat.m10;
208         m11 = mat.m11;
209     }
210 
211     /**
212      * Multiply this matrix by the supplied <code>right</code> matrix by assuming a third row in
213      * both matrices of <code>(0, 0, 1)</code>.
214      * <p>
215      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix,
216      * then the new matrix will be <code>M * R</code>. So when transforming a
217      * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
218      * transformation of the right matrix will be applied first!
219      * 
220      * @param right
221      *          the right operand of the matrix multiplication
222      * @return this
223      */
224     ref public Matrix3x2d mul(Matrix3x2d right) return {
225         mul(right, this);
226         return this;
227     }
228 
229     /**
230      * Multiply this matrix by the supplied <code>right</code> matrix by assuming a third row in
231      * both matrices of <code>(0, 0, 1)</code> and store the result in <code>dest</code>.
232      * <p>
233      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix,
234      * then the new matrix will be <code>M * R</code>. So when transforming a
235      * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the
236      * transformation of the right matrix will be applied first!
237      * 
238      * @param right
239      *          the right operand of the matrix multiplication
240      * @param dest
241      *          will hold the result
242      * @return dest
243      */
244     public Matrix3x2d mul(Matrix3x2d right, ref Matrix3x2d dest) {
245         double nm00 = m00 * right.m00 + m10 * right.m01;
246         double nm01 = m01 * right.m00 + m11 * right.m01;
247         double nm10 = m00 * right.m10 + m10 * right.m11;
248         double nm11 = m01 * right.m10 + m11 * right.m11;
249         double nm20 = m00 * right.m20 + m10 * right.m21 + m20;
250         double nm21 = m01 * right.m20 + m11 * right.m21 + m21;
251         dest.m00 = nm00;
252         dest.m01 = nm01;
253         dest.m10 = nm10;
254         dest.m11 = nm11;
255         dest.m20 = nm20;
256         dest.m21 = nm21;
257         return dest;
258     }
259 
260     /**
261      * Pre-multiply this matrix by the supplied <code>left</code> matrix and store the result in <code>this</code>.
262      * <p>
263      * If <code>M</code> is <code>this</code> matrix and <code>L</code> the <code>left</code> matrix,
264      * then the new matrix will be <code>L * M</code>. So when transforming a
265      * vector <code>v</code> with the new matrix by using <code>L * M * v</code>, the
266      * transformation of <code>this</code> matrix will be applied first!
267      *
268      * @param left
269      *          the left operand of the matrix multiplication
270      * @return this
271      */
272     ref public Matrix3x2d mulLocal(Matrix3x2d left) return {
273        mulLocal(left, this);
274        return this;
275     }
276 
277     public Matrix3x2d mulLocal(Matrix3x2d left, ref Matrix3x2d dest) {
278         double nm00 = left.m00 * m00 + left.m10 * m01;
279         double nm01 = left.m01 * m00 + left.m11 * m01;
280         double nm10 = left.m00 * m10 + left.m10 * m11;
281         double nm11 = left.m01 * m10 + left.m11 * m11;
282         double nm20 = left.m00 * m20 + left.m10 * m21 + left.m20;
283         double nm21 = left.m01 * m20 + left.m11 * m21 + left.m21;
284         dest.m00 = nm00;
285         dest.m01 = nm01;
286         dest.m10 = nm10;
287         dest.m11 = nm11;
288         dest.m20 = nm20;
289         dest.m21 = nm21;
290         return dest;
291     }
292 
293     /**
294      * Set the values within this matrix to the supplied double values. The result looks like this:
295      * <p>
296      * m00, m10, m20<br>
297      * m01, m11, m21<br>
298      * 
299      * @param m00
300      *          the new value of m00
301      * @param m01
302      *          the new value of m01
303      * @param m10
304      *          the new value of m10
305      * @param m11
306      *          the new value of m11
307      * @param m20
308      *          the new value of m20
309      * @param m21
310      *          the new value of m21
311      * @return this
312      */
313     ref public Matrix3x2d set(double m00, double m01, 
314                           double m10, double m11, 
315                           double m20, double m21) return {
316         this.m00 = m00;
317         this.m01 = m01;
318         this.m10 = m10;
319         this.m11 = m11;
320         this.m20 = m20;
321         this.m21 = m21;
322         return this;
323     }
324 
325     /**
326      * Set the values in this matrix based on the supplied double array. The result looks like this:
327      * <p>
328      * 0, 2, 4<br>
329      * 1, 3, 5<br>
330      * 
331      * This method only uses the first 6 values, all others are ignored.
332      * 
333      * @param m
334      *          the array to read the matrix values from
335      * @return this
336      */
337     ref public Matrix3x2d set(double[] m) return {
338         MemUtil.copy(m, 0, this);
339         return this;
340     }
341 
342     /**
343      * Return the determinant of this matrix.
344      * 
345      * @return the determinant
346      */
347     public double determinant() {
348         return m00 * m11 - m01 * m10;
349     }
350 
351     /**
352      * Invert this matrix by assuming a third row in this matrix of <code>(0, 0, 1)</code>.
353      *
354      * @return this
355      */
356     ref public Matrix3x2d invert() return {
357         invert(this);
358         return this;
359     }
360 
361     /**
362      * Invert the <code>this</code> matrix by assuming a third row in this matrix of <code>(0, 0, 1)</code>
363      * and store the result in <code>dest</code>.
364      * 
365      * @param dest
366      *             will hold the result
367      * @return dest
368      */
369     public Matrix3x2d invert(ref Matrix3x2d dest) {
370         // client must make sure that matrix is invertible
371         double s = 1.0 / (m00 * m11 - m01 * m10);
372         double nm00 =  m11 * s;
373         double nm01 = -m01 * s;
374         double nm10 = -m10 * s;
375         double nm11 =  m00 * s;
376         double nm20 = (m10 * m21 - m20 * m11) * s;
377         double nm21 = (m20 * m01 - m00 * m21) * s;
378         dest.m00 = nm00;
379         dest.m01 = nm01;
380         dest.m10 = nm10;
381         dest.m11 = nm11;
382         dest.m20 = nm20;
383         dest.m21 = nm21;
384         return dest;
385     }
386 
387     /**
388      * Set this matrix to be a simple translation matrix in a two-dimensional coordinate system.
389      * <p>
390      * The resulting matrix can be multiplied against another transformation
391      * matrix to obtain an additional translation.
392      * <p>
393      * In order to apply a translation via to an already existing transformation
394      * matrix, use {@link #translate(double, double) translate()} instead.
395      * 
396      * @see #translate(double, double)
397      * 
398      * @param x
399      *          the units to translate in x
400      * @param y
401      *          the units to translate in y
402      * @return this
403      */
404     ref public Matrix3x2d translation(double x, double y) return {
405         m00 = 1.0;
406         m01 = 0.0;
407         m10 = 0.0;
408         m11 = 1.0;
409         m20 = x;
410         m21 = y;
411         return this;
412     }
413 
414     /**
415      * Set this matrix to be a simple translation matrix in a two-dimensional coordinate system.
416      * <p>
417      * The resulting matrix can be multiplied against another transformation
418      * matrix to obtain an additional translation.
419      * <p>
420      * In order to apply a translation via to an already existing transformation
421      * matrix, use {@link #translate(Vector2d) translate()} instead.
422      * 
423      * @see #translate(Vector2d)
424      * 
425      * @param offset
426      *          the translation
427      * @return this
428      */
429     ref public Matrix3x2d translation(ref Vector2d offset) return {
430         return translation(offset.x, offset.y);
431     }
432 
433     /**
434      * Set only the translation components of this matrix <code>(m20, m21)</code> to the given values <code>(x, y)</code>.
435      * <p>
436      * To build a translation matrix instead, use {@link #translation(double, double)}.
437      * To apply a translation to another matrix, use {@link #translate(double, double)}.
438      * 
439      * @see #translation(double, double)
440      * @see #translate(double, double)
441      * 
442      * @param x
443      *          the offset to translate in x
444      * @param y
445      *          the offset to translate in y
446      * @return this
447      */
448     ref public Matrix3x2d setTranslation(double x, double y) return {
449         m20 = x;
450         m21 = y;
451         return this;
452     }
453 
454     /**
455      * Set only the translation components of this matrix <code>(m20, m21)</code> to the given values <code>(offset.x, offset.y)</code>.
456      * <p>
457      * To build a translation matrix instead, use {@link #translation(Vector2d)}.
458      * To apply a translation to another matrix, use {@link #translate(Vector2d)}.
459      * 
460      * @see #translation(Vector2d)
461      * @see #translate(Vector2d)
462      * 
463      * @param offset
464      *          the new translation to set
465      * @return this
466      */
467     ref public Matrix3x2d setTranslation(ref Vector2d offset) return {
468         return setTranslation(offset.x, offset.y);
469     }
470 
471     /**
472      * Apply a translation to this matrix by translating by the given number of units in x and y and store the result
473      * in <code>dest</code>.
474      * <p>
475      * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation
476      * matrix, then the new matrix will be <code>M * T</code>. So when
477      * transforming a vector <code>v</code> with the new matrix by using
478      * <code>M * T * v</code>, the translation will be applied first!
479      * <p>
480      * In order to set the matrix to a translation transformation without post-multiplying
481      * it, use {@link #translation(double, double)}.
482      * 
483      * @see #translation(double, double)
484      * 
485      * @param x
486      *          the offset to translate in x
487      * @param y
488      *          the offset to translate in y
489      * @param dest
490      *          will hold the result
491      * @return dest
492      */
493     public Matrix3x2d translate(double x, double y, ref Matrix3x2d dest) {
494         double rm20 = x;
495         double rm21 = y;
496         dest.m20 = m00 * rm20 + m10 * rm21 + m20;
497         dest.m21 = m01 * rm20 + m11 * rm21 + m21;
498         dest.m00 = m00;
499         dest.m01 = m01;
500         dest.m10 = m10;
501         dest.m11 = m11;
502         return dest;
503     }
504 
505     /**
506      * Apply a translation to this matrix by translating by the given number of units in x and y.
507      * <p>
508      * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation
509      * matrix, then the new matrix will be <code>M * T</code>. So when
510      * transforming a vector <code>v</code> with the new matrix by using
511      * <code>M * T * v</code>, the translation will be applied first!
512      * <p>
513      * In order to set the matrix to a translation transformation without post-multiplying
514      * it, use {@link #translation(double, double)}.
515      * 
516      * @see #translation(double, double)
517      * 
518      * @param x
519      *          the offset to translate in x
520      * @param y
521      *          the offset to translate in y
522      * @return this
523      */
524     ref public Matrix3x2d translate(double x, double y) return {
525         translate(x, y, this);
526         return this;
527     }
528 
529     /**
530      * Apply a translation to this matrix by translating by the given number of units in x and y, and
531      * store the result in <code>dest</code>.
532      * <p>
533      * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation
534      * matrix, then the new matrix will be <code>M * T</code>. So when
535      * transforming a vector <code>v</code> with the new matrix by using
536      * <code>M * T * v</code>, the translation will be applied first!
537      * <p>
538      * In order to set the matrix to a translation transformation without post-multiplying
539      * it, use {@link #translation(Vector2d)}.
540      * 
541      * @see #translation(Vector2d)
542      * 
543      * @param offset
544      *          the offset to translate
545      * @param dest
546      *          will hold the result
547      * @return dest
548      */
549     public Matrix3x2d translate(Vector2d offset, ref Matrix3x2d dest) {
550         return dest.translate(offset.x, offset.y, dest);
551     }
552 
553     /**
554      * Apply a translation to this matrix by translating by the given number of units in x and y.
555      * <p>
556      * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation
557      * matrix, then the new matrix will be <code>M * T</code>. So when
558      * transforming a vector <code>v</code> with the new matrix by using
559      * <code>M * T * v</code>, the translation will be applied first!
560      * <p>
561      * In order to set the matrix to a translation transformation without post-multiplying
562      * it, use {@link #translation(Vector2d)}.
563      * 
564      * @see #translation(Vector2d)
565      * 
566      * @param offset
567      *          the offset to translate
568      * @return this
569      */
570     ref public Matrix3x2d translate(Vector2d offset) return {
571         translate(offset.x, offset.y, this);
572         return this;
573     }
574 
575     /**
576      * Pre-multiply a translation to this matrix by translating by the given number of
577      * units in x and y.
578      * <p>
579      * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation
580      * matrix, then the new matrix will be <code>T * M</code>. So when
581      * transforming a vector <code>v</code> with the new matrix by using
582      * <code>T * M * v</code>, the translation will be applied last!
583      * <p>
584      * In order to set the matrix to a translation transformation without pre-multiplying
585      * it, use {@link #translation(Vector2d)}.
586      * 
587      * @see #translation(Vector2d)
588      * 
589      * @param offset
590      *          the number of units in x and y by which to translate
591      * @return this
592      */
593     ref public Matrix3x2d translateLocal(Vector2d offset) return {
594         return translateLocal(offset.x, offset.y);
595     }
596 
597     /**
598      * Pre-multiply a translation to this matrix by translating by the given number of
599      * units in x and y and store the result in <code>dest</code>.
600      * <p>
601      * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation
602      * matrix, then the new matrix will be <code>T * M</code>. So when
603      * transforming a vector <code>v</code> with the new matrix by using
604      * <code>T * M * v</code>, the translation will be applied last!
605      * <p>
606      * In order to set the matrix to a translation transformation without pre-multiplying
607      * it, use {@link #translation(Vector2d)}.
608      * 
609      * @see #translation(Vector2d)
610      * 
611      * @param offset
612      *          the number of units in x and y by which to translate
613      * @param dest
614      *          will hold the result
615      * @return dest
616      */
617     public Matrix3x2d translateLocal(Vector2d offset, ref Matrix3x2d dest) {
618         return translateLocal(offset.x, offset.y, dest);
619     }
620 
621     /**
622      * Pre-multiply a translation to this matrix by translating by the given number of
623      * units in x and y and store the result in <code>dest</code>.
624      * <p>
625      * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation
626      * matrix, then the new matrix will be <code>T * M</code>. So when
627      * transforming a vector <code>v</code> with the new matrix by using
628      * <code>T * M * v</code>, the translation will be applied last!
629      * <p>
630      * In order to set the matrix to a translation transformation without pre-multiplying
631      * it, use {@link #translation(double, double)}.
632      * 
633      * @see #translation(double, double)
634      * 
635      * @param x
636      *          the offset to translate in x
637      * @param y
638      *          the offset to translate in y
639      * @param dest
640      *          will hold the result
641      * @return dest
642      */
643     public Matrix3x2d translateLocal(double x, double y, ref Matrix3x2d dest) {
644         dest.m00 = m00;
645         dest.m01 = m01;
646         dest.m10 = m10;
647         dest.m11 = m11;
648         dest.m20 = m20 + x;
649         dest.m21 = m21 + y;
650         return dest;
651     }
652 
653     /**
654      * Pre-multiply a translation to this matrix by translating by the given number of
655      * units in x and y.
656      * <p>
657      * If <code>M</code> is <code>this</code> matrix and <code>T</code> the translation
658      * matrix, then the new matrix will be <code>T * M</code>. So when
659      * transforming a vector <code>v</code> with the new matrix by using
660      * <code>T * M * v</code>, the translation will be applied last!
661      * <p>
662      * In order to set the matrix to a translation transformation without pre-multiplying
663      * it, use {@link #translation(double, double)}.
664      * 
665      * @see #translation(double, double)
666      * 
667      * @param x
668      *          the offset to translate in x
669      * @param y
670      *          the offset to translate in y
671      * @return this
672      */
673     ref public Matrix3x2d translateLocal(double x, double y) return {
674         translateLocal(x, y, this);
675         return this;
676     }
677 
678     /**
679      * Get the current values of <code>this</code> matrix and store them into
680      * <code>dest</code>.
681      * <p>
682      * This is the reverse method of {@link #set(Matrix3x2d)} and allows to obtain
683      * intermediate calculation results when chaining multiple transformations.
684      * 
685      * @see #set(Matrix3x2d)
686      * 
687      * @param dest
688      *          the destination matrix
689      * @return dest
690      */
691     public Matrix3x2d get(ref Matrix3x2d dest) {
692         return dest.set(this);
693     }
694 
695 
696     /**
697      * Store this matrix into the supplied double array in column-major order at the given offset.
698      * 
699      * @param arr
700      *          the array to write the matrix values into
701      * @param offset
702      *          the offset into the array
703      * @return the passed in array
704      */
705     public double[] get(double[] arr, int offset) {
706         MemUtil.copy(this, arr, offset);
707         return arr;
708     }
709 
710     /**
711      * Store this matrix into the supplied double array in column-major order.
712      * <p>
713      * In order to specify an explicit offset into the array, use the method {@link #get(double[], int)}.
714      * 
715      * @see #get(double[], int)
716      * 
717      * @param arr
718      *          the array to write the matrix values into
719      * @return the passed in array
720      */
721     public double[] get(double[] arr) {
722         return get(arr, 0);
723     }
724 
725     /**
726      * Store this matrix as an equivalent 3x3 matrix in column-major order into the supplied float array at the given offset.
727      * 
728      * @param arr
729      *          the array to write the matrix values into
730      * @param offset
731      *          the offset into the array
732      * @return the passed in array
733      */
734     public double[] get3x3(double[] arr, int offset) {
735         MemUtil.copy3x3(this, arr, offset);
736         return arr;
737     }
738 
739     /**
740      * Store this matrix as an equivalent 3x3 matrix in column-major order into the supplied float array.
741      * <p>
742      * In order to specify an explicit offset into the array, use the method {@link #get3x3(double[], int)}.
743      * 
744      * @see #get3x3(double[], int)
745      * 
746      * @param arr
747      *          the array to write the matrix values into
748      * @return the passed in array
749      */
750     public double[] get3x3(double[] arr) {
751         return get3x3(arr, 0);
752     }
753 
754     /**
755      * Store this matrix as an equivalent 4x4 matrix in column-major order into the supplied float array at the given offset.
756      * 
757      * @param arr
758      *          the array to write the matrix values into
759      * @param offset
760      *          the offset into the array
761      * @return the passed in array
762      */
763     public double[] get4x4(double[] arr, int offset) {
764         MemUtil.copy4x4(this, arr, offset);
765         return arr;
766     }
767 
768     /**
769      * Store this matrix as an equivalent 4x4 matrix in column-major order into the supplied float array.
770      * <p>
771      * In order to specify an explicit offset into the array, use the method {@link #get4x4(double[], int)}.
772      * 
773      * @see #get4x4(double[], int)
774      * 
775      * @param arr
776      *          the array to write the matrix values into
777      * @return the passed in array
778      */
779     public double[] get4x4(double[] arr) {
780         return get4x4(arr, 0);
781     }
782 
783     /**
784      * Set all values within this matrix to zero.
785      * 
786      * @return this
787      */
788     ref public Matrix3x2d zero() return {
789         MemUtil.zero(this);
790         return this;
791     }
792 
793     /**
794      * Set this matrix to the identity.
795      * 
796      * @return this
797      */
798     ref public Matrix3x2d identity() return {
799         MemUtil.identity(this);
800         return this;
801     }
802 
803     /**
804      * Apply scaling to this matrix by scaling the unit axes by the given x and y and store the result in <code>dest</code>.
805      * <p>
806      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
807      * then the new matrix will be <code>M * S</code>. So when transforming a
808      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the scaling will be applied first!
809      * 
810      * @param x
811      *            the factor of the x component
812      * @param y
813      *            the factor of the y component
814      * @param dest
815      *            will hold the result
816      * @return dest
817      */
818     public Matrix3x2d scale(double x, double y, ref Matrix3x2d dest) {
819         dest.m00 = m00 * x;
820         dest.m01 = m01 * x;
821         dest.m10 = m10 * y;
822         dest.m11 = m11 * y;
823         dest.m20 = m20;
824         dest.m21 = m21;
825         return dest;
826     }
827 
828     /**
829      * Apply scaling to this matrix by scaling the base axes by the given x and y factors.
830      * <p>
831      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
832      * then the new matrix will be <code>M * S</code>. So when transforming a
833      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the scaling will be applied first!
834      * 
835      * @param x
836      *            the factor of the x component
837      * @param y
838      *            the factor of the y component
839      * @return this
840      */
841     ref public Matrix3x2d scale(double x, double y) return {
842         scale(x, y, this);
843         return this;
844     }
845 
846     /**
847      * Apply scaling to this matrix by scaling the base axes by the given <code>xy</code> factors.
848      * <p>
849      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
850      * then the new matrix will be <code>M * S</code>. So when transforming a
851      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the scaling will be applied first!
852      * 
853      * @param xy
854      *            the factors of the x and y component, respectively
855      * @return this
856      */
857     ref public Matrix3x2d scale(Vector2d xy) return {
858         scale(xy.x, xy.y, this);
859         return this;
860     }
861 
862     /**
863      * Apply scaling to this matrix by scaling the base axes by the given <code>xy</code> factors
864      * and store the result in <code>dest</code>.
865      * <p>
866      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
867      * then the new matrix will be <code>M * S</code>. So when transforming a
868      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the scaling will be applied first!
869      * 
870      * @param xy
871      *            the factors of the x and y component, respectively
872      * @param dest
873      *            will hold the result
874      * @return dest
875      */
876     public Matrix3x2d scale(Vector2d xy, ref Matrix3x2d dest) {
877         return scale(xy.x, xy.y, dest);
878     }
879 
880     /**
881      * Apply scaling to this matrix by uniformly scaling the two base axes by the given <code>xy</code> factor
882      * and store the result in <code>dest</code>.
883      * <p>
884      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
885      * then the new matrix will be <code>M * S</code>. So when transforming a
886      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the scaling will be applied first!
887      * 
888      * @see #scale(double, double, Matrix3x2d)
889      * 
890      * @param xy
891      *            the factor for the two components
892      * @param dest
893      *            will hold the result
894      * @return dest
895      */
896     public Matrix3x2d scale(double xy, ref Matrix3x2d dest) {
897         return scale(xy, xy, dest);
898     }
899 
900     /**
901      * Apply scaling to this matrix by uniformly scaling the two base axes by the given <code>xyz</code> factor.
902      * <p>
903      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
904      * then the new matrix will be <code>M * S</code>. So when transforming a
905      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the scaling will be applied first!
906      * 
907      * @see #scale(double, double)
908      * 
909      * @param xy
910      *            the factor for the two components
911      * @return this
912      */
913     ref public Matrix3x2d scale(double xy) return {
914         return scale(xy, xy);
915     }
916 
917     public Matrix3x2d scaleLocal(double x, double y, ref Matrix3x2d dest) {
918         dest.m00 = x * m00;
919         dest.m01 = y * m01;
920         dest.m10 = x * m10;
921         dest.m11 = y * m11;
922         dest.m20 = x * m20;
923         dest.m21 = y * m21;
924         return dest;
925     }
926 
927     /**
928      * Pre-multiply scaling to this matrix by scaling the base axes by the given x and y factors.
929      * <p>
930      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
931      * then the new matrix will be <code>S * M</code>. So when transforming a
932      * vector <code>v</code> with the new matrix by using <code>S * M * v</code>, the
933      * scaling will be applied last!
934      * 
935      * @param x
936      *            the factor of the x component
937      * @param y
938      *            the factor of the y component
939      * @return this
940      */
941     ref public Matrix3x2d scaleLocal(double x, double y) return {
942         scaleLocal(x, y, this);
943         return this;
944     }
945 
946     public Matrix3x2d scaleLocal(double xy, ref Matrix3x2d dest) {
947         return scaleLocal(xy, xy, dest);
948     }
949 
950     /**
951      * Pre-multiply scaling to this matrix by scaling the base axes by the given xy factor.
952      * <p>
953      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
954      * then the new matrix will be <code>S * M</code>. So when transforming a
955      * vector <code>v</code> with the new matrix by using <code>S * M * v</code>, the
956      * scaling will be applied last!
957      * 
958      * @param xy
959      *            the factor of the x and y component
960      * @return this
961      */
962     ref public Matrix3x2d scaleLocal(double xy) return {
963         scaleLocal(xy, xy, this);
964         return this;
965     }
966 
967     /**
968      * Apply scaling to <code>this</code> matrix by scaling the base axes by the given sx and
969      * sy factors while using <code>(ox, oy)</code> as the scaling origin, and store the result in <code>dest</code>.
970      * <p>
971      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
972      * then the new matrix will be <code>M * S</code>. So when transforming a
973      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>
974      * , the scaling will be applied first!
975      * <p>
976      * This method is equivalent to calling: <code>translate(ox, oy, dest).scale(sx, sy).translate(-ox, -oy)</code>
977      * 
978      * @param sx
979      *            the scaling factor of the x component
980      * @param sy
981      *            the scaling factor of the y component
982      * @param ox
983      *            the x coordinate of the scaling origin
984      * @param oy
985      *            the y coordinate of the scaling origin
986      * @param dest
987      *            will hold the result
988      * @return dest
989      */
990     public Matrix3x2d scaleAround(double sx, double sy, double ox, double oy, ref Matrix3x2d dest) {
991         double nm20 = m00 * ox + m10 * oy + m20;
992         double nm21 = m01 * ox + m11 * oy + m21;
993         dest.m00 = m00 * sx;
994         dest.m01 = m01 * sx;
995         dest.m10 = m10 * sy;
996         dest.m11 = m11 * sy;
997         dest.m20 = dest.m00 * -ox + dest.m10 * -oy + nm20;
998         dest.m21 = dest.m01 * -ox + dest.m11 * -oy + nm21;
999         return dest;
1000     }
1001 
1002     /**
1003      * Apply scaling to this matrix by scaling the base axes by the given sx and
1004      * sy factors while using <code>(ox, oy)</code> as the scaling origin.
1005      * <p>
1006      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
1007      * then the new matrix will be <code>M * S</code>. So when transforming a
1008      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the
1009      * scaling will be applied first!
1010      * <p>
1011      * This method is equivalent to calling: <code>translate(ox, oy).scale(sx, sy).translate(-ox, -oy)</code>
1012      * 
1013      * @param sx
1014      *            the scaling factor of the x component
1015      * @param sy
1016      *            the scaling factor of the y component
1017      * @param ox
1018      *            the x coordinate of the scaling origin
1019      * @param oy
1020      *            the y coordinate of the scaling origin
1021      * @return this
1022      */
1023     ref public Matrix3x2d scaleAround(double sx, double sy, double ox, double oy) return {
1024         scaleAround(sx, sy, ox, oy, this);
1025         return this;
1026     }
1027 
1028     /**
1029      * Apply scaling to this matrix by scaling the base axes by the given <code>factor</code>
1030      * while using <code>(ox, oy)</code> as the scaling origin,
1031      * and store the result in <code>dest</code>.
1032      * <p>
1033      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
1034      * then the new matrix will be <code>M * S</code>. So when transforming a
1035      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the
1036      * scaling will be applied first!
1037      * <p>
1038      * This method is equivalent to calling: <code>translate(ox, oy, dest).scale(factor).translate(-ox, -oy)</code>
1039      * 
1040      * @param factor
1041      *            the scaling factor for all three axes
1042      * @param ox
1043      *            the x coordinate of the scaling origin
1044      * @param oy
1045      *            the y coordinate of the scaling origin
1046      * @param dest
1047      *            will hold the result
1048      * @return this
1049      */
1050     ref public Matrix3x2d scaleAround(double factor, double ox, double oy, ref Matrix3x2d dest) return {
1051         scaleAround(factor, factor, ox, oy, this);
1052         return this;
1053     }
1054 
1055     /**
1056      * Apply scaling to this matrix by scaling the base axes by the given <code>factor</code>
1057      * while using <code>(ox, oy)</code> as the scaling origin.
1058      * <p>
1059      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
1060      * then the new matrix will be <code>M * S</code>. So when transforming a
1061      * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the
1062      * scaling will be applied first!
1063      * <p>
1064      * This method is equivalent to calling: <code>translate(ox, oy).scale(factor).translate(-ox, -oy)</code>
1065      * 
1066      * @param factor
1067      *            the scaling factor for all axes
1068      * @param ox
1069      *            the x coordinate of the scaling origin
1070      * @param oy
1071      *            the y coordinate of the scaling origin
1072      * @return this
1073      */
1074     ref public Matrix3x2d scaleAround(double factor, double ox, double oy) return {
1075         scaleAround(factor, factor, ox, oy, this);
1076         return this;
1077     }
1078 
1079     public Matrix3x2d scaleAroundLocal(double sx, double sy, double ox, double oy, ref Matrix3x2d dest) {
1080         dest.m00 = sx * m00;
1081         dest.m01 = sy * m01;
1082         dest.m10 = sx * m10;
1083         dest.m11 = sy * m11;
1084         dest.m20 = sx * m20 - sx * ox + ox;
1085         dest.m21 = sy * m21 - sy * oy + oy;
1086         return dest;
1087     }
1088 
1089     public Matrix3x2d scaleAroundLocal(double factor, double ox, double oy, ref Matrix3x2d dest) {
1090         return scaleAroundLocal(factor, factor, ox, oy, dest);
1091     }
1092 
1093     /**
1094      * Pre-multiply scaling to this matrix by scaling the base axes by the given sx and
1095      * sy factors while using <code>(ox, oy)</code> as the scaling origin.
1096      * <p>
1097      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
1098      * then the new matrix will be <code>S * M</code>. So when transforming a
1099      * vector <code>v</code> with the new matrix by using <code>S * M * v</code>, the
1100      * scaling will be applied last!
1101      * <p>
1102      * This method is equivalent to calling: <code>new Matrix3x2d().translate(ox, oy).scale(sx, sy).translate(-ox, -oy).mul(this, this)</code>
1103      * 
1104      * @param sx
1105      *            the scaling factor of the x component
1106      * @param sy
1107      *            the scaling factor of the y component
1108      * @param sz
1109      *            the scaling factor of the z component
1110      * @param ox
1111      *            the x coordinate of the scaling origin
1112      * @param oy
1113      *            the y coordinate of the scaling origin
1114      * @param oz
1115      *            the z coordinate of the scaling origin
1116      * @return this
1117      */
1118     ref public Matrix3x2d scaleAroundLocal(double sx, double sy, double sz, double ox, double oy, double oz) return {
1119         scaleAroundLocal(sx, sy, ox, oy, this);
1120         return this;
1121     }
1122 
1123     /**
1124      * Pre-multiply scaling to this matrix by scaling the base axes by the given <code>factor</code>
1125      * while using <code>(ox, oy)</code> as the scaling origin.
1126      * <p>
1127      * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix,
1128      * then the new matrix will be <code>S * M</code>. So when transforming a
1129      * vector <code>v</code> with the new matrix by using <code>S * M * v</code>, the
1130      * scaling will be applied last!
1131      * <p>
1132      * This method is equivalent to calling: <code>new Matrix3x2d().translate(ox, oy).scale(factor).translate(-ox, -oy).mul(this, this)</code>
1133      * 
1134      * @param factor
1135      *            the scaling factor for all three axes
1136      * @param ox
1137      *            the x coordinate of the scaling origin
1138      * @param oy
1139      *            the y coordinate of the scaling origin
1140      * @return this
1141      */
1142     ref public Matrix3x2d scaleAroundLocal(double factor, double ox, double oy) return {
1143         scaleAroundLocal(factor, factor, ox, oy, this);
1144         return this;
1145     }
1146 
1147     /**
1148      * Set this matrix to be a simple scale matrix, which scales the two base axes uniformly by the given factor.
1149      * <p>
1150      * The resulting matrix can be multiplied against another transformation
1151      * matrix to obtain an additional scaling.
1152      * <p>
1153      * In order to post-multiply a scaling transformation directly to a matrix, use {@link #scale(double) scale()} instead.
1154      * 
1155      * @see #scale(double)
1156      * 
1157      * @param factor
1158      *             the scale factor in x and y
1159      * @return this
1160      */
1161     ref public Matrix3x2d scaling(double factor) return {
1162         return scaling(factor, factor);
1163     }
1164 
1165     /**
1166      * Set this matrix to be a simple scale matrix.
1167      * 
1168      * @param x
1169      *             the scale in x
1170      * @param y
1171      *             the scale in y
1172      * @return this
1173      */
1174     ref public Matrix3x2d scaling(double x, double y) return {
1175         m00 = x;
1176         m01 = 0.0;
1177         m10 = 0.0;
1178         m11 = y;
1179         m20 = 0.0;
1180         m21 = 0.0;
1181         return this;
1182     }
1183 
1184     /**
1185      * Set this matrix to a rotation matrix which rotates the given radians.
1186      * <p>
1187      * The resulting matrix can be multiplied against another transformation
1188      * matrix to obtain an additional rotation.
1189      * <p>
1190      * In order to apply the rotation transformation to an existing transformation,
1191      * use {@link #rotate(double) rotate()} instead.
1192      * 
1193      * @see #rotate(double)
1194      * 
1195      * @param angle
1196      *          the angle in radians
1197      * @return this
1198      */
1199     ref public Matrix3x2d rotation(double angle) return {
1200         double cos = Math.cos(angle);
1201         double sin = Math.sin(angle);
1202         m00 = cos;
1203         m10 = -sin;
1204         m20 = 0.0;
1205         m01 = sin;
1206         m11 = cos;
1207         m21 = 0.0;
1208         return this;
1209     }
1210 
1211     /**
1212      * Transform/multiply the given vector by this matrix by assuming a third row in this matrix of <code>(0, 0, 1)</code>
1213      * and store the result in that vector.
1214      * 
1215      * @see Vector3d#mul(Matrix3x2d)
1216      * 
1217      * @param v
1218      *          the vector to transform and to hold the final result
1219      * @return v
1220      */
1221     public Vector3d transform(ref Vector3d v) {
1222         return v.mul(this);
1223     }
1224 
1225     /**
1226      * Transform/multiply the given vector by this matrix by assuming a third row in this matrix of <code>(0, 0, 1)</code>
1227      * and store the result in <code>dest</code>.
1228      * 
1229      * @see Vector3d#mul(Matrix3x2d, Vector3d)
1230      * 
1231      * @param v
1232      *          the vector to transform
1233      * @param dest
1234      *          will contain the result
1235      * @return dest
1236      */
1237     public Vector3d transform(Vector3d v, ref Vector3d dest) {
1238         return v.mul(this, dest);
1239     }
1240 
1241     /**
1242      * Transform/multiply the given vector <code>(x, y, z)</code> by this matrix and store the result in <code>dest</code>.
1243      * 
1244      * @param x
1245      *          the x component of the vector to transform
1246      * @param y
1247      *          the y component of the vector to transform
1248      * @param z
1249      *          the z component of the vector to transform
1250      * @param dest
1251      *          will contain the result
1252      * @return dest
1253      */
1254     public Vector3d transform(double x, double y, double z, ref Vector3d dest) {
1255        return dest.set(m00 * x + m10 * y + m20 * z, m01 * x + m11 * y + m21 * z, z);
1256     }
1257 
1258     /**
1259      * Transform/multiply the given 2D-vector, as if it was a 3D-vector with z=1, by
1260      * this matrix and store the result in that vector.
1261      * <p>
1262      * The given 2D-vector is treated as a 3D-vector with its z-component being 1.0, so it
1263      * will represent a position/location in 2D-space rather than a direction.
1264      * <p>
1265      * In order to store the result in another vector, use {@link #transformPosition(Vector2d, Vector2d)}.
1266      * 
1267      * @see #transformPosition(Vector2d, Vector2d)
1268      * @see #transform(Vector3d)
1269      * 
1270      * @param v
1271      *          the vector to transform and to hold the final result
1272      * @return v
1273      */
1274     public Vector2d transformPosition(ref Vector2d v) {
1275         v.set(m00 * v.x + m10 * v.y + m20,
1276               m01 * v.x + m11 * v.y + m21);
1277         return v;
1278     }
1279 
1280     /**
1281      * Transform/multiply the given 2D-vector, as if it was a 3D-vector with z=1, by
1282      * this matrix and store the result in <code>dest</code>.
1283      * <p>
1284      * The given 2D-vector is treated as a 3D-vector with its z-component being 1.0, so it
1285      * will represent a position/location in 2D-space rather than a direction.
1286      * <p>
1287      * In order to store the result in the same vector, use {@link #transformPosition(Vector2d)}.
1288      * 
1289      * @see #transformPosition(Vector2d)
1290      * @see #transform(Vector3d, Vector3d)
1291      * 
1292      * @param v
1293      *          the vector to transform
1294      * @param dest
1295      *          will hold the result
1296      * @return dest
1297      */
1298     public Vector2d transformPosition(Vector2d v, ref Vector2d dest) {
1299         dest.set(m00 * v.x + m10 * v.y + m20,
1300                  m01 * v.x + m11 * v.y + m21);
1301         return dest;
1302     }
1303 
1304     /**
1305      * Transform/multiply the given 2D-vector <code>(x, y)</code>, as if it was a 3D-vector with z=1, by
1306      * this matrix and store the result in <code>dest</code>.
1307      * <p>
1308      * The given 2D-vector is treated as a 3D-vector with its z-component being 1.0, so it
1309      * will represent a position/location in 2D-space rather than a direction.
1310      * <p>
1311      * In order to store the result in the same vector, use {@link #transformPosition(Vector2d)}.
1312      * 
1313      * @see #transformPosition(Vector2d)
1314      * @see #transform(Vector3d, Vector3d)
1315      * 
1316      * @param x
1317      *          the x component of the vector to transform
1318      * @param y
1319      *          the y component of the vector to transform
1320      * @param dest
1321      *          will hold the result
1322      * @return dest
1323      */
1324     public Vector2d transformPosition(double x, double y, ref Vector2d dest) {
1325         return dest.set(m00 * x + m10 * y + m20, m01 * x + m11 * y + m21);
1326     }
1327 
1328     /**
1329      * Transform/multiply the given 2D-vector, as if it was a 3D-vector with z=0, by
1330      * this matrix and store the result in that vector.
1331      * <p>
1332      * The given 2D-vector is treated as a 3D-vector with its z-component being <code>0.0</code>, so it
1333      * will represent a direction in 2D-space rather than a position. This method will therefore
1334      * not take the translation part of the matrix into account.
1335      * <p>
1336      * In order to store the result in another vector, use {@link #transformDirection(Vector2d, Vector2d)}.
1337      * 
1338      * @see #transformDirection(Vector2d, Vector2d)
1339      * 
1340      * @param v
1341      *          the vector to transform and to hold the final result
1342      * @return v
1343      */
1344     public Vector2d transformDirection(ref Vector2d v) {
1345         v.set(m00 * v.x + m10 * v.y,
1346               m01 * v.x + m11 * v.y);
1347         return v;
1348     }
1349 
1350     /**
1351      * Transform/multiply the given 2D-vector, as if it was a 3D-vector with z=0, by
1352      * this matrix and store the result in <code>dest</code>.
1353      * <p>
1354      * The given 2D-vector is treated as a 3D-vector with its z-component being <code>0.0</code>, so it
1355      * will represent a direction in 2D-space rather than a position. This method will therefore
1356      * not take the translation part of the matrix into account.
1357      * <p>
1358      * In order to store the result in the same vector, use {@link #transformDirection(Vector2d)}.
1359      * 
1360      * @see #transformDirection(Vector2d)
1361      * 
1362      * @param v
1363      *          the vector to transform and to hold the final result
1364      * @param dest
1365      *          will hold the result
1366      * @return dest
1367      */
1368     public Vector2d transformDirection(Vector2d v, ref Vector2d dest) {
1369         dest.set(m00 * v.x + m10 * v.y,
1370                  m01 * v.x + m11 * v.y);
1371         return dest;
1372     }
1373 
1374     /**
1375      * Transform/multiply the given 2D-vector <code>(x, y)</code>, as if it was a 3D-vector with z=0, by
1376      * this matrix and store the result in <code>dest</code>.
1377      * <p>
1378      * The given 2D-vector is treated as a 3D-vector with its z-component being <code>0.0</code>, so it
1379      * will represent a direction in 2D-space rather than a position. This method will therefore
1380      * not take the translation part of the matrix into account.
1381      * <p>
1382      * In order to store the result in the same vector, use {@link #transformDirection(Vector2d)}.
1383      * 
1384      * @see #transformDirection(Vector2d)
1385      * 
1386      * @param x
1387      *          the x component of the vector to transform
1388      * @param y
1389      *          the y component of the vector to transform
1390      * @param dest
1391      *          will hold the result
1392      * @return dest
1393      */
1394     public Vector2d transformDirection(double x, double y, ref Vector2d dest) {
1395         return dest.set(m00 * x + m10 * y, m01 * x + m11 * y);
1396     }
1397 
1398     /**
1399      * Apply a rotation transformation to this matrix by rotating the given amount of radians.
1400      * <p>
1401      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
1402      * then the new matrix will be <code>M * R</code>. So when transforming a
1403      * vector <code>v</code> with the new matrix by using <code>M * R * v</code>
1404      * , the rotation will be applied first!
1405      * 
1406      * @param ang
1407      *            the angle in radians
1408      * @return this
1409      */
1410     ref public Matrix3x2d rotate(double ang) return {
1411         rotate(ang, this);
1412         return this;
1413     }
1414 
1415     /**
1416      * Apply a rotation transformation to this matrix by rotating the given amount of radians and store the result in <code>dest</code>.
1417      * <p>
1418      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
1419      * then the new matrix will be <code>M * R</code>. So when transforming a
1420      * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the rotation will be applied first!
1421      * 
1422      * @param ang
1423      *            the angle in radians
1424      * @param dest
1425      *            will hold the result
1426      * @return dest
1427      */
1428     public Matrix3x2d rotate(double ang, ref Matrix3x2d dest) {
1429         double cos = Math.cos(ang);
1430         double sin = Math.sin(ang);
1431         double rm00 = cos;
1432         double rm01 = sin;
1433         double rm10 = -sin;
1434         double rm11 = cos;
1435         double nm00 = m00 * rm00 + m10 * rm01;
1436         double nm01 = m01 * rm00 + m11 * rm01;
1437         dest.m10 = m00 * rm10 + m10 * rm11;
1438         dest.m11 = m01 * rm10 + m11 * rm11;
1439         dest.m00 = nm00;
1440         dest.m01 = nm01;
1441         dest.m20 = m20;
1442         dest.m21 = m21;
1443         return dest;
1444     }
1445 
1446     /**
1447      * Pre-multiply a rotation to this matrix by rotating the given amount of radians and store the result in <code>dest</code>.
1448      * <p>
1449      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
1450      * then the new matrix will be <code>R * M</code>. So when transforming a
1451      * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
1452      * rotation will be applied last!
1453      * <p>
1454      * In order to set the matrix to a rotation matrix without pre-multiplying the rotation
1455      * transformation, use {@link #rotation(double) rotation()}.
1456      * <p>
1457      * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
1458      * 
1459      * @see #rotation(double)
1460      * 
1461      * @param ang
1462      *            the angle in radians to rotate
1463      * @param dest
1464      *            will hold the result
1465      * @return dest
1466      */
1467     public Matrix3x2d rotateLocal(double ang, ref Matrix3x2d dest) {
1468         double sin = Math.sin(ang);
1469         double cos = Math.cosFromSin(sin, ang);
1470         double nm00 = cos * m00 - sin * m01;
1471         double nm01 = sin * m00 + cos * m01;
1472         double nm10 = cos * m10 - sin * m11;
1473         double nm11 = sin * m10 + cos * m11;
1474         double nm20 = cos * m20 - sin * m21;
1475         double nm21 = sin * m20 + cos * m21;
1476         dest.m00 = nm00;
1477         dest.m01 = nm01;
1478         dest.m10 = nm10;
1479         dest.m11 = nm11;
1480         dest.m20 = nm20;
1481         dest.m21 = nm21;
1482         return dest;
1483     }
1484 
1485     /**
1486      * Pre-multiply a rotation to this matrix by rotating the given amount of radians.
1487      * <p>
1488      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
1489      * then the new matrix will be <code>R * M</code>. So when transforming a
1490      * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the
1491      * rotation will be applied last!
1492      * <p>
1493      * In order to set the matrix to a rotation matrix without pre-multiplying the rotation
1494      * transformation, use {@link #rotation(double) rotation()}.
1495      * <p>
1496      * Reference: <a href="http://en.wikipedia.org/wiki/Rotation_matrix#Rotation_matrix_from_axis_and_angle">http://en.wikipedia.org</a>
1497      * 
1498      * @see #rotation(double)
1499      * 
1500      * @param ang
1501      *            the angle in radians to rotate
1502      * @return this
1503      */
1504     ref public Matrix3x2d rotateLocal(double ang) return {
1505         rotateLocal(ang, this);
1506         return this;
1507     }
1508 
1509     /**
1510      * Apply a rotation transformation to this matrix by rotating the given amount of radians about
1511      * the specified rotation center <code>(x, y)</code>.
1512      * <p>
1513      * This method is equivalent to calling: <code>translate(x, y).rotate(ang).translate(-x, -y)</code>
1514      * <p>
1515      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
1516      * then the new matrix will be <code>M * R</code>. So when transforming a
1517      * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the rotation will be applied first!
1518      * 
1519      * @see #translate(double, double)
1520      * @see #rotate(double)
1521      * 
1522      * @param ang
1523      *            the angle in radians
1524      * @param x
1525      *            the x component of the rotation center
1526      * @param y
1527      *            the y component of the rotation center
1528      * @return this
1529      */
1530     ref public Matrix3x2d rotateAbout(double ang, double x, double y) return {
1531         rotateAbout(ang, x, y, this);
1532         return this;
1533     }
1534 
1535     /**
1536      * Apply a rotation transformation to this matrix by rotating the given amount of radians about
1537      * the specified rotation center <code>(x, y)</code> and store the result in <code>dest</code>.
1538      * <p>
1539      * This method is equivalent to calling: <code>translate(x, y, dest).rotate(ang).translate(-x, -y)</code>
1540      * <p>
1541      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
1542      * then the new matrix will be <code>M * R</code>. So when transforming a
1543      * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the rotation will be applied first!
1544      * 
1545      * @see #translate(double, double, Matrix3x2d)
1546      * @see #rotate(double, Matrix3x2d)
1547      * 
1548      * @param ang
1549      *            the angle in radians
1550      * @param x
1551      *            the x component of the rotation center
1552      * @param y
1553      *            the y component of the rotation center
1554      * @param dest
1555      *            will hold the result
1556      * @return dest
1557      */
1558     public Matrix3x2d rotateAbout(double ang, double x, double y, ref Matrix3x2d dest) {
1559         double tm20 = m00 * x + m10 * y + m20;
1560         double tm21 = m01 * x + m11 * y + m21;
1561         double cos = Math.cos(ang);
1562         double sin = Math.sin(ang);
1563         double nm00 = m00 * cos + m10 * sin;
1564         double nm01 = m01 * cos + m11 * sin;
1565         dest.m10 = m00 * -sin + m10 * cos;
1566         dest.m11 = m01 * -sin + m11 * cos;
1567         dest.m00 = nm00;
1568         dest.m01 = nm01;
1569         dest.m20 = dest.m00 * -x + dest.m10 * -y + tm20;
1570         dest.m21 = dest.m01 * -x + dest.m11 * -y + tm21;
1571         return dest;
1572     }
1573 
1574     /**
1575      * Apply a rotation transformation to this matrix that rotates the given normalized <code>fromDir</code> direction vector
1576      * to point along the normalized <code>toDir</code>, and store the result in <code>dest</code>.
1577      * <p>
1578      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
1579      * then the new matrix will be <code>M * R</code>. So when transforming a
1580      * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the rotation will be applied first!
1581      * 
1582      * @param fromDir
1583      *            the normalized direction which should be rotate to point along <code>toDir</code>
1584      * @param toDir
1585      *            the normalized destination direction
1586      * @param dest
1587      *            will hold the result
1588      * @return dest
1589      */
1590     public Matrix3x2d rotateTo(Vector2d fromDir, Vector2d toDir, ref Matrix3x2d dest) {
1591         double dot = fromDir.x * toDir.x + fromDir.y * toDir.y;
1592         double det = fromDir.x * toDir.y - fromDir.y * toDir.x;
1593         double rm00 = dot;
1594         double rm01 = det;
1595         double rm10 = -det;
1596         double rm11 = dot;
1597         double nm00 = m00 * rm00 + m10 * rm01;
1598         double nm01 = m01 * rm00 + m11 * rm01;
1599         dest.m10 = m00 * rm10 + m10 * rm11;
1600         dest.m11 = m01 * rm10 + m11 * rm11;
1601         dest.m00 = nm00;
1602         dest.m01 = nm01;
1603         dest.m20 = m20;
1604         dest.m21 = m21;
1605         return dest;
1606     }
1607 
1608     /**
1609      * Apply a rotation transformation to this matrix that rotates the given normalized <code>fromDir</code> direction vector
1610      * to point along the normalized <code>toDir</code>.
1611      * <p>
1612      * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix,
1613      * then the new matrix will be <code>M * R</code>. So when transforming a
1614      * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the rotation will be applied first!
1615      * 
1616      * @param fromDir
1617      *            the normalized direction which should be rotate to point along <code>toDir</code>
1618      * @param toDir
1619      *            the normalized destination direction
1620      * @return this
1621      */
1622     ref public Matrix3x2d rotateTo(Vector2d fromDir, Vector2d toDir) return {
1623         rotateTo(fromDir, toDir, this);
1624         return this;
1625     }
1626 
1627     /**
1628      * Apply a "view" transformation to this matrix that maps the given <code>(left, bottom)</code> and
1629      * <code>(right, top)</code> corners to <code>(-1, -1)</code> and <code>(1, 1)</code> respectively and store the result in <code>dest</code>.
1630      * <p>
1631      * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix,
1632      * then the new matrix will be <code>M * O</code>. So when transforming a
1633      * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the
1634      * orthographic projection transformation will be applied first!
1635      * 
1636      * @see #setView(double, double, double, double)
1637      * 
1638      * @param left
1639      *            the distance from the center to the left view edge
1640      * @param right
1641      *            the distance from the center to the right view edge
1642      * @param bottom
1643      *            the distance from the center to the bottom view edge
1644      * @param top
1645      *            the distance from the center to the top view edge
1646      * @param dest
1647      *            will hold the result
1648      * @return dest
1649      */
1650     public Matrix3x2d view(double left, double right, double bottom, double top, ref Matrix3x2d dest) {
1651         double rm00 = 2.0 / (right - left);
1652         double rm11 = 2.0 / (top - bottom);
1653         double rm20 = (left + right) / (left - right);
1654         double rm21 = (bottom + top) / (bottom - top);
1655         dest.m20 = m00 * rm20 + m10 * rm21 + m20;
1656         dest.m21 = m01 * rm20 + m11 * rm21 + m21;
1657         dest.m00 = m00 * rm00;
1658         dest.m01 = m01 * rm00;
1659         dest.m10 = m10 * rm11;
1660         dest.m11 = m11 * rm11;
1661         return dest;
1662     }
1663 
1664     /**
1665      * Apply a "view" transformation to this matrix that maps the given <code>(left, bottom)</code> and
1666      * <code>(right, top)</code> corners to <code>(-1, -1)</code> and <code>(1, 1)</code> respectively.
1667      * <p>
1668      * If <code>M</code> is <code>this</code> matrix and <code>O</code> the orthographic projection matrix,
1669      * then the new matrix will be <code>M * O</code>. So when transforming a
1670      * vector <code>v</code> with the new matrix by using <code>M * O * v</code>, the
1671      * orthographic projection transformation will be applied first!
1672      * 
1673      * @see #setView(double, double, double, double)
1674      * 
1675      * @param left
1676      *            the distance from the center to the left view edge
1677      * @param right
1678      *            the distance from the center to the right view edge
1679      * @param bottom
1680      *            the distance from the center to the bottom view edge
1681      * @param top
1682      *            the distance from the center to the top view edge
1683      * @return this
1684      */
1685     ref public Matrix3x2d view(double left, double right, double bottom, double top) return {
1686         view(left, right, bottom, top, this);
1687         return this;
1688     }
1689 
1690     /**
1691      * Set this matrix to define a "view" transformation that maps the given <code>(left, bottom)</code> and
1692      * <code>(right, top)</code> corners to <code>(-1, -1)</code> and <code>(1, 1)</code> respectively.
1693      * 
1694      * @see #view(double, double, double, double)
1695      * 
1696      * @param left
1697      *            the distance from the center to the left view edge
1698      * @param right
1699      *            the distance from the center to the right view edge
1700      * @param bottom
1701      *            the distance from the center to the bottom view edge
1702      * @param top
1703      *            the distance from the center to the top view edge
1704      * @return this
1705      */
1706     ref public Matrix3x2d setView(double left, double right, double bottom, double top) return {
1707         m00 = 2.0 / (right - left);
1708         m01 = 0.0;
1709         m10 = 0.0;
1710         m11 = 2.0 / (top - bottom);
1711         m20 = (left + right) / (left - right);
1712         m21 = (bottom + top) / (bottom - top);
1713         return this;
1714     }
1715 
1716     /**
1717      * Obtain the position that gets transformed to the origin by <code>this</code> matrix.
1718      * This can be used to get the position of the "camera" from a given <i>view</i> transformation matrix.
1719      * <p>
1720      * This method is equivalent to the following code:
1721      * <pre>
1722      * Matrix3x2d inv = new Matrix3x2d(this).invert();
1723      * inv.transform(origin.set(0, 0));
1724      * </pre>
1725      * 
1726      * @param origin
1727      *          will hold the position transformed to the origin
1728      * @return origin
1729      */
1730     public Vector2d origin(ref Vector2d origin) {
1731         double s = 1.0 / (m00 * m11 - m01 * m10);
1732         origin.x = (m10 * m21 - m20 * m11) * s;
1733         origin.y = (m20 * m01 - m00 * m21) * s;
1734         return origin;
1735     }
1736 
1737     /**
1738      * Obtain the extents of the view transformation of <code>this</code> matrix and store it in <code>area</code>.
1739      * This can be used to determine which region of the screen (i.e. the NDC space) is covered by the view.
1740      * 
1741      * @param area
1742      *          will hold the view area as <code>[minX, minY, maxX, maxY]</code>
1743      * @return area
1744      */
1745     public double[] viewArea(double[] area) {
1746         double s = 1.0 / (m00 * m11 - m01 * m10);
1747         double rm00 =  m11 * s;
1748         double rm01 = -m01 * s;
1749         double rm10 = -m10 * s;
1750         double rm11 =  m00 * s;
1751         double rm20 = (m10 * m21 - m20 * m11) * s;
1752         double rm21 = (m20 * m01 - m00 * m21) * s;
1753         double nxnyX = -rm00 - rm10;
1754         double nxnyY = -rm01 - rm11;
1755         double pxnyX =  rm00 - rm10;
1756         double pxnyY =  rm01 - rm11;
1757         double nxpyX = -rm00 + rm10;
1758         double nxpyY = -rm01 + rm11;
1759         double pxpyX =  rm00 + rm10;
1760         double pxpyY =  rm01 + rm11;
1761         double minX = nxnyX;
1762         minX = minX < nxpyX ? minX : nxpyX;
1763         minX = minX < pxnyX ? minX : pxnyX;
1764         minX = minX < pxpyX ? minX : pxpyX;
1765         double minY = nxnyY;
1766         minY = minY < nxpyY ? minY : nxpyY;
1767         minY = minY < pxnyY ? minY : pxnyY;
1768         minY = minY < pxpyY ? minY : pxpyY;
1769         double maxX = nxnyX;
1770         maxX = maxX > nxpyX ? maxX : nxpyX;
1771         maxX = maxX > pxnyX ? maxX : pxnyX;
1772         maxX = maxX > pxpyX ? maxX : pxpyX;
1773         double maxY = nxnyY;
1774         maxY = maxY > nxpyY ? maxY : nxpyY;
1775         maxY = maxY > pxnyY ? maxY : pxnyY;
1776         maxY = maxY > pxpyY ? maxY : pxpyY;
1777         area[0] = minX + rm20;
1778         area[1] = minY + rm21;
1779         area[2] = maxX + rm20;
1780         area[3] = maxY + rm21;
1781         return area;
1782     }
1783 
1784     public Vector2d positiveX(ref Vector2d dir) {
1785         double s = m00 * m11 - m01 * m10;
1786         s = 1.0 / s;
1787         dir.x =  m11 * s;
1788         dir.y = -m01 * s;
1789         return dir.normalize(dir);
1790     }
1791 
1792     public Vector2d normalizedPositiveX(ref Vector2d dir) {
1793         dir.x =  m11;
1794         dir.y = -m01;
1795         return dir;
1796     }
1797 
1798     public Vector2d positiveY(ref Vector2d dir) {
1799         double s = m00 * m11 - m01 * m10;
1800         s = 1.0 / s;
1801         dir.x = -m10 * s;
1802         dir.y =  m00 * s;
1803         return dir.normalize(dir);
1804     }
1805 
1806     public Vector2d normalizedPositiveY(ref Vector2d dir) {
1807         dir.x = -m10;
1808         dir.y =  m00;
1809         return dir;
1810     }
1811 
1812     /**
1813      * Unproject the given window coordinates <code>(winX, winY)</code> by <code>this</code> matrix using the specified viewport.
1814      * <p>
1815      * This method first converts the given window coordinates to normalized device coordinates in the range <code>[-1..1]</code>
1816      * and then transforms those NDC coordinates by the inverse of <code>this</code> matrix.  
1817      * <p>
1818      * As a necessary computation step for unprojecting, this method computes the inverse of <code>this</code> matrix.
1819      * In order to avoid computing the matrix inverse with every invocation, the inverse of <code>this</code> matrix can be built
1820      * once outside using {@link #invert(Matrix3x2d)} and then the method {@link #unprojectInv(double, double, int[], Vector2d) unprojectInv()} can be invoked on it.
1821      * 
1822      * @see #unprojectInv(double, double, int[], Vector2d)
1823      * @see #invert(Matrix3x2d)
1824      * 
1825      * @param winX
1826      *          the x-coordinate in window coordinates (pixels)
1827      * @param winY
1828      *          the y-coordinate in window coordinates (pixels)
1829      * @param viewport
1830      *          the viewport described by <code>[x, y, width, height]</code>
1831      * @param dest
1832      *          will hold the unprojected position
1833      * @return dest
1834      */
1835     public Vector2d unproject(double winX, double winY, int[] viewport, ref Vector2d dest) {
1836         double s = 1.0 / (m00 * m11 - m01 * m10);
1837         double im00 =  m11 * s;
1838         double im01 = -m01 * s;
1839         double im10 = -m10 * s;
1840         double im11 =  m00 * s;
1841         double im20 = (m10 * m21 - m20 * m11) * s;
1842         double im21 = (m20 * m01 - m00 * m21) * s;
1843         double ndcX = (winX-viewport[0])/viewport[2]*2.0-1.0;
1844         double ndcY = (winY-viewport[1])/viewport[3]*2.0-1.0;
1845         dest.x = im00 * ndcX + im10 * ndcY + im20;
1846         dest.y = im01 * ndcX + im11 * ndcY + im21;
1847         return dest;
1848     }
1849 
1850     /**
1851      * Unproject the given window coordinates <code>(winX, winY)</code> by <code>this</code> matrix using the specified viewport.
1852      * <p>
1853      * This method differs from {@link #unproject(double, double, int[], Vector2d) unproject()} 
1854      * in that it assumes that <code>this</code> is already the inverse matrix of the original projection matrix.
1855      * It exists to avoid recomputing the matrix inverse with every invocation.
1856      * 
1857      * @see #unproject(double, double, int[], Vector2d)
1858      * 
1859      * @param winX
1860      *          the x-coordinate in window coordinates (pixels)
1861      * @param winY
1862      *          the y-coordinate in window coordinates (pixels)
1863      * @param viewport
1864      *          the viewport described by <code>[x, y, width, height]</code>
1865      * @param dest
1866      *          will hold the unprojected position
1867      * @return dest
1868      */
1869     public Vector2d unprojectInv(double winX, double winY, int[] viewport, ref Vector2d dest) {
1870         double ndcX = (winX-viewport[0])/viewport[2]*2.0-1.0;
1871         double ndcY = (winY-viewport[1])/viewport[3]*2.0-1.0;
1872         dest.x = m00 * ndcX + m10 * ndcY + m20;
1873         dest.y = m01 * ndcX + m11 * ndcY + m21;
1874         return dest;
1875     }
1876 
1877     /**
1878      * Compute the extents of the coordinate system before this transformation was applied and store the resulting
1879      * corner coordinates in <code>corner</code> and the span vectors in <code>xDir</code> and <code>yDir</code>.
1880      * <p>
1881      * That means, given the maximum extents of the coordinate system between <code>[-1..+1]</code> in all dimensions,
1882      * this method returns one corner and the length and direction of the two base axis vectors in the coordinate
1883      * system before this transformation is applied, which transforms into the corner coordinates <code>[-1, +1]</code>.
1884      * 
1885      * @param corner
1886      *          will hold one corner of the span
1887      * @param xDir
1888      *          will hold the direction and length of the span along the positive X axis
1889      * @param yDir
1890      *          will hold the direction and length of the span along the positive Y axis
1891      * @return this
1892      */
1893     ref public Matrix3x2d span(Vector2d corner, Vector2d xDir, Vector2d yDir) return {
1894         double s = 1.0 / (m00 * m11 - m01 * m10);
1895         double nm00 =  m11 * s, nm01 = -m01 * s, nm10 = -m10 * s, nm11 =  m00 * s;
1896         corner.x = -nm00 - nm10 + (m10 * m21 - m20 * m11) * s;
1897         corner.y = -nm01 - nm11 + (m20 * m01 - m00 * m21) * s;
1898         xDir.x = 2.0 * nm00; xDir.y = 2.0 * nm01;
1899         yDir.x = 2.0 * nm10; yDir.y = 2.0 * nm11;
1900         return this;
1901     }
1902 
1903     public bool testPoint(double x, double y) {
1904         double nxX = +m00, nxY = +m10, nxW = 1.0f + m20;
1905         double pxX = -m00, pxY = -m10, pxW = 1.0f - m20;
1906         double nyX = +m01, nyY = +m11, nyW = 1.0f + m21;
1907         double pyX = -m01, pyY = -m11, pyW = 1.0f - m21;
1908         return nxX * x + nxY * y + nxW >= 0 && pxX * x + pxY * y + pxW >= 0 &&
1909                nyX * x + nyY * y + nyW >= 0 && pyX * x + pyY * y + pyW >= 0;
1910     }
1911 
1912     public bool testCircle(double x, double y, double r) {
1913         double invl;
1914         double nxX = +m00, nxY = +m10, nxW = 1.0f + m20;
1915         invl = Math.invsqrt(nxX * nxX + nxY * nxY);
1916         nxX *= invl; nxY *= invl; nxW *= invl;
1917         double pxX = -m00, pxY = -m10, pxW = 1.0f - m20;
1918         invl = Math.invsqrt(pxX * pxX + pxY * pxY);
1919         pxX *= invl; pxY *= invl; pxW *= invl;
1920         double nyX = +m01, nyY = +m11, nyW = 1.0f + m21;
1921         invl = Math.invsqrt(nyX * nyX + nyY * nyY);
1922         nyX *= invl; nyY *= invl; nyW *= invl;
1923         double pyX = -m01, pyY = -m11, pyW = 1.0f - m21;
1924         invl = Math.invsqrt(pyX * pyX + pyY * pyY);
1925         pyX *= invl; pyY *= invl; pyW *= invl;
1926         return nxX * x + nxY * y + nxW >= -r && pxX * x + pxY * y + pxW >= -r &&
1927                nyX * x + nyY * y + nyW >= -r && pyX * x + pyY * y + pyW >= -r;
1928     }
1929 
1930     public bool testAar(double minX, double minY, double maxX, double maxY) {
1931         double nxX = +m00, nxY = +m10, nxW = 1.0f + m20;
1932         double pxX = -m00, pxY = -m10, pxW = 1.0f - m20;
1933         double nyX = +m01, nyY = +m11, nyW = 1.0f + m21;
1934         double pyX = -m01, pyY = -m11, pyW = 1.0f - m21;
1935         /*
1936          * This is an implementation of the "2.4 Basic intersection test" of the mentioned site.
1937          * It does not distinguish between partially inside and fully inside, though, so the test with the 'p' vertex is omitted.
1938          */
1939         return nxX * (nxX < 0 ? minX : maxX) + nxY * (nxY < 0 ? minY : maxY) >= -nxW &&
1940                pxX * (pxX < 0 ? minX : maxX) + pxY * (pxY < 0 ? minY : maxY) >= -pxW &&
1941                nyX * (nyX < 0 ? minX : maxX) + nyY * (nyY < 0 ? minY : maxY) >= -nyW &&
1942                pyX * (pyX < 0 ? minX : maxX) + pyY * (pyY < 0 ? minY : maxY) >= -pyW;
1943     }
1944 
1945     public int hashCode() {
1946         immutable int prime = 31;
1947         int result = 1;
1948         long temp;
1949         temp = Math.doubleToLongBits(m00);
1950         result = prime * result + cast(int) (temp ^ (temp >>> 32));
1951         temp = Math.doubleToLongBits(m01);
1952         result = prime * result + cast(int) (temp ^ (temp >>> 32));
1953         temp = Math.doubleToLongBits(m10);
1954         result = prime * result + cast(int) (temp ^ (temp >>> 32));
1955         temp = Math.doubleToLongBits(m11);
1956         result = prime * result + cast(int) (temp ^ (temp >>> 32));
1957         temp = Math.doubleToLongBits(m20);
1958         result = prime * result + cast(int) (temp ^ (temp >>> 32));
1959         temp = Math.doubleToLongBits(m21);
1960         result = prime * result + cast(int) (temp ^ (temp >>> 32));
1961         return result;
1962     }
1963 
1964     public bool equals(Matrix3x2d m, double delta) {
1965         if (this == m)
1966             return true;
1967         if (!Math.equals(m00, m.m00, delta))
1968             return false;
1969         if (!Math.equals(m01, m.m01, delta))
1970             return false;
1971         if (!Math.equals(m10, m.m10, delta))
1972             return false;
1973         if (!Math.equals(m11, m.m11, delta))
1974             return false;
1975         if (!Math.equals(m20, m.m20, delta))
1976             return false;
1977         if (!Math.equals(m21, m.m21, delta))
1978             return false;
1979         return true;
1980     }
1981 
1982     public bool isFinite() {
1983         return Math.isFinite(m00) && Math.isFinite(m01) &&
1984                Math.isFinite(m10) && Math.isFinite(m11) &&
1985                Math.isFinite(m20) && Math.isFinite(m21);
1986     }
1987 }