using System; // using JNGame.Collision2D; using JNGame.Math; // using Debug = JNGame.Logging.Debug; namespace JNGame.PathFinding { /// /// 导航三角形在二叉空间分割树中的引用 /// 一个导航三角形可能会被树分割为多个三角形引用 /// public class TriangleRef { /// /// 当前三角形引用关联的导航三角形索引 /// public int index; /// /// 三角形顶点A /// public LVector2 vertexA; /// /// 三角形顶点B /// public LVector2 vertexB; /// /// 三角形顶点C /// public LVector2 vertexC; /// /// 是否是分割的三角形 /// public bool IsSplit { get; private set; } = false; /// /// 三角形的边框 /// public SplitLine[] borders; /// /// 根据下标获取三角形的顶点,合法下标0/1/2 /// /// /// /// public LVector2 this[int index] { get { return index switch { 0 => vertexA, 1 => vertexB, 2 => vertexC, _ => throw new IndexOutOfRangeException("vector idx invalid" + index), }; } } /// /// 根据原始导航三角形创建引用 /// 由此构造的三角形引用认为是未切割过的三角形 /// /// 原始的导航三角形 public TriangleRef(NavTriangle srcTriangle) : this(srcTriangle.vertexA.ToLVector2XZ(), srcTriangle.vertexB.ToLVector2XZ(), srcTriangle.vertexC.ToLVector2XZ(), srcTriangle.index) { } /// /// 根据分割的三个顶点和原始导航三角形创建引用 /// 由此构造的三角形引用认为是切割过的三角形 /// /// 三角形顶点A /// 三角形顶点B /// 三角形顶点C /// 原始的导航三角形 public TriangleRef(in LVector2 vertexA, in LVector2 vertexB, in LVector2 vertexC, TriangleRef srcTriangle) : this(vertexA, vertexB, vertexC, srcTriangle.index) { IsSplit = true; } /// /// 私有构造 /// /// 三角形顶点A /// 三角形顶点B /// 三角形顶点C /// 引用的导航三角形索引 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(); } /// /// 三角形三点不可重合 /// private void CheckValid() { for (int i = 0; i < 3; i++) { if (borders[i].Direction == LVector2.Zero) { // Debug.Assert(false); } } } /// /// 判断点是否在此三角形内 /// /// /// 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; } } }