001/* 002 * Trident - A Multithreaded Server Alternative 003 * Copyright 2014 The TridentSDK Team 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018package net.tridentsdk.util; 019 020import com.google.common.base.Objects; 021import net.tridentsdk.base.Position; 022import net.tridentsdk.world.World; 023 024import javax.annotation.concurrent.ThreadSafe; 025import java.io.Serializable; 026 027/** 028 * Just like in math, a vector represents magnitude and direction, where magnitude is usually the speed of an entity. 029 * 030 * <p>This class is essentially just 3 arbitrary values</p> 031 * 032 * @author The TridentSDK Team 033 * @since 0.3-alpha-DP 034 */ 035@ThreadSafe 036public class Vector implements Serializable, Cloneable { 037 private static final long serialVersionUID = -7634050835106851288L; 038 039 protected volatile double x; 040 protected volatile double y; 041 protected volatile double z; 042 043 /** 044 * Creates a default vector with x, y, and z set to (0, 0, 0) 045 */ 046 public Vector() { 047 this(0, 0, 0); 048 } 049 050 /** 051 * Creates a vector with the directional values set to the provided values 052 * 053 * @param x the x value of the vector 054 * @param y the y value of the vector 055 * @param z the z value of the vector 056 */ 057 public Vector(double x, double y, double z) { 058 this.setX(x); 059 this.setY(y); 060 this.setZ(z); 061 } 062 063 /** 064 * Creates a vector with the directional values set to the provided values 065 * 066 * @param x the x value of the vector 067 * @param y the y value of the vector 068 * @param z the z value of the vector 069 */ 070 public Vector(int x, int y, int z) { 071 this.setX((double) x); 072 this.setY((double) y); 073 this.setZ((double) z); 074 } 075 076 /** 077 * Adds the vector x, y, and z to the current vector coordinates 078 * 079 * @param vector the vector to retrieve the values to be added 080 * @return the current vector with updated coordinates 081 */ 082 public Vector add(Vector vector) { 083 return this.add(vector.x(), vector.y(), vector.z()); 084 } 085 086 /** 087 * Adds the coordinate values to the current vector's coordinates with double accuracy 088 * 089 * @param x the x value of the vector to add 090 * @param y the y value of the vector to add 091 * @param z the z value of the vector to add 092 * @return the current vector with updated coordinates 093 */ 094 public Vector add(double x, double y, double z) { 095 this.setX(this.x() + x); 096 this.setY(this.y() + y); 097 this.setZ(this.z() + z); 098 099 return this; 100 } 101 102 /** 103 * Adds the coordinate values to the current vector's coordinates 104 * 105 * @param x the x value of the vector to add 106 * @param y the y value of the vector to add 107 * @param z the z value of the vector to add 108 * @return the current vector with updated coordinates 109 */ 110 public Vector add(int x, int y, int z) { 111 return this.add((double) x, (double) y, (double) z); 112 /* Implementation detail: 113 DO NOT CREATE A NEW VECTOR HERE JUST BECAUSE (!) 114 Doing so wastes memory and adds unnecessary object 115 creation overhead, therefore, delegate to the 116 setters instead of the previous implementation. 117 Same with the other methods */ 118 } 119 120 /** 121 * Takes the current vector coordinates and subtract them with the vector x, y, and z 122 * 123 * @param vector the vector to retrieve the values to be subtracted 124 * @return the current vector with updated coordinates 125 */ 126 public Vector subtract(Vector vector) { 127 return this.subtract(vector.x(), vector.y(), vector.z()); 128 } 129 130 /** 131 * Takes the the current vector's coordinates and subtracts them from the coordinate values with double accuracy 132 * 133 * @param x the x value of the vector to subtract 134 * @param y the y value of the vector to subtract 135 * @param z the z value of the vector to subtract 136 * @return the current vector with updated coordinates 137 */ 138 public Vector subtract(double x, double y, double z) { 139 this.setX(this.x() - x); 140 this.setY(this.y() - y); 141 this.setZ(this.z() - z); 142 143 return this; 144 } 145 146 /** 147 * Takes the the current vector's coordinates and subtracts them from the coordinate values 148 * 149 * @param x the x value of the vector to subtract 150 * @param y the y value of the vector to subtract 151 * @param z the z value of the vector to subtract 152 * @return the current vector with updated coordinates 153 */ 154 public Vector subtract(int x, int y, int z) { 155 return this.subtract((double) x, (double) y, (double) z); 156 } 157 158 /** 159 * Multiplies the vector x, y, and z to the current vector coordinates 160 * 161 * @param vec the vector to retrieve the values to be multiplied 162 * @return the current vector with updated coordinates 163 */ 164 public Vector multiply(Vector vec) { 165 return this.multiply(vec.x(), vec.y(), vec.z()); 166 } 167 168 /** 169 * Multiplies the magnitude of this vector by a double 170 * 171 * @param amount The amount to multiply by 172 * @return This vector, with updated coordinates 173 */ 174 public Vector multiply(double amount) { 175 return this.multiply(amount, amount, amount); 176 } 177 178 /** 179 * Multiplies the coordinate values to the current vector's coordinates with double accuracy 180 * 181 * @param x the x value of the vector to multiply 182 * @param y the y value of the vector to multiply 183 * @param z the z value of the vector to multiply 184 * @return the current vector with updated coordinates 185 */ 186 public Vector multiply(double x, double y, double z) { 187 this.setX(this.x() * x); 188 this.setY(this.y() * y); 189 this.setZ(this.z() * z); 190 191 return this; 192 } 193 194 /** 195 * Multiplies the coordinate values to the current vector's coordinates 196 * 197 * @param x the x value of the vector to multiply 198 * @param y the y value of the vector to multiply 199 * @param z the z value of the vector to multiply 200 * @return the current vector with updated coordinates 201 */ 202 public Vector multiply(int x, int y, int z) { 203 return this.multiply((double) x, (double) y, (double) z); 204 } 205 206 /** 207 * Takes the current vector coordinates and divide them with the vector x, y, and z 208 * 209 * @param vec the vector to retrieve the values to be divided 210 * @return the current vector with updated coordinates 211 */ 212 public Vector divide(Vector vec) { 213 return this.divide(vec.x(), vec.y(), vec.z()); 214 } 215 216 /** 217 * Divides the magnitude of this vector by a given amount. 218 * 219 * @param amount The amount to divide by 220 * @return this vector 221 */ 222 public Vector divide(double amount) { 223 return this.divide(amount, amount, amount); 224 } 225 226 /** 227 * Takes the the current vector's coordinates and divides them from the coordinate values with double accuracy 228 * 229 * @param x the x value of the vector to divide 230 * @param y the y value of the vector to divide 231 * @param z the z value of the vector to divide 232 * @return the current vector with updated coordinates 233 */ 234 public Vector divide(double x, double y, double z) { 235 this.setX(this.x() / x); 236 this.setY(this.y() / y); 237 this.setZ(this.z() / z); 238 239 return this; 240 } 241 242 /** 243 * Takes the the current vector's coordinates and divides them from the coordinate values 244 * 245 * @param x the x value of the vector to divide 246 * @param y the y value of the vector to divide 247 * @param z the z value of the vector to divide 248 * @return the current vector with updated coordinates 249 */ 250 public Vector divide(int x, int y, int z) { 251 return this.divide((double) x, (double) y, (double) z); 252 } 253 254 /** 255 * Sets the current vector to the crossproduct between this vector and another one 256 * 257 * @param vector the vector to crossproduct with 258 * @return this vector, updated with the crossproduct with the other vector 259 */ 260 public Vector crossProduct(Vector vector) { 261 double x = this.x; 262 double y = this.y; 263 double z = this.z; 264 265 this.setX(y * vector.z() - vector.y() * z); 266 this.setY(z * vector.x() - vector.z() - x); 267 this.setZ(x * vector.y() - vector.x() * y); 268 269 return this; 270 } 271 272 /** 273 * Gets the square of the magnitude of this vector 274 * 275 * @return The magnitude of this vector, squared 276 */ 277 public double magnitudeSquared() { 278 return this.x * this.x + this.y * this.y + this.z * this.z; 279 } 280 281 /** 282 * Gets the magnitude for this vector Note that this is an expensive operation, and if possible, you should use 283 * magnitudeSquared() instead 284 * 285 * @return The magnitude of this vector 286 */ 287 public double magnitude() { 288 return Math.sqrt(this.magnitudeSquared()); 289 } 290 291 /** 292 * Normalizes this vector (changes the magnitude to 1 without changing the direction) 293 * 294 * @return This vector 295 */ 296 public Vector normalize() { 297 return this.divide(this.magnitude()); 298 } 299 300 /** 301 * Calculates the dot product of this vector and another 302 * 303 * @param vec the other vector 304 * @return dot product of the two vectors 305 */ 306 public double dotProduct(Vector vec) { 307 return this.x * vec.x + this.y * vec.y + this.z * vec.z; 308 } 309 310 /** 311 * Returns a new position in this world, with the coordinates the x, y, and z values 312 */ 313 public Position asLocation(World world) { 314 return Position.create(world, this.x, this.y, this.z); 315 } 316 317 /** 318 * Gets the x directional-magnitude value 319 * 320 * @return the vector x value 321 */ 322 public double x() { 323 return this.x; 324 } 325 326 /** 327 * Sets this vector's x value 328 * 329 * @param x the x value to set this vector 330 */ 331 public void setX(double x) { 332 this.x = x; 333 } 334 335 /** 336 * Gets the y directional-magnitude value 337 * 338 * @return the vector y value 339 */ 340 public double y() { 341 return this.y; 342 } 343 344 /** 345 * Sets this vector's y value 346 * 347 * @param y the y value to set this vector 348 */ 349 public void setY(double y) { 350 this.y = y; 351 } 352 353 /** 354 * Gets the z directional-magnitude value 355 * 356 * @return the vector z value 357 */ 358 public double z() { 359 return this.z; 360 } 361 362 /** 363 * Sets this vector's z value 364 * 365 * @param z the z value to set this vector 366 */ 367 public void setZ(double z) { 368 this.z = z; 369 } 370 371 /** 372 * Clones this Vector. 373 * 374 * @return the cloned vector 375 */ 376 @Override 377 public Vector clone() { 378 try { 379 return (Vector) super.clone(); 380 } catch (CloneNotSupportedException e) { 381 return null; 382 } 383 } 384 385 @Override 386 public boolean equals(Object obj) { 387 if (!(obj instanceof Vector)) 388 return false; 389 if (obj.hashCode() != this.hashCode()) 390 return false; 391 if (x != ((Vector) obj).x) { 392 return false; 393 } else if (y != ((Vector) obj).y) { 394 return false; 395 } else if (z != ((Vector) obj).z) { 396 return false; 397 } 398 399 return true; 400 } 401 402 @Override 403 public int hashCode() { 404 return Objects.hashCode(x, y, z); 405 } 406 407 @Override 408 public String toString(){ 409 return "Vector{" + 410 "x=" + x + 411 ", y=" + y + 412 ", z=" + z + 413 '}'; 414 } 415}