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 }