ZeroVR/ZeroPacientVR/Assets/CodeRespawn/DungeonArchitect/ThirdParty/SharpNav/Geometry/Triangle3.cs

350 lines
8.1 KiB
C#

// Copyright (c) 2013-2015 Robert Rouhani <robert.rouhani@gmail.com> and other contributors (see CONTRIBUTORS file).
// Licensed under the MIT License - https://raw.github.com/Robmaister/SharpNav/master/LICENSE
using System;
using System.Runtime.InteropServices;
#if MONOGAME
using Vector3 = Microsoft.Xna.Framework.Vector3;
#elif OPENTK
using Vector3 = OpenTK.Vector3;
#elif SHARPDX
using Vector3 = SharpDX.Vector3;
#endif
namespace SharpNav.Geometry
{
/// <summary>
/// A 3d triangle.
/// </summary>
[Serializable]
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct Triangle3 : IEquatable<Triangle3>
{
#region Fields
/// <summary>
/// The first point.
/// </summary>
public Vector3 A;
/// <summary>
/// The second point.
/// </summary>
public Vector3 B;
/// <summary>
/// The third point.
/// </summary>
public Vector3 C;
#endregion
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="Triangle3"/> struct.
/// </summary>
/// <param name="a">The second point.</param>
/// <param name="b">The first point.</param>
/// <param name="c">The third point.</param>
public Triangle3(Vector3 a, Vector3 b, Vector3 c)
{
A = a;
B = b;
C = c;
}
#endregion
#region Properties
/// <summary>
/// Gets the directed line segment from <see cref="A"/> to <see cref="B"/>.
/// </summary>
public Vector3 AB
{
get
{
Vector3 result;
Vector3.Subtract(ref B, ref A, out result);
return result;
}
}
/// <summary>
/// Gets the directed line segment from <see cref="A"/> to <see cref="C"/>.
/// </summary>
public Vector3 AC
{
get
{
Vector3 result;
Vector3.Subtract(ref C, ref A, out result);
return result;
}
}
/// <summary>
/// Gets the directed line segment from <see cref="B"/> to <see cref="A"/>.
/// </summary>
public Vector3 BA
{
get
{
Vector3 result;
Vector3.Subtract(ref A, ref B, out result);
return result;
}
}
/// <summary>
/// Gets the directed line segment from <see cref="B"/> to <see cref="C"/>.
/// </summary>
public Vector3 BC
{
get
{
Vector3 result;
Vector3.Subtract(ref C, ref B, out result);
return result;
}
}
/// <summary>
/// Gets the directed line segment from <see cref="C"/> to <see cref="A"/>.
/// </summary>
public Vector3 CA
{
get
{
Vector3 result;
Vector3.Subtract(ref A, ref C, out result);
return result;
}
}
/// <summary>
/// Gets the directed line segment from <see cref="C"/> to <see cref="B"/>.
/// </summary>
public Vector3 CB
{
get
{
Vector3 result;
Vector3.Subtract(ref B, ref C, out result);
return result;
}
}
/// <summary>
/// Gets the area of the triangle.
/// </summary>
public float Area
{
get
{
return Vector3.Cross(AB, AC).Length() * 0.5f;
}
}
/// <summary>
/// Gets the perimeter of the triangle.
/// </summary>
public float Perimeter
{
get
{
return AB.Length() + AC.Length() + BC.Length();
}
}
/// <summary>
/// Gets the centroid of the triangle.
/// </summary>
public Vector3 Centroid
{
get
{
const float OneThird = 1f / 3f;
return A * OneThird + B * OneThird + C * OneThird;
}
}
/// <summary>
/// Gets the <see cref="Triangle3"/>'s surface normal. Assumes clockwise ordering of A, B, and C.
/// </summary>
public Vector3 Normal
{
get
{
return Vector3.Normalize(Vector3.Cross(AB, AC));
}
}
#endregion
#region Operators
/// <summary>
/// Compares two <see cref="Triangle3"/>'s for equality.
/// </summary>
/// <param name="left">The first triangle.</param>
/// <param name="right">The second triangle.</param>
/// <returns>A value indicating whether the two triangles are equal.</returns>
public static bool operator ==(Triangle3 left, Triangle3 right)
{
return left.Equals(right);
}
/// <summary>
/// Compares two <see cref="Triangle3"/>'s for inequality.
/// </summary>
/// <param name="left">The first triangle.</param>
/// <param name="right">The second triangle.</param>
/// <returns>A value indicating whether the two triangles are not equal.</returns>
public static bool operator !=(Triangle3 left, Triangle3 right)
{
return !left.Equals(right);
}
#endregion
#region Methods
/// <summary>
/// Calculates the bounding box of a triangle.
/// </summary>
/// <param name="tri">A triangle.</param>
/// <returns>The triangle's bounding box.</returns>
public static BBox3 GetBoundingBox(Triangle3 tri)
{
BBox3 b;
GetBoundingBox(ref tri, out b);
return b;
}
/// <summary>
/// Calculates the bounding box of a triangle.
/// </summary>
/// <param name="tri">A triangle.</param>
/// <param name="bbox">The triangle's bounding box.</param>
public static void GetBoundingBox(ref Triangle3 tri, out BBox3 bbox)
{
GetBoundingBox(ref tri.A, ref tri.B, ref tri.C, out bbox);
}
/// <summary>
/// Calculates the bounding box of a triangle from its vertices.
/// </summary>
/// <param name="a">The first vertex.</param>
/// <param name="b">The second vertex.</param>
/// <param name="c">The third vertex.</param>
/// <param name="bbox">The bounding box between the points.</param>
public static void GetBoundingBox(ref Vector3 a, ref Vector3 b, ref Vector3 c, out BBox3 bbox)
{
Vector3 min = a, max = a;
if (b.X < min.X) min.X = b.X;
if (b.Y < min.Y) min.Y = b.Y;
if (b.Z < min.Z) min.Z = b.Z;
if (c.X < min.X) min.X = c.X;
if (c.Y < min.Y) min.Y = c.Y;
if (c.Z < min.Z) min.Z = c.Z;
if (b.X > max.X) max.X = b.X;
if (b.Y > max.Y) max.Y = b.Y;
if (b.Z > max.Z) max.Z = b.Z;
if (c.X > max.X) max.X = c.X;
if (c.Y > max.Y) max.Y = c.Y;
if (c.Z > max.Z) max.Z = c.Z;
bbox.Min = min;
bbox.Max = max;
}
/// <summary>
/// Gets the area of the triangle projected onto the XZ-plane.
/// </summary>
/// <param name="a">The first point.</param>
/// <param name="b">The second point.</param>
/// <param name="c">The third point.</param>
/// <param name="area">The calculated area.</param>
public static void Area2D(ref Vector3 a, ref Vector3 b, ref Vector3 c, out float area)
{
float abx = b.X - a.X;
float abz = b.Z - a.Z;
float acx = c.X - a.X;
float acz = c.Z - a.Z;
area = acx * abz - abx * acz;
}
/// <summary>
/// Gets the area of the triangle projected onto the XZ-plane.
/// </summary>
/// <param name="a">The first point.</param>
/// <param name="b">The second point.</param>
/// <param name="c">The third point.</param>
/// <returns>The calculated area.</returns>
public static float Area2D(Vector3 a, Vector3 b, Vector3 c)
{
float result;
Area2D(ref a, ref b, ref c, out result);
return result;
}
/// <summary>
/// Checks for equality with another <see cref="Triangle3"/>.
/// </summary>
/// <param name="other">The other triangle.</param>
/// <returns>A value indicating whether other is equivalent to the triangle.</returns>
public bool Equals(Triangle3 other)
{
return
A.Equals(other.A) &&
B.Equals(other.B) &&
C.Equals(other.C);
}
/// <summary>
/// Checks for equality with another object.
/// </summary>
/// <param name="obj">The other object.</param>
/// <returns>A value indicating whether other is equivalent to the triangle.</returns>
public override bool Equals(object obj)
{
Triangle3? other = obj as Triangle3?;
if (other.HasValue)
return this.Equals(other.Value);
else
return false;
}
/// <summary>
/// Gets a unique hash code for the triangle.
/// </summary>
/// <returns>A hash code.</returns>
public override int GetHashCode()
{
//see http://stackoverflow.com/a/263416/1122135
int hash = 17;
hash = hash * 23 + A.GetHashCode();
hash = hash * 23 + B.GetHashCode();
hash = hash * 23 + C.GetHashCode();
return hash;
}
/// <summary>
/// Converts the triangle's data into a human-readable format.
/// </summary>
/// <returns>A string containing the triangle's data.</returns>
public override string ToString()
{
return "(" + A.ToString() + ", " + B.ToString() + ", " + C.ToString() + ")";
}
#endregion
}
}