Click here to Skip to main content
15,897,273 members
Articles / Desktop Programming / WPF

Building an Extensible Application with MEF, WPF, and MVVM

Rate me:
Please Sign up or sign in to vote.
4.88/5 (45 votes)
15 Nov 2009LGPL316 min read 303.5K   7.4K   185  
An article for anyone interested in how to build an extensible application using WPF and the Model-View-ViewModel pattern.
#region MIT License
/*
 * Copyright (c) 2005-2008 Jonathan Mark Porter. http://physics2d.googlepages.com/
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy 
 * of this software and associated documentation files (the "Software"), to deal 
 * in the Software without restriction, including without limitation the rights to 
 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 
 * the Software, and to permit persons to whom the Software is furnished to do so, 
 * subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be 
 * included in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */
#endregion



#if UseDouble
using Scalar = System.Double;
#else
using Scalar = System.Single;
#endif
using System;
using System.Runtime.InteropServices;
using AdvanceMath.Design;
using System.Xml.Serialization;

namespace AdvanceMath
{

    /// <summary>
    /// This is the Vector Class.
    /// </summary>
    /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29"/></remarks>
    [StructLayout(LayoutKind.Sequential, Size = Vector2D.Size)]
    [AdvBrowsableOrder("X,Y"), Serializable]
#if !CompactFramework && !WindowsCE && !PocketPC && !XBOX360 && !SILVERLIGHT 
    [System.ComponentModel.TypeConverter(typeof(AdvTypeConverter<Vector2D>))]
#endif
    public struct Vector2D : IVector<Vector2D>
    {
        #region const fields
        /// <summary>
        /// The number of Scalar values in the class.
        /// </summary>
        public const int Count = 2;
        /// <summary>
        /// The Size of the class in bytes;
        /// </summary>
        public const int Size = sizeof(Scalar) * Count;
        #endregion
        #region readonly fields
        /// <summary>
        /// Vector2D(1,1)
        /// </summary>
        public static readonly Vector2D One = new Vector2D(1,1);
        /// <summary>
        /// Vector2D(0,0)
        /// </summary>
        public static readonly Vector2D Zero = new Vector2D();
        /// <summary>
        /// Vector2D(1,0)
        /// </summary>
        public static readonly Vector2D XAxis = new Vector2D(1, 0);
        /// <summary>
        /// Vector2D(0,1)
        /// </summary>
        public static readonly Vector2D YAxis = new Vector2D(0, 1);
        /// <summary>
        /// Vector2D(0.707...,0.707...)
        /// </summary>
        public static readonly Vector2D XYAxis = new Vector2D((Scalar)0.7071067811865475244008443621052, (Scalar)0.7071067811865475244008443621052);


        private static readonly string FormatString = MatrixHelper.CreateVectorFormatString(Count);
        private readonly static string FormatableString = MatrixHelper.CreateVectorFormatableString(Count);
        #endregion
        #region static methods
        public static void Copy(ref Vector2D vector, Scalar[] destArray)
        {
            Copy(ref vector, destArray, 0);
        }
        public static void Copy(ref Vector2D vector, Scalar[] destArray, int index)
        {
            ThrowHelper.CheckCopy(destArray, index, Count);

            destArray[index] = vector.X;
            destArray[++index] = vector.Y;
        }
        public static void Copy(Scalar[] sourceArray, out Vector2D result)
        {
            Copy(sourceArray, 0, out result);
        }
        public static void Copy(Scalar[] sourceArray, int index, out Vector2D result)
        {
            ThrowHelper.CheckCopy(sourceArray, index, Count);

            result.X = sourceArray[index];
            result.Y = sourceArray[++index];
        }
        public static void Copy(ref Vector4D source, out Vector2D dest)
        {
            dest.X = source.X;
            dest.Y = source.Y;
        }
        public static void Copy(ref Vector3D source, out Vector2D dest)
        {
            dest.X = source.X;
            dest.Y = source.Y;
        }

        /// <summary>
        /// Binds a value to 
        /// </summary>
        /// <param name="value"></param>
        /// <param name="lower"></param>
        /// <param name="upper"></param>
        /// <returns></returns>
        public static Vector2D Clamp(Vector2D value, Vector2D min, Vector2D max)
        {
            Vector2D result;
            MathHelper.Clamp(ref value.X, ref  min.X, ref  max.X, out result.X);
            MathHelper.Clamp(ref value.Y, ref  min.Y, ref  max.Y, out result.Y);
            return result;
        }
        public static void Clamp(ref Vector2D value, ref Vector2D min, ref Vector2D max, out Vector2D result)
        {
            MathHelper.Clamp(ref value.X, ref  min.X, ref  max.X, out result.X);
            MathHelper.Clamp(ref value.Y, ref  min.Y, ref  max.Y, out result.Y);
        }

        public static Vector2D Lerp(Vector2D left, Vector2D right, Scalar amount)
        {
            Vector2D result;
            Lerp(ref left, ref right, ref amount, out result);
            return result;
        }
        public static void Lerp(ref Vector2D left, ref Vector2D right, ref Scalar amount, out Vector2D result)
        {
            result.X = (right.X - left.X) * amount + left.X;
            result.Y = (right.Y - left.Y) * amount + left.Y;
        }
        public static Vector2D Lerp(Vector2D left, Vector2D right, Vector2D amount)
        {
            Vector2D result;
            Lerp(ref left, ref right, ref amount, out result);
            return result;
        }
        public static void Lerp(ref Vector2D left, ref Vector2D right, ref Vector2D amount, out Vector2D result)
        {
            result.X = (right.X - left.X) * amount.X + left.X;
            result.Y = (right.Y - left.Y) * amount.Y + left.Y;
        }

