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