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