        public static Scalar Distance(Vector2D left, Vector2D right)
        {
            Scalar x, y;
            x = left.X - right.X;
            y = left.Y - right.Y;
            return MathHelper.Sqrt(x * x + y * y);
        }
        public static void Distance(ref Vector2D left, ref Vector2D right, out Scalar result)
        {
            Scalar x, y;
            x = left.X - right.X;
            y = left.Y - right.Y;
            result = MathHelper.Sqrt(x * x + y * y);
        }
        public static Scalar DistanceSq(Vector2D left, Vector2D right)
        {
            Scalar x, y;
            x = left.X - right.X;
            y = left.Y - right.Y;
            return x * x + y * y;
        }
        public static void DistanceSq(ref Vector2D left, ref Vector2D right, out Scalar result)
        {
            Scalar x, y;
            x = left.X - right.X;
            y = left.Y - right.Y;
            result = x * x + y * y;
        }
        /// <summary>
        /// Creates a Vector2D With the given length (<see cref="Magnitude"/>) and the given <see cref="Angle"/>.
        /// </summary>
        /// <param name="length">The length (<see cref="Magnitude"/>) of the Vector2D to be created</param>
        /// <param name="radianAngle">The angle of the from the (<see cref="XAxis"/>) in Radians</param>
        /// <returns>a Vector2D With the given length and angle.</returns>
        /// <remarks>
        /// <code>FromLengthAndAngle(1,Math.PI/2)</code>
        ///  would create a Vector2D equil to 
        ///  <code>new Vector2D(0,1)</code>. 
        ///  And <code>FromLengthAndAngle(1,0)</code>
        ///  would create a Vector2D equil to 
        ///  <code>new Vector2D(1,0)</code>.
        /// </remarks>
        public static Vector2D FromLengthAndAngle(Scalar length, Scalar radianAngle)
        {
            Vector2D result;
            result.X = length * MathHelper.Cos(radianAngle);
            result.Y = length * MathHelper.Sin(radianAngle);
            return result;
        }
        public static void FromLengthAndAngle(ref Scalar length, ref  Scalar radianAngle, out Vector2D result)
        {
            result.X = length * MathHelper.Cos(radianAngle);
            result.Y = length * MathHelper.Sin(radianAngle);
        }
        /// <summary>
        /// Rotates a Vector2D.
        /// </summary>
        /// <param name="radianAngle">The <see cref="Angle"/> in radians of the amount it is to be rotated.</param>
        /// <param name="source">The Vector2D to be Rotated.</param>
        /// <returns>The Rotated Vector2D</returns>
        public static Vector2D Rotate(Scalar radianAngle, Vector2D source)
        {
            Scalar negradianAngle = -radianAngle;
            Scalar cos = MathHelper.Cos(negradianAngle);
            Scalar sin = MathHelper.Sin(negradianAngle);
            Vector2D result;
            result.X = source.X * cos + source.Y * sin;
            result.Y = source.Y * cos - source.X * sin;
            return result;
        }
        public static void Rotate(ref Scalar radianAngle, ref Vector2D source, out Vector2D result)
        {
            Scalar negradianAngle = -radianAngle;
            Scalar cos = MathHelper.Cos(negradianAngle);
            Scalar sin = MathHelper.Sin(negradianAngle);
            result.X = source.X * cos + source.Y * sin;
            result.Y = source.Y * cos - source.X * sin;
        }
        /// <summary>
        /// Sets the <see cref="Angle"/> of a Vector2D without changing the <see cref="Magnitude"/>.
        /// </summary>
        /// <param name="source">The Vector2D to have its Angle set.</param>
        /// <param name="radianAngle">The angle of the from the (<see cref="XAxis"/>) in Radians</param>
        /// <returns>A Vector2D with a new Angle.</returns>
        public static Vector2D SetAngle(Vector2D source, Scalar radianAngle)
        {
            Scalar magnitude;
            GetMagnitude(ref source, out magnitude);
            Vector2D result;
            result.X = magnitude * MathHelper.Cos(radianAngle);
            result.Y = magnitude * MathHelper.Sin(radianAngle);
            return result;
        }
        public static void SetAngle(ref Vector2D source, ref Scalar radianAngle, out Vector2D result)
        {
            Scalar magnitude;
            GetMagnitude(ref source, out magnitude);
            result.X = magnitude * MathHelper.Cos(radianAngle);
            result.Y = magnitude * MathHelper.Sin(radianAngle);
        }
        /// <summary>
        /// Determines the current <see cref="Angle"/> in radians of the Vector2D and Returns it.
        /// </summary>
        /// <param name="source">The Vector2D of whos angle is to be Determined.</param>
        /// <returns>The <see cref="Angle"/> in radians of the Vector2D.</returns>
        public static Scalar GetAngle(Vector2D source)
        {
            Scalar result = MathHelper.Atan2(source.Y, source.X);
            if (result < 0) { result += MathHelper.TwoPi; }
            return result;
        }
        public static void GetAngle(ref Vector2D source, out Scalar result)
        {
            result = MathHelper.Atan2(source.Y, source.X);
            if (result < 0) { result += MathHelper.TwoPi; }
        }
        /// <summary>
        /// Adds 2 Vectors2Ds.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Sum of the 2 Vector2Ds.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
        public static Vector2D Add(Vector2D left, Vector2D right)
        {
            Vector2D result;
            result.X = left.X + right.X;
            result.Y = left.Y + right.Y;
            return result;
        }
        public static void Add(ref Vector2D left, ref  Vector2D right, out Vector2D result)
        {
            result.X = left.X + right.X;
            result.Y = left.Y + right.Y;
        }
        /// <summary>
        /// Subtracts 2 Vector2Ds.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Difference of the 2 Vector2Ds.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
        public static Vector2D Subtract(Vector2D left, Vector2D right)
        {
            Vector2D result;
            result.X = left.X - right.X;
            result.Y = left.Y - right.Y;
            return result;
        }
        public static void Subtract(ref Vector2D left, ref  Vector2D right, out Vector2D result)
        {
            result.X = left.X - right.X;
            result.Y = left.Y - right.Y;
        }
        /// <summary>
        /// Uses a matrix multiplication to Transform the vector.
        /// </summary>
        /// <param name="matrix">The Transformation matrix</param>
        /// <param name="source">The Vector to be transformed</param>
        /// <returns>The transformed vector.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations"/></remarks>
        public static Vector2D Transform(Matrix3x3 matrix, Vector2D source)
        {
            Scalar inverseZ = 1 / (source.X * matrix.m20 + source.Y * matrix.m21 + matrix.m22);
            Vector2D result;
            result.X = (source.X * matrix.m00 + source.Y * matrix.m01 + matrix.m02) * inverseZ;
            result.Y = (source.X * matrix.m10 + source.Y * matrix.m11 + matrix.m12) * inverseZ;
            return result;
        }
        public static void Transform(ref Matrix3x3 matrix, ref Vector2D source, out Vector2D result)
        {
            Scalar X = source.X;
            Scalar inverseZ = 1 / (X * matrix.m20 + source.Y * matrix.m21 + matrix.m22);
            result.X = (X * matrix.m00 + source.Y * matrix.m01 + matrix.m02) * inverseZ;
            result.Y = (X * matrix.m10 + source.Y * matrix.m11 + matrix.m12) * inverseZ;
        }
        public static Vector2D TransformNormal(Matrix3x3 matrix, Vector2D source)
        {
            Vector2D result;
            result.X = (source.X * matrix.m00 + source.Y * matrix.m01);
            result.Y = (source.X * matrix.m10 + source.Y * matrix.m11);
            return result;
        }
        public static void TransformNormal(ref Matrix3x3 matrix, ref Vector2D source, out Vector2D result)
        {
            Scalar X = source.X;
            result.X = (X * matrix.m00 + source.Y * matrix.m01);
            result.Y = (X * matrix.m10 + source.Y * matrix.m11);
        }
        /// <summary>
        /// Uses a matrix multiplication to Transform the vector.
        /// </summary>
        /// <param name="matrix">The Transformation matrix</param>
        /// <param name="source">The Vector to be transformed</param>
        /// <returns>The transformed vector.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Transformation_matrix#Affine_transformations"/></remarks>
        public static Vector2D Transform(Matrix2x3 matrix, Vector2D source)
        {
            Vector2D result;
            result.X = (source.X * matrix.m00 + source.Y * matrix.m01 + matrix.m02);
            result.Y = (source.X * matrix.m10 + source.Y * matrix.m11 + matrix.m12);
            return result;
        }
        public static void Transform(ref Matrix2x3 matrix, ref Vector2D source, out Vector2D result)
        {
            Scalar X = source.X;
            result.X = (X * matrix.m00 + source.Y * matrix.m01 + matrix.m02);
            result.Y = (X * matrix.m10 + source.Y * matrix.m11 + matrix.m12);
        }
        public static Vector2D TransformNormal(Matrix2x3 matrix, Vector2D source)
        {
            Vector2D result;
            result.X = (source.X * matrix.m00 + source.Y * matrix.m01);
            result.Y = (source.X * matrix.m10 + source.Y * matrix.m11);
            return result;
        }
        public static void TransformNormal(ref Matrix2x3 matrix, ref Vector2D source, out Vector2D result)
        {
            Scalar X = source.X;
            result.X = (X * matrix.m00 + source.Y * matrix.m01);
            result.Y = (X * matrix.m10 + source.Y * matrix.m11);
        }
        /// <summary>
        /// Uses a matrix multiplication to Transform the vector.
        /// </summary>
        /// <param name="matrix">The rotation matrix</param>
        /// <param name="source">The Vector to be transformed</param>
        /// <returns>The transformed vector.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Transformation_matrix#Rotation"/></remarks>
        public static Vector2D Transform(Matrix2x2 matrix, Vector2D source)
        {
            Vector2D result;
            result.X = (source.X * matrix.m00 + source.Y * matrix.m01);
            result.Y = (source.X * matrix.m10 + source.Y * matrix.m11);
            return result;
        }
        public static void Transform(ref Matrix2x2 matrix, ref Vector2D source, out Vector2D result)
        {
            Scalar X = source.X;
            result.X = (X * matrix.m00 + source.Y * matrix.m01);
            result.Y = (X * matrix.m10 + source.Y * matrix.m11);
        }
        /// <summary>
        /// Does Scaler Multiplication on a Vector2D.
        /// </summary>
        /// <param name="scalar">The scalar value that will multiply the Vector2D.</param>
        /// <param name="source">The Vector2D to be multiplied.</param>
        /// <returns>The Product of the Scaler Multiplication.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Scalar_multiplication"/></remarks>
        public static Vector2D Multiply(Vector2D source, Scalar scalar)
        {
            Vector2D result;
            result.X = source.X * scalar;
            result.Y = source.Y * scalar;
            return result;
        }
        public static void Multiply(ref Vector2D source, ref  Scalar scalar, out Vector2D result)
        {
            result.X = source.X * scalar;
            result.Y = source.Y * scalar;
        }

