Project: SPaTo_Visual_Explorer
Code Examples
/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */
 
/*
  Part of the Processing project - http://processing.org 
 
  Copyright (c) 200X Dan Shiffman 
  Copyright (c) 2008 Ben Fry and Casey Reas 
 
  This library is free software; you can redistribute it and/or 
  modify it under the terms of the GNU Lesser General Public 
  License as published by the Free Software Foundation; either 
  version 2.1 of the License, or (at your option) any later version. 
 
  This library is distributed in the hope that it will be useful, 
  but WITHOUT ANY WARRANTY; without even the implied warranty of 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
  Lesser General Public License for more details. 
 
  You should have received a copy of the GNU Lesser General 
  Public License along with this library; if not, write to the 
  Free Software Foundation, Inc., 59 Temple Place, Suite 330, 
  Boston, MA  02111-1307  USA 
 */
 
 
package processing.core; 
 
/**
 * A class to describe a two or three dimensional vector. 
 * <p> 
 * The result of all functions are applied to the vector itself, with the 
 * exception of cross(), which returns a new PVector (or writes to a specified 
 * 'target' PVector). That is, add() will add the contents of one vector to 
 * this one. Using add() with additional parameters allows you to put the 
 * result into a new PVector. Functions that act on multiple vectors also 
 * include static versions. Because creating new objects can be computationally 
 * expensive, most functions include an optional 'target' PVector, so that a 
 * new PVector object is not created with each operation. 
 * <p> 
 * Initially based on the Vector3D class by <a href="http://www.shiffman.net">Dan Shiffman</a>. 
 */
 
public class PVector { 
 
  /** The x component of the vector. */ 
  public float x; 
 
  /** The y component of the vector. */ 
  public float y; 
 
  /** The z component of the vector. */ 
  public float z; 
 
  /** Array so that this can be temporarily used in an array context */ 
  protected float[] array; 
 
 
  /**
   * Constructor for an empty vector: x, y, and z are set to 0. 
   */
 
  public PVector() { 
  } 
 
 
  /**
   * Constructor for a 3D vector. 
   * 
   * @param  x the x coordinate. 
   * @param  y the y coordinate. 
   * @param  z the y coordinate. 
   */
 
  public PVector(float x, float y, float z) { 
    this.x = x; 
    this.y = y; 
    this.z = z; 
  } 
 
 
  /**
   * Constructor for a 2D vector: z coordinate is set to 0. 
   * 
   * @param  x the x coordinate. 
   * @param  y the y coordinate. 
   */
 
  public PVector(float x, float y) { 
    this.x = x; 
    this.y = y; 
    this.z = 0
  } 
 
 
  /**
   * Set x, y, and z coordinates. 
   * 
   * @param x the x coordinate. 
   * @param y the y coordinate. 
   * @param z the z coordinate. 
   */
 
  public void set(float x, float y, float z) { 
    this.x = x; 
    this.y = y; 
    this.z = z; 
  } 
 
 
  /**
   * Set x, y, and z coordinates from a Vector3D object. 
   * 
   * @param v the PVector object to be copied 
   */
 
  public void set(PVector v) { 
    x = v.x; 
    y = v.y; 
    z = v.z; 
  } 
 
 
  /**
   * Set the x, y (and maybe z) coordinates using a float[] array as the source. 
   * @param source array to copy from 
   */
 
  public void set(float[] source) { 
    if (source.length >= 2) { 
      x = source[0]; 
      y = source[1]; 
    } 
    if (source.length >= 3) { 
      z = source[2]; 
    } 
  } 
 
 
  /**
   * Get a copy of this vector. 
   */
 
  public PVector get() { 
    return new PVector(x, y, z); 
  } 
 
 
  public float[] get(float[] target) { 
    if (target == null) { 
      return new float[] { x, y, z }; 
    } 
    if (target.length >= 2) { 
      target[0] = x; 
      target[1] = y; 
    } 
    if (target.length >= 3) { 
      target[2] = z; 
    } 
    return target; 
  } 
 
 
  /**
   * Calculate the magnitude (length) of the vector 
   * @return the magnitude of the vector 
   */
 
  public float mag() { 
    return (float) Math.sqrt(x*x + y*y + z*z); 
  } 
 
 
  /**
   * Add a vector to this vector 
   * @param v the vector to be added 
   */
 
  public void add(PVector v) { 
    x += v.x; 
    y += v.y; 
    z += v.z; 
  } 
 
 
  public void add(float x, float y, float z) { 
    this.x += x; 
    this.y += y; 
    this.z += z; 
  } 
 
 
  /**
   * Add two vectors 
   * @param v1 a vector 
   * @param v2 another vector 
   * @return a new vector that is the sum of v1 and v2 
   */
 
  static public PVector add(PVector v1, PVector v2) { 
    return add(v1, v2, null); 
  } 
 
 
  /**
   * Add two vectors into a target vector 
   * @param v1 a vector 
   * @param v2 another vector 
   * @param target the target vector (if null, a new vector will be created) 
   * @return a new vector that is the sum of v1 and v2 
   */
 
