1 module matrix_2d; 2 3 import Math = math; 4 import MemUtil = mem_util; 5 6 import matrix_3d; 7 import matrix_3x2d; 8 9 import vector_2d; 10 11 12 /* 13 * The MIT License 14 * 15 * Copyright (c) 2020-2021 JOML 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 /** 39 * Contains the definition of a 2x2 matrix of doubles, and associated functions to transform 40 * it. The matrix is column-major to match OpenGL's interpretation, and it looks like this: 41 * <p> 42 * m00 m10<br> 43 * m01 m11<br> 44 * 45 * @author Joseph Burton 46 */ 47 public struct Matrix2d { 48 49 // Defaults to identity 50 double m00 = 1.0; 51 double m01 = 0.0; 52 double m10 = 0.0; 53 double m11 = 1.0; 54 55 56 /** 57 * Create a new {@link Matrix2d} and make it a copy of the given matrix. 58 * 59 * @param mat 60 * the {@link Matrix2d} to copy the values from 61 */ 62 this(Matrix2d mat) { 63 setMatrix2d(mat); 64 } 65 66 67 /** 68 * Create a new {@link Matrix2d} and make it a copy of the upper left 2x2 of the given {@link Matrix3d}. 69 * 70 * @param mat 71 * the {@link Matrix3d} to copy the values from 72 */ 73 this(Matrix3d mat) { 74 setMatrix3d(mat); 75 } 76 77 78 /** 79 * Create a new 2x2 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 */ 91 this(double m00, double m01, 92 double m10, double m11) { 93 this.m00 = m00; 94 this.m01 = m01; 95 this.m10 = m10; 96 this.m11 = m11; 97 } 98 99 /** 100 * Create a new {@link Matrix2d} and initialize its two columns using the supplied vectors. 101 * 102 * @param col0 103 * the first column 104 * @param col1 105 * the second column 106 */ 107 this(Vector2d col0, Vector2d col1) { 108 m00 = col0.x; 109 m01 = col0.y; 110 m10 = col1.x; 111 m11 = col1.y; 112 } 113 114 /** 115 * Set the value of the matrix element at column 0 and row 0. 116 * 117 * @param m00 118 * the new value 119 * @return this 120 */ 121 ref public Matrix2d setm00(double m00) return { 122 this.m00 = m00; 123 return this; 124 } 125 /** 126 * Set the value of the matrix element at column 0 and row 1. 127 * 128 * @param m01 129 * the new value 130 * @return this 131 */ 132 ref public Matrix2d setm01(double m01) return { 133 this.m01 = m01; 134 return this; 135 } 136 /** 137 * Set the value of the matrix element at column 1 and row 0. 138 * 139 * @param m10 140 * the new value 141 * @return this 142 */ 143 ref public Matrix2d setm10(double m10) return { 144 this.m10 = m10; 145 return this; 146 } 147 /** 148 * Set the value of the matrix element at column 1 and row 1. 149 * 150 * @param m11 151 * the new value 152 * @return this 153 */ 154 ref public Matrix2d setm11(double m11) return { 155 this.m11 = m11; 156 return this; 157 } 158 159 /** 160 * Set the value of the matrix element at column 0 and row 0. 161 * 162 * @param m00 163 * the new value 164 * @return this 165 */ 166 ref Matrix2d _m00(double m00) return { 167 this.m00 = m00; 168 return this; 169 } 170 /** 171 * Set the value of the matrix element at column 0 and row 1. 172 * 173 * @param m01 174 * the new value 175 * @return this 176 */ 177 ref Matrix2d _m01(double m01) return { 178 this.m01 = m01; 179 return this; 180 } 181 /** 182 * Set the value of the matrix element at column 1 and row 0. 183 * 184 * @param m10 185 * the new value 186 * @return this 187 */ 188 ref Matrix2d _m10(double m10) return { 189 this.m10 = m10; 190 return this; 191 } 192 /** 193 * Set the value of the matrix element at column 1 and row 1. 194 * 195 * @param m11 196 * the new value 197 * @return this 198 */ 199 ref Matrix2d _m11(double m11) return { 200 this.m11 = m11; 201 return this; 202 } 203 204 /** 205 * Set the elements of this matrix to the ones in <code>m</code>. 206 * 207 * @param m 208 * the matrix to copy the elements from 209 * @return this 210 */ 211 ref public Matrix2d set(Matrix2d m) return { 212 setMatrix2d(m); 213 return this; 214 } 215 private void setMatrix2d(Matrix2d mat) { 216 m00 = mat.m00; 217 m01 = mat.m01; 218 m10 = mat.m10; 219 m11 = mat.m11; 220 } 221 222 223 /** 224 * Set the elements of this matrix to the left 2x2 submatrix of <code>m</code>. 225 * 226 * @param m 227 * the matrix to copy the elements from 228 * @return this 229 */ 230 ref public Matrix2d set(Matrix3x2d m) return { 231 setMatrix3x2d(m); 232 return this; 233 } 234 private void setMatrix3x2d(Matrix3x2d mat) { 235 m00 = mat.m00; 236 m01 = mat.m01; 237 m10 = mat.m10; 238 m11 = mat.m11; 239 } 240 241 /** 242 * Set the elements of this matrix to the upper left 2x2 of the given {@link Matrix3d}. 243 * 244 * @param m 245 * the {@link Matrix3d} to copy the values from 246 * @return this 247 */ 248 ref public Matrix2d set(Matrix3d m) return { 249 setMatrix3d(m); 250 return this; 251 } 252 private void setMatrix3d(Matrix3d mat) { 253 m00 = mat.m00; 254 m01 = mat.m01; 255 m10 = mat.m10; 256 m11 = mat.m11; 257 } 258 259 260 /** 261 * Multiply this matrix by the supplied <code>right</code> matrix. 262 * <p> 263 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the <code>right</code> matrix, 264 * then the new matrix will be <code>M * R</code>. So when transforming a 265 * vector <code>v</code> with the new matrix by using <code>M * R * v</code>, the 266 * transformation of the right matrix will be applied first! 267 * 268 * @param right 269 * the right operand of the matrix multiplication 270 * @return this 271 */ 272 ref public Matrix2d mul(Matrix2d right) return { 273 this.mul(right, this); 274 return this; 275 } 276 277 public Matrix2d mul(Matrix2d right, ref Matrix2d dest) { 278 double nm00 = m00 * right.m00 + m10 * right.m01; 279 double nm01 = m01 * right.m00 + m11 * right.m01; 280 double nm10 = m00 * right.m10 + m10 * right.m11; 281 double nm11 = m01 * right.m10 + m11 * right.m11; 282 dest.m00 = nm00; 283 dest.m01 = nm01; 284 dest.m10 = nm10; 285 dest.m11 = nm11; 286 return dest; 287 } 288 289 /** 290 * Pre-multiply this matrix by the supplied <code>left</code> matrix and store the result in <code>this</code>. 291 * <p> 292 * If <code>M</code> is <code>this</code> matrix and <code>L</code> the <code>left</code> matrix, 293 * then the new matrix will be <code>L * M</code>. So when transforming a 294 * vector <code>v</code> with the new matrix by using <code>L * M * v</code>, the 295 * transformation of <code>this</code> matrix will be applied first! 296 * 297 * @param left 298 * the left operand of the matrix multiplication 299 * @return this 300 */ 301 ref public Matrix2d mulLocal(Matrix2d left) return { 302 this.mulLocal(left, this); 303 return this; 304 } 305 306 public Matrix2d mulLocal(Matrix2d left, ref Matrix2d dest) { 307 double nm00 = left.m00 * m00 + left.m10 * m01; 308 double nm01 = left.m01 * m00 + left.m11 * m01; 309 double nm10 = left.m00 * m10 + left.m10 * m11; 310 double nm11 = left.m01 * m10 + left.m11 * m11; 311 dest.m00 = nm00; 312 dest.m01 = nm01; 313 dest.m10 = nm10; 314 dest.m11 = nm11; 315 return dest; 316 } 317 318 /** 319 * Set the values within this matrix to the supplied double values. The result looks like this: 320 * <p> 321 * m00, m10<br> 322 * m01, m11<br> 323 * 324 * @param m00 325 * the new value of m00 326 * @param m01 327 * the new value of m01 328 * @param m10 329 * the new value of m10 330 * @param m11 331 * the new value of m11 332 * @return this 333 */ 334 ref public Matrix2d set(double m00, double m01, 335 double m10, double m11) return { 336 this.m00 = m00; 337 this.m01 = m01; 338 this.m10 = m10; 339 this.m11 = m11; 340 return this; 341 } 342 /** 343 * Set the two columns of this matrix to the supplied vectors, respectively. 344 * 345 * @param col0 346 * the first column 347 * @param col1 348 * the second column 349 * @return this 350 */ 351 ref public Matrix2d set(Vector2d col0, Vector2d col1) return { 352 m00 = col0.x; 353 m01 = col0.y; 354 m10 = col1.x; 355 m11 = col1.y; 356 return this; 357 } 358 359 public double determinant() { 360 return m00 * m11 - m10 * m01; 361 } 362 363 /** 364 * Invert this matrix. 365 * 366 * @return this 367 */ 368 ref public Matrix2d invert() return { 369 this.invert(this); 370 return this; 371 } 372 373 public Matrix2d invert(ref Matrix2d dest) { 374 double s = 1.0 / determinant(); 375 double nm00 = m11 * s; 376 double nm01 = -m01 * s; 377 double nm10 = -m10 * s; 378 double nm11 = m00 * s; 379 dest.m00 = nm00; 380 dest.m01 = nm01; 381 dest.m10 = nm10; 382 dest.m11 = nm11; 383 return dest; 384 } 385 386 /** 387 * Transpose this matrix. 388 * 389 * @return this 390 */ 391 ref public Matrix2d transpose() return { 392 this.transpose(this); 393 return this; 394 } 395 396 public Matrix2d transpose(ref Matrix2d dest) { 397 dest.set(m00, m10, 398 m01, m11); 399 return dest; 400 } 401 402 403 /** 404 * Get the current values of <code>this</code> matrix and store them into 405 * <code>dest</code>. 406 * <p> 407 * This is the reverse method of {@link #set(Matrix2d)} and allows to obtain 408 * intermediate calculation results when chaining multiple transformations. 409 * 410 * @see #set(Matrix2d) 411 * 412 * @param dest 413 * the destination matrix 414 * @return the passed in destination 415 */ 416 public Matrix2d get(ref Matrix2d dest) { 417 return dest.set(this); 418 } 419 420 public Matrix3x2d get(ref Matrix3x2d dest) { 421 return dest.set(this); 422 } 423 424 public Matrix3d get(ref Matrix3d dest) { 425 return dest.set(this); 426 } 427 428 public double getRotation() { 429 return cast(double) Math.atan2(m01, m11); 430 } 431 432 /** 433 * Set all values within this matrix to zero. 434 * 435 * @return this 436 */ 437 ref public Matrix2d zero() return { 438 MemUtil.zero(this); 439 return this; 440 } 441 442 /** 443 * Set this matrix to the identity. 444 * 445 * @return this 446 */ 447 ref public Matrix2d identity() return { 448 m00 = 1.0; 449 m01 = 0.0; 450 m10 = 0.0; 451 m11 = 1.0; 452 return this; 453 } 454 455 public Matrix2d scale(Vector2d xy, ref Matrix2d dest) { 456 return scale(xy.x, xy.y, dest); 457 } 458 459 /** 460 * Apply scaling to this matrix by scaling the base axes by the given <code>xy.x</code> and 461 * <code>xy.y</code> factors, respectively. 462 * <p> 463 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 464 * then the new matrix will be <code>M * S</code>. So when transforming a 465 * vector <code>v</code> with the new matrix by using <code>M * S * v</code>, the 466 * scaling will be applied first! 467 * 468 * @param xy 469 * the factors of the x and y component, respectively 470 * @return this 471 */ 472 ref public Matrix2d scale(Vector2d xy) return { 473 this.scale(xy.x, xy.y, this); 474 return this; 475 } 476 477 public Matrix2d scale(double x, double y, ref Matrix2d dest) { 478 // scale matrix elements: 479 // m00 = x, m11 = y 480 // all others = 0 481 dest.m00 = m00 * x; 482 dest.m01 = m01 * x; 483 dest.m10 = m10 * y; 484 dest.m11 = m11 * y; 485 return dest; 486 } 487 488 /** 489 * Apply scaling to this matrix by scaling the base axes by the given x and 490 * y factors. 491 * <p> 492 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 493 * then the new matrix will be <code>M * S</code>. So when transforming a 494 * vector <code>v</code> with the new matrix by using <code>M * S * v</code> 495 * , the scaling will be applied first! 496 * 497 * @param x 498 * the factor of the x component 499 * @param y 500 * the factor of the y component 501 * @return this 502 */ 503 ref public Matrix2d scale(double x, double y) return { 504 this.scale(x, y, this); 505 return this; 506 } 507 508 public Matrix2d scale(double xy, ref Matrix2d dest) { 509 return scale(xy, xy, dest); 510 } 511 512 /** 513 * Apply scaling to this matrix by uniformly scaling all base axes by the given <code>xy</code> factor. 514 * <p> 515 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 516 * then the new matrix will be <code>M * S</code>. So when transforming a 517 * vector <code>v</code> with the new matrix by using <code>M * S * v</code> 518 * , the scaling will be applied first! 519 * 520 * @see #scale(double, double) 521 * 522 * @param xy 523 * the factor for all components 524 * @return this 525 */ 526 ref public Matrix2d scale(double xy) return { 527 return scale(xy, xy); 528 } 529 530 public Matrix2d scaleLocal(double x, double y, ref Matrix2d dest) { 531 dest.m00 = x * m00; 532 dest.m01 = y * m01; 533 dest.m10 = x * m10; 534 dest.m11 = y * m11; 535 return dest; 536 } 537 538 /** 539 * Pre-multiply scaling to this matrix by scaling the base axes by the given x and 540 * y factors. 541 * <p> 542 * If <code>M</code> is <code>this</code> matrix and <code>S</code> the scaling matrix, 543 * then the new matrix will be <code>S * M</code>. So when transforming a 544 * vector <code>v</code> with the new matrix by using <code>S * M * v</code>, the 545 * scaling will be applied last! 546 * 547 * @param x 548 * the factor of the x component 549 * @param y 550 * the factor of the y component 551 * @return this 552 */ 553 ref public Matrix2d scaleLocal(double x, double y) return { 554 this.scaleLocal(x, y, this); 555 return this; 556 } 557 558 /** 559 * Set this matrix to be a simple scale matrix, which scales all axes uniformly by the given factor. 560 * <p> 561 * The resulting matrix can be multiplied against another transformation 562 * matrix to obtain an additional scaling. 563 * <p> 564 * In order to post-multiply a scaling transformation directly to a 565 * matrix, use {@link #scale(double) scale()} instead. 566 * 567 * @see #scale(double) 568 * 569 * @param factor 570 * the scale factor in x and y 571 * @return this 572 */ 573 ref public Matrix2d scaling(double factor) return { 574 MemUtil.zero(this); 575 m00 = factor; 576 m11 = factor; 577 return this; 578 } 579 580 /** 581 * Set this matrix to be a simple scale matrix. 582 * 583 * @param x 584 * the scale in x 585 * @param y 586 * the scale in y 587 * @return this 588 */ 589 ref public Matrix2d scaling(double x, double y) return { 590 MemUtil.zero(this); 591 m00 = x; 592 m11 = y; 593 return this; 594 } 595 596 /** 597 * Set this matrix to be a simple scale matrix which scales the base axes by <code>xy.x</code> and <code>xy.y</code> respectively. 598 * <p> 599 * The resulting matrix can be multiplied against another transformation 600 * matrix to obtain an additional scaling. 601 * <p> 602 * In order to post-multiply a scaling transformation directly to a 603 * matrix use {@link #scale(Vector2d) scale()} instead. 604 * 605 * @see #scale(Vector2d) 606 * 607 * @param xy 608 * the scale in x and y respectively 609 * @return this 610 */ 611 ref public Matrix2d scaling(Vector2d xy) return { 612 return scaling(xy.x, xy.y); 613 } 614 615 /** 616 * Set this matrix to a rotation matrix which rotates the given radians about the origin. 617 * <p> 618 * The produced rotation will rotate a vector counter-clockwise around the origin. 619 * <p> 620 * The resulting matrix can be multiplied against another transformation 621 * matrix to obtain an additional rotation. 622 * <p> 623 * In order to post-multiply a rotation transformation directly to a 624 * matrix, use {@link #rotate(double) rotate()} instead. 625 * 626 * @see #rotate(double) 627 * 628 * @param angle 629 * the angle in radians 630 * @return this 631 */ 632 ref public Matrix2d rotation(double angle) return { 633 double sin = Math.sin(angle); 634 double cos = Math.cosFromSin(sin, angle); 635 m00 = cos; 636 m01 = sin; 637 m10 = -sin; 638 m11 = cos; 639 return this; 640 } 641 642 public Vector2d transform(Vector2d v) { 643 return v.mul(this); 644 } 645 646 public Vector2d transform(Vector2d v, ref Vector2d dest) { 647 v.mul(this, dest); 648 return dest; 649 } 650 651 public Vector2d transform(double x, double y, ref Vector2d dest) { 652 dest.set(m00 * x + m10 * y, 653 m01 * x + m11 * y); 654 return dest; 655 } 656 657 public Vector2d transformTranspose(Vector2d v) { 658 return v.mulTranspose(this); 659 } 660 661 public Vector2d transformTranspose(Vector2d v, ref Vector2d dest) { 662 v.mulTranspose(this, dest); 663 return dest; 664 } 665 666 public Vector2d transformTranspose(double x, double y, ref Vector2d dest) { 667 dest.set(m00 * x + m01 * y, 668 m10 * x + m11 * y); 669 return dest; 670 } 671 672 /** 673 * Apply rotation about the origin to this matrix by rotating the given amount of radians. 674 * <p> 675 * The produced rotation will rotate a vector counter-clockwise around the origin. 676 * <p> 677 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 678 * then the new matrix will be <code>M * R</code>. So when transforming a 679 * vector <code>v</code> with the new matrix by using <code>M * R * v</code> 680 * , the rotation will be applied first! 681 * <p> 682 * Reference: <a href="https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions">http://en.wikipedia.org</a> 683 * 684 * @param angle 685 * the angle in radians 686 * @return this 687 */ 688 ref public Matrix2d rotate(double angle) return { 689 this.rotate(angle, this); 690 return this; 691 } 692 693 public Matrix2d rotate(double angle, ref Matrix2d dest) { 694 double s = Math.sin(angle); 695 double c = Math.cosFromSin(s, angle); 696 // rotation matrix elements: 697 // m00 = c, m01 = s, m10 = -s, m11 = c 698 double nm00 = m00 * c + m10 * s; 699 double nm01 = m01 * c + m11 * s; 700 double nm10 = m10 * c - m00 * s; 701 double nm11 = m11 * c - m01 * s; 702 dest.m00 = nm00; 703 dest.m01 = nm01; 704 dest.m10 = nm10; 705 dest.m11 = nm11; 706 return dest; 707 } 708 709 /** 710 * Pre-multiply a rotation to this matrix by rotating the given amount of radians about the origin. 711 * <p> 712 * The produced rotation will rotate a vector counter-clockwise around the origin. 713 * <p> 714 * If <code>M</code> is <code>this</code> matrix and <code>R</code> the rotation matrix, 715 * then the new matrix will be <code>R * M</code>. So when transforming a 716 * vector <code>v</code> with the new matrix by using <code>R * M * v</code>, the 717 * rotation will be applied last! 718 * <p> 719 * In order to set the matrix to a rotation matrix without pre-multiplying the rotation 720 * transformation, use {@link #rotation(double) rotation()}. 721 * <p> 722 * Reference: <a href="https://en.wikipedia.org/wiki/Rotation_matrix#In_two_dimensions">http://en.wikipedia.org</a> 723 * 724 * @see #rotation(double) 725 * 726 * @param angle 727 * the angle in radians to rotate about the X axis 728 * @return this 729 */ 730 ref public Matrix2d rotateLocal(double angle) return { 731 this.rotateLocal(angle, this); 732 return this; 733 } 734 735 public Matrix2d rotateLocal(double angle, ref Matrix2d dest) { 736 double s = Math.sin(angle); 737 double c = Math.cosFromSin(s, angle); 738 // rotation matrix elements: 739 // m00 = c, m01 = s, m10 = -s, m11 = c 740 double nm00 = c * m00 - s * m01; 741 double nm01 = s * m00 + c * m01; 742 double nm10 = c * m10 - s * m11; 743 double nm11 = s * m10 + c * m11; 744 dest.m00 = nm00; 745 dest.m01 = nm01; 746 dest.m10 = nm10; 747 dest.m11 = nm11; 748 return dest; 749 } 750 751 public Vector2d getRow(int row, ref Vector2d dest) { 752 switch (row) { 753 case 0: 754 dest.x = m00; 755 dest.y = m10; 756 break; 757 case 1: 758 dest.x = m01; 759 dest.y = m11; 760 break; 761 default: {} 762 } 763 return dest; 764 } 765 766 /** 767 * Set the row at the given <code>row</code> index, starting with <code>0</code>. 768 * 769 * @param row 770 * the row index in <code>[0..1]</code> 771 * @param src 772 * the row components to set 773 * @return this 774 * @throws IndexOutOfBoundsException if <code>row</code> is not in <code>[0..1]</code> 775 */ 776 ref public Matrix2d setRow(int row, Vector2d src) return { 777 return setRow(row, src.x, src.y); 778 } 779 780 /** 781 * Set the row at the given <code>row</code> index, starting with <code>0</code>. 782 * 783 * @param row 784 * the row index in <code>[0..1]</code> 785 * @param x 786 * the first element in the row 787 * @param y 788 * the second element in the row 789 * @return this 790 * @throws IndexOutOfBoundsException if <code>row</code> is not in <code>[0..1]</code> 791 */ 792 ref public Matrix2d setRow(int row, double x, double y) return { 793 switch (row) { 794 case 0: 795 this.m00 = x; 796 this.m10 = y; 797 break; 798 case 1: 799 this.m01 = x; 800 this.m11 = y; 801 break; 802 default:{} 803 } 804 return this; 805 } 806 807 public Vector2d getColumn(int column, ref Vector2d dest){ 808 switch (column) { 809 case 0: 810 dest.x = m00; 811 dest.y = m01; 812 break; 813 case 1: 814 dest.x = m10; 815 dest.y = m11; 816 break; 817 default:{} 818 } 819 return dest; 820 } 821 822 /** 823 * Set the column at the given <code>column</code> index, starting with <code>0</code>. 824 * 825 * @param column 826 * the column index in <code>[0..1]</code> 827 * @param src 828 * the column components to set 829 * @return this 830 * @throws IndexOutOfBoundsException if <code>column</code> is not in <code>[0..1]</code> 831 */ 832 ref public Matrix2d setColumn(int column, Vector2d src) return { 833 return setColumn(column, src.x, src.y); 834 } 835 836 /** 837 * Set the column at the given <code>column</code> index, starting with <code>0</code>. 838 * 839 * @param column 840 * the column index in <code>[0..1]</code> 841 * @param x 842 * the first element in the column 843 * @param y 844 * the second element in the column 845 * @return this 846 * @throws IndexOutOfBoundsException if <code>column</code> is not in <code>[0..1]</code> 847 */ 848 ref public Matrix2d setColumn(int column, double x, double y) return { 849 switch (column) { 850 case 0: 851 this.m00 = x; 852 this.m01 = y; 853 break; 854 case 1: 855 this.m10 = x; 856 this.m11 = y; 857 break; 858 default: {} 859 } 860 return this; 861 } 862 863 public double get(int column, int row) { 864 switch (column) { 865 case 0: 866 switch (row) { 867 case 0: 868 return m00; 869 case 1: 870 return m01; 871 default: 872 break; 873 } 874 break; 875 case 1: 876 switch (row) { 877 case 0: 878 return m10; 879 case 1: 880 return m11; 881 default: 882 break; 883 } 884 break; 885 default:{} 886 } 887 return 0; 888 } 889 890 /** 891 * Set the matrix element at the given column and row to the specified value. 892 * 893 * @param column 894 * the colum index in <code>[0..1]</code> 895 * @param row 896 * the row index in <code>[0..1]</code> 897 * @param value 898 * the value 899 * @return this 900 */ 901 ref public Matrix2d set(int column, int row, double value) return { 902 switch (column) { 903 case 0: 904 switch (row) { 905 case 0: 906 this.m00 = value; 907 return this; 908 case 1: 909 this.m01 = value; 910 return this; 911 default: 912 break; 913 } 914 break; 915 case 1: 916 switch (row) { 917 case 0: 918 this.m10 = value; 919 return this; 920 case 1: 921 this.m11 = value; 922 return this; 923 default: 924 break; 925 } 926 break; 927 default:{} 928 } 929 return this; 930 } 931 932 /** 933 * Set <code>this</code> matrix to its own normal matrix. 934 * <p> 935 * Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors, 936 * then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix. 937 * In this case, use {@link #set(Matrix2d)} to set a given Matrix2d to this matrix. 938 * 939 * @see #set(Matrix2d) 940 * 941 * @return this 942 */ 943 ref public Matrix2d normal() return { 944 this.normal(this); 945 return this; 946 } 947 948 /** 949 * Compute a normal matrix from <code>this</code> matrix and store it into <code>dest</code>. 950 * <p> 951 * Please note that, if <code>this</code> is an orthogonal matrix or a matrix whose columns are orthogonal vectors, 952 * then this method <i>need not</i> be invoked, since in that case <code>this</code> itself is its normal matrix. 953 * In this case, use {@link #set(Matrix2d)} to set a given Matrix2d to this matrix. 954 * 955 * @see #set(Matrix2d) 956 * 957 * @param dest 958 * will hold the result 959 * @return dest 960 */ 961 public Matrix2d normal(ref Matrix2d dest) { 962 double det = m00 * m11 - m10 * m01; 963 double s = 1.0 / det; 964 /* Invert and transpose in one go */ 965 double nm00 = m11 * s; 966 double nm01 = -m10 * s; 967 double nm10 = -m01 * s; 968 double nm11 = m00 * s; 969 dest.m00 = nm00; 970 dest.m01 = nm01; 971 dest.m10 = nm10; 972 dest.m11 = nm11; 973 return dest; 974 } 975 976 public Vector2d getScale(ref Vector2d dest) { 977 dest.x = Math.sqrt(m00 * m00 + m01 * m01); 978 dest.y = Math.sqrt(m10 * m10 + m11 * m11); 979 return dest; 980 } 981 982 public Vector2d positiveX(Vector2d dir) { 983 if (m00 * m11 < m01 * m10) { // negative determinant? 984 dir.x = -m11; 985 dir.y = m01; 986 } else { 987 dir.x = m11; 988 dir.y = -m01; 989 } 990 return dir.normalize(dir); 991 } 992 993 public Vector2d normalizedPositiveX(Vector2d dir) { 994 if (m00 * m11 < m01 * m10) { // negative determinant? 995 dir.x = -m11; 996 dir.y = m01; 997 } else { 998 dir.x = m11; 999 dir.y = -m01; 1000 } 1001 return dir; 1002 } 1003 1004 public Vector2d positiveY(Vector2d dir) { 1005 if (m00 * m11 < m01 * m10) { // negative determinant? 1006 dir.x = m10; 1007 dir.y = -m00; 1008 } else { 1009 dir.x = -m10; 1010 dir.y = m00; 1011 } 1012 return dir.normalize(dir); 1013 } 1014 1015 public Vector2d normalizedPositiveY(Vector2d dir) { 1016 if (m00 * m11 < m01 * m10) { // negative determinant? 1017 dir.x = m10; 1018 dir.y = -m00; 1019 } else { 1020 dir.x = -m10; 1021 dir.y = m00; 1022 } 1023 return dir; 1024 } 1025 1026 public int hashCode() { 1027 immutable int prime = 31; 1028 int result = 1; 1029 long temp; 1030 temp = Math.doubleToLongBits(m00); 1031 result = prime * result + cast(int) ((temp >>> 32) ^ temp); 1032 temp = Math.doubleToLongBits(m01); 1033 result = prime * result + cast(int) ((temp >>> 32) ^ temp); 1034 temp = Math.doubleToLongBits(m10); 1035 result = prime * result + cast(int) ((temp >>> 32) ^ temp); 1036 temp = Math.doubleToLongBits(m11); 1037 result = prime * result + cast(int) ((temp >>> 32) ^ temp); 1038 return result; 1039 } 1040 1041 public bool equals(Matrix2d m, double delta) { 1042 if (this == m) 1043 return true; 1044 if (!Math.equals(m00, m.m00, delta)) 1045 return false; 1046 if (!Math.equals(m01, m.m01, delta)) 1047 return false; 1048 if (!Math.equals(m10, m.m10, delta)) 1049 return false; 1050 if (!Math.equals(m11, m.m11, delta)) 1051 return false; 1052 return true; 1053 } 1054 1055 /** 1056 * Exchange the values of <code>this</code> matrix with the given <code>other</code> matrix. 1057 * 1058 * @param other 1059 * the other matrix to exchange the values with 1060 * @return this 1061 */ 1062 ref public Matrix2d swap(ref Matrix2d other) return { 1063 MemUtil.swap(this, other); 1064 return this; 1065 } 1066 1067 /** 1068 * Component-wise add <code>this</code> and <code>other</code>. 1069 * 1070 * @param other 1071 * the other addend 1072 * @return this 1073 */ 1074 ref public Matrix2d add(Matrix2d other) return { 1075 this.add(other, this); 1076 return this; 1077 } 1078 1079 public Matrix2d add(Matrix2d other, ref Matrix2d dest) { 1080 dest.m00 = m00 + other.m00; 1081 dest.m01 = m01 + other.m01; 1082 dest.m10 = m10 + other.m10; 1083 dest.m11 = m11 + other.m11; 1084 return dest; 1085 } 1086 1087 /** 1088 * Component-wise subtract <code>subtrahend</code> from <code>this</code>. 1089 * 1090 * @param subtrahend 1091 * the subtrahend 1092 * @return this 1093 */ 1094 ref public Matrix2d sub(Matrix2d subtrahend) return { 1095 this.sub(subtrahend, this); 1096 return this; 1097 } 1098 1099 public Matrix2d sub(Matrix2d other, ref Matrix2d dest) { 1100 dest.m00 = m00 - other.m00; 1101 dest.m01 = m01 - other.m01; 1102 dest.m10 = m10 - other.m10; 1103 dest.m11 = m11 - other.m11; 1104 return dest; 1105 } 1106 1107 /** 1108 * Component-wise multiply <code>this</code> by <code>other</code>. 1109 * 1110 * @param other 1111 * the other matrix 1112 * @return this 1113 */ 1114 public Matrix2d mulComponentWise(Matrix2d other) { 1115 return sub(other, this); 1116 } 1117 1118 public Matrix2d mulComponentWise(Matrix2d other, ref Matrix2d dest) { 1119 dest.m00 = m00 * other.m00; 1120 dest.m01 = m01 * other.m01; 1121 dest.m10 = m10 * other.m10; 1122 dest.m11 = m11 * other.m11; 1123 return dest; 1124 } 1125 1126 /** 1127 * Linearly interpolate <code>this</code> and <code>other</code> using the given interpolation factor <code>t</code> 1128 * and store the result in <code>this</code>. 1129 * <p> 1130 * If <code>t</code> is <code>0.0</code> then the result is <code>this</code>. If the interpolation factor is <code>1.0</code> 1131 * then the result is <code>other</code>. 1132 * 1133 * @param other 1134 * the other matrix 1135 * @param t 1136 * the interpolation factor between 0.0 and 1.0 1137 * @return this 1138 */ 1139 public Matrix2d lerp(Matrix2d other, double t) { 1140 return lerp(other, t, this); 1141 } 1142 1143 public Matrix2d lerp(Matrix2d other, double t, ref Matrix2d dest) { 1144 dest.m00 = Math.fma(other.m00 - m00, t, m00); 1145 dest.m01 = Math.fma(other.m01 - m01, t, m01); 1146 dest.m10 = Math.fma(other.m10 - m10, t, m10); 1147 dest.m11 = Math.fma(other.m11 - m11, t, m11); 1148 return dest; 1149 } 1150 1151 public bool isFinite() { 1152 return Math.isFinite(m00) && Math.isFinite(m01) && 1153 Math.isFinite(m10) && Math.isFinite(m11); 1154 } 1155 }