        public static Vector2D Multiply(Scalar scalar, Vector2D source)
        {
            Vector2D result;
            result.X = scalar * source.X;
            result.Y = scalar * source.Y;
            return result;
        }
        public static void Multiply(ref Scalar scalar, ref  Vector2D source, out Vector2D result)
        {
            result.X = scalar * source.X;
            result.Y = scalar * source.Y;
        }
        /// <summary>
        /// Does a Dot Operation Also know as an Inner Product.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Dot Product (Inner Product).</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Dot_product"/></remarks>
        public static Scalar Dot(Vector2D left, Vector2D right)
        {
            return left.Y * right.Y + left.X * right.X;
        }
        public static void Dot(ref Vector2D left, ref Vector2D right, out Scalar result)
        {
            result = left.X * right.X + left.Y * right.Y;
        }
        /// <summary>
        /// Does a "2D" Cross Product also know as an Outer Product.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Z value of the resulting vector.</returns>
        /// <remarks>
        /// This 2D Cross Product is using a cheat. Since the Cross product (in 3D space) 
        /// always generates a vector perpendicular (orthogonal) to the 2 vectors used as 
        /// arguments. The cheat is that the only vector that can be perpendicular to two 
        /// vectors in the XY Plane will parallel to the Z Axis. Since any vector that is 
        /// parallel to the Z Axis will have zeros in both the X and Y Fields I can represent
        /// the cross product of 2 vectors in the XY plane as single scalar: Z. Also the 
        /// Cross Product of and Vector on the XY plan and that of one ont on the Z Axis 
        /// will result in a vector on the XY Plane. So the ZCross Methods were well thought
        /// out and can be trusted.
        /// <seealso href="http://en.wikipedia.org/wiki/Cross_product"/>
        /// </remarks>
        public static Scalar ZCross(Vector2D left, Vector2D right)
        {
            return left.X * right.Y - left.Y * right.X;
        }
        public static void ZCross(ref Vector2D left, ref Vector2D right, out Scalar result)
        {
            result = left.X * right.Y - left.Y * right.X;
        }
        /// <summary>
        /// Does a "2D" Cross Product also know as an Outer Product.
        /// </summary>
        /// <param name="leftZ">The Z value of the left vector operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Vector2D that fully represents the resulting vector.</returns>
        /// <remarks>
        /// This 2D Cross Product is using a cheat. Since the Cross product (in 3D space) 
        /// always generates a vector perpendicular (orthogonal) to the 2 vectors used as 
        /// arguments. The cheat is that the only vector that can be perpendicular to two 
        /// vectors in the XY Plane will parallel to the Z Axis. Since any vector that is 
        /// parallel to the Z Axis will have zeros in both the X and Y Fields I can represent
        /// the cross product of 2 vectors in the XY plane as single scalar: Z. Also the 
        /// Cross Product of and Vector on the XY plan and that of one ont on the Z Axis 
        /// will result in a vector on the XY Plane. So the ZCross Methods were well thought
        /// out and can be trusted.
        /// <seealso href="http://en.wikipedia.org/wiki/Cross_product"/>
        /// </remarks>
        public static Vector2D ZCross(Scalar leftZ, Vector2D right)
        {
            Vector2D result;
            result.X = -leftZ * right.Y;
            result.Y = leftZ * right.X;
            return result;
        }
        public static void ZCross(ref Scalar leftZ, ref Vector2D right, out Vector2D result)
        {
            Scalar rightX = right.X;
            result.X = -leftZ * right.Y;
            result.Y = leftZ * rightX;
        }
        /// <summary>
        /// Does a "2D" Cross Product also know as an Outer Product.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="rightZ">The Z value of the right vector operand.</param>
        /// <returns>The Vector2D that fully represents the resulting vector.</returns>
        /// <remarks>
        /// This 2D Cross Product is using a cheat. Since the Cross product (in 3D space) 
        /// always generates a vector perpendicular (orthogonal) to the 2 vectors used as 
        /// arguments. The cheat is that the only vector that can be perpendicular to two 
        /// vectors in the XY Plane will parallel to the Z Axis. Since any vector that is 
        /// parallel to the Z Axis will have zeros in both the X and Y Fields I can represent
        /// the cross product of 2 vectors in the XY plane as single scalar: Z. Also the 
        /// Cross Product of and Vector on the XY plan and that of one ont on the Z Axis 
        /// will result in a vector on the XY Plane. So the ZCross Methods were well thought
        /// out and can be trusted.
        /// <seealso href="http://en.wikipedia.org/wiki/Cross_product"/>
        /// </remarks>
        public static Vector2D ZCross(Vector2D left, Scalar rightZ)
        {
            Vector2D result;
            result.X = left.Y * rightZ;
            result.Y = -left.X * rightZ;
            return result;
        }
        public static void ZCross(ref Vector2D left, ref Scalar rightZ, out Vector2D result)
        {
            Scalar leftX = left.X;
            result.X = left.Y * rightZ;
            result.Y = -leftX * rightZ;
        }
        /// <summary>
        /// Gets the Squared <see cref="Magnitude"/> of the Vector2D that is passed.
        /// </summary>
        /// <param name="source">The Vector2D whos Squared Magnitude is te be returned.</param>
        /// <returns>The Squared Magnitude.</returns>
        public static Scalar GetMagnitudeSq(Vector2D source)
        {
            return source.X * source.X + source.Y * source.Y;
        }
        public static void GetMagnitudeSq(ref Vector2D source, out Scalar result)
        {
            result = source.X * source.X + source.Y * source.Y;
        }
        /// <summary>
        /// Gets the <see cref="Magnitude"/> of the Vector2D that is passed.
        /// </summary>
        /// <param name="source">The Vector2D whos Magnitude is te be returned.</param>
        /// <returns>The Magnitude.</returns>
        public static Scalar GetMagnitude(Vector2D source)
        {
            return MathHelper.Sqrt(source.X * source.X + source.Y * source.Y);
        }
        public static void GetMagnitude(ref Vector2D source, out Scalar result)
        {
            result = MathHelper.Sqrt(source.X * source.X + source.Y * source.Y);
        }
        /// <summary>
        /// Sets the <see cref="Magnitude"/> of a Vector2D without changing the  <see cref="Angle"/>.
        /// </summary>
        /// <param name="source">The Vector2D whose Magnitude is to be changed.</param>
        /// <param name="magnitude">The Magnitude.</param>
        /// <returns>A Vector2D with the new Magnitude</returns>
        public static Vector2D SetMagnitude(Vector2D source, Scalar magnitude)
        {
            Vector2D result;
            SetMagnitude(ref source, ref magnitude, out result);
            return result;
        }
        public static void SetMagnitude(ref Vector2D source, ref Scalar magnitude, out Vector2D result)
        {
            if (magnitude == 0) { result = Zero; return; }
            Scalar oldmagnitude = MathHelper.Sqrt(source.X * source.X + source.Y * source.Y);
            if (oldmagnitude == 0) { result = Zero; return; }
            oldmagnitude = (magnitude / oldmagnitude);
            result.X = source.X * oldmagnitude;
            result.Y = source.Y * oldmagnitude;
        }
        /// <summary>
        /// Negates a Vector2D.
        /// </summary>
        /// <param name="source">The Vector2D to be Negated.</param>
        /// <returns>The Negated Vector2D.</returns>
        public static Vector2D Negate(Vector2D source)
        {
            Vector2D result;
            result.X = -source.X;
            result.Y = -source.Y;
            return result;
        }
        [CLSCompliant(false)]
        public static void Negate(ref Vector2D source)
        {
            Negate(ref source, out source);
        }
        public static void Negate(ref Vector2D source, out Vector2D result)
        {
            result.X = -source.X;
            result.Y = -source.Y;
        }
        /// <summary>
        /// This returns the Normalized Vector2D that is passed. This is also known as a Unit Vector.
        /// </summary>
        /// <param name="source">The Vector2D to be Normalized.</param>
        /// <returns>The Normalized Vector2D. (Unit Vector)</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Unit_vector"/></remarks>
        public static Vector2D Normalize(Vector2D source)
        {
            Scalar oldmagnitude;
            GetMagnitude(ref source, out oldmagnitude);
            if (oldmagnitude == 0) { return Vector2D.Zero; }
            oldmagnitude = (1 / oldmagnitude);
            Vector2D result;
            result.X = source.X * oldmagnitude;
            result.Y = source.Y * oldmagnitude;
            return result;
        }
        public static void Normalize(ref Vector2D source, out Vector2D result)
        {
            Scalar oldmagnitude;
            GetMagnitude(ref source, out oldmagnitude);
            if (oldmagnitude == 0) { result = Zero; return; }
            oldmagnitude = (1 / oldmagnitude);
            result.X = source.X * oldmagnitude;
            result.Y = source.Y * oldmagnitude;
        }
        [CLSCompliant(false)]
        public static void Normalize(ref Vector2D source)
        {
            Normalize(ref source, out source);
        }
        /// <summary>
        /// This returns the Normalized Vector2D that is passed. This is also known as a Unit Vector.
        /// </summary>
        /// <param name="source">The Vector2D to be Normalized.</param>
        /// <param name="magnitude">the magitude of the Vector2D passed</param>
        /// <returns>The Normalized Vector2D. (Unit Vector)</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Unit_vector"/></remarks>
        public static Vector2D Normalize(Vector2D source, out Scalar magnitude)
        {
            Vector2D result;
            Normalize(ref source, out magnitude, out result);
            return result;
        }
        public static void Normalize(ref Vector2D source, out Scalar magnitude, out Vector2D result)
        {
            GetMagnitude(ref source, out magnitude);
            if (magnitude > 0)
            {
                Scalar magnitudeInv = (1 / magnitude);
                result.X = source.X * magnitudeInv;
                result.Y = source.Y * magnitudeInv;
            }
            else
            {
                result = Zero;
            }
        }
        /// <summary>
        /// Thie Projects the left Vector2D onto the Right Vector2D.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Projected Vector2D.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Projection_%28linear_algebra%29"/></remarks>
        public static Vector2D Project(Vector2D left, Vector2D right)
        {
            Vector2D result;
            Project(ref left, ref right, out result);
            return result;
        }
        public static void Project(ref Vector2D left, ref Vector2D right, out Vector2D result)
        {
            Scalar tmp, magsq;
            Dot(ref left, ref  right, out tmp);
            GetMagnitudeSq(ref right, out magsq);
            tmp /= magsq;
            Multiply(ref right, ref tmp, out result);
        }
        /// <summary>
        /// Gets a Vector2D that is perpendicular(orthogonal) to the passed Vector2D while staying on the XY Plane.
        /// </summary>
        /// <param name="source">The Vector2D whose perpendicular(orthogonal) is to be determined.</param>
        /// <returns>An perpendicular(orthogonal) Vector2D using the Right Hand Rule</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Right-hand_rule"/></remarks>
        public static Vector2D GetRightHandNormal(Vector2D source)
        {
            Vector2D result;
            result.X = -source.Y;
            result.Y = source.X;
            return result;
        }
        public static void GetRightHandNormal(ref Vector2D source, out Vector2D result)
        {
            Scalar sourceX = source.X;
            result.X = -source.Y;
            result.Y = sourceX;
        }
        /// <summary>
        /// Gets a Vector2D that is perpendicular(orthogonal) to the passed Vector2D while staying on the XY Plane.
        /// </summary>
        /// <param name="source">The Vector2D whose perpendicular(orthogonal) is to be determined.</param>
        /// <returns>An perpendicular(orthogonal) Vector2D using the Left Hand Rule (opposite of the Right hand Rule)</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Right-hand_rule#Left-hand_rule"/></remarks>
        public static Vector2D GetLeftHandNormal(Vector2D source)
        {
            Vector2D result;
            result.X = source.Y;
            result.Y = -source.X;
            return result;
        }
        public static void GetLeftHandNormal(ref Vector2D source, out Vector2D result)
        {
            Scalar sourceX = source.X;
            result.X = source.Y;
            result.Y = -sourceX;
        }

