1/*
2 * Copyright (c) 2009-2010 jMonkeyEngine
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 *   notice, this list of conditions and the following disclaimer.
11 *
12 * * Redistributions in binary form must reproduce the above copyright
13 *   notice, this list of conditions and the following disclaimer in the
14 *   documentation and/or other materials provided with the distribution.
15 *
16 * * Neither the name of 'jMonkeyEngine' nor the names of its contributors
17 *   may be used to endorse or promote products derived from this software
18 *   without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33package com.jme3.math;
34
35import com.jme3.export.*;
36import java.io.Externalizable;
37import java.io.IOException;
38import java.io.ObjectInput;
39import java.io.ObjectOutput;
40import java.util.logging.Logger;
41
42/**
43 * <code>Vector2f</code> defines a Vector for a two float value vector.
44 *
45 * @author Mark Powell
46 * @author Joshua Slack
47 */
48public final class Vector2f implements Savable, Cloneable, java.io.Serializable {
49
50    static final long serialVersionUID = 1;
51    private static final Logger logger = Logger.getLogger(Vector2f.class.getName());
52
53    public static final Vector2f ZERO = new Vector2f(0f, 0f);
54    public static final Vector2f UNIT_XY = new Vector2f(1f, 1f);
55
56    /**
57     * the x value of the vector.
58     */
59    public float x;
60    /**
61     * the y value of the vector.
62     */
63    public float y;
64
65    /**
66     * Creates a Vector2f with the given initial x and y values.
67     *
68     * @param x
69     *            The x value of this Vector2f.
70     * @param y
71     *            The y value of this Vector2f.
72     */
73    public Vector2f(float x, float y) {
74        this.x = x;
75        this.y = y;
76    }
77
78    /**
79     * Creates a Vector2f with x and y set to 0. Equivalent to Vector2f(0,0).
80     */
81    public Vector2f() {
82        x = y = 0;
83    }
84
85    /**
86     * Creates a new Vector2f that contains the passed vector's information
87     *
88     * @param vector2f
89     *            The vector to copy
90     */
91    public Vector2f(Vector2f vector2f) {
92        this.x = vector2f.x;
93        this.y = vector2f.y;
94    }
95
96    /**
97     * set the x and y values of the vector
98     *
99     * @param x
100     *            the x value of the vector.
101     * @param y
102     *            the y value of the vector.
103     * @return this vector
104     */
105    public Vector2f set(float x, float y) {
106        this.x = x;
107        this.y = y;
108        return this;
109    }
110
111    /**
112     * set the x and y values of the vector from another vector
113     *
114     * @param vec
115     *            the vector to copy from
116     * @return this vector
117     */
118    public Vector2f set(Vector2f vec) {
119        this.x = vec.x;
120        this.y = vec.y;
121        return this;
122    }
123
124    /**
125     * <code>add</code> adds a provided vector to this vector creating a
126     * resultant vector which is returned. If the provided vector is null, null
127     * is returned.
128     *
129     * @param vec
130     *            the vector to add to this.
131     * @return the resultant vector.
132     */
133    public Vector2f add(Vector2f vec) {
134        if (null == vec) {
135            logger.warning("Provided vector is null, null returned.");
136            return null;
137        }
138        return new Vector2f(x + vec.x, y + vec.y);
139    }
140
141    /**
142     * <code>addLocal</code> adds a provided vector to this vector internally,
143     * and returns a handle to this vector for easy chaining of calls. If the
144     * provided vector is null, null is returned.
145     *
146     * @param vec
147     *            the vector to add to this vector.
148     * @return this
149     */
150    public Vector2f addLocal(Vector2f vec) {
151        if (null == vec) {
152            logger.warning("Provided vector is null, null returned.");
153            return null;
154        }
155        x += vec.x;
156        y += vec.y;
157        return this;
158    }
159
160    /**
161     * <code>addLocal</code> adds the provided values to this vector
162     * internally, and returns a handle to this vector for easy chaining of
163     * calls.
164     *
165     * @param addX
166     *            value to add to x
167     * @param addY
168     *            value to add to y
169     * @return this
170     */
171    public Vector2f addLocal(float addX, float addY) {
172        x += addX;
173        y += addY;
174        return this;
175    }
176
177    /**
178     * <code>add</code> adds this vector by <code>vec</code> and stores the
179     * result in <code>result</code>.
180     *
181     * @param vec
182     *            The vector to add.
183     * @param result
184     *            The vector to store the result in.
185     * @return The result vector, after adding.
186     */
187    public Vector2f add(Vector2f vec, Vector2f result) {
188        if (null == vec) {
189            logger.warning("Provided vector is null, null returned.");
190            return null;
191        }
192        if (result == null)
193            result = new Vector2f();
194        result.x = x + vec.x;
195        result.y = y + vec.y;
196        return result;
197    }
198
199    /**
200     * <code>dot</code> calculates the dot product of this vector with a
201     * provided vector. If the provided vector is null, 0 is returned.
202     *
203     * @param vec
204     *            the vector to dot with this vector.
205     * @return the resultant dot product of this vector and a given vector.
206     */
207    public float dot(Vector2f vec) {
208        if (null == vec) {
209            logger.warning("Provided vector is null, 0 returned.");
210            return 0;
211        }
212        return x * vec.x + y * vec.y;
213    }
214
215    /**
216     * <code>cross</code> calculates the cross product of this vector with a
217     * parameter vector v.
218     *
219     * @param v
220     *            the vector to take the cross product of with this.
221     * @return the cross product vector.
222     */
223    public Vector3f cross(Vector2f v) {
224        return new Vector3f(0, 0, determinant(v));
225    }
226
227    public float determinant(Vector2f v) {
228        return (x * v.y) - (y * v.x);
229    }
230
231    /**
232     * Sets this vector to the interpolation by changeAmnt from this to the
233     * finalVec this=(1-changeAmnt)*this + changeAmnt * finalVec
234     *
235     * @param finalVec
236     *            The final vector to interpolate towards
237     * @param changeAmnt
238     *            An amount between 0.0 - 1.0 representing a percentage change
239     *            from this towards finalVec
240     */
241    public Vector2f interpolate(Vector2f finalVec, float changeAmnt) {
242        this.x = (1 - changeAmnt) * this.x + changeAmnt * finalVec.x;
243        this.y = (1 - changeAmnt) * this.y + changeAmnt * finalVec.y;
244        return this;
245    }
246
247    /**
248     * Sets this vector to the interpolation by changeAmnt from beginVec to
249     * finalVec this=(1-changeAmnt)*beginVec + changeAmnt * finalVec
250     *
251     * @param beginVec
252     *            The begining vector (delta=0)
253     * @param finalVec
254     *            The final vector to interpolate towards (delta=1)
255     * @param changeAmnt
256     *            An amount between 0.0 - 1.0 representing a precentage change
257     *            from beginVec towards finalVec
258     */
259    public Vector2f interpolate(Vector2f beginVec, Vector2f finalVec,
260            float changeAmnt) {
261        this.x = (1 - changeAmnt) * beginVec.x + changeAmnt * finalVec.x;
262        this.y = (1 - changeAmnt) * beginVec.y + changeAmnt * finalVec.y;
263        return this;
264    }
265
266    /**
267     * Check a vector... if it is null or its floats are NaN or infinite, return
268     * false. Else return true.
269     *
270     * @param vector
271     *            the vector to check
272     * @return true or false as stated above.
273     */
274    public static boolean isValidVector(Vector2f vector) {
275      if (vector == null) return false;
276      if (Float.isNaN(vector.x) ||
277          Float.isNaN(vector.y)) return false;
278      if (Float.isInfinite(vector.x) ||
279          Float.isInfinite(vector.y)) return false;
280      return true;
281    }
282
283    /**
284     * <code>length</code> calculates the magnitude of this vector.
285     *
286     * @return the length or magnitude of the vector.
287     */
288    public float length() {
289        return FastMath.sqrt(lengthSquared());
290    }
291
292    /**
293     * <code>lengthSquared</code> calculates the squared value of the
294     * magnitude of the vector.
295     *
296     * @return the magnitude squared of the vector.
297     */
298    public float lengthSquared() {
299        return x * x + y * y;
300    }
301
302    /**
303     * <code>distanceSquared</code> calculates the distance squared between
304     * this vector and vector v.
305     *
306     * @param v the second vector to determine the distance squared.
307     * @return the distance squared between the two vectors.
308     */
309    public float distanceSquared(Vector2f v) {
310        double dx = x - v.x;
311        double dy = y - v.y;
312        return (float) (dx * dx + dy * dy);
313    }
314
315    /**
316     * <code>distanceSquared</code> calculates the distance squared between
317     * this vector and vector v.
318     *
319     * @param otherX The X coordinate of the v vector
320     * @param otherY The Y coordinate of the v vector
321     * @return the distance squared between the two vectors.
322     */
323    public float distanceSquared(float otherX, float otherY) {
324        double dx = x - otherX;
325        double dy = y - otherY;
326        return (float) (dx * dx + dy * dy);
327    }
328
329    /**
330     * <code>distance</code> calculates the distance between this vector and
331     * vector v.
332     *
333     * @param v the second vector to determine the distance.
334     * @return the distance between the two vectors.
335     */
336    public float distance(Vector2f v) {
337        return FastMath.sqrt(distanceSquared(v));
338    }
339
340    /**
341     * <code>mult</code> multiplies this vector by a scalar. The resultant
342     * vector is returned.
343     *
344     * @param scalar
345     *            the value to multiply this vector by.
346     * @return the new vector.
347     */
348    public Vector2f mult(float scalar) {
349        return new Vector2f(x * scalar, y * scalar);
350    }
351
352    /**
353     * <code>multLocal</code> multiplies this vector by a scalar internally,
354     * and returns a handle to this vector for easy chaining of calls.
355     *
356     * @param scalar
357     *            the value to multiply this vector by.
358     * @return this
359     */
360    public Vector2f multLocal(float scalar) {
361        x *= scalar;
362        y *= scalar;
363        return this;
364    }
365
366    /**
367     * <code>multLocal</code> multiplies a provided vector to this vector
368     * internally, and returns a handle to this vector for easy chaining of
369     * calls. If the provided vector is null, null is returned.
370     *
371     * @param vec
372     *            the vector to mult to this vector.
373     * @return this
374     */
375    public Vector2f multLocal(Vector2f vec) {
376        if (null == vec) {
377            logger.warning("Provided vector is null, null returned.");
378            return null;
379        }
380        x *= vec.x;
381        y *= vec.y;
382        return this;
383    }
384
385    /**
386     * Multiplies this Vector2f's x and y by the scalar and stores the result in
387     * product. The result is returned for chaining. Similar to
388     * product=this*scalar;
389     *
390     * @param scalar
391     *            The scalar to multiply by.
392     * @param product
393     *            The vector2f to store the result in.
394     * @return product, after multiplication.
395     */
396    public Vector2f mult(float scalar, Vector2f product) {
397        if (null == product) {
398            product = new Vector2f();
399        }
400
401        product.x = x * scalar;
402        product.y = y * scalar;
403        return product;
404    }
405
406    /**
407     * <code>divide</code> divides the values of this vector by a scalar and
408     * returns the result. The values of this vector remain untouched.
409     *
410     * @param scalar
411     *            the value to divide this vectors attributes by.
412     * @return the result <code>Vector</code>.
413     */
414    public Vector2f divide(float scalar) {
415        return new Vector2f(x / scalar, y / scalar);
416    }
417
418    /**
419     * <code>divideLocal</code> divides this vector by a scalar internally,
420     * and returns a handle to this vector for easy chaining of calls. Dividing
421     * by zero will result in an exception.
422     *
423     * @param scalar
424     *            the value to divides this vector by.
425     * @return this
426     */
427    public Vector2f divideLocal(float scalar) {
428        x /= scalar;
429        y /= scalar;
430        return this;
431    }
432
433    /**
434     * <code>negate</code> returns the negative of this vector. All values are
435     * negated and set to a new vector.
436     *
437     * @return the negated vector.
438     */
439    public Vector2f negate() {
440        return new Vector2f(-x, -y);
441    }
442
443    /**
444     * <code>negateLocal</code> negates the internal values of this vector.
445     *
446     * @return this.
447     */
448    public Vector2f negateLocal() {
449        x = -x;
450        y = -y;
451        return this;
452    }
453
454    /**
455     * <code>subtract</code> subtracts the values of a given vector from those
456     * of this vector creating a new vector object. If the provided vector is
457     * null, an exception is thrown.
458     *
459     * @param vec
460     *            the vector to subtract from this vector.
461     * @return the result vector.
462     */
463    public Vector2f subtract(Vector2f vec) {
464        return subtract(vec, null);
465    }
466
467    /**
468     * <code>subtract</code> subtracts the values of a given vector from those
469     * of this vector storing the result in the given vector object. If the
470     * provided vector is null, an exception is thrown.
471     *
472     * @param vec
473     *            the vector to subtract from this vector.
474     * @param store
475     *            the vector to store the result in. It is safe for this to be
476     *            the same as vec. If null, a new vector is created.
477     * @return the result vector.
478     */
479    public Vector2f subtract(Vector2f vec, Vector2f store) {
480        if (store == null)
481            store = new Vector2f();
482        store.x = x - vec.x;
483        store.y = y - vec.y;
484        return store;
485    }
486
487    /**
488     * <code>subtract</code> subtracts the given x,y values from those of this
489     * vector creating a new vector object.
490     *
491     * @param valX
492     *            value to subtract from x
493     * @param valY
494     *            value to subtract from y
495     * @return this
496     */
497    public Vector2f subtract(float valX, float valY) {
498        return new Vector2f(x - valX, y - valY);
499    }
500
501    /**
502     * <code>subtractLocal</code> subtracts a provided vector to this vector
503     * internally, and returns a handle to this vector for easy chaining of
504     * calls. If the provided vector is null, null is returned.
505     *
506     * @param vec
507     *            the vector to subtract
508     * @return this
509     */
510    public Vector2f subtractLocal(Vector2f vec) {
511        if (null == vec) {
512            logger.warning("Provided vector is null, null returned.");
513            return null;
514        }
515        x -= vec.x;
516        y -= vec.y;
517        return this;
518    }
519
520    /**
521     * <code>subtractLocal</code> subtracts the provided values from this
522     * vector internally, and returns a handle to this vector for easy chaining
523     * of calls.
524     *
525     * @param valX
526     *            value to subtract from x
527     * @param valY
528     *            value to subtract from y
529     * @return this
530     */
531    public Vector2f subtractLocal(float valX, float valY) {
532        x -= valX;
533        y -= valY;
534        return this;
535    }
536
537    /**
538     * <code>normalize</code> returns the unit vector of this vector.
539     *
540     * @return unit vector of this vector.
541     */
542    public Vector2f normalize() {
543        float length = length();
544        if (length != 0) {
545            return divide(length);
546        }
547
548        return divide(1);
549    }
550
551    /**
552     * <code>normalizeLocal</code> makes this vector into a unit vector of
553     * itself.
554     *
555     * @return this.
556     */
557    public Vector2f normalizeLocal() {
558        float length = length();
559        if (length != 0) {
560            return divideLocal(length);
561        }
562
563        return divideLocal(1);
564    }
565
566    /**
567     * <code>smallestAngleBetween</code> returns (in radians) the minimum
568     * angle between two vectors. It is assumed that both this vector and the
569     * given vector are unit vectors (iow, normalized).
570     *
571     * @param otherVector
572     *            a unit vector to find the angle against
573     * @return the angle in radians.
574     */
575    public float smallestAngleBetween(Vector2f otherVector) {
576        float dotProduct = dot(otherVector);
577        float angle = FastMath.acos(dotProduct);
578        return angle;
579    }
580
581    /**
582     * <code>angleBetween</code> returns (in radians) the angle required to
583     * rotate a ray represented by this vector to lie colinear to a ray
584     * described by the given vector. It is assumed that both this vector and
585     * the given vector are unit vectors (iow, normalized).
586     *
587     * @param otherVector
588     *            the "destination" unit vector
589     * @return the angle in radians.
590     */
591    public float angleBetween(Vector2f otherVector) {
592        float angle = FastMath.atan2(otherVector.y, otherVector.x)
593                - FastMath.atan2(y, x);
594        return angle;
595    }
596
597    public float getX() {
598        return x;
599    }
600
601    public Vector2f setX(float x) {
602        this.x = x;
603        return this;
604    }
605
606    public float getY() {
607        return y;
608    }
609
610    public Vector2f setY(float y) {
611        this.y = y;
612        return this;
613    }
614    /**
615     * <code>getAngle</code> returns (in radians) the angle represented by
616     * this Vector2f as expressed by a conversion from rectangular coordinates (<code>x</code>,&nbsp;<code>y</code>)
617     * to polar coordinates (r,&nbsp;<i>theta</i>).
618     *
619     * @return the angle in radians. [-pi, pi)
620     */
621    public float getAngle() {
622        return FastMath.atan2(y, x);
623    }
624
625    /**
626     * <code>zero</code> resets this vector's data to zero internally.
627     */
628    public Vector2f zero() {
629        x = y = 0;
630        return this;
631    }
632
633    /**
634     * <code>hashCode</code> returns a unique code for this vector object
635     * based on it's values. If two vectors are logically equivalent, they will
636     * return the same hash code value.
637     *
638     * @return the hash code value of this vector.
639     */
640    public int hashCode() {
641        int hash = 37;
642        hash += 37 * hash + Float.floatToIntBits(x);
643        hash += 37 * hash + Float.floatToIntBits(y);
644        return hash;
645    }
646
647    @Override
648    public Vector2f clone() {
649        try {
650            return (Vector2f) super.clone();
651        } catch (CloneNotSupportedException e) {
652            throw new AssertionError(); // can not happen
653        }
654    }
655
656    /**
657     * Saves this Vector2f into the given float[] object.
658     *
659     * @param floats
660     *            The float[] to take this Vector2f. If null, a new float[2] is
661     *            created.
662     * @return The array, with X, Y float values in that order
663     */
664    public float[] toArray(float[] floats) {
665        if (floats == null) {
666            floats = new float[2];
667        }
668        floats[0] = x;
669        floats[1] = y;
670        return floats;
671    }
672
673    /**
674     * are these two vectors the same? they are is they both have the same x and
675     * y values.
676     *
677     * @param o
678     *            the object to compare for equality
679     * @return true if they are equal
680     */
681    public boolean equals(Object o) {
682        if (!(o instanceof Vector2f)) {
683            return false;
684        }
685
686        if (this == o) {
687            return true;
688        }
689
690        Vector2f comp = (Vector2f) o;
691        if (Float.compare(x, comp.x) != 0)
692            return false;
693        if (Float.compare(y, comp.y) != 0)
694            return false;
695        return true;
696    }
697
698    /**
699     * <code>toString</code> returns the string representation of this vector
700     * object. The format of the string is such: com.jme.math.Vector2f
701     * [X=XX.XXXX, Y=YY.YYYY]
702     *
703     * @return the string representation of this vector.
704     */
705    public String toString() {
706        return "(" + x + ", " + y + ")";
707    }
708
709    /**
710     * Used with serialization. Not to be called manually.
711     *
712     * @param in
713     *            ObjectInput
714     * @throws IOException
715     * @throws ClassNotFoundException
716     * @see java.io.Externalizable
717     */
718    public void readExternal(ObjectInput in) throws IOException,
719            ClassNotFoundException {
720        x = in.readFloat();
721        y = in.readFloat();
722    }
723
724    /**
725     * Used with serialization. Not to be called manually.
726     *
727     * @param out
728     *            ObjectOutput
729     * @throws IOException
730     * @see java.io.Externalizable
731     */
732    public void writeExternal(ObjectOutput out) throws IOException {
733        out.writeFloat(x);
734        out.writeFloat(y);
735    }
736
737    public void write(JmeExporter e) throws IOException {
738        OutputCapsule capsule = e.getCapsule(this);
739        capsule.write(x, "x", 0);
740        capsule.write(y, "y", 0);
741    }
742
743    public void read(JmeImporter e) throws IOException {
744        InputCapsule capsule = e.getCapsule(this);
745        x = capsule.readFloat("x", 0);
746        y = capsule.readFloat("y", 0);
747    }
748
749    public void rotateAroundOrigin(float angle, boolean cw) {
750        if (cw)
751            angle = -angle;
752        float newX = FastMath.cos(angle) * x - FastMath.sin(angle) * y;
753        float newY = FastMath.sin(angle) * x + FastMath.cos(angle) * y;
754        x = newX;
755        y = newY;
756    }
757}
758