// ========================================== 合并 ============================================= // /// <summary> /// 合并两个交叉的多边形(多边形必须先转换为顺时针方向,调用CW()函数!) /// </summary> /// <param name="other"></param> /// <param name="polyRes"></param> /// <returns></returns> public PolyResCode Union(Polygon other, ref List <Polygon> polyRes) { if (this.m_lstPoints.Count == 0 || other.m_lstPoints.Count == 0) { return(PolyResCode.ErrEmpty); } else if (!NMath.CheckCross(GetCoverRect(), other.GetCoverRect())) { return(PolyResCode.ErrNotCross); } // 转换为顺时针方向 //this.CW(); //other.CW(); List <NavNode> mainNode = new List <NavNode>(); //主多边形顶点 List <NavNode> subNode = new List <NavNode>(); //需要合并的多边形顶点 // init main nodes for (int i = 0; i < this.m_lstPoints.Count; i++) { NavNode currNode = new NavNode(this.m_lstPoints[i], false, true); if (i > 0) { NavNode preNode = mainNode[i - 1]; preNode.next = currNode; } mainNode.Add(currNode); } // init sub nodes for (int j = 0; j < other.m_lstPoints.Count; j++) { NavNode currNode = new NavNode(other.m_lstPoints[j], false, false); if (j > 0) { NavNode preNode = subNode[j - 1]; preNode.next = currNode; } subNode.Add(currNode); } int insCnt = 0; PolyResCode result = NavUtil.NavNodeIntersectPoint(mainNode, subNode, out insCnt); if (result == PolyResCode.Success && insCnt > 0) { if (insCnt % 2 != 0) { return(PolyResCode.ErrCrossNum); } else { PolyResCode linkRes = NavUtil.LinkToPolygon(mainNode, subNode, ref polyRes); return(linkRes); } } return(PolyResCode.ErrCrossNum); }
/// <summary> /// Checks the line cross. /// </summary> /// <returns><c>true</c>, if line cross was checked, <c>false</c> otherwise.</returns> public bool CheckLineCross() { Vector2 p1s, p1e, p2s, p2e; int iPointCount = this.m_lstPoints.Count; // 如果点的列表中只有两个点, 可以添加新点. if (iPointCount <= 2) { return(true); } for (int i = 0; i < iPointCount - 2; i++) { p1s.x = this.m_lstPoints[i].transform.position.x; p1s.y = this.m_lstPoints[i].transform.position.z; p1e.x = this.m_lstPoints[i + 1].transform.position.x; p1e.y = this.m_lstPoints[i + 1].transform.position.z; for (int j = i + 2; j < iPointCount; j++) { if (j != iPointCount - 1) { p2s.x = this.m_lstPoints[j].transform.position.x; p2s.y = this.m_lstPoints[j].transform.position.z; p2e.x = this.m_lstPoints[j + 1].transform.position.x; p2e.y = this.m_lstPoints[j + 1].transform.position.z; } else { p2s.x = this.m_lstPoints[j].transform.position.x; p2s.y = this.m_lstPoints[j].transform.position.z; p2e.x = this.m_lstPoints[0].transform.position.x; p2e.y = this.m_lstPoints[0].transform.position.z; if (0 == i) { continue; } } if (NMath.CheckCross(p1s, p1e, p2s, p2e)) { return(false); } } } return(true); }
/// <summary> /// 计算两条二维线段的交点 /// </summary> /// <param name="other">Other line</param> /// <param name="intersectPoint">输出的线段交点</param> /// <returns>返回值说明了两条线段的位置关系(COLINE,PARALLEL,CROSS,NOT_CROSS) </returns> public LineCrossState Intersection(Line2D other, out Vector2 intersectPoint) { intersectPoint.x = intersectPoint.y = float.NaN; if (!NMath.CheckCross(this.m_cStartPoint, this.m_cEndPoint, other.m_cStartPoint, other.m_cEndPoint)) { return(LineCrossState.NOT_CROSS); } double A1, B1, C1, A2, B2, C2; A1 = this.m_cEndPoint.y - this.m_cStartPoint.y; B1 = this.m_cStartPoint.x - this.m_cEndPoint.x; C1 = this.m_cEndPoint.x * this.m_cStartPoint.y - this.m_cStartPoint.x * this.m_cEndPoint.y; A2 = other.m_cEndPoint.y - other.m_cStartPoint.y; B2 = other.m_cStartPoint.x - other.m_cEndPoint.x; C2 = other.m_cEndPoint.x * other.m_cStartPoint.y - other.m_cStartPoint.x * other.m_cEndPoint.y; if (NMath.IsEqualZero(A1 * B2 - B1 * A2)) { if (NMath.IsEqualZero((A1 + B1) * C2 - (A2 + B2) * C1)) { return(LineCrossState.COLINE); } else { return(LineCrossState.PARALLEL); } } else { intersectPoint.x = (float)((B2 * C1 - B1 * C2) / (A2 * B1 - A1 * B2)); intersectPoint.y = (float)((A1 * C2 - A2 * C1) / (A2 * B1 - A1 * B2)); return(LineCrossState.CROSS); } }
/// <summary> /// 根据原始点计算出正确的落在导航区内的位置,修复无效点和三角形 /// </summary> /// <param name="orgTarTri">起源三角形</param> /// <param name="orgTarPos">起源点</param> /// <param name="otherTri">参考方向三角形</param> /// <param name="otherPos">参考方向点</param> /// <returns>结果</returns> private PathResCode FixPos(ref NavTriangle orgTarTri, ref Vector2 orgTarPos, NavTriangle otherTri, Vector2 otherPos, int extendLength) { Vector2 tarPos = orgTarPos; ////////////////////////////////////////////////////////////////////////// //为了精确判断,需要逆向延长线段一定长度 if (extendLength > 0) { Vector2 newTarPos = NMath.ExtendPos(otherPos, tarPos, extendLength); tarPos = newTarPos; } ////////////////////////////////////////////////////////////////////////// Line2D linePath = new Line2D(tarPos, otherPos); //参考线段 Rect lineRect = NMath.LineRect(linePath); //获取线段矩形包围盒 //1)找到所有与参考线段矩形相交的三角形,并判断是否groupID相等 List <NavTriangle> crossNavTris = new List <NavTriangle>(); foreach (NavTriangle tri in this.m_lstTriangle) { if (NMath.CheckCross(lineRect, tri.GetBoxCollider())) { if (otherTri != null && otherTri.GetGroupID() != tri.GetGroupID()) { continue; } crossNavTris.Add(tri); } } //2)找出所有与参考线段相交的三角形,并记录相交点 List <Vector2> crossPoints = new List <Vector2>(); //相交点列表 List <int> triIndex = new List <int>(); //相交三角形索引列表 for (int index = 0; index < crossNavTris.Count; index++) { NavTriangle crossTri = crossNavTris[index]; Line2D triLine; for (int i = 0; i < 3; i++) { Vector2 insPoint; triLine = new Line2D(crossTri.GetPoint(i), crossTri.GetPoint((i + 1) % 3)); if (linePath.Intersection(triLine, out insPoint) == LineCrossState.CROSS) { crossPoints.Add(insPoint); triIndex.Add(index); } } } if (crossPoints.Count == 0) { return(PathResCode.NoCrossPoint); } //3)找到最接近起源点的点 Vector2 lastPos = crossPoints[0]; int lastTriIndex = triIndex[0]; double lastLength = Math.Pow(lastPos.x - orgTarPos.x, 2.0) + Math.Pow(lastPos.y - orgTarPos.y, 2.0); for (int i = 1; i < crossPoints.Count; i++) { double newLength = Math.Pow(crossPoints[i].x - orgTarPos.x, 2.0) + Math.Pow(crossPoints[i].y - orgTarPos.y, 2.0); if (newLength < lastLength) { lastPos = crossPoints[i]; lastTriIndex = triIndex[i]; lastLength = newLength; } } //4)保存目标 orgTarPos = lastPos; orgTarTri = crossNavTris[lastTriIndex]; return(PathResCode.Success); }