        public static Vector2D Hermite(Vector2D value1, Vector2D tangent1, Vector2D value2, Vector2D tangent2, Scalar amount)
        {
            Vector2D result;
            Hermite(ref value1, ref tangent1, ref value2, ref tangent2, amount, out result);
            return result;
        }
        public static void Hermite(ref  Vector2D value1, ref Vector2D tangent1, ref Vector2D value2, ref Vector2D tangent2, Scalar amount, out Vector2D result)
        {
            Scalar h1, h2, h3, h4;
            MathHelper.HermiteHelper(amount, out h1, out h2, out h3, out h4);
            result.X = h1 * value1.X + h2 * value2.X + h3 * tangent1.X + h4 * tangent2.X;
            result.Y = h1 * value1.Y + h2 * value2.Y + h3 * tangent1.Y + h4 * tangent2.Y;
        }

        public static Vector2D CatmullRom(Vector2D value1, Vector2D value2, Vector2D value3, Vector2D value4, Scalar amount)
        {
            Vector2D result;
            CatmullRom(ref value1, ref value2, ref value3, ref value4, amount, out result);
            return result;
        }
        public static void CatmullRom(ref Vector2D value1, ref Vector2D value2, ref Vector2D value3, ref Vector2D value4, Scalar amount, out Vector2D result)
        {
            Scalar amountSq = amount * amount;
            Scalar amountCu = amountSq * amount;
            result.X =
                0.5f * ((2 * value2.X) +
                (-value1.X + value3.X) * amount +
                (2 * value1.X - 5 * value2.X + 4 * value3.X - value4.X) * amountSq +
                (-value1.X + 3 * value2.X - 3 * value3.X + value4.X) * amountCu);
            result.Y =
                0.5f * ((2 * value2.Y) +
                (-value1.Y + value3.Y) * amount +
                (2 * value1.Y - 5 * value2.Y + 4 * value3.Y - value4.Y) * amountSq +
                (-value1.Y + 3 * value2.Y - 3 * value3.Y + value4.Y) * amountCu);
        }

