UltimateZoneBuilder/Source/Geometry/Vector2D.cs

271 lines
6 KiB
C#

#region ================== Copyright (c) 2007 Pascal vd Heiden
/*
* Copyright (c) 2007 Pascal vd Heiden, www.codeimp.com
* This program is released under GNU General Public License
*
* 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 General Public License for more details.
*
*/
#endregion
#region ================== Namespaces
using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
#endregion
namespace CodeImp.DoomBuilder.Geometry
{
public struct Vector2D
{
#region ================== Constants
private const float TINY_VALUE = 0.0000000001f;
#endregion
#region ================== Variables
// Coordinates
public float x;
public float y;
#endregion
#region ================== Constructors
// Constructor
public Vector2D(float x, float y)
{
this.x = x;
this.y = y;
}
// Constructor
public Vector2D(Vector3D v)
{
this.x = v.x;
this.y = v.y;
}
#endregion
#region ================== Statics
// Conversion to Vector3D
public static implicit operator Vector3D(Vector2D a)
{
return new Vector3D(a);
}
// This adds two vectors
public static Vector2D operator +(Vector2D a, Vector2D b)
{
return new Vector2D(a.x + b.x, a.y + b.y);
}
// This adds to a vector
public static Vector2D operator +(float a, Vector2D b)
{
return new Vector2D(a + b.x, a + b.y);
}
// This adds to a vector
public static Vector2D operator +(Vector2D a, float b)
{
return new Vector2D(a.x + b, a.y + b);
}
// This subtracts two vectors
public static Vector2D operator -(Vector2D a, Vector2D b)
{
return new Vector2D(a.x - b.x, a.y - b.y);
}
// This subtracts from a vector
public static Vector2D operator -(Vector2D a, float b)
{
return new Vector2D(a.x - b, a.y - b);
}
// This subtracts from a vector
public static Vector2D operator -(float a, Vector2D b)
{
return new Vector2D(a - b.x, a - b.y);
}
// This reverses a vector
public static Vector2D operator -(Vector2D a)
{
return new Vector2D(-a.x, -a.y);
}
// This scales a vector
public static Vector2D operator *(float s, Vector2D a)
{
return new Vector2D(a.x * s, a.y * s);
}
// This scales a vector
public static Vector2D operator *(Vector2D a, float s)
{
return new Vector2D(a.x * s, a.y * s);
}
// This scales a vector
public static Vector2D operator *(Vector2D a, Vector2D b)
{
return new Vector2D(a.x * b.x, a.y * b.y);
}
// This scales a vector
public static Vector2D operator /(float s, Vector2D a)
{
return new Vector2D(a.x / s, a.y / s);
}
// This scales a vector
public static Vector2D operator /(Vector2D a, float s)
{
return new Vector2D(a.x / s, a.y / s);
}
// This scales a vector
public static Vector2D operator /(Vector2D a, Vector2D b)
{
return new Vector2D(a.x / b.x, a.y / b.y);
}
// This calculates the dot product
public static float DotProduct(Vector2D a, Vector2D b)
{
// Calculate and return the dot product
return a.x * b.x + a.y * b.y;
}
// This reflects the vector v over mirror m
// Note that mirror m must be normalized!
// R = V - 2 * M * (M dot V)
public static Vector2D Reflect(Vector2D v, Vector2D m)
{
// Get the dot product of v and m
float dp = Vector2D.DotProduct(m, v);
// Make the reflected vector
Vector2D mv = new Vector2D();
mv.x = v.x - (2f * m.x * dp);
mv.y = v.y - (2f * m.y * dp);
// Return the reflected vector
return mv;
}
// This returns the reversed vector
public static Vector2D Reversed(Vector2D v)
{
// Return reversed vector
return new Vector2D(-v.x, -v.y);
}
// This returns a vector from an angle
public static Vector2D FromAngle(float angle)
{
// Return vector from angle
return new Vector2D((float)Math.Sin(angle), -(float)Math.Cos(angle));
}
// This returns a vector from an angle with a given legnth
public static Vector2D FromAngle(float angle, float length)
{
// Return vector from angle
return FromAngle(angle) * length;
}
#endregion
#region ================== Methods
// This calculates the angle
public float GetAngle()
{
// Calculate and return the angle
return -(float)Math.Atan2(-y, x) + (float)Math.PI * 0.5f;
}
// This calculates the length
public float GetLength()
{
// Calculate and return the length
return (float)Math.Sqrt(x * x + y * y);
}
// This calculates the square length
public float GetLengthSq()
{
// Calculate and return the square length
return x * x + y * y;
}
// This calculates the length
public float GetManhattanLength()
{
// Calculate and return the length
return Math.Abs(x) + Math.Abs(y);
}
// This returns a normalized vector
public Vector2D GetNormal()
{
float lensq = this.GetLengthSq();
if(lensq > TINY_VALUE)
{
// Divide each element by the length
float mul = 1f / (float)Math.Sqrt(lensq);
return new Vector2D(x * mul, y * mul);
}
else
{
// Cannot make normal
return new Vector2D(0f, 0f);
}
}
// This scales the vector
public Vector2D GetScaled(float s)
{
// Scale the vector
return new Vector2D(x * s, y * s);
}
// This changes the vector length
public Vector2D GetFixedLength(float l)
{
// Normalize, then scale
return this.GetNormal().GetScaled(l);
}
// Output
public override string ToString()
{
return x + ", " + y;
}
// Transform
public Vector2D GetTransformed(Vector2D offset, Vector2D scale)
{
return new Vector2D((x + offset.x) * scale.x, (y + offset.y) * scale.y);
}
#endregion
}
}