Home | History | Annotate | Download | only in math
      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 
     33 package com.jme3.math;
     34 
     35 import com.jme3.export.*;
     36 import java.io.Externalizable;
     37 import java.io.IOException;
     38 import java.io.ObjectInput;
     39 import java.io.ObjectOutput;
     40 import 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  */
     48 public 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