        public static Vector2D Max(Vector2D value1, Vector2D value2)
        {
            Vector2D result;
            Max(ref value1, ref value2, out result);
            return result;
        }
        public static void Max(ref Vector2D value1, ref Vector2D value2, out Vector2D result)
        {
            result.X = (value1.X < value2.X) ? (value2.X) : (value1.X);
            result.Y = (value1.Y < value2.Y) ? (value2.Y) : (value1.Y);
        }

        public static Vector2D Min(Vector2D value1, Vector2D value2)
        {
            Vector2D result;
            Min(ref value1, ref value2, out result);
            return result;
        }
        public static void Min(ref Vector2D value1, ref Vector2D value2, out Vector2D result)
        {
            result.X = (value1.X > value2.X) ? (value2.X) : (value1.X);
            result.Y = (value1.Y > value2.Y) ? (value2.Y) : (value1.Y);
        }

        #endregion
        #region fields
        /// <summary>
        /// This is the X value. (Usually represents a horizontal position or direction.)
        /// </summary>
        [AdvBrowsable]
        [XmlAttribute]
        [System.ComponentModel.Description("The Magnitude on the X-Axis")]
        public Scalar X;
        /// <summary>
        /// This is the Y value. (Usually represents a vertical position or direction.)
        /// </summary>
        [AdvBrowsable]
        [XmlAttribute]
        [System.ComponentModel.Description("The Magnitude on the Y-Axis")]
        public Scalar Y;
        #endregion
        #region constructors
        /// <summary>
        /// Creates a New Vector2D Instance on the Stack.
        /// </summary>
        /// <param name="X">The X value.</param>
        /// <param name="Y">The Y value.</param>
        [InstanceConstructor("X,Y")]
        public Vector2D(Scalar X, Scalar Y)
        {
            this.X = X;
            this.Y = Y;
        }
        public Vector2D(Scalar[] vals) : this(vals, 0) { }
        public Vector2D(Scalar[] vals, int index)
        {
            Copy(vals, index, out this);
        }
        #endregion
        #region indexers
#if UNSAFE
        /// <summary>
        ///		Allows the Vector to be accessed linearly (v[0] -> v[Count-1]).  
        /// </summary>
        /// <remarks>
        ///    This indexer is only provided as a convenience, and is <b>not</b> recommended for use in
        ///    intensive applications.  
        /// </remarks>
        public Scalar this[int index]
        {
            get
            {
                ThrowHelper.CheckIndex("index", index, Count);
                unsafe
                {
                    fixed (Scalar* ptr = &this.X)
                    {
                        return ptr[index];
                    }
                }
            }
            set
            {
                ThrowHelper.CheckIndex("index", index, Count);
                unsafe
                {
                    fixed (Scalar* ptr = &this.X)
                    {
                        ptr[index] = value;
                    }
                }
            }
        }
#endif
        #endregion
        #region public properties
        /// <summary>
        /// Gets A perpendicular(orthogonal) Vector2D using the Right Hand Rule.
        /// </summary>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Right-hand_rule"/></remarks>
        public Vector2D RightHandNormal
        {
            get
            {
                return GetRightHandNormal(this);
            }
        }
        /// <summary>
        /// Gets A perpendicular(orthogonal) Vector2D using the Left Hand Rule.
        /// </summary>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Right-hand_rule#Left-hand_rule"/></remarks>
        public Vector2D LeftHandNormal
        {
            get
            {
                return GetLeftHandNormal(this);
            }
        }
        /// <summary>
        /// Gets or Sets the Magnitude (Length) of the Vector2D. 
        /// </summary>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Length_of_a_vector"/></remarks>
        [XmlIgnore]
        public Scalar Magnitude
        {
            get
            {
                return MathHelper.Sqrt(this.X * this.X + this.Y * this.Y);
            }
            set
            {
                SetMagnitude(ref this, ref value, out this);
            }
        }
        /// <summary>
        /// Gets the Squared Magnitude of the Vector2D.
        /// </summary>
        public Scalar MagnitudeSq
        {
            get
            {
                return this.X * this.X + this.Y * this.Y;
            }
        }
        /// <summary>
        /// Gets or Sets the Angle in radians of the Vector2D.
        /// </summary>
        /// <remarks>
        /// If the Magnitude of the Vector is 1 then The 
        /// Angles {0,Math.PI/2,Math.PI/2,3*Math.PI/2} would have the vectors {(1,0),(0,1),(-1,0),(0,-1)} respectively.
        /// </remarks>
        [XmlIgnore]
        public Scalar Angle
        {
            get
            {
                Scalar result;
                GetAngle(ref this, out result);
                return result;
            }
            set
            {
                SetAngle(ref this, ref value, out this);
            }
        }
        /// <summary>
        /// Gets the Normalized Vector2D. (Unit Vector)
        /// </summary>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Unit_vector"/></remarks>
        public Vector2D Normalized
        {
            get
            {
                return Normalize(this);
            }
        }
        /// <summary>
        /// The Number of Variables accesable though the indexer.
        /// </summary>
        int IAdvanceValueType.Count { get { return Count; } }
        #endregion
        #region public methods
        public Scalar[] ToArray()
        {
            Scalar[] array = new Scalar[Count];
            Copy(ref this, array, 0);
            return array;
        }
        public void CopyFrom(Scalar[] array, int index)
        {
            Copy(array, index, out this);
        }
        public void CopyTo(Scalar[] array, int index)
        {
            Copy(ref this, array, index);
        }
        public Vector3D ToVector3D(Scalar Z)
        {
            Vector3D rv;
            rv.X = this.X;
            rv.Y = this.Y;
            rv.Z = Z;
            return rv;
        }
        #endregion
        #region operators
        /// <summary>
        /// Adds 2 Vectors2Ds.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Sum of the 2 Vector2Ds.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
        public static Vector2D operator +(Vector2D left, Vector2D right)
        {
            Vector2D result;
            result.X = left.X + right.X;
            result.Y = left.Y + right.Y;
            return result;
        }
        /// <summary>
        /// Subtracts 2 Vector2Ds.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Difference of the 2 Vector2Ds.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Vector_addition_and_subtraction"/></remarks>
        public static Vector2D operator -(Vector2D left, Vector2D right)
        {
            Vector2D result;
            result.X = left.X - right.X;
            result.Y = left.Y - right.Y;
            return result;
        }
        /// <summary>
        /// Does Scaler Multiplication on a Vector2D.
        /// </summary>
        /// <param name="source">The Vector2D to be multiplied.</param>
        /// <param name="scalar">The scalar value that will multiply the Vector2D.</param>
        /// <returns>The Product of the Scaler Multiplication.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Scalar_multiplication"/></remarks>
        public static Vector2D operator *(Vector2D source, Scalar scalar)
        {
            Vector2D result;
            result.X = source.X * scalar;
            result.Y = source.Y * scalar;
            return result;
        }
        /// <summary>
        /// Does Scaler Multiplication on a Vector2D.
        /// </summary>
        /// <param name="scalar">The scalar value that will multiply the Vector2D.</param>
        /// <param name="source">The Vector2D to be multiplied.</param>
        /// <returns>The Product of the Scaler Multiplication.</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Vector_%28spatial%29#Scalar_multiplication"/></remarks>
        public static Vector2D operator *(Scalar scalar, Vector2D source)
        {
            Vector2D result;
            result.X = scalar * source.X;
            result.Y = scalar * source.Y;
            return result;
        }
        /// <summary>
        /// Does a Dot Operation Also know as an Inner Product.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Dot Product (Inner Product).</returns>
        /// <remarks><seealso href="http://en.wikipedia.org/wiki/Dot_product"/></remarks>
        public static Scalar operator *(Vector2D left, Vector2D right)
        {
            return left.Y * right.Y + left.X * right.X;
        }
        public static Vector2D operator *(Matrix2x3 matrix, Vector2D source)
        {
            Vector2D result;
            result.X = (source.X * matrix.m00 + source.Y * matrix.m01 + matrix.m02);
            result.Y = (source.X * matrix.m10 + source.Y * matrix.m11 + matrix.m12);
            return result;
        }
        public static Vector2D operator *(Matrix3x3 matrix, Vector2D source)
        {
            Scalar inverseZ = 1 / (source.X * matrix.m20 + source.Y * matrix.m21 + matrix.m22);
            Vector2D result;
            result.X = (source.X * matrix.m00 + source.Y * matrix.m01 + matrix.m02) * inverseZ;
            result.Y = (source.X * matrix.m10 + source.Y * matrix.m11 + matrix.m12) * inverseZ;
            return result;
        }
        public static Vector2D operator *(Matrix2x2 matrix, Vector2D source)
        {
            Vector2D result;
            result.X = (source.X * matrix.m00 + source.Y * matrix.m01);
            result.Y = (source.X * matrix.m10 + source.Y * matrix.m11);
            return result;
        }
        /// <summary>
        /// Negates a Vector2D.
        /// </summary>
        /// <param name="source">The Vector2D to be Negated.</param>
        /// <returns>The Negated Vector2D.</returns>
        public static Vector2D operator -(Vector2D source)
        {
            Vector2D result;
            result.X = -source.X;
            result.Y = -source.Y;
            return result;
        }
        /// <summary>
        /// Does a "2D" Cross Product also know as an Outer Product.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Z value of the resulting vector.</returns>
        /// <remarks>
        /// This 2D Cross Product is using a cheat. Since the Cross product (in 3D space) 
        /// always generates a vector perpendicular (orthogonal) to the 2 vectors used as 
        /// arguments. The cheat is that the only vector that can be perpendicular to two 
        /// vectors in the XY Plane will parallel to the Z Axis. Since any vector that is 
        /// parallel to the Z Axis will have zeros in both the X and Y Fields I can represent
        /// the cross product of 2 vectors in the XY plane as single scalar: Z. Also the 
        /// Cross Product of and Vector on the XY plan and that of one ont on the Z Axis 
        /// will result in a vector on the XY Plane. So the ZCross Methods were well thought
        /// out and can be trusted.
        /// <seealso href="http://en.wikipedia.org/wiki/Cross_product"/>
        /// </remarks>
        public static Scalar operator ^(Vector2D left, Vector2D right)
        {
            return left.X * right.Y - left.Y * right.X;
        }
        /// <summary>
        /// Does a "2D" Cross Product also know as an Outer Product.
        /// </summary>
        /// <param name="leftZ">The Z value of the left vector operand.</param>
        /// <param name="right">The right Vector2D operand.</param>
        /// <returns>The Vector2D that fully represents the resulting vector.</returns>
        /// <remarks>
        /// This 2D Cross Product is using a cheat. Since the Cross product (in 3D space) 
        /// always generates a vector perpendicular (orthogonal) to the 2 vectors used as 
        /// arguments. The cheat is that the only vector that can be perpendicular to two 
        /// vectors in the XY Plane will parallel to the Z Axis. Since any vector that is 
        /// parallel to the Z Axis will have zeros in both the X and Y Fields I can represent
        /// the cross product of 2 vectors in the XY plane as single scalar: Z. Also the 
        /// Cross Product of and Vector on the XY plan and that of one ont on the Z Axis 
        /// will result in a vector on the XY Plane. So the ZCross Methods were well thought
        /// out and can be trusted.
        /// <seealso href="http://en.wikipedia.org/wiki/Cross_product"/>
        /// </remarks>
        public static Vector2D operator ^(Scalar leftZ, Vector2D right)
        {
            Vector2D result;
            result.X = -leftZ * right.Y;
            result.Y = leftZ * right.X;
            return result;
        }
        /// <summary>
        /// Does a "2D" Cross Product also know as an Outer Product.
        /// </summary>
        /// <param name="left">The left Vector2D operand.</param>
        /// <param name="rightZ">The Z value of the right vector operand.</param>
        /// <returns>The Vector2D that fully represents the resulting vector.</returns>
        /// <remarks>
        /// This 2D Cross Product is using a cheat. Since the Cross product (in 3D space) 
        /// always generates a vector perpendicular (orthogonal) to the 2 vectors used as 
        /// arguments. The cheat is that the only vector that can be perpendicular to two 
        /// vectors in the XY Plane will parallel to the Z Axis. Since any vector that is 
        /// parallel to the Z Axis will have zeros in both the X and Y Fields I can represent
        /// the cross product of 2 vectors in the XY plane as single scalar: Z. Also the 
        /// Cross Product of and Vector on the XY plan and that of one ont on the Z Axis 
        /// will result in a vector on the XY Plane. So the ZCross Methods were well thought
        /// out and can be trusted.
        /// <seealso href="http://en.wikipedia.org/wiki/Cross_product"/>
        /// </remarks>
        public static Vector2D operator ^(Vector2D left, Scalar rightZ)
        {
            Vector2D result;
            result.X = left.Y * rightZ;
            result.Y = -left.X * rightZ;
            return result;
        }
        /// <summary>
        /// Specifies whether the Vector2Ds contain the same coordinates.
        /// </summary>
        /// <param name="left">The left Vector2D to test.</param>
        /// <param name="right">The right Vector2D to test.</param>
        /// <returns>true if the Vector2Ds have the same coordinates; otherwise false</returns>
        public static bool operator ==(Vector2D left, Vector2D right)
        {
            return left.X == right.X && left.Y == right.Y;
        }
        /// <summary>
        /// Specifies whether the Vector2Ds do not contain the same coordinates.
        /// </summary>
        /// <param name="left">The left Vector2D to test.</param>
        /// <param name="right">The right Vector2D to test.</param>
        /// <returns>true if the Vector2Ds do not have the same coordinates; otherwise false</returns>
        public static bool operator !=(Vector2D left, Vector2D right)
        {
            return !(left.X == right.X && left.Y == right.Y);
        }



