/*
* Open Source Physics software is free software as described near the bottom of this code file.
*
* For additional information and documentation on Open Source Physics please see:
* <http://www.opensourcephysics.org/>
*/
package org.opensourcephysics.numerics;
/**
* VectorMath is a utility class for vector math.
*
* Contains static methods for dot products, cross products, etc.
*
* @author Wolfgang Christian
* @version 1.0
*/
public final class VectorMath {
private VectorMath() {} // all methods are static so prohibit instantiation
/**
* Add a vector times a scalar to a vector.
* Elements in the first vector are modified and set equal to the sum.
*
* @param a the first vector
* @param b the second vector
* @param c the scalar multiplier
*
* @return double[] the first vector.
*/
static public double[] plus(double[] a, double[] b, double c) {
int aLength = a.length;
if(aLength!=b.length) {
throw new UnsupportedOperationException("ERROR: Vectors must be of equal length to add."); //$NON-NLS-1$
}
for(int i = 0; i<aLength; i++) {
a[i] += c*b[i];
}
return a;
}
/**
* Add two vectors.
* Elements in the first vector are modified and set equal to the sum.
*
* @param a the first vector
* @param b the second vector
*
* @return double[] the first vector.
*/
static public double[] plus(double[] a, double[] b) {
int aLength = a.length;
if(aLength!=b.length) {
throw new UnsupportedOperationException("ERROR: Vectors must be of equal length to add."); //$NON-NLS-1$
}
for(int i = 0; i<aLength; i++) {
a[i] += b[i];
}
return a;
}
static public double[] normalize(double[] a) {
double mag = magnitude(a);
if(mag==0) { // return unit vector along first direction
a[0] = 1;
return a;
}
a[0] /= mag;
a[1] /= mag;
a[2] /= mag;
return a;
}
/**
* Calculate the dot product of two vectors.
* @param a the first vector
* @param b the second vector
* @return the dot product
*/
static public double dot(double[] a, double[] b) {
int aLength = a.length;
if(aLength!=b.length) {
throw new UnsupportedOperationException("ERROR: Vectors must be of equal dimension in dot product."); //$NON-NLS-1$
}
double sum = 0;
for(int i = 0; i<aLength; i++) {
sum += a[i]*b[i];
}
return sum;
}
/**
* Projects the first vector onto the second vector.
* @param a the first vector
* @param b the second vector
* @return the projection
*/
static public double[] project(double[] a, double[] b) {
int aLength = a.length;
if(aLength!=b.length) {
throw new UnsupportedOperationException("ERROR: Vectors must be of equal dimension to compute projection."); //$NON-NLS-1$
}
double[] result = b.clone();
double asquared = 0;
double dot = 0;
for(int i = 0; i<aLength; i++) {
dot += a[i]*b[i];
asquared += a[i]*a[i];
}
dot /= asquared;
for(int i = 0; i<aLength; i++) {
result[i] /= dot;
}
return result;
}
/**
* Computes the part of the first vector that is perpendicular to the second vector.
* @param a the first vector
* @param b the second vector
* @return the perpendicular part
*/
static public double[] perp(double[] a, double[] b) {
int aLength = a.length;
if(aLength!=b.length) {
throw new UnsupportedOperationException("ERROR: Vectors must be of equal dimension to find the perpendicular component."); //$NON-NLS-1$
}
double[] result = b.clone();
double asquared = 0;
double dot = 0;
for(int i = 0; i<aLength; i++) {
dot += a[i]*b[i];
asquared += a[i]*a[i];
}
dot /= asquared;
for(int i = 0; i<aLength; i++) {
result[i] = a[i]-b[i]/dot;
}
return result;
}
/**
* Computes the magnitdue squared of this vector.
* The magnitude squared is dot product of a vector with itself.
* @param a the vector
* @return the magnitude squared
*/
static public double magnitudeSquared(double[] a) {
int aLength = a.length;
double sum = 0;
for(int i = 0; i<aLength; i++) {
sum += a[i]*a[i];
}
return sum;
}
/**
* Calculates the magnitude a vector.
* @param a the vector
* @return the magnitude
*/
static public double magnitude(double[] a) {
double sum = 0;
for(int i = 0, n = a.length; i<n; i++) {
sum += a[i]*a[i];
}
return Math.sqrt(sum);
}
/**
* Calculates the vector cross product of double[3] vectors v1 and v2.
* @param v1 the first vector
* @param v2 the second vector
*
* @return double[] the 3D cross product
*/
static public final double[] cross3D(double[] v1, double[] v2) {
double[] v = new double[3];
v[0] = v1[1]*v2[2]-v1[2]*v2[1];
v[1] = v2[0]*v1[2]-v2[2]*v1[0];
v[2] = v1[0]*v2[1]-v1[1]*v2[0];
return v;
}
/**
* Calculates the cross product of a double[2] vector in a plane and a vector perpendicular to that plane.
*
* Elements in the given vector are modified. The resulting vector componets are in the basis set of
* the given vector.
*
* @param v the vector in the plane
* @param b the vector perpendicular to the plane
*
* @return the cropss product
*/
static public double[] cross2D(double[] v, double b) {
if(v.length!=2) {
throw new UnsupportedOperationException("ERROR: Cross2D product requires 2 component array."); //$NON-NLS-1$
}
double temp = v[0];
v[0] = v[1]*b;
v[1] = -temp*b;
return v;
}
/**
* Calculate the cross product of two-component vectors.
* The result is the component perpendicular to the plane.
*
* @param a the first vector
* @param b the second vector
* @return the cross product.
*/
static public double cross2D(double[] a, double[] b) {
if((a.length!=2)||(b.length!=2)) {
throw new UnsupportedOperationException("ERROR: Cross2D product requires 2 component arrays."); //$NON-NLS-1$
}
return a[0]*b[1]-a[1]*b[0];
}
}
/*
* Open Source Physics software is free software; you can redistribute
* it and/or modify it under the terms of the GNU General Public License (GPL) as
* published by the Free Software Foundation; either version 2 of the License,
* or(at your option) any later version.
* Code that uses any portion of the code in the org.opensourcephysics package
* or any subpackage (subdirectory) of this package must must also be be released
* under the GNU GPL license.
*
* This software 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston MA 02111-1307 USA
* or view the license online at http://www.gnu.org/copyleft/gpl.html
*
* Copyright (c) 2007 The Open Source Physics project
* http://www.opensourcephysics.org
*/