using JNGame.Math; namespace JNGame.PathFinding { /// /// 二叉空间树的切割线 /// public struct SplitLine { /// /// 切割线起点 /// public LVector2 vertexA; /// /// 切割线终点 /// public LVector2 vertexB; /// /// 切割线方向 /// public readonly LVector2 Direction => vertexB - vertexA; /// /// 构造切割线 /// /// /// public SplitLine(in LVector2 vertexA, in LVector2 vertexB) { this.vertexA = vertexA; this.vertexB = vertexB; } /// /// 获取三角形的切割结果 /// /// 切割线 /// 切割三角形 /// 切割线左侧、右侧或经过切割线 public static EnumSplitType GetSplitResult(in SplitLine line, TriangleRef tri) { var lineDir = line.Direction; // 三角形三个顶点与切割线的位置关系 var valA = LVector2.Cross(lineDir, tri.vertexA - line.vertexA); var valB = LVector2.Cross(lineDir, tri.vertexB - line.vertexA); var valC = LVector2.Cross(lineDir, tri.vertexC - line.vertexA); var isRight = false; if (valA != 0) isRight = valA < 0; if (valB != 0) isRight = valB < 0; if (valC != 0) isRight = valC < 0; var isA = valA <= 0; var isB = valB <= 0; var isC = valC <= 0; if (isA == isB && isB == isC) { return isRight ? EnumSplitType.Right : EnumSplitType.Left; } isA = valA >= 0; isB = valB >= 0; isC = valC >= 0; if (isA == isB && isB == isC) { return isRight ? EnumSplitType.Right : EnumSplitType.Left; } return EnumSplitType.OnPlane; } /// /// 获取顶点和切割线的位置关系 /// /// 切割线 /// 顶点 /// public static EnumSplitType ClassifyPointToPlane(in SplitLine line, in LVector2 vertex) { var val = LVector2.Cross(line.Direction, vertex - line.vertexA); if (val == 0) { return EnumSplitType.OnPlane; } else { return val < 0 ? EnumSplitType.Right : EnumSplitType.Left; } } /// /// 计算p0p1,p2p3的交点 /// /// /// /// /// /// public static LVector2 GetIntersectPoint(in LVector2 p0, in LVector2 p1, in LVector2 p2, in LVector2 p3) { var diff = p2 - p0; var d1 = p1 - p0; var d2 = p3 - p2; var demo = LMath.Cross(d1, d2); //det if (LMath.Abs(demo) < LFloat.EPSILON) { // 叉积结果为0,说明两个向量平行 return p0; } var t1 = LMath.Cross(diff, d2) / demo; // Cross2D(diff,-d2) return p0 + (p1 - p0) * t1; } } }