        public static explicit operator Vector2D(Vector3D source)
        {
            Vector2D result;
            result.X = source.X;
            result.Y = source.Y;
            return result;
        }

        #endregion
        #region overrides
        private string ToStringInternal(string FormatString)
        {
            return string.Format(FormatString, X, Y);
        }
        /// <summary>
        /// Converts the numeric value of this instance to its equivalent string representation, using the specified format.
        /// </summary>
        /// <param name="format">the format for each scaler in this Vector</param>
        /// <returns></returns>
        public string ToString(string format)
        {
            return ToStringInternal(string.Format(FormatableString, format));
        }
        public override string ToString()
        {
            return ToStringInternal(FormatString);
        }

#if !CompactFramework && !WindowsCE && !PocketPC && !XBOX360 && !SILVERLIGHT 
        public static bool TryParse(string s, out Vector2D result)
        {
            if (s == null)
            {
                result = Zero;
                return false;
            }
            string[] vals = ParseHelper.SplitStringVector(s);
            if (vals.Length != Count)
            {
                result = Zero;
                return false;
            }
            if (Scalar.TryParse(vals[0], out result.X) &&
                Scalar.TryParse(vals[1], out result.Y))
            {
                return true;
            }
            else
            {
                result = Zero;
                return false;
            }
        }
#endif
        [ParseMethod]
        public static Vector2D Parse(string s)
        {
            if (s == null)
            {
                throw new ArgumentNullException("s");
            }
            string[] vals = ParseHelper.SplitStringVector(s);
            if (vals.Length != Count)
            {
                ThrowHelper.ThrowVectorFormatException(s, Count, FormatString);
            }
            Vector2D value;
            value.X = Scalar.Parse(vals[0]);
            value.Y = Scalar.Parse(vals[1]);
            return value;
        }

