Ejemplo n.º 1
0
        // ========================================== 合并 ============================================= //

        /// <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);
        }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 3
0
        /// <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);
            }
        }
Ejemplo n.º 4
0
        /// <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);
        }