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