/*=============================================================================
* 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:
*/