PC-20230316NUNE\Administrator 894100ae37 提交Unity 联机Pro
2024-08-17 14:27:18 +08:00

115 lines
3.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using JNGame.Math;
namespace JNGame.PathFinding
{
/// <summary>
/// 二叉空间树的切割线
/// </summary>
public struct SplitLine
{
/// <summary>
/// 切割线起点
/// </summary>
public LVector2 vertexA;
/// <summary>
/// 切割线终点
/// </summary>
public LVector2 vertexB;
/// <summary>
/// 切割线方向
/// </summary>
public readonly LVector2 Direction => vertexB - vertexA;
/// <summary>
/// 构造切割线
/// </summary>
/// <param name="vertexA"></param>
/// <param name="vertexB"></param>
public SplitLine(in LVector2 vertexA, in LVector2 vertexB)
{
this.vertexA = vertexA;
this.vertexB = vertexB;
}
/// <summary>
/// 获取三角形的切割结果
/// </summary>
/// <param name="line">切割线</param>
/// <param name="tri">切割三角形</param>
/// <returns>切割线左侧、右侧或经过切割线</returns>
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;
}
/// <summary>
/// 获取顶点和切割线的位置关系
/// </summary>
/// <param name="line">切割线</param>
/// <param name="vertex">顶点</param>
/// <returns></returns>
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;
}
}
/// <summary>
/// 计算p0p1,p2p3的交点
/// </summary>
/// <param name="p0"></param>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <param name="p3"></param>
/// <returns></returns>
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;
}
}
}