using System; namespace ActiveProtect.Models { /// /// 表示三维空间中的向量 /// public class Vector3D(double x, double y, double z) { // 添加静态单位向量属性 public static Vector3D UnitX => new(1, 0, 0); public static Vector3D UnitY => new(0, 1, 0); public static Vector3D UnitZ => new(0, 0, 1); public static Vector3D Zero => new(0, 0, 0); /// /// X 坐标 /// public double X { get; set; } = x; /// /// Y 坐标 /// public double Y { get; set; } = y; /// /// Z 坐标 /// public double Z { get; set; } = 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(double yaw, double pitch, double roll) { /// /// 偏航角(绕Y轴旋转) /// public double Yaw { get; set; } = yaw; /// /// 俯仰角(绕X轴旋转) /// public double Pitch { get; set; } = pitch; /// /// 滚转角(绕Z轴旋转) /// public double Roll { get; set; } = 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(0, 0); } }