  static public PVector add(PVector v1, PVector v2, PVector target) { 
    if (target == null) { 
      target = new PVector(v1.x + v2.x,v1.y + v2.y, v1.z + v2.z); 
    } else { 
      target.set(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z); 
    } 
    return target; 
  } 
 
 
  /**
   * Subtract a vector from this vector 
   * @param v the vector to be subtracted 
   */
 
  public void sub(PVector v) { 
    x -= v.x; 
    y -= v.y; 
    z -= v.z; 
  } 
 
 
  public void sub(float x, float y, float z) { 
    this.x -= x; 
    this.y -= y; 
    this.z -= z; 
  } 
 
 
  /**
   * Subtract one vector from another 
   * @param v1 a vector 
   * @param v2 another vector 
   * @return a new vector that is v1 - v2 
   */
 
  static public PVector sub(PVector v1, PVector v2) { 
    return sub(v1, v2, null); 
  } 
 
 
  static public PVector sub(PVector v1, PVector v2, PVector target) { 
    if (target == null) { 
      target = new PVector(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); 
    } else { 
      target.set(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z); 
    } 
    return target; 
  } 
 
 
  /**
   * Multiply this vector by a scalar 
   * @param n the value to multiply by 
   */
 
  public void mult(float n) { 
    x *= n; 
    y *= n; 
    z *= n; 
  } 
 
 
  /**
   * Multiply a vector by a scalar 
   * @param v a vector 
   * @param n scalar 
   * @return a new vector that is v1 * n 
   */
 
  static public PVector mult(PVector v, float n) { 
    return mult(v, n, null); 
  } 
 
 
  /**
   * Multiply a vector by a scalar, and write the result into a target PVector. 
   * @param v a vector 
   * @param n scalar 
   * @param target PVector to store the result 
   * @return the target vector, now set to v1 * n 
   */
 
  static public PVector mult(PVector v, float n, PVector target) { 
    if (target == null) { 
      target = new PVector(v.x*n, v.y*n, v.z*n); 
    } else { 
      target.set(v.x*n, v.y*n, v.z*n); 
    } 
    return target; 
  } 
 
 
  /**
   * Multiply each element of one vector by the elements of another vector. 
   * @param v the vector to multiply by 
   */
 
  public void mult(PVector v) { 
    x *= v.x; 
    y *= v.y; 
    z *= v.z; 
  } 
 
 
  /**
   * Multiply each element of one vector by the individual elements of another 
   * vector, and return the result as a new PVector. 
   */
 
  static public PVector mult(PVector v1, PVector v2) { 
    return mult(v1, v2, null); 
  } 
 
 
  /**
   * Multiply each element of one vector by the individual elements of another 
   * vector, and write the result into a target vector. 
   * @param v1 the first vector 
   * @param v2 the second vector 
   * @param target PVector to store the result 
   */
 
  static public PVector mult(PVector v1, PVector v2, PVector target) { 
    if (target == null) { 
      target = new PVector(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z); 
    } else { 
      target.set(v1.x*v2.x, v1.y*v2.y, v1.z*v2.z); 
    } 
    return target; 
  } 
 
 
  /**
   * Divide this vector by a scalar 
   * @param n the value to divide by 
   */
 
  public void div(float n) { 
    x /= n; 
    y /= n; 
    z /= n; 
  } 
 
 
  /**
   * Divide a vector by a scalar and return the result in a new vector. 
   * @param v a vector 
   * @param n scalar 
   * @return a new vector that is v1 / n 
   */
 
  static public PVector div(PVector v, float n) { 
    return div(v, n, null); 
  } 
 
 
  static public PVector div(PVector v, float n, PVector target) { 
    if (target == null) { 
      target = new PVector(v.x/n, v.y/n, v.z/n); 
    } else { 
      target.set(v.x/n, v.y/n, v.z/n); 
    } 
    return target; 
  } 
 
 
  /**
   * Divide each element of one vector by the elements of another vector. 
   */
 
  public void div(PVector v) { 
    x /= v.x; 
    y /= v.y; 
    z /= v.z; 
  } 
 
 
  /**
   * Multiply each element of one vector by the individual elements of another 
   * vector, and return the result as a new PVector. 
   */
 
  static public PVector div(PVector v1, PVector v2) { 
    return div(v1, v2, null); 
  } 
 
 
  /**
   * Divide each element of one vector by the individual elements of another 
   * vector, and write the result into a target vector. 
   * @param v1 the first vector 
   * @param v2 the second vector 
   * @param target PVector to store the result 
   */
 
  static public PVector div(PVector v1, PVector v2, PVector target) { 
    if (target == null) { 
      target = new PVector(v1.x/v2.x, v1.y/v2.y, v1.z/v2.z); 
    } else { 
      target.set(v1.x/v2.x, v1.y/v2.y, v1.z/v2.z); 
    } 
    return target; 
  } 
 
 
  /**
   * Calculate the Euclidean distance between two points (considering a point as a vector object) 
   * @param v another vector 
   * @return the Euclidean distance between 
   */
 
