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