An SDL wrapper library for .NET.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

174 lines
8.7 KiB

using DotSDL.Exceptions;
using System;
using System.Collections.Generic;
namespace DotSDL.Math.Vector {
/// <summary>
/// Represents a generic vector type.
/// </summary>
public class Vector2<T> : IEquatable<Vector2<T>> {
public T X { get; set; }
public T Y { get; set; }
/// <summary>
/// Initializes a new <see cref="Vector2{T}"/> object.
/// </summary>
/// <exception cref="InvalidTypeException">Thrown if this <see cref="Vector2{T}"/> is created with an unsupported type.</exception>
public Vector2() {
if(!VectorBase<T>.IsNumericType())
throw new InvalidTypeException(GetType().ToString(), typeof(T));
}
/// <summary>
/// Initializes a new <see cref="Vector2{T}"/> object using the values from another <see cref="Vector2{T}"/>.
/// </summary>
/// <param name="initialValue">The <see cref="Vector2{T}"/> that should be used to initialize the new object.</param>
/// <exception cref="InvalidTypeException">Thrown if this <see cref="Vector2{T}"/> is created with an unsupported type.</exception>
public Vector2(Vector2<T> initialValue) : this() {
X = initialValue.X;
Y = initialValue.Y;
}
/// <summary>
/// Initializes a new <see cref="Vector2{T}"/> object with the X and Y values both set to a given value.
/// </summary>
/// <param name="initialValue">The value to initialize the X and Y values to.</param>
/// <exception cref="InvalidTypeException">Thrown if this <see cref="Vector2{T}"/> is created with an unsupported type.</exception>
public Vector2(T initialValue) : this() {
X = Y = initialValue;
}
/// <summary>
/// Initializes a new <see cref="Vector2{T}"/> object with preset X and Y values.
/// </summary>
/// <param name="initialX">The initial value to set the X component to.</param>
/// <param name="initialY">The initial value to set the Y component to.</param>
/// <exception cref="InvalidTypeException">Thrown if this <see cref="Vector2{T}"/> is created with an unsupported type.</exception>
public Vector2(T initialX, T initialY) : this() {
X = initialX;
Y = initialY;
}
/// <summary>
/// Checks to see if two <see cref="Vector2{T}"/> objects are equal.
/// </summary>
/// <param name="left">The first <see cref="Vector2{T}"/> in the comparison.</param>
/// <param name="right">The second <see cref="Vector2{T}"/> in the comparison.</param>
/// <returns><c>true</c> if the two <see cref="Vector2{T}"/> objects are equal, otherwise <c>false</c>.</returns>
public static bool operator ==(Vector2<T> left, Vector2<T> right) {
if(left is null && right is null) return true;
if(left is null || right is null) return false;
if(left.GetType() != right.GetType()) return false;
return left.X.Equals(right.X) && left.Y.Equals(right.Y);
}
/// <summary>
/// Checks to see if two <see cref="Vector2{T}"/> objects are different.
/// </summary>
/// <param name="left">The first <see cref="Vector2{T}"/> in the comparison.</param>
/// <param name="right">The second <see cref="Vector2{T}"/> in the comparison.</param>
/// <returns><c>true</c> if the two <see cref="Vector2{T}"/> objects are different, otherwise <c>false</c>.</returns>
public static bool operator !=(Vector2<T> left, Vector2<T> right) {
return !(left == right);
}
/// <summary>
/// Adds two <see cref="Vector2{T}"/> objects together.
/// </summary>
/// <param name="left">The <see cref="Vector2{T}"/> to use as the operator.</param>
/// <param name="right">The <see cref="Vector2{T}"/> to use as the operand.</param>
/// <returns>A <see cref="Vector2{T}"/> containing the result.</returns>
public static Vector2<T> operator +(Vector2<T> left, Vector2<T> right) =>
new Vector2<T>(
(dynamic)left.X + (dynamic)right.X,
(dynamic)left.Y + (dynamic)right.Y
);
/// <summary>
/// Adds a <see cref="Vector2{T}"/> object with a scalar value.
/// </summary>
/// <param name="vec">The <see cref="Vector2{T}"/> to use as the operator.</param>
/// <param name="scalar">The <see cref="T"/> to use as the operand.</param>
/// <returns>A <see cref="Vector2{T}"/> containing the result.</returns>
public static Vector2<T> operator +(Vector2<T> vec, T scalar) =>
new Vector2<T>((dynamic)vec.X + scalar, (dynamic)vec.Y + scalar);
/// <summary>
/// Subtracts two <see cref="Vector2{T}"/> objects.
/// </summary>
/// <param name="left">The <see cref="Vector2{T}"/> to use as the operator.</param>
/// <param name="right">The <see cref="Vector2{T}"/> to use as the operand.</param>
/// <returns>A <see cref="Vector2{T}"/> containing the result.</returns>
public static Vector2<T> operator -(Vector2<T> left, Vector2<T> right) =>
new Vector2<T>(
(dynamic)left.X - (dynamic)right.X,
(dynamic)left.Y - (dynamic)right.Y
);
/// <summary>
/// Multiples a <see cref="Vector2{T}"/> by a scalar value.
/// </summary>
/// <param name="vec">The <see cref="Vector2{T}"/> to use as the operator.</param>
/// <param name="scalar">The <see cref="T"/> to use as the operand.</param>
/// <returns>A <see cref="Vector2{T}"/> containing the result.</returns>
public static Vector2<T> operator *(Vector2<T> vec, T scalar) =>
new Vector2<T>((dynamic)vec.X * scalar, (dynamic)vec.Y + scalar);
/// <summary>
/// Subtracts a scalar value from a <see cref="Vector2{T}"/>.
/// </summary>
/// <param name="vec">The <see cref="Vector2{T}"/> to use as the operator.</param>
/// <param name="scalar">The <see cref="T"/> to use as the operand.</param>
/// <returns>A <see cref="Vector2{T}"/> containing the result.</returns>
public static Vector2<T> operator -(Vector2<T> vec, T scalar) =>
new Vector2<T>((dynamic)vec.X - scalar, (dynamic)vec.Y - scalar);
/// <summary>Returns a new <see cref="Vector2{T}"/> with both X and Y set to 1.</summary>
public static Vector2<T> One => new Vector2<T>(VectorBase<T>.GetOne());
/// <summary>Returns a new <see cref="Vector2{T}"/> containing (1, 0).</summary>
public static Vector2<T> UnitX => new Vector2<T>(VectorBase<T>.GetOne(), VectorBase<T>.GetZero());
/// <summary>Returns a new <see cref="Vector2{T}"/> containing (0, 1).</summary>
public static Vector2<T> UnitY => new Vector2<T>(VectorBase<T>.GetZero(), VectorBase<T>.GetOne());
/// <summary>Returns a new <see cref="Vector2{T}"/> with both X and Y set to 0.</summary>
public static Vector2<T> Zero => new Vector2<T>(VectorBase<T>.GetZero());
/// <summary>
/// Calculates the dot product of two <see cref="Vector2{T}"/> objects.
/// </summary>
/// <param name="left">The <see cref="Vector2{T}"/> to use as the operator.</param>
/// <param name="right">The <see cref="Vector2{T}"/> to use as the operand.</param>
/// <returns>A <see cref="T"/> containing the result.</returns>
public T Dot(Vector2<T> left, Vector2<T> right) =>
(dynamic)left.X * (dynamic)right.X + (dynamic)left.Y + (dynamic)right.Y;
/// <inheritdoc/>
public bool Equals(Vector2<T> other) {
if(ReferenceEquals(null, other)) return false;
if(ReferenceEquals(this, other)) return true;
return EqualityComparer<T>.Default.Equals(X, other.X) && EqualityComparer<T>.Default.Equals(Y, other.Y);
}
/// <summary>
/// Determines whether this <see cref="Vector2{T}"/> is equal to another one.
/// </summary>
/// <param name="other">Another <see cref="Vector2{T}"/> to compare this instance to.</param>
/// <returns><c>true</c> if the two <see cref="Vector2{T}"/> objects are equal, otherwise <c>false</c>.</returns>
public override bool Equals(object obj) {
if(!(obj is Vector2<T>)) return false;
return this == (Vector2<T>)obj;
}
/// <inheritdoc/>
public override int GetHashCode() {
unchecked {
return (EqualityComparer<T>.Default.GetHashCode(X) * 397) ^ EqualityComparer<T>.Default.GetHashCode(Y);
}
}
public override string ToString() => $"{X}, {Y}";
}
}