  public float dist(PVector v) { 
    float dx = x - v.x; 
    float dy = y - v.y; 
    float dz = z - v.z; 
    return (float) Math.sqrt(dx*dx + dy*dy + dz*dz); 
  } 
 
 
  /**
   * Calculate the Euclidean distance between two points (considering a point as a vector object) 
   * @param v1 a vector 
   * @param v2 another vector 
   * @return the Euclidean distance between v1 and v2 
   */
 
  static public float dist(PVector v1, PVector v2) { 
    float dx = v1.x - v2.x; 
    float dy = v1.y - v2.y; 
    float dz = v1.z - v2.z; 
    return (float) Math.sqrt(dx*dx + dy*dy + dz*dz); 
  } 
 
 
  /**
   * Calculate the dot product with another vector 
   * @return the dot product 
   */
 
  public float dot(PVector v) { 
    return x*v.x + y*v.y + z*v.z; 
  } 
 
 
  public float dot(float x, float y, float z) { 
    return this.x*x + this.y*y + this.z*z; 
  } 
   
   
  static public float dot(PVector v1, PVector v2) { 
      return v1.x*v2.x + v1.y*v2.y + v1.z*v2.z; 
  } 
 
 
  /**
   * Return a vector composed of the cross product between this and another. 
   */
 
  public PVector cross(PVector v) { 
    return cross(v, null); 
  } 
 
 
  /**
   * Perform cross product between this and another vector, and store the 
   * result in 'target'. If target is null, a new vector is created. 
   */
 
  public PVector cross(PVector v, PVector target) { 
    float crossX = y * v.z - v.y * z; 
    float crossY = z * v.x - v.z * x; 
    float crossZ = x * v.y - v.x * y; 
 
    if (target == null) { 
      target = new PVector(crossX, crossY, crossZ); 
    } else { 
      target.set(crossX, crossY, crossZ); 
    } 
    return target; 
  } 
 
 
  static public PVector cross(PVector v1, PVector v2, PVector target) { 
    float crossX = v1.y * v2.z - v2.y * v1.z; 
    float crossY = v1.z * v2.x - v2.z * v1.x; 
    float crossZ = v1.x * v2.y - v2.x * v1.y; 
 
    if (target == null) { 
      target = new PVector(crossX, crossY, crossZ); 
    } else { 
      target.set(crossX, crossY, crossZ); 
    } 
    return target; 
  } 
 
 
  /**
   * Normalize the vector to length 1 (make it a unit vector) 
   */
 
  public void normalize() { 
    float m = mag(); 
    if (m != 0 && m != 1) { 
      div(m); 
    } 
  } 
 
 
  /**
   * Normalize this vector, storing the result in another vector. 
   * @param target Set to null to create a new vector 
   * @return a new vector (if target was null), or target 
   */
 
  public PVector normalize(PVector target) { 
    if (target == null) { 
      target = new PVector(); 
    } 
    float m = mag(); 
    if (m > 0) { 
      target.set(x/m, y/m, z/m); 
    } else { 
      target.set(x, y, z); 
    } 
    return target; 
  } 
 
 
  /**
   * Limit the magnitude of this vector 
   * @param max the maximum length to limit this vector 
   */
 
  public void limit(float max) { 
    if (mag() > max) { 
      normalize(); 
      mult(max); 
    } 
  } 
 
 
  /**
   * Calculate the angle of rotation for this vector (only 2D vectors) 
   * @return the angle of rotation 
   */
 
  public float heading2D() { 
    float angle = (float) Math.atan2(-y, x); 
    return -1*angle; 
  } 
 
 
  /**
   * Calculate the angle between two vectors, using the dot product 
   * @param v1 a vector 
   * @param v2 another vector 
   * @return the angle between the vectors 
   */
 
  static public float angleBetween(PVector v1, PVector v2) { 
    double dot = v1.x * v2.x + v1.y * v2.y + v1.z * v2.z; 
    double v1mag = Math.sqrt(v1.x * v1.x + v1.y * v1.y + v1.z * v1.z); 
    double v2mag = Math.sqrt(v2.x * v2.x + v2.y * v2.y + v2.z * v2.z); 
    return (float) Math.acos(dot / (v1mag * v2mag)); 
  } 
 
 
  public String toString() { 
    return "[ " + x + ", " + y + ", " + z + " ]"
  } 
 
 
  /**
   * Return a representation of this vector as a float array. This is only for 
   * temporary use. If used in any other fashion, the contents should be copied 
   * by using the get() command to copy into your own array. 
   */
 
  public float[] array() { 
    if (array == null) { 
      array = new float[3]; 
    } 
    array[0] = x; 
    array[1] = y; 
    array[2] = z; 
    return array; 
  } 
}