        /// <summary>
        ///		Provides a unique hash code based on the member variables of this
        ///		class.  This should be done because the equality operators (==, !=)
        ///		have been overriden by this class.
        ///		<p/>
        ///		The standard implementation is a simple XOR operation between all local
        ///		member variables.
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return X.GetHashCode() ^ Y.GetHashCode();
        }
        /// <summary>
        ///		Compares this Vector to another object.  This should be done because the 
        ///		equality operators (==, !=) have been overriden by this class.
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            return (obj is Vector2D) && Equals((Vector2D)obj);
        }
        public bool Equals(Vector2D other)
        {
            return Equals(ref this, ref other);
        }
        public static bool Equals(Vector2D left, Vector2D right)
        {
            return
                left.X == right.X &&
                left.Y == right.Y;
        }
        [CLSCompliant(false)]
        public static bool Equals(ref Vector2D left, ref Vector2D right)
        {
            return
                left.X == right.X &&
                left.Y == right.Y;
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)


Written By
Engineer
Canada Canada
By day I'm a Professional Engineer, doing .NET, VB6, SQL Server, and Automation (Ladder Logic, etc.) programming.

On weekends I write and maintain an open source extensible application framework called SoapBox Core.

In the evenings I provide front line technical support for moms4mom.com and I help out with administrative tasks (like formatting stuff). I also pitch in as a moderator from time to time.

You can follow me on twitter.

Comments and Discussions