#region Sharp3D.Math, Copyright(C) 2003-2004 Eran Kampf, Licensed under LGPL.
// Sharp3D.Math math library
// Copyright (C) 2003-2004
// Eran Kampf
// tentacle@zahav.net.il
// http://tentacle.flipcode.com
//
// 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
#endregion
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Collections;
using System.IO;
using System.Runtime.Serialization;
using System.Security.Permissions;
using NUnit.Framework;
namespace Sharp3D.Math.Core
{
/// <summary>
/// Represents 4-Dimentional vector of double-precision floating point numbers.
/// </summary>
[Serializable]
[TypeConverter(typeof(ExpandableObjectConverter))]
public struct Vector4D : ISerializable, ICloneable
{
#region Private fields
private double _x;
private double _y;
private double _z;
private double _w;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Vector4D"/> class with the specified coordinates.
/// </summary>
/// <param name="x">The vector's X coordinate.</param>
/// <param name="y">The vector's Y coordinate.</param>
/// <param name="z">The vector's Z coordinate.</param>
/// <param name="w">The vector's W coordinate.</param>
public Vector4D(double x, double y, double z, double w)
{
_x = x;
_y = y;
_z = z;
_w = w;
}
/// <summary>
/// Initializes a new instance of the <see cref="Vector4D"/> class with the specified coordinates.
/// </summary>
/// <param name="coordinates">An array containing the coordinate parameters.</param>
public Vector4D(double[] coordinates)
{
Debug.Assert(coordinates != null);
Debug.Assert(coordinates.Length >= 4);
_x = coordinates[0];
_y = coordinates[1];
_z = coordinates[2];
_w = coordinates[3];
}
/// <summary>
/// Initializes a new instance of the <see cref="Vector4D"/> class using coordinates from a given <see cref="Vector4D"/> instance.
/// </summary>
/// <param name="vector">A <see cref="Vector4D"/> to get the coordinates from.</param>
public Vector4D(Vector4D vector)
{
_x = vector.X;
_y = vector.Y;
_z = vector.Z;
_w = vector.W;
}
/// <summary>
/// Initializes a new instance of the <see cref="Vector4D"/> class with serialized data.
/// </summary>
/// <param name="info">The object that holds the serialized object data.</param>
/// <param name="context">The contextual information about the source or destination.</param>
private Vector4D(SerializationInfo info, StreamingContext context)
{
_x = info.GetSingle("X");
_y = info.GetSingle("Y");
_z = info.GetSingle("Z");
_w = info.GetSingle("W");
}
#endregion
#region Constants
/// <summary>
/// 4-Dimentional double-precision floating point zero vector.
/// </summary>
public static readonly Vector4D Zero = new Vector4D(0.0f, 0.0f, 0.0f, 0.0f);
/// <summary>
/// 4-Dimentional double-precision floating point X-Axis vector.
/// </summary>
public static readonly Vector4D XAxis = new Vector4D(1.0f, 0.0f, 0.0f, 0.0f);
/// <summary>
/// 4-Dimentional double-precision floating point Y-Axis vector.
/// </summary>
public static readonly Vector4D YAxis = new Vector4D(0.0f, 1.0f, 0.0f, 0.0f);
/// <summary>
/// 4-Dimentional double-precision floating point Y-Axis vector.
/// </summary>
public static readonly Vector4D ZAxis = new Vector4D(0.0f, 0.0f, 1.0f, 0.0f);
/// <summary>
/// 4-Dimentional double-precision floating point Y-Axis vector.
/// </summary>
public static readonly Vector4D WAxis = new Vector4D(0.0f, 0.0f, 0.0f, 1.0f);
#endregion
#region Public properties
/// <summary>
/// Gets or sets the x-coordinate of this vector.
/// </summary>
/// <value>The x-coordinate of this vector.</value>
public double X
{
get { return _x; }
set { _x = value;}
}
/// <summary>
/// Gets or sets the y-coordinate of this vector.
/// </summary>
/// <value>The y-coordinate of this vector.</value>
public double Y
{
get { return _y; }
set { _y = value;}
}
/// <summary>
/// Gets or sets the z-coordinate of this vector.
/// </summary>
/// <value>The z-coordinate of this vector.</value>
public double Z
{
get { return _z; }
set { _z = value;}
}
/// <summary>
/// Gets or sets the w-coordinate of this vector.
/// </summary>
/// <value>The w-coordinate of this vector.</value>
public double W
{
get { return _w; }
set { _w = value;}
}
#endregion
#region ICloneable Members
/// <summary>
/// Creates an exact copy of this <see cref="Vector4D"/> object.
/// </summary>
/// <returns>The <see cref="Vector4D"/> object this method creates, cast as an object.</returns>
object ICloneable.Clone()
{
return new Vector4D(this);
}
/// <summary>
/// Creates an exact copy of this <see cref="Vector4D"/> object.
/// </summary>
/// <returns>The <see cref="Vector4D"/> object this method creates.</returns>
public Vector4D Clone()
{
return new Vector4D(this);
}
#endregion
#region ISerializable Members
/// <summary>
/// Populates a <see cref="SerializationInfo"/> with the data needed to serialize this object.
/// </summary>
/// <param name="info">The <see cref="SerializationInfo"/> to populate with data. </param>
/// <param name="context">The destination (see <see cref="StreamingContext"/>) for this serialization.</param>
[SecurityPermissionAttribute(SecurityAction.Demand, SerializationFormatter=true)]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
info.AddValue("X", _x);
info.AddValue("Y", _y);
info.AddValue("Z", _z);
info.AddValue("W", _w);
}
#endregion
#region Public Static Parse Methods
/// <summary>
/// Converts the specified string to its <see cref="Vector4D"/> equivalent.
/// </summary>
/// <param name="s">A string representation of a <see cref="Vector4D"/></param>
/// <returns>A <see cref="Vector4D"/> that represents the vector specified by the <paramref name="s"/> parameter.</returns>
public static Vector4D Parse(string s)
{
throw new NotImplementedException();
}
/// <summary>
/// Converts the specified string to its <see cref="Vector4D"/> equivalent.
/// </summary>
/// <param name="reader">A <see cref="TextReader"/> to read the string representation of a <see cref="Vector4D"/> from.</param>
/// <returns>A <see cref="Vector4D"/> that represents the vector specified by the <paramref name="s"/> parameter.</returns>
public static Vector4D Parse(TextReader reader)
{
throw new NotImplementedException();
}
#endregion
#region Public Static Vector Arithmetics
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="w">A <see cref="Vector4D"/> instance.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the sum.</returns>
public static Vector4D Add(Vector4D v, Vector4D w)
{
return new Vector4D(v.X + w.X, v.Y + w.Y, v.Z + w.Z, v.W + w.W);
}
/// <summary>
/// Adds a vector and a scalar.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the sum.</returns>
public static Vector4D Add(Vector4D v, double s)
{
return new Vector4D(v.X + s, v.Y + s, v.Z + s, v.W +s);
}
/// <summary>
/// Adds two vectors and put the result in the third vector.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="v">A <see cref="Vector4D"/> instance</param>
/// <param name="w">A <see cref="Vector4D"/> instance to hold the result.</param>
public static void Add(Vector4D u, Vector4D v, Vector4D w)
{
w.X = u.X + v.X;
w.Y = u.Y + v.Y;
w.Z = u.Z + v.Z;
w.W = u.W + v.W;
}
/// <summary>
/// Adds a vector and a scalar and put the result into another vector.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <param name="v">A <see cref="Vector4D"/> instance to hold the result.</param>
public static void Add(Vector4D u, double s, Vector4D v)
{
v.X = u.X + s;
v.Y = u.Y + s;
v.Z = u.Z + s;
v.W = u.W + s;
}
/// <summary>
/// Subtracts a vector from a vector.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="w">A <see cref="Vector4D"/> instance.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the difference.</returns>
/// <remarks>
/// result[i] = v[i] - w[i].
/// </remarks>
public static Vector4D Subtract(Vector4D v, Vector4D w)
{
return new Vector4D(v.X - w.X, v.Y - w.Y, v.Z - w.Z, v.W - w.W);
}
/// <summary>
/// Subtracts a scalar from a vector.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the difference.</returns>
/// <remarks>
/// result[i] = v[i] - s
/// </remarks>
public static Vector4D Subtract(Vector4D v, double s)
{
return new Vector4D(v.X - s, v.Y - s, v.Z - s, v.W - s);
}
/// <summary>
/// Subtracts a vector from a scalar.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the difference.</returns>
/// <remarks>
/// result[i] = s - v[i]
/// </remarks>
public static Vector4D Subtract(double s, Vector4D v)
{
return new Vector4D(s - v.X, s - v.Y, s - v.Z, s - v.W);
}
/// <summary>
/// Subtracts a vector from a second vector and puts the result into a third vector.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="v">A <see cref="Vector4D"/> instance</param>
/// <param name="w">A <see cref="Vector4D"/> instance to hold the result.</param>
/// <remarks>
/// w[i] = v[i] - w[i].
/// </remarks>
public static void Subtract(Vector4D u, Vector4D v, Vector4D w)
{
w.X = u.X - v.X;
w.Y = u.Y - v.Y;
w.Z = u.Z - v.Z;
w.W = u.W - v.W;
}
/// <summary>
/// Subtracts a vector from a scalar and put the result into another vector.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <param name="v">A <see cref="Vector4D"/> instance to hold the result.</param>
/// <remarks>
/// v[i] = u[i] - s
/// </remarks>
public static void Subtract(Vector4D u, double s, Vector4D v)
{
v.X = u.X - s;
v.Y = u.Y - s;
v.Z = u.Z - s;
v.W = u.W - s;
}
/// <summary>
/// Subtracts a scalar from a vector and put the result into another vector.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <param name="v">A <see cref="Vector4D"/> instance to hold the result.</param>
/// <remarks>
/// v[i] = s - u[i]
/// </remarks>
public static void Subtract(double s, Vector4D u, Vector4D v)
{
v.X = s - u.X;
v.Y = s - u.Y;
v.Z = s - u.Z;
v.W = s - u.W;
}
/// <summary>
/// Divides a vector by another vector.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <returns>A new <see cref="Vector4D"/> containing the quotient.</returns>
/// <remarks>
/// result[i] = u[i] / v[i].
/// </remarks>
public static Vector4D Divide(Vector4D u, Vector4D v)
{
return new Vector4D(u.X / v.X, u.Y / v.Y, u.Z / v.Z, u.W / v.W);
}
/// <summary>
/// Divides a vector by a scalar.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar</param>
/// <returns>A new <see cref="Vector4D"/> containing the quotient.</returns>
/// <remarks>
/// result[i] = v[i] / s;
/// </remarks>
public static Vector4D Divide(Vector4D v, double s)
{
return new Vector4D(v.X / s, v.Y / s, v.Z / s, v.W / s);
}
/// <summary>
/// Divides a scalar by a vector.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar</param>
/// <returns>A new <see cref="Vector4D"/> containing the quotient.</returns>
/// <remarks>
/// result[i] = s / v[i]
/// </remarks>
public static Vector4D Divide(double s, Vector4D v)
{
return new Vector4D(s / v.X, s/ v.Y, s / v.Z, s/ v.W);
}
/// <summary>
/// Divides a vector by another vector.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="w">A <see cref="Vector4D"/> instance to hold the result.</param>
/// <remarks>
/// w[i] = u[i] / v[i]
/// </remarks>
public static void Divide(Vector4D u, Vector4D v, Vector4D w)
{
w.X = u.X / v.X;
w.Y = u.Y / v.Y;
w.Z = u.Z / v.Z;
w.W = u.W / v.W;
}
/// <summary>
/// Divides a vector by a scalar.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar</param>
/// <param name="v">A <see cref="Vector4D"/> instance to hold the result.</param>
/// <remarks>
/// v[i] = u[i] / s
/// </remarks>
public static void Divide(Vector4D u, double s, Vector4D v)
{
v.X = u.X / s;
v.Y = u.Y / s;
v.Z = u.Z / s;
v.W = u.W / s;
}
/// <summary>
/// Divides a scalar by a vector.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar</param>
/// <param name="v">A <see cref="Vector4D"/> instance to hold the result.</param>
/// <remarks>
/// v[i] = s / u[i]
/// </remarks>
public static void Divide(double s, Vector4D u, Vector4D v)
{
v.X = s / u.X;
v.Y = s / u.Y;
v.Z = s / u.Z;
v.W = s / u.W;
}
/// <summary>
/// Multiplies a vector by a scalar.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <returns>A new <see cref="Vector4D"/> containing the result.</returns>
public static Vector4D Multiply(Vector4D u, double s)
{
return new Vector4D(u.X * s, u.Y * s, u.Z * s, u.W * s);
}
/// <summary>
/// Multiplies a vector by a scalar and put the result in another vector.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <param name="v">A <see cref="Vector4D"/> instance to hold the result.</param>
public static void Multiply(Vector4D u, double s, Vector4D v)
{
v.X = u.X * s;
v.Y = u.Y * s;
v.Z = u.Z * s;
v.W = u.W * s;
}
/// <summary>
/// Calculates the dot product of two vectors.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <returns>The dot product value.</returns>
public static double DotProduct(Vector4D u, Vector4D v)
{
return (u.X * v.X) + (u.Y * v.Y) + (u.Z * v.Z) + (u.W * v.W);
}
/// <summary>
/// Negates a vector.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the negated values.</returns>
public static Vector4D Negate(Vector4D v)
{
return new Vector4D(-v.X, -v.Y, -v.Z, -v.W);
}
/// <summary>
/// Tests whether two vectors are approximately equal using default tolerance value.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <returns>True if the two vectors are approximately equal; otherwise, False.</returns>
public static bool ApproxEqual(Vector4D v, Vector4D u)
{
return ApproxEqual(v,u, MathFunctions.EpsilonD);
}
/// <summary>
/// Tests whether two vectors are approximately equal given a tolerance value.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="tolerance">The tolerance value used to test approximate equality.</param>
/// <returns>True if the two vectors are approximately equal; otherwise, False.</returns>
public static bool ApproxEqual(Vector4D v, Vector4D u, double tolerance)
{
return
(
(System.Math.Abs(v.X - u.X) <= tolerance) &&
(System.Math.Abs(v.Y - u.Y) <= tolerance) &&
(System.Math.Abs(v.Z - u.Z) <= tolerance) &&
(System.Math.Abs(v.W - u.W) <= tolerance)
);
}
#endregion
#region Public Methods
/// <summary>
/// Scale the vector so that its length is 1.
/// </summary>
public void Normalize()
{
double length = GetLength();
if (length == 0)
{
throw new DivideByZeroException("Trying to normalize a vector with length of zero.");
}
_x /= length;
_y /= length;
_z /= length;
_w /= length;
}
/// <summary>
/// Returns the length of the vector.
/// </summary>
/// <returns>The length of the vector. (Sqrt(X*X + Y*Y))</returns>
public double GetLength()
{
return System.Math.Sqrt(_x*_x + _y*_y + _z*_z + _w*_w);
}
/// <summary>
/// Returns the squared length of the vector.
/// </summary>
/// <returns>The squared length of the vector. (X*X + Y*Y)</returns>
public double GetLengthSquared()
{
return (_x*_x + _y*_y + _z*_z + _w*_w);
}
#endregion
#region Overrides
/// <summary>
/// Returns the hashcode for this instance.
/// </summary>
/// <returns>A 32-bit signed integer hash code.</returns>
public override int GetHashCode()
{
return _x.GetHashCode() ^ _y.GetHashCode() ^ _z.GetHashCode() ^ _w.GetHashCode();
}
/// <summary>
/// Returns a value indicating whether this instance is equal to
/// the specified object.
/// </summary>
/// <param name="obj">An object to compare to this instance.</param>
/// <returns>True if <paramref name="obj"/> is a <see cref="Vector4D"/> and has the same values as this instance; otherwise, False.</returns>
public override bool Equals(object obj)
{
if (obj is Vector4D)
{
Vector4D v = (Vector4D)obj;
return (_x == v.X) && (_y == v.Y) && (_z == v.Z) && (_w == v.W);
}
return false;
}
/// <summary>
/// Returns a string representation of this object.
/// </summary>
/// <returns>A string representation of this object.</returns>
public override string ToString()
{
return string.Format("Vector4D({0}, {1}, {2}, {3})", _x, _y, _z, _w);
}
#endregion
#region Comparison Operators
/// <summary>
/// Tests whether two specified vectors are equal.
/// </summary>
/// <param name="u">The left-hand vector.</param>
/// <param name="v">The right-hand vector.</param>
/// <returns>True if the two vectors are equal; otherwise, False.</returns>
public static bool operator==(Vector4D u, Vector4D v)
{
if (Object.Equals(u, null))
{
return Object.Equals(v, null);
}
if (Object.Equals(v, null))
{
return Object.Equals(u, null);
}
return (u.X == v.X) && (u.Y == v.Y) && (u.Z == v.Z) && (u.W == v.W);
}
/// <summary>
/// Tests whether two specified vectors are not equal.
/// </summary>
/// <param name="u">The left-hand vector.</param>
/// <param name="v">The right-hand vector.</param>
/// <returns>True if the two vectors are not equal; otherwise, False.</returns>
public static bool operator!=(Vector4D u, Vector4D v)
{
if (Object.Equals(u, null))
{
return !Object.Equals(v, null);
}
if (Object.Equals(v, null))
{
return !Object.Equals(u, null);
}
return !((u.X == v.X) && (u.Y == v.Y) && (u.Z == v.Z) && (u.W == v.W));
}
#endregion
#region Unary Operators
/// <summary>
/// Negates the values of the vector.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the negated values.</returns>
public static Vector4D operator-(Vector4D v)
{
return Vector4D.Negate(v);
}
#endregion
#region Binary Operators
/// <summary>
/// Adds two vectors.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the sum.</returns>
public static Vector4D operator+(Vector4D u, Vector4D v)
{
return Vector4D.Add(u,v);
}
/// <summary>
/// Adds a vector and a scalar.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the sum.</returns>
public static Vector4D operator+(Vector4D v, double s)
{
return Vector4D.Add(v,s);
}
/// <summary>
/// Adds a vector and a scalar.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the sum.</returns>
public static Vector4D operator+(double s, Vector4D v)
{
return Vector4D.Add(v,s);
}
/// <summary>
/// Subtracts a vector from a vector.
/// </summary>
/// <param name="u">A <see cref="Vector4D"/> instance.</param>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the difference.</returns>
/// <remarks>
/// result[i] = v[i] - w[i].
/// </remarks>
public static Vector4D operator-(Vector4D u, Vector4D v)
{
return Vector4D.Subtract(u,v);
}
/// <summary>
/// Subtracts a scalar from a vector.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the difference.</returns>
/// <remarks>
/// result[i] = v[i] - s
/// </remarks>
public static Vector4D operator-(Vector4D v, double s)
{
return Vector4D.Subtract(v, s);
}
/// <summary>
/// Subtracts a vector from a scalar.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <returns>A new <see cref="Vector4D"/> instance containing the difference.</returns>
/// <remarks>
/// result[i] = s - v[i]
/// </remarks>
public static Vector4D operator-(double s, Vector4D v)
{
return Vector4D.Subtract(s, v);
}
/// <summary>
/// Multiplies a vector by a scalar.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <returns>A new <see cref="Vector4D"/> containing the result.</returns>
public static Vector4D operator*(Vector4D v, double s)
{
return Vector4D.Multiply(v,s);
}
/// <summary>
/// Multiplies a vector by a scalar.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar.</param>
/// <returns>A new <see cref="Vector4D"/> containing the result.</returns>
public static Vector4D operator*(double s, Vector4D v)
{
return Vector4D.Multiply(v,s);
}
/// <summary>
/// Divides a vector by a scalar.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar</param>
/// <returns>A new <see cref="Vector4D"/> containing the quotient.</returns>
/// <remarks>
/// result[i] = v[i] / s;
/// </remarks>
public static Vector4D operator/(Vector4D v, double s)
{
return Vector4D.Divide(v,s);
}
/// <summary>
/// Divides a scalar by a vector.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <param name="s">A scalar</param>
/// <returns>A new <see cref="Vector4D"/> containing the quotient.</returns>
/// <remarks>
/// result[i] = s / v[i]
/// </remarks>
public static Vector4D operator/(double s, Vector4D v)
{
return Vector4D.Divide(s,v);
}
#endregion
#region Array Indexing Operator
/// <summary>
/// Indexer ( [x, y] ).
/// </summary>
public double this[int index]
{
get
{
switch( index )
{
case 0:
return _x;
case 1:
return _y;
case 2:
return _z;
case 3:
return _w;
default:
throw new IndexOutOfRangeException();
}
}
set
{
switch( index )
{
case 0:
_x = value;
break;
case 1:
_y = value;
break;
case 2:
_z = value;
break;
case 3:
_w = value;
break;
default:
throw new IndexOutOfRangeException();
}
}
}
#endregion
#region Conversion Operators
/// <summary>
/// Converts the vector to an array of double-precision floating point values.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <returns>An array of double-precision floating point values.</returns>
public static explicit operator double[](Vector4D v)
{
double[] array = new double[4];
array[0] = v.X;
array[1] = v.Y;
array[2] = v.Z;
array[3] = v.W;
return array;
}
/// <summary>
/// Converts the vector to an array of double-precision floating point values.
/// </summary>
/// <param name="v">A <see cref="Vector4D"/> instance.</param>
/// <returns>An array of double-precision floating point values.</returns>
public static explicit operator DoubleArrayList(Vector4D v)
{
DoubleArrayList array = new DoubleArrayList(4);
array[0] = v.X;
array[1] = v.Y;
array[2] = v.Z;
array[3] = v.W;
return array;
}
#endregion
}
#region TestVector4D
/// <summary>
/// Tests the Vector4D class.
/// </summary>
[TestFixture]
public class TestVector4D
{
/// <summary>
/// Tests vector initialization.
/// </summary>
[Test]
public void Initialization()
{
Vector4D v;
v = Vector4D.Zero;
Assert.IsTrue( (v.X == 0) && (v.Y == 0) && (v.Z == 0) && (v.W == 0) );
v = Vector4D.XAxis;
Assert.IsTrue( (v.X == 1) && (v.Y == 0) && (v.Z == 0) && (v.W == 0) );
v = Vector4D.YAxis;
Assert.IsTrue( (v.X == 0) && (v.Y == 1) && (v.Z == 0) && (v.W == 0) );
v = Vector4D.ZAxis;
Assert.IsTrue( (v.X == 0) && (v.Y == 0) && (v.Z == 1) && (v.W == 0) );
v = Vector4D.WAxis;
Assert.IsTrue( (v.X == 0) && (v.Y == 0) && (v.Z == 0) && (v.W == 1) );
v = new Vector4D(0.1, 0.2, 0.3, 0.4);
Assert.IsTrue( (v.X == 0.1) && (v.Y == 0.2) && (v.Z == 0.3) && (v.W == 0.4) );
double[] coordinates = {0.1 , 0.2, 0.3, 0.4};
v = new Vector4D(coordinates);
Assert.IsTrue( (v.X == 0.1) && (v.Y == 0.2) && (v.Z == 0.3) && (v.W == 0.4) );
v = new Vector4D(new Vector4D(0.1, 0.2, 0.3, 0.4));
Assert.IsTrue( (v.X == 0.1) && (v.Y == 0.2) && (v.Z == 0.3) && (v.W == 0.4) );
}
/// <summary>
/// Tests vector accessors.
/// </summary>
[Test]
public void Accessors()
{
Vector4D v = new Vector4D(0.1, 0.2, 0.3, 0.4);
Assertion.AssertEquals(v.X, v[0]);
Assertion.AssertEquals(v.Y, v[1]);
Assertion.AssertEquals(v.Z, v[2]);
Assertion.AssertEquals(v.W, v[3]);
}
/// <summary>
/// Tests unary operators.
/// </summary>
public void UnaryOperators()
{
Vector4D v = new Vector4D(0.1, 0.2, 0.3, 0.4);
Assertion.Assert(Vector4D.ApproxEqual(-v, new Vector4D(-0.1, -0.2, -0.3, -0.4)));
}
/// <summary>
/// Tests binary operators.
/// </summary>
[Test]
public void BinaryOperators()
{
Vector4D v = new Vector4D(0.1, 0.2, 0.3, 0.4);
// Scalar operators
v += 1.0f;
Assertion.Assert(Vector4D.ApproxEqual(v, new Vector4D(1.1, 1.2, 1.3, 1.4)));
v -= 1.0f;
Assertion.Assert(Vector4D.ApproxEqual(v, new Vector4D(0.1, 0.2, 0.3, 0.4)));
v = v * 2.0f;
Assertion.Assert(Vector4D.ApproxEqual(v, new Vector4D(0.2, 0.4, 0.6, 0.8)));
v = v / 2.0f;
Assertion.Assert(Vector4D.ApproxEqual(v, new Vector4D(0.1, 0.2, 0.3, 0.4)));
v = 2.0f * v;
Assertion.Assert(Vector4D.ApproxEqual(v, new Vector4D(0.2, 0.4, 0.6, 0.8)));
v.X = 2; v.Y = 2; v.Z = 2; v.W = 2;
v = 1 / v;
Assertion.Assert(Vector4D.ApproxEqual(v, new Vector4D(0.5, 0.5, 0.5, 0.5)));
// Vector operators
v = new Vector4D(1,2,3,4) + new Vector4D(3,4,5,6);
Assertion.Assert(Vector4D.ApproxEqual(v, new Vector4D(4, 6, 8, 10)));
v = new Vector4D(1,2,3,4) - new Vector4D(3,4,5,6);
Assertion.Assert(Vector4D.ApproxEqual(v, new Vector4D(-2, -2, -2, -2)));
}
/// <summary>
/// Tests comparison operators.
/// </summary>
[Test]
public void ComparisonOperators()
{
Assert.IsTrue(new Vector4D(2,3,4,5) != new Vector4D(3,10,4,5));
Assert.IsFalse(new Vector4D(2,3,4,5) == new Vector4D(3,10,4,5));
Assert.IsFalse(new Vector4D(3,4,5,6) != new Vector4D(3,4,5,6));
Assert.IsTrue(new Vector4D(3,4,5,6) == new Vector4D(3,4,5,6));
}
/// <summary>
/// Tests the vector length methods.
/// </summary>
[Test]
public void Length()
{
Vector4D v = new Vector4D(0.1, 0.2, 0.3, 0.4);
Assertion.Assert(MathFunctions.ApproxEquals(v.GetLength() * v.GetLength(), v.GetLengthSquared()));
}
}
#endregion
}