using System;
namespace ActiveProtect.Models
{
///
/// 表示三维空间中的向量
///
public class Vector3D
{
// 添加静态单位向量属性
public static Vector3D UnitX => new Vector3D(1, 0, 0);
public static Vector3D UnitY => new Vector3D(0, 1, 0);
public static Vector3D UnitZ => new Vector3D(0, 0, 1);
public static Vector3D Zero => new Vector3D(0, 0, 0);
///
/// X 坐标
///
public double X { get; set; }
///
/// Y 坐标
///
public double Y { get; set; }
///
/// Z 坐标
///
public double Z { get; set; }
///
/// 构造函数
///
public Vector3D(double x, double y, double z)
{
X = x;
Y = y;
Z = z;
}
///
/// 计算两个向量之间的距离
///
/// 第一个向量
/// 第二个向量
/// 两个向量之间的距离
public static double Distance(Vector3D v1, Vector3D v2)
{
return Math.Sqrt(Math.Pow(v1.X - v2.X, 2) + Math.Pow(v1.Y - v2.Y, 2) + Math.Pow(v1.Z - v2.Z, 2));
}
///
/// 将向量转换为字符串表示
///
/// 向量的字符串表示
public override string ToString()
{
return $"({X:F2}, {Y:F2}, {Z:F2})";
}
///
/// 向量减法运算符重载
///
public static Vector3D operator -(Vector3D a, Vector3D b)
{
return new Vector3D(a.X - b.X, a.Y - b.Y, a.Z - b.Z);
}
///
/// 向量加法运算符重载
///
public static Vector3D operator +(Vector3D a, Vector3D b)
{
return new Vector3D(a.X + b.X, a.Y + b.Y, a.Z + b.Z);
}
///
/// 向量与标量乘法运算符重载
///
public static Vector3D operator *(Vector3D a, double scalar)
{
return new Vector3D(a.X * scalar, a.Y * scalar, a.Z * scalar);
}
///
/// 向量与标量除法运算符重载
///
public static Vector3D operator /(Vector3D a, double scalar)
{
return new Vector3D(a.X / scalar, a.Y / scalar, a.Z / scalar);
}
///
/// 向量反向
///
public static Vector3D operator -(Vector3D a)
{
return new Vector3D(-a.X, -a.Y, -a.Z);
}
///
/// 计算向量的模长
///
/// 向量的模长
public double Magnitude()
{
return Math.Sqrt(X * X + Y * Y + Z * Z);
}
///
/// 计算向量模长的平方
///
/// 向量模长的平方
public double MagnitudeSquared()
{
return X * X + Y * Y + Z * Z;
}
///
/// 向量归一化
///
/// 归一化后的向量
public Vector3D Normalize()
{
double mag = Magnitude();
if (mag > 0)
{
return new Vector3D(X / mag, Y / mag, Z / mag);
}
return new Vector3D(0, 0, 0);
}
///
/// 计算两个向量的叉积
///
/// 第一个向量
/// 第二个向量
/// 叉积结果
public static Vector3D CrossProduct(Vector3D a, Vector3D b)
{
return new Vector3D(
a.Y * b.Z - a.Z * b.Y,
a.Z * b.X - a.X * b.Z,
a.X * b.Y - a.Y * b.X
);
}
///
/// 计算两个向量的点积
///
/// 第一个向量
/// 第二个向量
/// 点积结果
public static double DotProduct(Vector3D a, Vector3D b)
{
return a.X * b.X + a.Y * b.Y + a.Z * b.Z;
}
///
/// 向量取反
///
/// 输入向量
/// 取反后的向量
public static Vector3D Negate(Vector3D a)
{
return new Vector3D(-a.X, -a.Y, -a.Z);
}
}
///
/// 表示三维空间中的方向
///
public struct Orientation
{
///
/// 偏航角(绕Y轴旋转)
///
public double Yaw { get; set; }
///
/// 俯仰角(绕X轴旋转)
///
public double Pitch { get; set; }
///
/// 滚转角(绕Z轴旋转)
///
public double Roll { get; set; }
///
/// 构造函数
///
public Orientation(double yaw, double pitch, double roll)
{
Yaw = yaw;
Pitch = pitch;
Roll = roll;
}
///
/// 将方向转换为字符串表示
///
/// 方向的字符串表示
public override readonly string ToString()
{
return $"(Yaw: {Yaw:F2}, Pitch: {Pitch:F2}, Roll: {Roll:F2})";
}
///
/// 将角度归一化到 [-π, π] 范围内
///
public void Normalize()
{
Yaw = NormalizeAngle(Yaw);
Pitch = NormalizeAngle(Pitch);
Roll = NormalizeAngle(Roll);
}
///
/// 将单个角度归一化到 [-π, π] 范围内
///
/// 输入角度
/// 归一化后的角度
private static double NormalizeAngle(double angle)
{
while (angle > Math.PI) angle -= 2 * Math.PI;
while (angle <= -Math.PI) angle += 2 * Math.PI;
return angle;
}
///
/// 根据给定的方向向量创建方向
///
/// 方向向量
/// 对应的方向
public static Orientation LookAt(Vector3D direction)
{
double yaw = Math.Atan2(direction.Z, direction.X);
double pitch = Math.Atan2(direction.Y, Math.Sqrt(direction.X * direction.X + direction.Z * direction.Z));
return new Orientation(yaw, pitch, 0);
}
///
/// 将方向转换为单位向量
///
/// 对应的单位向量
public readonly Vector3D ToVector()
{
double cosYaw = Math.Cos(Yaw);
double sinYaw = Math.Sin(Yaw);
double cosPitch = Math.Cos(Pitch);
double sinPitch = Math.Sin(Pitch);
return new Vector3D(
cosYaw * cosPitch,
sinPitch,
sinYaw * cosPitch
);
}
///
/// 从向量创建方向
///
/// 输入向量
/// 对应的方向
public static Orientation FromVector(Vector3D vector)
{
Vector3D normalized = vector.Normalize();
double pitch = Math.Asin(normalized.Y);
double yaw;
if (Math.Abs(normalized.Y) > 0.9999) // 接近垂直
{
yaw = 0; // 或者保持之前的偏航角
}
else
{
yaw = Math.Atan2(normalized.Z, normalized.X);
}
return new Orientation(yaw, pitch, 0);
}
}
public struct Vector2D
{
public double X { get; set; }
public double Y { get; set; }
public Vector2D(double x, double y)
{
X = x;
Y = y;
}
public static Vector2D Zero => new Vector2D(0, 0);
}
}