#region License /* MIT License Copyright(c) 2017-2018 Mattias Edlund 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 using System; using System.Globalization; namespace MeshDecimator.Math { /// /// A 2D integer vector. /// public struct Vector2i : IEquatable { #region Static Read-Only /// /// The zero vector. /// public static readonly Vector2i zero = new Vector2i(0, 0); #endregion #region Fields /// /// The x component. /// public int x; /// /// The y component. /// public int y; #endregion #region Properties /// /// Gets the magnitude of this vector. /// public int Magnitude { get { return (int)System.Math.Sqrt(x * x + y * y); } } /// /// Gets the squared magnitude of this vector. /// public int MagnitudeSqr { get { return (x * x + y * y); } } /// /// Gets or sets a specific component by index in this vector. /// /// The component index. public int this[int index] { get { switch (index) { case 0: return x; case 1: return y; default: throw new IndexOutOfRangeException("Invalid Vector2i index!"); } } set { switch (index) { case 0: x = value; break; case 1: y = value; break; default: throw new IndexOutOfRangeException("Invalid Vector2i index!"); } } } #endregion #region Constructor /// /// Creates a new vector with one value for all components. /// /// The value. public Vector2i(int value) { this.x = value; this.y = value; } /// /// Creates a new vector. /// /// The x value. /// The y value. public Vector2i(int x, int y) { this.x = x; this.y = y; } #endregion #region Operators /// /// Adds two vectors. /// /// The first vector. /// The second vector. /// The resulting vector. public static Vector2i operator +(Vector2i a, Vector2i b) { return new Vector2i(a.x + b.x, a.y + b.y); } /// /// Subtracts two vectors. /// /// The first vector. /// The second vector. /// The resulting vector. public static Vector2i operator -(Vector2i a, Vector2i b) { return new Vector2i(a.x - b.x, a.y - b.y); } /// /// Scales the vector uniformly. /// /// The vector. /// The scaling value. /// The resulting vector. public static Vector2i operator *(Vector2i a, int d) { return new Vector2i(a.x * d, a.y * d); } /// /// Scales the vector uniformly. /// /// The scaling value. /// The vector. /// The resulting vector. public static Vector2i operator *(int d, Vector2i a) { return new Vector2i(a.x * d, a.y * d); } /// /// Divides the vector with a float. /// /// The vector. /// The dividing float value. /// The resulting vector. public static Vector2i operator /(Vector2i a, int d) { return new Vector2i(a.x / d, a.y / d); } /// /// Subtracts the vector from a zero vector. /// /// The vector. /// The resulting vector. public static Vector2i operator -(Vector2i a) { return new Vector2i(-a.x, -a.y); } /// /// Returns if two vectors equals eachother. /// /// The left hand side vector. /// The right hand side vector. /// If equals. public static bool operator ==(Vector2i lhs, Vector2i rhs) { return (lhs.x == rhs.x && lhs.y == rhs.y); } /// /// Returns if two vectors don't equal eachother. /// /// The left hand side vector. /// The right hand side vector. /// If not equals. public static bool operator !=(Vector2i lhs, Vector2i rhs) { return (lhs.x != rhs.x || lhs.y != rhs.y); } /// /// Explicitly converts from a single-precision vector into an integer vector. /// /// The single-precision vector. public static explicit operator Vector2i(Vector2 v) { return new Vector2i((int)v.x, (int)v.y); } /// /// Explicitly converts from a double-precision vector into an integer vector. /// /// The double-precision vector. public static explicit operator Vector2i(Vector2d v) { return new Vector2i((int)v.x, (int)v.y); } #endregion #region Public Methods #region Instance /// /// Set x and y components of an existing vector. /// /// The x value. /// The y value. public void Set(int x, int y) { this.x = x; this.y = y; } /// /// Multiplies with another vector component-wise. /// /// The vector to multiply with. public void Scale(ref Vector2i scale) { x *= scale.x; y *= scale.y; } /// /// Clamps this vector between a specific range. /// /// The minimum component value. /// The maximum component value. public void Clamp(int min, int max) { if (x < min) x = min; else if (x > max) x = max; if (y < min) y = min; else if (y > max) y = max; } #endregion #region Object /// /// Returns a hash code for this vector. /// /// The hash code. public override int GetHashCode() { return x.GetHashCode() ^ y.GetHashCode() << 2; } /// /// Returns if this vector is equal to another one. /// /// The other vector to compare to. /// If equals. public override bool Equals(object other) { if (!(other is Vector2i)) { return false; } Vector2i vector = (Vector2i)other; return (x == vector.x && y == vector.y); } /// /// Returns if this vector is equal to another one. /// /// The other vector to compare to. /// If equals. public bool Equals(Vector2i other) { return (x == other.x && y == other.y); } /// /// Returns a nicely formatted string for this vector. /// /// The string. public override string ToString() { return string.Format("({0}, {1})", x.ToString(CultureInfo.InvariantCulture), y.ToString(CultureInfo.InvariantCulture)); } /// /// Returns a nicely formatted string for this vector. /// /// The integer format. /// The string. public string ToString(string format) { return string.Format("({0}, {1})", x.ToString(format, CultureInfo.InvariantCulture), y.ToString(format, CultureInfo.InvariantCulture)); } #endregion #region Static /// /// Multiplies two vectors component-wise. /// /// The first vector. /// The second vector. /// The resulting vector. public static void Scale(ref Vector2i a, ref Vector2i b, out Vector2i result) { result = new Vector2i(a.x * b.x, a.y * b.y); } #endregion #endregion } }