// // Distributed under the BSD Licence (see LICENCE file). // // Copyright (c) 2014, Nition, http://www.momentstudio.co.nz/ // Copyright (c) 2017, Máté Cserép, http://codenet.hu // All rights reserved. // namespace Octree { using System; using System.Runtime.Serialization; /// /// Representation of 3D points and vectors. /// /// /// This class was inspired by the Vector3 type of the Unity Engine and /// designed with the exact same interface to provide maximum compatibility. /// [Serializable] public struct Point { /// /// Gets or sets the X coordinate. /// public double X { get; set; } /// /// Gets or sets the Y coordinate. /// public double Y { get; set; } /// /// Gets or sets the Z coordinate. /// public double Z { get; set; } /// /// Gets or set point coordinates. /// public double[] Coor { get { return new double[] { X, Y, Z }; } set { if (value.Length != 3) throw new NotSupportedException(); X = value[0]; Y = value[1]; Z = value[2]; } } /// /// Gets the length of the vector. /// public double Magnitude { get { return Math.Sqrt(X * X + Y * Y + Z * Z); } } /// /// Gets the squared length of the vector. /// public double SqrMagnitude { get { return X * X + Y * Y + Z * Z; } } /// /// Gets the vector with a magnitude of 1. /// public Point Normalized { get { Point copy = this; copy.Normalize(); return copy; } } /// /// Creates a new vector with given coordinates. /// /// The X coordinate. /// The Y coordinate. /// The Z coordinate. public Point(double x, double y, double z = 0f) { X = x; Y = y; Z = z; } /// /// Creates a new vector with given coordinates as array. /// /// Point coordinates as array. public Point(double[] coor) { X = coor[0]; Y = coor[1]; Z = coor[2]; } /// /// Normalizes the vector with a magnitude of 1. /// public void Normalize() { double num = Magnitude; if (num > 1E-05f) { this /= num; } else { this = Point.Zero; } } /// /// Returns a hash code for this instance. /// /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. public override int GetHashCode() { return X.GetHashCode() ^ Y.GetHashCode() << 2 ^ Z.GetHashCode() >> 2; } /// /// Determines whether the specified object as a is exactly equal to this instance. /// /// /// Due to floating point inaccuracies, this might return false for vectors which are essentially (but not exactly) equal. Use the to test two points for approximate equality. /// /// The object to compare with this instance. /// true if the specified point is equal to this instance; otherwise, false. public override bool Equals(object other) { bool result; if (!(other is Point)) { result = false; } else { Point vector = (Point)other; result = (X.Equals(vector.X) && Y.Equals(vector.Y) && Z.Equals(vector.Z)); } return result; } /// /// Returns a nicely formatted string for this vector. /// public override string ToString() { return String.Format("({0:F3}, {1:F3}, {2:F3})", X, Y, Z); } /// /// Returns a nicely formatted string for this vector. /// /// The format for each coordinate. public string ToString(string format) { return String.Format("({0}, {1}, {2})", X.ToString(format), Y.ToString(format), Z.ToString(format)); } /// /// Shorthand for writing Point(0, 0, 0). /// public static Point Zero = new Point(0f, 0f, 0f); /// /// Shorthand for writing Point(1, 1, 1). /// public static Point One = new Point(1f, 1f, 1f); /// /// Shorthand for writing Point(0, 0, 1). /// public static Point Forward = new Point(0f, 0f, 1f); /// /// Shorthand for writing Point(0, 0, -1). /// public static Point Back = new Point(0f, 0f, -1f); /// /// Shorthand for writing Point(0, 1, 0). /// public static Point Up = new Point(0f, 1f, 0f); /// /// Shorthand for writing Point(0, -1, 0). /// public static Point Down = new Point(0f, -1f, 0f); /// /// Shorthand for writing Point(-1, 0, 0). /// public static Point Left = new Point(-1f, 0f, 0f); /// /// Shorthand for writing Point(1, 0, 0). /// public static Point Right = new Point(1f, 0f, 0f); /// /// Returns the distance between two points. /// /// The first point. /// The second point. /// The distance. public static double Distance(Point a, Point b) { Point vector = new Point(a.X - b.X, a.Y - b.Y, a.Z - b.Z); return Math.Sqrt(vector.X * vector.X + vector.Y * vector.Y + vector.Z * vector.Z); } /// /// Multiplies two vectors component-wise. /// /// The first vector. /// The second vector. /// The scaled up vector. public static Point Scale(Point a, Point b) { return new Point(a.X * b.X, a.Y * b.Y, a.Z * b.Z); } /// /// Cross-product of two vectors. /// /// The first vector. /// The second vector. /// The cross product vector. public static Point Cross(Point a, Point b) { return new Point(a.Y * b.Z - a.Z * b.Y, a.Z * b.X - a.X * b.Z, a.X * b.Y - a.Y * b.X); } /// /// Dot-product of two vectors. /// /// The first vector. /// The second vector. /// The dot product vector. public static double Dot(Point a, Point b) { return a.X * b.X + a.Y * b.Y + a.Z * b.Z; } /// /// Dot-product of two vectors. /// /// The first vector. /// The second vector in coor. /// The dot product vector. public static double Dot(Point a, double[] b) { return a.X * b[0] + a.Y * b[1] + a.Z * b[3]; } /// /// Returns a point that is made from the smallest components of two points. /// /// The first point. /// The second point. /// The minimal coordinates. public static Point Min(Point a, Point b) { return new Point(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y), Math.Min(a.Z, b.Z)); } /// /// Returns a point that is made from the largest components of two points. /// /// The first point. /// The second point. /// The maximal coordinates. public static Point Max(Point a, Point b) { return new Point(Math.Max(a.X, b.X), Math.Max(a.Y, b.Y), Math.Max(a.Z, b.Z)); } /// /// Adds two vectors. /// /// The first vector. /// The second vector. public static Point operator +(Point a, Point b) { return new Point(a.X + b.X, a.Y + b.Y, a.Z + b.Z); } /// /// Subtracts one vector from another. /// /// The first vector. /// The second vector. public static Point operator -(Point a, Point b) { return new Point(a.X - b.X, a.Y - b.Y, a.Z - b.Z); } /// /// Negates a vector. /// /// The vector. public static Point operator -(Point a) { return new Point(-a.X, -a.Y, -a.Z); } /// /// Multiplies a vector by a number. /// /// The vector. /// The number. public static Point operator *(Point a, double d) { return new Point(a.X * d, a.Y * d, a.Z * d); } /// /// Multiplies a vector by a number. /// /// The number. /// The vector. public static Point operator *(double d, Point a) { return new Point(a.X * d, a.Y * d, a.Z * d); } /// /// Divides a vector by a number. /// /// The vector. /// The number. public static Point operator /(Point a, double d) { return new Point(a.X / d, a.Y / d, a.Z / d); } /// /// Determines whether two points are approximately equal. /// /// /// To allow for floating point inaccuracies, the two vectors are considered equal if the magnitude of their difference is less than 1e-5.. /// /// The first point. /// The second point. public static bool operator ==(Point a, Point b) { return (a - b).SqrMagnitude < 9.99999944E-11f; } /// /// Determines whether two points are different. /// /// /// To allow for floating point inaccuracies, the two vectors are considered equal if the magnitude of their difference is less than 1e-5. /// /// The first point. /// The second point. public static bool operator !=(Point a, Point b) { return !(a == b); } } }