1 // 获取start到target的stepNumber个等分点 2 public static bool GetPoints(Vector3 start, Vector3 target, float theta, int stepNumber, Vertex center, out List<Vector3> points) 3 { 4 points = new List<Vector3>(); 5 6 Vector3 normalVec = center.Normal; 7 8 Vector3 localStartPoint = start - center.Position; 9 Vector3 localEndPoint = target - center.Position; 10 11 if (stepNumber > 0) 12 { 13 for (int i = 1; i < stepNumber; i++) 14 { 15 Matrix4x4 rotateMat = Matrix4x4.CreateFromAxisAngle(normalVec, MathEx.Lerp(0, (float)theta, (float)i / stepNumber)); 16 Vector3 localPos = Vector3.Transform(localStartPoint, rotateMat); 17 points.Add(center.Position + localPos); 18 } 19 points.Add(target); 20 } 21 return true; 22 } 23 24 // 检查三点是否共线 25 private static bool ArePointsColinear(Vector3 p1, Vector3 p2, Vector3 p3) 26 { 27 // 计算向量 28 Vector3 v1 = p2 - p1; 29 Vector3 v2 = p3 - p1; 30 31 // 计算叉积 32 Vector3 cross = Vector3.Cross(v1, v2); 33 34 // 如果叉积接近零向量,则三点共线 35 return cross.LengthSquared() < 1e-10f; 36 } 37 38 // 计算平面法向量 39 private static Vector3 CalculatePlaneNormal(Vector3 p1, Vector3 p2, Vector3 p3) 40 { 41 Vector3 v1 = p2 - p1; 42 Vector3 v2 = p3 - p1; 43 Vector3 normal = Vector3.Cross(v1, v2); 44 return Vector3.Normalize(normal); 45 } 46 47 // 计算圆心(外心) 48 private static Vector3 CalculateCircumcenter(Vector3 p0, Vector3 p1, Vector3 p2) 49 { 50 var center = Vector3.Zero; 51 Vector3 v0 = Vector3.Normalize(p1 - p0); 52 Vector3 v1 = Vector3.Normalize(p2 - p0); 53 if (v0 == v1 || v0 == -v1) { throw new Exception("计算圆心错误!"); } 54 55 double a1 = (p0.Y * p1.Z - p1.Y * p0.Z - p0.Y * p2.Z + p2.Y * p0.Z + p1.Y * p2.Z - p2.Y * p1.Z), 56 b1 = -(p0.X * p1.Z - p1.X * p0.Z - p0.X * p2.Z + p2.X * p0.Z + p1.X * p2.Z - p2.X * p1.Z), 57 c1 = (p0.X * p1.Y - p1.X * p0.Y - p0.X * p2.Y + p2.X * p0.Y + p1.X * p2.Y - p2.X * p1.Y), 58 d1 = -(p0.X * p1.Y * p2.Z - p0.X * p2.Y * p1.Z - p1.X * p0.Y * p2.Z + p1.X * p2.Y * p0.Z + p2.X * p0.Y * p1.Z - p2.X * p1.Y * p0.Z); 59 60 double a2 = 2 * (p1.X - p0.X), 61 b2 = 2 * (p1.Y - p0.Y), 62 c2 = 2 * (p1.Z - p0.Z), 63 d2 = p0.X * p0.X + p0.Y * p0.Y + p0.Z * p0.Z - p1.X * p1.X - p1.Y * p1.Y - p1.Z * p1.Z; 64 65 double a3 = 2 * (p2.X - p0.X), 66 b3 = 2 * (p2.Y - p0.Y), 67 c3 = 2 * (p2.Z - p0.Z), 68 d3 = p0.X * p0.X + p0.Y * p0.Y + p0.Z * p0.Z - p2.X * p2.X - p2.Y * p2.Y - p2.Z * p2.Z; 69 70 center.X = (float)(-(b1 * c2 * d3 - b1 * c3 * d2 - b2 * c1 * d3 + b2 * c3 * d1 + b3 * c1 * d2 - b3 * c2 * d1) 71 / (a1 * b2 * c3 - a1 * b3 * c2 - a2 * b1 * c3 + a2 * b3 * c1 + a3 * b1 * c2 - a3 * b2 * c1)); 72 center.Y = (float)((a1 * c2 * d3 - a1 * c3 * d2 - a2 * c1 * d3 + a2 * c3 * d1 + a3 * c1 * d2 - a3 * c2 * d1) 73 / (a1 * b2 * c3 - a1 * b3 * c2 - a2 * b1 * c3 + a2 * b3 * c1 + a3 * b1 * c2 - a3 * b2 * c1)); 74 center.Z = (float)(-(a1 * b2 * d3 - a1 * b3 * d2 - a2 * b1 * d3 + a2 * b3 * d1 + a3 * b1 * d2 - a3 * b2 * d1) 75 / (a1 * b2 * c3 - a1 * b3 * c2 - a2 * b1 * c3 + a2 * b3 * c1 + a3 * b1 * c2 - a3 * b2 * c1)); 76 return center; 77 } 78 79 // 计算弧度 80 private static float CalculateMinorArcAngle(Vector3 start, Vector3 target, Vertex center) 81 { 82 //圆的法向量 83 Vector3 normalVec = center.Normal; 84 85 Vector3 localStartPoint = start - center.Position; 86 Vector3 localEndPoint = target - center.Position; 87 double theta = Math.Acos(Vector3.Dot(Vector3.Normalize(localStartPoint), Vector3.Normalize(localEndPoint))); 88 89 //算出从起点旋转theta角度以及(2 * Math.PI - theta)角度的点去与终点比对 90 Matrix4x4 startEndMat1 = Matrix4x4.CreateFromAxisAngle(normalVec, (float)theta); 91 Vector3 localEndPos1 = Vector3.Transform(localStartPoint, startEndMat1); 92 Matrix4x4 startEndMat2 = Matrix4x4.CreateFromAxisAngle(normalVec, (float)(2 * Math.PI - theta)); 93 Vector3 localEndPos2 = Vector3.Transform(localStartPoint, startEndMat2); 94 if (Vector3.Distance(localEndPos1, localEndPoint) > Vector3.Distance(localEndPos2, localEndPoint)) 95 { 96 theta = 2 * Math.PI - theta; 97 } 98 return (float)theta; 99 } 100 101 // 从start经过middle到target,检测movingPoint是否经过了middle点 102 public static bool HasPassedMiddlePoint(Vector3 start, Vector3 middle, Vector3 target, Vector3 movingPoint) 103 { 104 // 计算路径向量 105 Vector3 pathVector = target - start; 106 float pathLength = pathVector.Length(); 107 108 // 如果路径长度接近0,说明起点和终点重合,无法形成有效路径 109 if (pathLength < float.Epsilon) return false; 110 111 // 计算中间点在路径上的投影参数 112 Vector3 middleVector = middle - start; 113 float middleProjection = Vector3.Dot(middleVector, pathVector) / (pathLength * pathLength); 114 115 // 计算运动点在路径上的投影参数 116 Vector3 movingVector = movingPoint - start; 117 float movingProjection = Vector3.Dot(movingVector, pathVector) / (pathLength * pathLength); 118 119 // 检查运动点是否已经过了中间点的投影位置 120 bool hasPassedProjection = movingProjection > middleProjection; 121 122 // 综合判断:在路径附近且投影位置已过中间点 123 return hasPassedProjection; 124 }