1 /** 2 * Contains the definition of a Vector comprising 4 ints and associated 3 * transformations. 4 * 5 * @author Richard Greenlees 6 * @author Kai Burjack 7 * @author Hans Uhlig 8 */ 9 module doml.vector_4i; 10 11 import Math = doml.math; 12 13 import doml.vector_3i; 14 import doml.vector_2i; 15 import doml.vector_4d; 16 17 18 /* 19 * The MIT License 20 * 21 * Copyright (c) 2015-2021 Richard Greenlees 22 $@$ Translated by jordan4ibanez 23 * 24 * Permission is hereby granted, free of charge, to any person obtaining a copy 25 * of this software and associated documentation files (the "Software"), to deal 26 * in the Software without restriction, including without limitation the rights 27 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 28 * copies of the Software, and to permit persons to whom the Software is 29 * furnished to do so, subject to the following conditions: 30 * 31 * The above copyright notice and this permission notice shall be included in 32 * all copies or substantial portions of the Software. 33 * 34 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 35 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 36 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 37 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 38 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 39 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 40 * THE SOFTWARE. 41 */ 42 43 /** 44 * Contains the definition of a Vector comprising 4 ints and associated 45 * transformations. 46 * 47 * @author Richard Greenlees 48 * @author Kai Burjack 49 * @author Hans Uhlig 50 */ 51 struct Vector4i { 52 53 /** 54 * The x component of the vector. 55 */ 56 int x = 0; 57 /** 58 * The y component of the vector. 59 */ 60 int y = 0; 61 /** 62 * The z component of the vector. 63 */ 64 int z = 0; 65 /** 66 * The w component of the vector. 67 */ 68 int w = 1; 69 70 /** 71 * Create a new {@link Vector4i} with the same values as <code>v</code>. 72 * 73 * @param v 74 * the {@link Vector4i} to copy the values from 75 */ 76 this(Vector4i v) { 77 this.x = v.x; 78 this.y = v.y; 79 this.z = v.z; 80 this.w = v.w; 81 } 82 83 /** 84 * Create a new {@link Vector4i} with the first three components from the 85 * given <code>v</code> and the given <code>w</code>. 86 * 87 * @param v 88 * the {@link Vector3i} 89 * @param w 90 * the w component 91 */ 92 this(Vector3i v, int w) { 93 this.x = v.x; 94 this.y = v.y; 95 this.z = v.z; 96 this.w = w; 97 } 98 99 /** 100 * Create a new {@link Vector4i} with the first two components from the 101 * given <code>v</code> and the given <code>z</code>, and <code>w</code>. 102 * 103 * @param v 104 * the {@link Vector2i} 105 * @param z 106 * the z component 107 * @param w 108 * the w component 109 */ 110 this(Vector2i v, int z, int w) { 111 this.x = v.x; 112 this.y = v.y; 113 this.z = z; 114 this.w = w; 115 } 116 117 /** 118 * Create a new {@link Vector4i} and initialize its components to the rounded value of 119 * the given vector. 120 * 121 * @param v 122 * the {@link Vector4d} to round and copy the values from 123 * @param mode 124 * the {@link RoundingMode} to use 125 */ 126 this(Vector4d v, int mode) { 127 x = Math.roundUsing(v.x, mode); 128 y = Math.roundUsing(v.y, mode); 129 z = Math.roundUsing(v.z, mode); 130 w = Math.roundUsing(v.w, mode); 131 } 132 133 /** 134 * Create a new {@link Vector4i} and initialize all four components with the 135 * given value. 136 * 137 * @param s 138 * scalar value of all four components 139 */ 140 this(int s) { 141 this.x = s; 142 this.y = s; 143 this.z = s; 144 this.w = s; 145 } 146 147 /** 148 * Create a new {@link Vector4i} with the given component values. 149 * 150 * @param x 151 * the x component 152 * @param y 153 * the y component 154 * @param z 155 * the z component 156 * @param w 157 * the w component 158 */ 159 this(int x, int y, int z, int w) { 160 this.x = x; 161 this.y = y; 162 this.z = z; 163 this.w = w; 164 } 165 166 /** 167 * Create a new {@link Vector4i} and initialize its four components from the first 168 * four elements of the given array. 169 * 170 * @param xyzw 171 * the array containing at least four elements 172 */ 173 this(int[] xyzw) { 174 this.x = xyzw[0]; 175 this.y = xyzw[1]; 176 this.z = xyzw[2]; 177 this.w = xyzw[3]; 178 } 179 180 /** 181 * Set this {@link Vector4i} to the values of the given <code>v</code>. 182 * 183 * @param v 184 * the vector whose values will be copied into this 185 * @return this 186 */ 187 ref public Vector4i set(Vector4i v) return { 188 this.x = v.x; 189 this.y = v.y; 190 this.z = v.z; 191 this.w = v.w; 192 return this; 193 } 194 195 /** 196 * Set this {@link Vector4i} to the values of v using {@link RoundingMode#TRUNCATE} rounding. 197 * <p> 198 * Note that due to the given vector <code>v</code> storing the components 199 * in double-precision, there is the possibility to lose precision. 200 * 201 * @param v 202 * the vector to copy from 203 * @return this 204 */ 205 ref public Vector4i set(Vector4d v) return { 206 this.x = cast(int) v.x; 207 this.y = cast(int) v.y; 208 this.z = cast(int) v.z; 209 this.w = cast(int) v.w; 210 return this; 211 } 212 213 /** 214 * Set this {@link Vector4i} to the values of v using the given {@link RoundingMode}. 215 * <p> 216 * Note that due to the given vector <code>v</code> storing the components 217 * in double-precision, there is the possibility to lose precision. 218 * 219 * @param v 220 * the vector to copy from 221 * @param mode 222 * the {@link RoundingMode} to use 223 * @return this 224 */ 225 ref public Vector4i set(Vector4d v, int mode) return { 226 this.x = Math.roundUsing(v.x, mode); 227 this.y = Math.roundUsing(v.y, mode); 228 this.z = Math.roundUsing(v.z, mode); 229 this.w = Math.roundUsing(v.w, mode); 230 return this; 231 } 232 233 /** 234 * Set the first three components of this to the components of 235 * <code>v</code> and the last component to <code>w</code>. 236 * 237 * @param v 238 * the {@link Vector3i} to copy 239 * @param w 240 * the w component 241 * @return this 242 */ 243 ref public Vector4i set(Vector3i v, int w) return { 244 this.x = v.x; 245 this.y = v.y; 246 this.z = v.z; 247 this.w = w; 248 return this; 249 } 250 251 /** 252 * Sets the first two components of this to the components of given 253 * <code>v</code> and last two components to the given <code>z</code>, and 254 * <code>w</code>. 255 * 256 * @param v 257 * the {@link Vector2i} 258 * @param z 259 * the z component 260 * @param w 261 * the w component 262 * @return this 263 */ 264 ref public Vector4i set(Vector2i v, int z, int w) return { 265 this.x = v.x; 266 this.y = v.y; 267 this.z = z; 268 this.w = w; 269 return this; 270 } 271 272 /** 273 * Set the x, y, z, and w components to the supplied value. 274 * 275 * @param s 276 * the value of all four components 277 * @return this 278 */ 279 ref public Vector4i set(int s) return { 280 this.x = s; 281 this.y = s; 282 this.z = s; 283 this.w = s; 284 return this; 285 } 286 287 /** 288 * Set the x, y, z, and w components to the supplied values. 289 * 290 * @param x 291 * the x component 292 * @param y 293 * the y component 294 * @param z 295 * the z component 296 * @param w 297 * the w component 298 * @return this 299 */ 300 ref public Vector4i set(int x, int y, int z, int w) return { 301 this.x = x; 302 this.y = y; 303 this.z = z; 304 this.w = w; 305 return this; 306 } 307 308 /** 309 * Set the four components of this vector to the first four elements of the given array. 310 * 311 * @param xyzw 312 * the array containing at least four elements 313 * @return this 314 */ 315 ref public Vector4i set(int[] xyzw) return { 316 this.x = xyzw[0]; 317 this.y = xyzw[1]; 318 this.z = xyzw[2]; 319 this.w = xyzw[3]; 320 return this; 321 } 322 323 public int get(int component) { 324 switch (component) { 325 case 0: 326 return x; 327 case 1: 328 return y; 329 case 2: 330 return z; 331 case 3: 332 return w; 333 default: 334 return 0; // do nothing 335 } 336 } 337 338 public int maxComponent() { 339 int absX = Math.abs(x); 340 int absY = Math.abs(y); 341 int absZ = Math.abs(z); 342 int absW = Math.abs(w); 343 if (absX >= absY && absX >= absZ && absX >= absW) { 344 return 0; 345 } else if (absY >= absZ && absY >= absW) { 346 return 1; 347 } else if (absZ >= absW) { 348 return 2; 349 } 350 return 3; 351 } 352 353 public int minComponent() { 354 int absX = Math.abs(x); 355 int absY = Math.abs(y); 356 int absZ = Math.abs(z); 357 int absW = Math.abs(w); 358 if (absX < absY && absX < absZ && absX < absW) { 359 return 0; 360 } else if (absY < absZ && absY < absW) { 361 return 1; 362 } else if (absZ < absW) { 363 return 2; 364 } 365 return 3; 366 } 367 368 /** 369 * Set the value of the specified component of this vector. 370 * 371 * @param component 372 * the component whose value to set, within <code>[0..3]</code> 373 * @param value 374 * the value to set 375 * @return this 376 * @throws IllegalArgumentException if <code>component</code> is not within <code>[0..3]</code> 377 */ 378 ref public Vector4i setComponent(int component, int value) return { 379 switch (component) { 380 case 0: 381 x = value; 382 break; 383 case 1: 384 y = value; 385 break; 386 case 2: 387 z = value; 388 break; 389 case 3: 390 w = value; 391 break; 392 default: {} 393 } 394 return this; 395 } 396 397 /** 398 * Subtract the supplied vector from this one. 399 * 400 * @param v 401 * the vector to subtract 402 * @return this 403 */ 404 ref public Vector4i sub(Vector4i v) return { 405 this.x = this.x - v.x; 406 this.y = this.y - v.y; 407 this.z = this.z - v.z; 408 this.w = this.w - v.w; 409 return this; 410 } 411 412 /** 413 * Subtract <code>(x, y, z, w)</code> from this. 414 * 415 * @param x 416 * the x component to subtract 417 * @param y 418 * the y component to subtract 419 * @param z 420 * the z component to subtract 421 * @param w 422 * the w component to subtract 423 * @return this 424 */ 425 ref public Vector4i sub(int x, int y, int z, int w) return { 426 this.x = this.x - x; 427 this.y = this.y - y; 428 this.z = this.z - z; 429 this.w = this.w - w; 430 return this; 431 } 432 433 public Vector4i sub(Vector4i v, ref Vector4i dest) { 434 dest.x = this.x - v.x; 435 dest.y = this.y - v.y; 436 dest.z = this.z - v.z; 437 dest.w = this.w - v.w; 438 return dest; 439 } 440 441 public Vector4i sub(int x, int y, int z, int w, ref Vector4i dest) { 442 dest.x = this.x - x; 443 dest.y = this.y - y; 444 dest.z = this.z - z; 445 dest.w = this.w - w; 446 return dest; 447 } 448 449 /** 450 * Add the supplied vector to this one. 451 * 452 * @param v 453 * the vector to add 454 * @return this 455 */ 456 ref public Vector4i add(Vector4i v) return { 457 this.x = this.x + v.x; 458 this.y = this.y + v.y; 459 this.z = this.z + v.z; 460 this.w = this.w + v.w; 461 return this; 462 } 463 464 public Vector4i add(Vector4i v, ref Vector4i dest) { 465 dest.x = this.x + v.x; 466 dest.y = this.y + v.y; 467 dest.z = this.z + v.z; 468 dest.w = this.w + v.w; 469 return dest; 470 } 471 472 /** 473 * Increment the components of this vector by the given values. 474 * 475 * @param x 476 * the x component to add 477 * @param y 478 * the y component to add 479 * @param z 480 * the z component to add 481 * @param w 482 * the w component to add 483 * @return this 484 */ 485 ref public Vector4i add(int x, int y, int z, int w) return { 486 this.x = this.x + x; 487 this.y = this.y + y; 488 this.z = this.z + z; 489 this.w = this.w + w; 490 return this; 491 } 492 493 public Vector4i add(int x, int y, int z, int w, ref Vector4i dest) { 494 dest.x = this.x + x; 495 dest.y = this.y + y; 496 dest.z = this.z + z; 497 dest.w = this.w + w; 498 return dest; 499 } 500 501 /** 502 * Multiply this Vector4i component-wise by another Vector4i. 503 * 504 * @param v 505 * the other vector 506 * @return this 507 */ 508 ref public Vector4i mul(Vector4i v) return { 509 this.x = x * v.x; 510 this.y = y * v.y; 511 this.z = z * v.z; 512 this.w = w * v.w; 513 return this; 514 } 515 516 public Vector4i mul(Vector4i v, ref Vector4i dest) { 517 dest.x = x * v.x; 518 dest.y = y * v.y; 519 dest.z = z * v.z; 520 dest.w = w * v.w; 521 return dest; 522 } 523 524 /** 525 * Divide this Vector4i component-wise by another Vector4i. 526 * 527 * @param v 528 * the vector to divide by 529 * @return this 530 */ 531 ref public Vector4i div(Vector4i v) return { 532 this.x = x / v.x; 533 this.y = y / v.y; 534 this.z = z / v.z; 535 this.w = w / v.w; 536 return this; 537 } 538 539 public Vector4i div(Vector4i v, ref Vector4i dest) { 540 dest.x = x / v.x; 541 dest.y = y / v.y; 542 dest.z = z / v.z; 543 dest.w = w / v.w; 544 return dest; 545 } 546 547 /** 548 * Multiply all components of this {@link Vector4i} by the given scalar 549 * value. 550 * 551 * @param scalar 552 * the scalar to multiply by 553 * @return this 554 */ 555 ref public Vector4i mul(int scalar) return { 556 this.x = x * scalar; 557 this.y = y * scalar; 558 this.z = z * scalar; 559 this.w = w * scalar; 560 return this; 561 } 562 563 public Vector4i mul(int scalar, ref Vector4i dest) { 564 dest.x = x * scalar; 565 dest.y = y * scalar; 566 dest.z = z * scalar; 567 dest.w = w * scalar; 568 return dest; 569 } 570 571 /** 572 * Divide all components of this {@link Vector3i} by the given scalar value. 573 * 574 * @param scalar 575 * the scalar to divide by 576 * @return this 577 */ 578 ref public Vector4i div(double scalar) return { 579 double invscalar = 1.0f / scalar; 580 this.x = cast(int) (x * invscalar); 581 this.y = cast(int) (y * invscalar); 582 this.z = cast(int) (z * invscalar); 583 this.w = cast(int) (w * invscalar); 584 return this; 585 } 586 587 public Vector4i div(double scalar, ref Vector4i dest) { 588 double invscalar = 1.0f / scalar; 589 dest.x = cast(int) (x * invscalar); 590 dest.y = cast(int) (y * invscalar); 591 dest.z = cast(int) (z * invscalar); 592 dest.w = cast(int) (w * invscalar); 593 return dest; 594 } 595 596 /** 597 * Divide all components of this {@link Vector4i} by the given scalar value. 598 * 599 * @param scalar 600 * the scalar to divide by 601 * @return this 602 */ 603 ref public Vector4i div(int scalar) return { 604 this.x = x / scalar; 605 this.y = y / scalar; 606 this.z = z / scalar; 607 this.w = w / scalar; 608 return this; 609 } 610 611 public Vector4i div(int scalar, ref Vector4i dest) { 612 dest.x = x / scalar; 613 dest.y = y / scalar; 614 dest.z = z / scalar; 615 dest.w = w / scalar; 616 return dest; 617 } 618 619 public long lengthSquared() { 620 return x * x + y * y + z * z + w * w; 621 } 622 623 /** 624 * Get the length squared of a 4-dimensional single-precision vector. 625 * 626 * @param x The vector's x component 627 * @param y The vector's y component 628 * @param z The vector's z component 629 * @param w The vector's w component 630 * 631 * @return the length squared of the given vector 632 */ 633 public static long lengthSquared(int x, int y, int z, int w) { 634 return x * x + y * y + z * z + w * w; 635 } 636 637 public double length() { 638 return Math.sqrt(x * x + y * y + z * z + w * w); 639 } 640 641 /** 642 * Get the length of a 4-dimensional single-precision vector. 643 * 644 * @param x The vector's x component 645 * @param y The vector's y component 646 * @param z The vector's z component 647 * @param w The vector's w component 648 * 649 * @return the length squared of the given vector 650 */ 651 public static double length(int x, int y, int z, int w) { 652 return Math.sqrt(x * x + y * y + z * z + w * w); 653 } 654 655 public double distance(Vector4i v) { 656 int dx = this.x - v.x; 657 int dy = this.y - v.y; 658 int dz = this.z - v.z; 659 int dw = this.w - v.w; 660 return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, Math.fma(dz, dz, dw * dw)))); 661 } 662 663 public double distance(int x, int y, int z, int w) { 664 int dx = this.x - x; 665 int dy = this.y - y; 666 int dz = this.z - z; 667 int dw = this.w - w; 668 return Math.sqrt(Math.fma(dx, dx, Math.fma(dy, dy, Math.fma(dz, dz, dw * dw)))); 669 } 670 671 public long gridDistance(Vector4i v) { 672 return Math.abs(v.x - this.x) + Math.abs(v.y - this.y) + Math.abs(v.z - this.z) + Math.abs(v.w - this.w); 673 } 674 675 public long gridDistance(int x, int y, int z, int w) { 676 return Math.abs(x - this.x) + Math.abs(y - this.y) + Math.abs(z - this.z) + Math.abs(w - this.w); 677 } 678 679 public int distanceSquared(Vector4i v) { 680 int dx = this.x - v.x; 681 int dy = this.y - v.y; 682 int dz = this.z - v.z; 683 int dw = this.w - v.w; 684 return dx * dx + dy * dy + dz * dz + dw * dw; 685 } 686 687 public int distanceSquared(int x, int y, int z, int w) { 688 int dx = this.x - x; 689 int dy = this.y - y; 690 int dz = this.z - z; 691 int dw = this.w - w; 692 return dx * dx + dy * dy + dz * dz + dw * dw; 693 } 694 695 /** 696 * Return the distance between <code>(x1, y1, z1, w1)</code> and <code>(x2, y2, z2, w2)</code>. 697 * 698 * @param x1 699 * the x component of the first vector 700 * @param y1 701 * the y component of the first vector 702 * @param z1 703 * the z component of the first vector 704 * @param w1 705 * the w component of the first vector 706 * @param x2 707 * the x component of the second vector 708 * @param y2 709 * the y component of the second vector 710 * @param z2 711 * the z component of the second vector 712 * @param w2 713 * the 2 component of the second vector 714 * @return the euclidean distance 715 */ 716 public static double distance(int x1, int y1, int z1, int w1, int x2, int y2, int z2, int w2) { 717 int dx = x1 - x2; 718 int dy = y1 - y2; 719 int dz = z1 - z2; 720 int dw = w1 - w2; 721 return Math.sqrt(dx * dx + dy * dy + dz * dz + dw * dw); 722 } 723 724 /** 725 * Return the squared distance between <code>(x1, y1, z1, w1)</code> and <code>(x2, y2, z2, w2)</code>. 726 * 727 * @param x1 728 * the x component of the first vector 729 * @param y1 730 * the y component of the first vector 731 * @param z1 732 * the z component of the first vector 733 * @param w1 734 * the w component of the first vector 735 * @param x2 736 * the x component of the second vector 737 * @param y2 738 * the y component of the second vector 739 * @param z2 740 * the z component of the second vector 741 * @param w2 742 * the w component of the second vector 743 * @return the euclidean distance squared 744 */ 745 public static long distanceSquared(int x1, int y1, int z1, int w1, int x2, int y2, int z2, int w2) { 746 int dx = x1 - x2; 747 int dy = y1 - y2; 748 int dz = z1 - z2; 749 int dw = w1 - w2; 750 return dx * dx + dy * dy + dz * dz + dw * dw; 751 } 752 753 public int dot(Vector4i v) { 754 return x * v.x + y * v.y + z * v.z + w * v.w; 755 } 756 757 /** 758 * Set all components to zero. 759 * 760 * @return this 761 */ 762 ref public Vector4i zero() return { 763 x = 0; 764 y = 0; 765 z = 0; 766 w = 0; 767 return this; 768 } 769 770 /** 771 * Negate this vector. 772 * 773 * @return this 774 */ 775 ref public Vector4i negate() return { 776 this.x = -x; 777 this.y = -y; 778 this.z = -z; 779 this.w = -w; 780 return this; 781 } 782 783 public Vector4i negate(ref Vector4i dest) { 784 dest.x = -x; 785 dest.y = -y; 786 dest.z = -z; 787 dest.w = -w; 788 return dest; 789 } 790 791 /** 792 * Set the components of this vector to be the component-wise minimum of this and the other vector. 793 * 794 * @param v 795 * the other vector 796 * @return this 797 */ 798 ref public Vector4i min(Vector4i v) return { 799 this.x = x < v.x ? x : v.x; 800 this.y = y < v.y ? y : v.y; 801 this.z = z < v.z ? z : v.z; 802 this.w = w < v.w ? w : v.w; 803 return this; 804 } 805 806 public Vector4i min(Vector4i v, ref Vector4i dest) { 807 dest.x = x < v.x ? x : v.x; 808 dest.y = y < v.y ? y : v.y; 809 dest.z = z < v.z ? z : v.z; 810 dest.w = w < v.w ? w : v.w; 811 return dest; 812 } 813 814 /** 815 * Set the components of this vector to be the component-wise maximum of this and the other vector. 816 * 817 * @param v 818 * the other vector 819 * @return this 820 */ 821 ref public Vector4i max(Vector4i v) return { 822 this.x = x > v.x ? x : v.x; 823 this.y = y > v.y ? y : v.y; 824 this.z = z > v.z ? z : v.z; 825 this.w = w > v.w ? w : v.w; 826 return this; 827 } 828 829 public Vector4i max(Vector4i v, ref Vector4i dest) { 830 dest.x = x > v.x ? x : v.x; 831 dest.y = y > v.y ? y : v.y; 832 dest.z = z > v.z ? z : v.z; 833 dest.w = w > v.w ? w : v.w; 834 return dest; 835 } 836 837 /** 838 * Compute the absolute of each of this vector's components. 839 * 840 * @return this 841 */ 842 ref public Vector4i absolute() return { 843 this.x = Math.abs(x); 844 this.y = Math.abs(y); 845 this.z = Math.abs(z); 846 this.w = Math.abs(w); 847 return this; 848 } 849 850 public Vector4i absolute(ref Vector4i dest) { 851 dest.x = Math.abs(x); 852 dest.y = Math.abs(y); 853 dest.z = Math.abs(z); 854 dest.w = Math.abs(w); 855 return dest; 856 } 857 858 public int hashCode() { 859 immutable int prime = 31; 860 int result = 1; 861 result = prime * result + x; 862 result = prime * result + y; 863 result = prime * result + z; 864 result = prime * result + w; 865 return result; 866 } 867 868 public bool equals(int x, int y, int z, int w) { 869 if (this.x != x) 870 return false; 871 if (this.y != y) 872 return false; 873 if (this.z != z) 874 return false; 875 if (this.w != w) 876 return false; 877 return true; 878 } 879 880 public bool equals(Vector4i other) { 881 if (this.x != other.x) 882 return false; 883 if (this.y != other.y) 884 return false; 885 if (this.z != other.z) 886 return false; 887 if (this.w != other.w) 888 return false; 889 return true; 890 } 891 892 }