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

137 lines
4.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 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;
}
}
}