137 lines
4.6 KiB
C#
Raw Normal View History

2024-08-17 14:27:18 +08:00
using System;
// using JNGame.Collision2D;
using JNGame.Math;
// using Debug = JNGame.Logging.Debug;
namespace JNGame.PathFinding
{
/// <summary>
/// 导航三角形在二叉空间分割树中的引用
/// <para>一个导航三角形可能会被树分割为多个三角形引用</para>
/// </summary>
public class TriangleRef
{
/// <summary>
/// 当前三角形引用关联的导航三角形索引
/// </summary>
public int index;
/// <summary>
/// 三角形顶点A
/// </summary>
public LVector2 vertexA;
/// <summary>
/// 三角形顶点B
/// </summary>
public LVector2 vertexB;
/// <summary>
/// 三角形顶点C
/// </summary>
public LVector2 vertexC;
/// <summary>
/// 是否是分割的三角形
/// </summary>
public bool IsSplit { get; private set; } = false;
/// <summary>
/// 三角形的边框
/// </summary>
public SplitLine[] borders;
/// <summary>
/// 根据下标获取三角形的顶点合法下标0/1/2
/// </summary>
/// <param name="index"></param>
/// <returns></returns>
/// <exception cref="IndexOutOfRangeException"></exception>
public LVector2 this[int index]
{
get
{
return index switch
{
0 => vertexA,
1 => vertexB,
2 => vertexC,
_ => throw new IndexOutOfRangeException("vector idx invalid" + index),
};
}
}
/// <summary>
/// 根据原始导航三角形创建引用
/// <para>由此构造的三角形引用认为是未切割过的三角形</para>
/// </summary>
/// <param name="srcTriangle">原始的导航三角形</param>
public TriangleRef(NavTriangle srcTriangle)
: this(srcTriangle.vertexA.ToLVector2XZ(), srcTriangle.vertexB.ToLVector2XZ(), srcTriangle.vertexC.ToLVector2XZ(), srcTriangle.index)
{ }
/// <summary>
/// 根据分割的三个顶点和原始导航三角形创建引用
/// <para>由此构造的三角形引用认为是切割过的三角形</para>
/// </summary>
/// <param name="vertexA">三角形顶点A</param>
/// <param name="vertexB">三角形顶点B</param>
/// <param name="vertexC">三角形顶点C</param>
/// <param name="srcTriangle">原始的导航三角形</param>
public TriangleRef(in LVector2 vertexA, in LVector2 vertexB, in LVector2 vertexC, TriangleRef srcTriangle)
: this(vertexA, vertexB, vertexC, srcTriangle.index)
{
IsSplit = true;
}
/// <summary>
/// 私有构造
/// </summary>
/// <param name="vertexA">三角形顶点A</param>
/// <param name="vertexB">三角形顶点B</param>
/// <param name="vertexC">三角形顶点C</param>
/// <param name="idx">引用的导航三角形索引</param>
private TriangleRef(in LVector2 vertexA, in LVector2 vertexB, in LVector2 vertexC, int idx)
{
this.vertexA = vertexA;
this.vertexB = vertexB;
this.vertexC = vertexC;
index = idx;
borders = new SplitLine[]
{
new SplitLine(vertexA, vertexB),
new SplitLine(vertexB, vertexC),
new SplitLine(vertexC, vertexA)
};
//check valid
CheckValid();
}
/// <summary>
/// 三角形三点不可重合
/// </summary>
private void CheckValid()
{
for (int i = 0; i < 3; i++)
{
if (borders[i].Direction == LVector2.Zero)
{
// Debug.Assert(false);
}
}
}
/// <summary>
/// 判断点是否在此三角形内
/// </summary>
/// <param name="pos"></param>
/// <returns></returns>
public bool Contain(in LVector2 pos)
{
// ABC三个顶点绕序为顺时针三个叉积都需要为负则点在三角形内
var isRightA = LVector2.Cross(vertexB - vertexA, pos - vertexA) > 0;
if (isRightA) return false;
var isRightB = LVector2.Cross(vertexC - vertexB, pos - vertexB) > 0;
if (isRightB) return false;
var isRightC = LVector2.Cross(vertexA - vertexC, pos - vertexC) > 0;
if (isRightC) return false;
return true;
}
}
}