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;
}
}
}