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