/*============================================================================= * Copyright Rob Clark 2000. All Rights Reserved. * * This program 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 of the License, or (at your option) any later version. * * This program 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 * * $ProjectHeader: OSCRIPT 0.155 Fri, 20 Dec 2002 18:34:22 -0800 rclark $ */ const var Math = java.lang.Math; /** * A vector, as in a mathmatical vector. Like an <code>Array</code>, but * supports vector addition/subtraction and multiplication/division with * a scalar. * * @param args... a variable number of args, the elements of the vector */ public function Vector(args...) extends Array() { for( var i=0; i<args.length(); i++ ) this[i] = args[i]; /*=======================================================================*/ /** * Perform the "+" operation. * <pre> * C = A + B * C[n] = A[n] + B[n] * </pre> * * @param val the other value * @return a vector * @throws NoSuchMethodException */ public function bopPlus(val) { if( val.length() != length() ) return val.bopPlusR( this, new pkg.IllegalArgumentException("cannot add vectors of different size") ); var result = new Vector(); for( var i=length()-1; i>=0; i-- ) result[i] = this[i] + val[i]; return result; } public function bopPlusR( val, e ) { if( val.length() != length() ) throw e; var result = new Vector(); for( var i=length()-1; i>=0; i-- ) result[i] = val[i] + this[i]; return result; } /*=======================================================================*/ /** * Perform the "-" operation. * <pre> * C = A - B * C[n] = A[n] - B[n] * </pre> * * @param val the other value * @return a vector * @throws NoSuchMethodException */ public function bopMinus(val) { if( val.length() != length() ) return val.bopMinusR( this, new pkg.IllegalArgumentException("cannot subtract vectors of different size") ); var result = new Vector(); for( var i=length()-1; i>=0; i-- ) result[i] = this[i] - val[i]; return result; } public function bopMinusR( val, e ) { if( val.length() != length() ) throw e; var result = new Vector(); for( var i=length()-1; i>=0; i-- ) result[i] = val[i] - this[i]; return result; } /*=======================================================================*/ /** * Perform the "*" operation. If <code>val</code> is a <code>Vector</code>, * this performs the cross-product operation (see <code>crossProduct</code>) * otherwise the performs scalar multiplication. * <pre> * C = A * b * C[n] = A[n] * b * </pre> * * @param val the other value * @return a vector or scalar * @throws NoSuchMethodException */ public function bopMultiply(val) { if( val instanceof Array ) return crossProduct(val); var result = new Vector(); for( var i=length()-1; i>=0; i-- ) result[i] = this[i] * val; return result; } public function bopMultiplyR( val, e ) { if( val instanceof Array ) return val.crossProduct(this); var result = new Vector(); for( var i=length()-1; i>=0; i-- ) result[i] = val * this[i]; return result; } /*=======================================================================*/ /** * Perform the "/" operation. This performs scalar division. * <pre> * C = A / b * C[n] = A[n] / b * </pre> * * @param val the other value * @return a vector * @throws NoSuchMethodException */ public function bopDivide(val) { var result = new Vector(); for( var i=length()-1; i>=0; i-- ) result[i] = this[i] / val; return result; } public function bopDivideR( val, e ) { var result = new Vector(); for( var i=length()-1; i>=0; i-- ) result[i] = val / this[i]; return result; } /*=======================================================================*/ /** * Perform the dot-product operation. * <pre> * c = A . B * c = A[1]*B[1] + ... + A[n]*B[n] * </pre> * * @param val the "B" value * @return a scalar */ public function dotProduct(val) { if( val.length() != length() ) throw new pkg.IllegalArgumentException("cannot compute dot product of vectors of different size"); var result = 0; for( var i=length()-1; i>=0; i-- ) result = this[i] * val[i] + result; // += could force this[i] * val[i] to be ExactNumber return result; } /*=======================================================================*/ /** * Perform the cross product operation on 3-dimensional vectors. * <pre> * C = A x B * C[0] = A[1]*B[2] - A[2]*B[1] * C[1] = A[0]*B[2] - A[2]*B[0] * C[2] = A[0]*B[1] - A[1]*B[0] * </pre> * * @param val the "B" value * @return a vector */ public function crossProduct(val) { if( (length() != 3) || (val.length() != 3) ) throw new pkg.IllegalArgumentException("cannot compute cross product for non-3d vectors"); var result = new Vector(); result[2] = (this[0] * val[1]) - (this[1] * val[0]); result[1] = (this[0] * val[2]) - (this[2] * val[0]); result[0] = (this[1] * val[2]) - (this[2] * val[1]); return result; } /*=======================================================================*/ /** * Note that the <code>length</code> method of this class returns the * array length, ie the dimensions. This method returns the euclidean * length: * <pre> * |V| = sqrare_root( V[0]^2 + V[1]^2 + ... + V[n]^2 ) * </pre> * * @return a scalar number */ public function euclideanLength() { var result = 0; for( var i=length()-1; i>=0; i-- ) result += this[i] * this[i]; return Math.sqrt(result); } /*=======================================================================*/ /** * The normalized vector has the euclidean-length of 1 * * @return a normalized vector */ public function normalize() { return this / euclideanLength(); } } /* * Local Variables: * tab-width: 2 * indent-tabs-mode: nil * mode: java * c-indentation-style: java * c-basic-offset: 2 * eval: (c-set-offset 'statement-cont '0) * eval: (c-set-offset 'substatement-open '0) * eval: (c-set-offset 'case-label '+) * eval: (c-set-offset 'inclass '+) * eval: (c-set-offset 'inline-open '0) * End: */