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