001 package org.bukkit.util; 002 003 import java.util.LinkedHashMap; 004 import java.util.Map; 005 import java.util.Random; 006 import org.bukkit.Location; 007 import org.bukkit.World; 008 import org.bukkit.configuration.serialization.ConfigurationSerializable; 009 import org.bukkit.configuration.serialization.SerializableAs; 010 011 /** 012 * Represents a mutable vector. Because the components of Vectors are mutable, 013 * storing Vectors long term may be dangerous if passing code modifies the 014 * Vector later. If you want to keep around a Vector, it may be wise to call 015 * <code>clone()</code> in order to get a copy. 016 */ 017 @SerializableAs("Vector") 018 public class Vector implements Cloneable, ConfigurationSerializable { 019 private static final long serialVersionUID = -2657651106777219169L; 020 021 private static Random random = new Random(); 022 023 /** 024 * Threshold for fuzzy equals(). 025 */ 026 private static final double epsilon = 0.000001; 027 028 protected double x; 029 protected double y; 030 protected double z; 031 032 /** 033 * Construct the vector with all components as 0. 034 */ 035 public Vector() { 036 this.x = 0; 037 this.y = 0; 038 this.z = 0; 039 } 040 041 /** 042 * Construct the vector with provided integer components. 043 * 044 * @param x X component 045 * @param y Y component 046 * @param z Z component 047 */ 048 public Vector(int x, int y, int z) { 049 this.x = x; 050 this.y = y; 051 this.z = z; 052 } 053 054 /** 055 * Construct the vector with provided double components. 056 * 057 * @param x X component 058 * @param y Y component 059 * @param z Z component 060 */ 061 public Vector(double x, double y, double z) { 062 this.x = x; 063 this.y = y; 064 this.z = z; 065 } 066 067 /** 068 * Construct the vector with provided float components. 069 * 070 * @param x X component 071 * @param y Y component 072 * @param z Z component 073 */ 074 public Vector(float x, float y, float z) { 075 this.x = x; 076 this.y = y; 077 this.z = z; 078 } 079 080 /** 081 * Adds a vector to this one 082 * 083 * @param vec The other vector 084 * @return the same vector 085 */ 086 public Vector add(Vector vec) { 087 x += vec.x; 088 y += vec.y; 089 z += vec.z; 090 return this; 091 } 092 093 /** 094 * Subtracts a vector from this one. 095 * 096 * @param vec The other vector 097 * @return the same vector 098 */ 099 public Vector subtract(Vector vec) { 100 x -= vec.x; 101 y -= vec.y; 102 z -= vec.z; 103 return this; 104 } 105 106 /** 107 * Multiplies the vector by another. 108 * 109 * @param vec The other vector 110 * @return the same vector 111 */ 112 public Vector multiply(Vector vec) { 113 x *= vec.x; 114 y *= vec.y; 115 z *= vec.z; 116 return this; 117 } 118 119 /** 120 * Divides the vector by another. 121 * 122 * @param vec The other vector 123 * @return the same vector 124 */ 125 public Vector divide(Vector vec) { 126 x /= vec.x; 127 y /= vec.y; 128 z /= vec.z; 129 return this; 130 } 131 132 /** 133 * Copies another vector 134 * 135 * @param vec The other vector 136 * @return the same vector 137 */ 138 public Vector copy(Vector vec) { 139 x = vec.x; 140 y = vec.y; 141 z = vec.z; 142 return this; 143 } 144 145 /** 146 * Gets the magnitude of the vector, defined as sqrt(x^2+y^2+z^2). The 147 * value of this method is not cached and uses a costly square-root 148 * function, so do not repeatedly call this method to get the vector's 149 * magnitude. NaN will be returned if the inner result of the sqrt() 150 * function overflows, which will be caused if the length is too long. 151 * 152 * @return the magnitude 153 */ 154 public double length() { 155 return Math.sqrt(NumberConversions.square(x) + NumberConversions.square(y) + NumberConversions.square(z)); 156 } 157 158 /** 159 * Gets the magnitude of the vector squared. 160 * 161 * @return the magnitude 162 */ 163 public double lengthSquared() { 164 return NumberConversions.square(x) + NumberConversions.square(y) + NumberConversions.square(z); 165 } 166 167 /** 168 * Get the distance between this vector and another. The value of this 169 * method is not cached and uses a costly square-root function, so do not 170 * repeatedly call this method to get the vector's magnitude. NaN will be 171 * returned if the inner result of the sqrt() function overflows, which 172 * will be caused if the distance is too long. 173 * 174 * @param o The other vector 175 * @return the distance 176 */ 177 public double distance(Vector o) { 178 return Math.sqrt(NumberConversions.square(x - o.x) + NumberConversions.square(y - o.y) + NumberConversions.square(z - o.z)); 179 } 180 181 /** 182 * Get the squared distance between this vector and another. 183 * 184 * @param o The other vector 185 * @return the distance 186 */ 187 public double distanceSquared(Vector o) { 188 return NumberConversions.square(x - o.x) + NumberConversions.square(y - o.y) + NumberConversions.square(z - o.z); 189 } 190 191 /** 192 * Gets the angle between this vector and another in radians. 193 * 194 * @param other The other vector 195 * @return angle in radians 196 */ 197 public float angle(Vector other) { 198 double dot = dot(other) / (length() * other.length()); 199 200 return (float) Math.acos(dot); 201 } 202 203 /** 204 * Sets this vector to the midpoint between this vector and another. 205 * 206 * @param other The other vector 207 * @return this same vector (now a midpoint) 208 */ 209 public Vector midpoint(Vector other) { 210 x = (x + other.x) / 2; 211 y = (y + other.y) / 2; 212 z = (z + other.z) / 2; 213 return this; 214 } 215 216 /** 217 * Gets a new midpoint vector between this vector and another. 218 * 219 * @param other The other vector 220 * @return a new midpoint vector 221 */ 222 public Vector getMidpoint(Vector other) { 223 double x = (this.x + other.x) / 2; 224 double y = (this.y + other.y) / 2; 225 double z = (this.z + other.z) / 2; 226 return new Vector(x, y, z); 227 } 228 229 /** 230 * Performs scalar multiplication, multiplying all components with a 231 * scalar. 232 * 233 * @param m The factor 234 * @return the same vector 235 */ 236 public Vector multiply(int m) { 237 x *= m; 238 y *= m; 239 z *= m; 240 return this; 241 } 242 243 /** 244 * Performs scalar multiplication, multiplying all components with a 245 * scalar. 246 * 247 * @param m The factor 248 * @return the same vector 249 */ 250 public Vector multiply(double m) { 251 x *= m; 252 y *= m; 253 z *= m; 254 return this; 255 } 256 257 /** 258 * Performs scalar multiplication, multiplying all components with a 259 * scalar. 260 * 261 * @param m The factor 262 * @return the same vector 263 */ 264 public Vector multiply(float m) { 265 x *= m; 266 y *= m; 267 z *= m; 268 return this; 269 } 270 271 /** 272 * Calculates the dot product of this vector with another. The dot product 273 * is defined as x1*x2+y1*y2+z1*z2. The returned value is a scalar. 274 * 275 * @param other The other vector 276 * @return dot product 277 */ 278 public double dot(Vector other) { 279 return x * other.x + y * other.y + z * other.z; 280 } 281 282 /** 283 * Calculates the cross product of this vector with another. The cross 284 * product is defined as: 285 * <ul> 286 * <li>x = y1 * z2 - y2 * z1 287 * <li>y = z1 * x2 - z2 * x1 288 * <li>z = x1 * y2 - x2 * y1 289 * </ul> 290 * 291 * @param o The other vector 292 * @return the same vector 293 */ 294 public Vector crossProduct(Vector o) { 295 double newX = y * o.z - o.y * z; 296 double newY = z * o.x - o.z * x; 297 double newZ = x * o.y - o.x * y; 298 299 x = newX; 300 y = newY; 301 z = newZ; 302 return this; 303 } 304 305 /** 306 * Converts this vector to a unit vector (a vector with length of 1). 307 * 308 * @return the same vector 309 */ 310 public Vector normalize() { 311 double length = length(); 312 313 x /= length; 314 y /= length; 315 z /= length; 316 317 return this; 318 } 319 320 /** 321 * Zero this vector's components. 322 * 323 * @return the same vector 324 */ 325 public Vector zero() { 326 x = 0; 327 y = 0; 328 z = 0; 329 return this; 330 } 331 332 /** 333 * Returns whether this vector is in an axis-aligned bounding box. 334 * <p> 335 * The minimum and maximum vectors given must be truly the minimum and 336 * maximum X, Y and Z components. 337 * 338 * @param min Minimum vector 339 * @param max Maximum vector 340 * @return whether this vector is in the AABB 341 */ 342 public boolean isInAABB(Vector min, Vector max) { 343 return x >= min.x && x <= max.x && y >= min.y && y <= max.y && z >= min.z && z <= max.z; 344 } 345 346 /** 347 * Returns whether this vector is within a sphere. 348 * 349 * @param origin Sphere origin. 350 * @param radius Sphere radius 351 * @return whether this vector is in the sphere 352 */ 353 public boolean isInSphere(Vector origin, double radius) { 354 return (NumberConversions.square(origin.x - x) + NumberConversions.square(origin.y - y) + NumberConversions.square(origin.z - z)) <= NumberConversions.square(radius); 355 } 356 357 /** 358 * Gets the X component. 359 * 360 * @return The X component. 361 */ 362 public double getX() { 363 return x; 364 } 365 366 /** 367 * Gets the floored value of the X component, indicating the block that 368 * this vector is contained with. 369 * 370 * @return block X 371 */ 372 public int getBlockX() { 373 return NumberConversions.floor(x); 374 } 375 376 /** 377 * Gets the Y component. 378 * 379 * @return The Y component. 380 */ 381 public double getY() { 382 return y; 383 } 384 385 /** 386 * Gets the floored value of the Y component, indicating the block that 387 * this vector is contained with. 388 * 389 * @return block y 390 */ 391 public int getBlockY() { 392 return NumberConversions.floor(y); 393 } 394 395 /** 396 * Gets the Z component. 397 * 398 * @return The Z component. 399 */ 400 public double getZ() { 401 return z; 402 } 403 404 /** 405 * Gets the floored value of the Z component, indicating the block that 406 * this vector is contained with. 407 * 408 * @return block z 409 */ 410 public int getBlockZ() { 411 return NumberConversions.floor(z); 412 } 413 414 /** 415 * Set the X component. 416 * 417 * @param x The new X component. 418 * @return This vector. 419 */ 420 public Vector setX(int x) { 421 this.x = x; 422 return this; 423 } 424 425 /** 426 * Set the X component. 427 * 428 * @param x The new X component. 429 * @return This vector. 430 */ 431 public Vector setX(double x) { 432 this.x = x; 433 return this; 434 } 435 436 /** 437 * Set the X component. 438 * 439 * @param x The new X component. 440 * @return This vector. 441 */ 442 public Vector setX(float x) { 443 this.x = x; 444 return this; 445 } 446 447 /** 448 * Set the Y component. 449 * 450 * @param y The new Y component. 451 * @return This vector. 452 */ 453 public Vector setY(int y) { 454 this.y = y; 455 return this; 456 } 457 458 /** 459 * Set the Y component. 460 * 461 * @param y The new Y component. 462 * @return This vector. 463 */ 464 public Vector setY(double y) { 465 this.y = y; 466 return this; 467 } 468 469 /** 470 * Set the Y component. 471 * 472 * @param y The new Y component. 473 * @return This vector. 474 */ 475 public Vector setY(float y) { 476 this.y = y; 477 return this; 478 } 479 480 /** 481 * Set the Z component. 482 * 483 * @param z The new Z component. 484 * @return This vector. 485 */ 486 public Vector setZ(int z) { 487 this.z = z; 488 return this; 489 } 490 491 /** 492 * Set the Z component. 493 * 494 * @param z The new Z component. 495 * @return This vector. 496 */ 497 public Vector setZ(double z) { 498 this.z = z; 499 return this; 500 } 501 502 /** 503 * Set the Z component. 504 * 505 * @param z The new Z component. 506 * @return This vector. 507 */ 508 public Vector setZ(float z) { 509 this.z = z; 510 return this; 511 } 512 513 /** 514 * Checks to see if two objects are equal. 515 * <p> 516 * Only two Vectors can ever return true. This method uses a fuzzy match 517 * to account for floating point errors. The epsilon can be retrieved 518 * with epsilon. 519 */ 520 @Override 521 public boolean equals(Object obj) { 522 if (!(obj instanceof Vector)) { 523 return false; 524 } 525 526 Vector other = (Vector) obj; 527 528 return Math.abs(x - other.x) < epsilon && Math.abs(y - other.y) < epsilon && Math.abs(z - other.z) < epsilon && (this.getClass().equals(obj.getClass())); 529 } 530 531 /** 532 * Returns a hash code for this vector 533 * 534 * @return hash code 535 */ 536 @Override 537 public int hashCode() { 538 int hash = 7; 539 540 hash = 79 * hash + (int) (Double.doubleToLongBits(this.x) ^ (Double.doubleToLongBits(this.x) >>> 32)); 541 hash = 79 * hash + (int) (Double.doubleToLongBits(this.y) ^ (Double.doubleToLongBits(this.y) >>> 32)); 542 hash = 79 * hash + (int) (Double.doubleToLongBits(this.z) ^ (Double.doubleToLongBits(this.z) >>> 32)); 543 return hash; 544 } 545 546 /** 547 * Get a new vector. 548 * 549 * @return vector 550 */ 551 @Override 552 public Vector clone() { 553 try { 554 return (Vector) super.clone(); 555 } catch (CloneNotSupportedException e) { 556 throw new Error(e); 557 } 558 } 559 560 /** 561 * Returns this vector's components as x,y,z. 562 */ 563 @Override 564 public String toString() { 565 return x + "," + y + "," + z; 566 } 567 568 /** 569 * Gets a Location version of this vector with yaw and pitch being 0. 570 * 571 * @param world The world to link the location to. 572 * @return the location 573 */ 574 public Location toLocation(World world) { 575 return new Location(world, x, y, z); 576 } 577 578 /** 579 * Gets a Location version of this vector. 580 * 581 * @param world The world to link the location to. 582 * @param yaw The desired yaw. 583 * @param pitch The desired pitch. 584 * @return the location 585 */ 586 public Location toLocation(World world, float yaw, float pitch) { 587 return new Location(world, x, y, z, yaw, pitch); 588 } 589 590 /** 591 * Get the block vector of this vector. 592 * 593 * @return A block vector. 594 */ 595 public BlockVector toBlockVector() { 596 return new BlockVector(x, y, z); 597 } 598 599 /** 600 * Get the threshold used for equals(). 601 * 602 * @return The epsilon. 603 */ 604 public static double getEpsilon() { 605 return epsilon; 606 } 607 608 /** 609 * Gets the minimum components of two vectors. 610 * 611 * @param v1 The first vector. 612 * @param v2 The second vector. 613 * @return minimum 614 */ 615 public static Vector getMinimum(Vector v1, Vector v2) { 616 return new Vector(Math.min(v1.x, v2.x), Math.min(v1.y, v2.y), Math.min(v1.z, v2.z)); 617 } 618 619 /** 620 * Gets the maximum components of two vectors. 621 * 622 * @param v1 The first vector. 623 * @param v2 The second vector. 624 * @return maximum 625 */ 626 public static Vector getMaximum(Vector v1, Vector v2) { 627 return new Vector(Math.max(v1.x, v2.x), Math.max(v1.y, v2.y), Math.max(v1.z, v2.z)); 628 } 629 630 /** 631 * Gets a random vector with components having a random value between 0 632 * and 1. 633 * 634 * @return A random vector. 635 */ 636 public static Vector getRandom() { 637 return new Vector(random.nextDouble(), random.nextDouble(), random.nextDouble()); 638 } 639 640 public Map<String, Object> serialize() { 641 Map<String, Object> result = new LinkedHashMap<String, Object>(); 642 643 result.put("x", getX()); 644 result.put("y", getY()); 645 result.put("z", getZ()); 646 647 return result; 648 } 649 650 public static Vector deserialize(Map<String, Object> args) { 651 double x = 0; 652 double y = 0; 653 double z = 0; 654 655 if (args.containsKey("x")) { 656 x = (Double) args.get("x"); 657 } 658 if (args.containsKey("y")) { 659 y = (Double) args.get("y"); 660 } 661 if (args.containsKey("z")) { 662 z = (Double) args.get("z"); 663 } 664 665 return new Vector(x, y, z); 666 } 667 }