Files
2026-01-19 09:50:54 +09:00

192 lines
6.3 KiB
C#

using System;
namespace Nanomesh
{
public readonly struct Vector3 : IEquatable<Vector3>, IInterpolable<Vector3>
{
public readonly double x;
public readonly double y;
public readonly double z;
public Vector3(double x, double y, double z)
{
this.x = x;
this.y = y;
this.z = z;
}
public Vector3(double x, double y)
{
this.x = x;
this.y = y;
z = 0.0;
}
public double this[int index]
{
get
{
switch (index)
{
case 0: return x;
case 1: return y;
case 2: return z;
default:
throw new IndexOutOfRangeException("Invalid Vector3 index!");
}
}
}
public override int GetHashCode()
{
return x.GetHashCode() ^ (y.GetHashCode() << 2) ^ (z.GetHashCode() >> 2);
}
public override bool Equals(object other)
{
if (!(other is Vector3))
{
return false;
}
return Equals((Vector3)other);
}
public bool Equals(Vector3 other)
{
return x == other.x && y == other.y && z == other.z;
}
public static Vector3 operator +(in Vector3 a, in Vector3 b) { return new Vector3(a.x + b.x, a.y + b.y, a.z + b.z); }
public static Vector3 operator -(in Vector3 a, in Vector3 b) { return new Vector3(a.x - b.x, a.y - b.y, a.z - b.z); }
public static Vector3 operator -(in Vector3 a) { return new Vector3(-a.x, -a.y, -a.z); }
public static Vector3 operator *(in Vector3 a, double d) { return new Vector3(a.x * d, a.y * d, a.z * d); }
public static Vector3 operator *(double d, in Vector3 a) { return new Vector3(a.x * d, a.y * d, a.z * d); }
public static Vector3 operator /(in Vector3 a, double d) { return new Vector3(MathUtils.DivideSafe(a.x, d), MathUtils.DivideSafe(a.y, d), MathUtils.DivideSafe(a.z, d)); }
public static bool operator ==(in Vector3 lhs, in Vector3 rhs)
{
double diff_x = lhs.x - rhs.x;
double diff_y = lhs.y - rhs.y;
double diff_z = lhs.z - rhs.z;
double sqrmag = diff_x * diff_x + diff_y * diff_y + diff_z * diff_z;
return sqrmag < MathUtils.EpsilonDouble;
}
public static bool operator !=(in Vector3 lhs, in Vector3 rhs)
{
return !(lhs == rhs);
}
public static Vector3 Cross(in Vector3 lhs, in Vector3 rhs)
{
return new Vector3(
lhs.y * rhs.z - lhs.z * rhs.y,
lhs.z * rhs.x - lhs.x * rhs.z,
lhs.x * rhs.y - lhs.y * rhs.x);
}
public static implicit operator Vector3F(Vector3 vec)
{
return new Vector3F((float)vec.x, (float)vec.y, (float)vec.z);
}
public static explicit operator Vector3(Vector3F vec)
{
return new Vector3(vec.x, vec.y, vec.z);
}
public static double Dot(in Vector3 lhs, in Vector3 rhs)
{
return lhs.x * rhs.x + lhs.y * rhs.y + lhs.z * rhs.z;
}
public static Vector3 Normalize(in Vector3 value)
{
double mag = Magnitude(value);
return value / mag;
}
public Vector3 Normalized => Vector3.Normalize(this);
public static double Distance(in Vector3 a, in Vector3 b)
{
double diff_x = a.x - b.x;
double diff_y = a.y - b.y;
double diff_z = a.z - b.z;
return Math.Sqrt(diff_x * diff_x + diff_y * diff_y + diff_z * diff_z);
}
public static double Magnitude(in Vector3 vector)
{
return Math.Sqrt(vector.x * vector.x + vector.y * vector.y + vector.z * vector.z);
}
public static Vector3 ProjectPointOnLine(in Vector3 linePoint, in Vector3 lineVec, in Vector3 point)
{
Vector3 linePointToPoint = point - linePoint;
return linePoint + lineVec * Dot(linePointToPoint, lineVec);
}
public static double DistancePointLine(in Vector3 point, in Vector3 lineStart, in Vector3 lineEnd)
{
return Magnitude(ProjectPointOnLine(lineStart, (lineEnd - lineStart).Normalized, point) - point);
}
public double LengthSquared => x * x + y * y + z * z;
public double Length => Math.Sqrt(x * x + y * y + z * z);
public static Vector3 Min(in Vector3 lhs, in Vector3 rhs)
{
return new Vector3(Math.Min(lhs.x, rhs.x), Math.Min(lhs.y, rhs.y), Math.Min(lhs.z, rhs.z));
}
public static Vector3 Max(in Vector3 lhs, in Vector3 rhs)
{
return new Vector3(Math.Max(lhs.x, rhs.x), Math.Max(lhs.y, rhs.y), Math.Max(lhs.z, rhs.z));
}
public static readonly Vector3 zeroVector = new Vector3(0f, 0f, 0f);
public static readonly Vector3 oneVector = new Vector3(1f, 1f, 1f);
public static readonly Vector3 positiveInfinityVector = new Vector3(float.PositiveInfinity, float.PositiveInfinity, float.PositiveInfinity);
public static readonly Vector3 negativeInfinityVector = new Vector3(float.NegativeInfinity, float.NegativeInfinity, float.NegativeInfinity);
public static Vector3 Zero => zeroVector;
public static Vector3 One => oneVector;
public static Vector3 PositiveInfinity => positiveInfinityVector;
public static Vector3 NegativeInfinity => negativeInfinityVector;
public static double AngleRadians(in Vector3 from, in Vector3 to)
{
double denominator = Math.Sqrt(from.LengthSquared * to.LengthSquared);
if (denominator < 1e-15F)
{
return 0F;
}
double dot = MathF.Clamp(Dot(from, to) / denominator, -1.0, 1.0);
return Math.Acos(dot);
}
public static double AngleDegrees(in Vector3 from, in Vector3 to)
{
return AngleRadians(from, to) / Math.PI * 180d;
}
public override string ToString()
{
return $"{x}, {y}, {z}";
}
public Vector3 Interpolate(Vector3 other, double ratio) => this * ratio + other * (1 - ratio);
}
}