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    }