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