Exemple #1
0
        /// <summary>
        /// Checks the cross.
        /// </summary>
        /// <returns><c>true</c>, if cross was checked, <c>false</c> otherwise.</returns>
        /// <param name="line">Line.</param>
        /// <param name="pos">Position.</param>
        /// <param name="radius">Radius.</param>
        public static bool CheckCross(Line2D line, Vector2 pos, float radius)
        {
            float fDis = line.GetLength();

            Vector2 d;

            d.x = (line.GetEndPoint().x - line.GetStartPoint().x) / fDis;
            d.y = (line.GetEndPoint().y - line.GetStartPoint().y) / fDis;

            Vector2 E;

            E.x = pos.x - line.GetStartPoint().x;
            E.y = pos.y - line.GetStartPoint().y;

            float a  = E.x * d.x + E.y * d.y;
            float a2 = a * a;

            float e2 = E.x * E.x + E.y * E.y;

            float r2 = radius * radius;

            if ((r2 - e2 + a2) < 0)
            {
                return(false);
            }
            return(true);
        }
        //         void SplitBigTriangle(ref List<Triangle> triangles)
        //         {
        //             // 将面积过大的三角形拆分成三个小三角形
        //             for (int i = 0; i < triangles.Count; i++)
        //             {
        //                 if (triangles[i].Area() > NeedSplitSize)
        //                 {
        //                 }
        //             }
        //         }

        /// <summary>
        /// 判断点是否是线段的可见点,组成的三角形没有和其他边相交
        /// </summary>
        /// <param name="line"></param>
        /// <param name="point"></param>
        /// <returns></returns>
        private bool IsPointVisibleOfLine(Line2D line, Vector2 point)
        {
            if (line == null)
            {
                return(false);
            }

            Vector2 sPnt = line.GetStartPoint();
            Vector2 ePnt = line.GetEndPoint();

            // 是否是线段端点
            if (point == sPnt || point == ePnt)
            {
                return(false);
            }
            //点不在线段的右侧(多边形顶点顺序为顺时针)
            if (line.ClassifyPoint(point) != PointSide.RIGHT_SIDE)
            {
                return(false);
            }

            if (!IsVisibleIn2Point(sPnt, point))
            {
                return(false);
            }

            if (!IsVisibleIn2Point(ePnt, point))
            {
                return(false);
            }

            return(true);
        }
Exemple #3
0
        /// <summary>
        /// 根据线段生成矩形
        /// </summary>
        /// <param name="linePath">线段</param>
        /// <returns>矩形</returns>
        public static Rect LineRect(Line2D linePath)
        {
            Rect lineRect = new Rect();

            if (linePath.GetStartPoint().x < linePath.GetEndPoint().x)
            {
                lineRect.xMin = linePath.GetStartPoint().x;
            }
            else
            {
                lineRect.xMin = linePath.GetEndPoint().x;
            }

            if (linePath.GetStartPoint().y < linePath.GetEndPoint().y)
            {
                lineRect.yMin = linePath.GetStartPoint().y;
            }
            else
            {
                lineRect.yMin = linePath.GetEndPoint().y;
            }

            lineRect.width  = Math.Abs(linePath.GetEndPoint().x - linePath.GetStartPoint().x);
            lineRect.height = Math.Abs(linePath.GetEndPoint().y - linePath.GetStartPoint().y);

            return(lineRect);
        }
Exemple #4
0
 /// <summary>
 /// Checks the cross.
 /// </summary>
 /// <returns><c>true</c>, if cross was checked, <c>false</c> otherwise.</returns>
 /// <param name="line">Line.</param>
 /// <param name="tri">Tri.</param>
 public static bool CheckCross(Line2D line, Triangle tri)
 {
     for (int i = 0; i < 3; i++)
     {
         Line2D lineTri = tri.GetSide(i);
         if (CheckCross(line.GetStartPoint(), line.GetEndPoint(),
                        lineTri.GetStartPoint(), lineTri.GetEndPoint())
             )
         {
             return(true);
         }
     }
     return(false);
 }
Exemple #5
0
        /// <summary>
        /// 根据拐点计算法获得导航网格的下一个拐点
        /// </summary>
        /// <param name="way"></param>
        /// <param name="triPathList"></param>
        /// <param name="endPos"></param>
        /// <param name="offSet"></param>
        /// <returns></returns>
        private WayPoint GetFurthestWayPoint(WayPoint way, List <NavTriangle> triPathList, Vector2 endPos, int offSet)
        {
            WayPoint    nextWay = null;
            Vector2     currPnt = way.GetPoint();
            NavTriangle currTri = way.GetTriangle();
            NavTriangle lastTriA = currTri;
            NavTriangle lastTriB = currTri;
            int         startIndex = triPathList.IndexOf(currTri);            //开始路点所在的网格索引
            Line2D      outSide = currTri.GetSide(currTri.GetOutWallIndex()); //路径线在网格中的穿出边?
            Vector2     lastPntA = outSide.GetStartPoint();
            Vector2     lastPntB = outSide.GetEndPoint();
            Line2D      lastLineA = new Line2D(currPnt, lastPntA);
            Line2D      lastLineB = new Line2D(currPnt, lastPntB);
            Vector2     testPntA, testPntB;

            for (int i = startIndex + 1; i < triPathList.Count; i++)
            {
                currTri = triPathList[i];
                outSide = currTri.GetSide(currTri.GetOutWallIndex());
                if (i == triPathList.Count - 1)
                {
                    testPntA = endPos;
                    testPntB = endPos;
                }
                else
                {
                    testPntA = outSide.GetStartPoint();
                    testPntB = outSide.GetEndPoint();
                }

                if (lastPntA != testPntA)
                {
                    if (lastLineB.ClassifyPoint(testPntA) == PointSide.RIGHT_SIDE)
                    {
                        nextWay = new WayPoint(lastPntB, lastTriB);
                        return(nextWay);
                    }
                    else if (lastLineA.ClassifyPoint(testPntA) != PointSide.LEFT_SIDE)
                    {
                        lastPntA = testPntA;
                        lastTriA = currTri;
                        //重设直线
                        lastLineA = new Line2D(lastLineA.GetStartPoint(), lastPntA);
                    }
                }

                if (lastPntB != testPntB)
                {
                    if (lastLineA.ClassifyPoint(testPntB) == PointSide.LEFT_SIDE)
                    {
                        nextWay = new WayPoint(lastPntA, lastTriA);
                        return(nextWay);
                    }
                    else if (lastLineB.ClassifyPoint(testPntB) != PointSide.RIGHT_SIDE)
                    {
                        lastPntB = testPntB;
                        lastTriB = currTri;
                        //重设直线
                        lastLineB = new Line2D(lastLineB.GetStartPoint(), lastPntB);
                    }
                }
            }

            //到达终点
            nextWay = new WayPoint(endPos, triPathList[triPathList.Count - 1]);

            return(nextWay);
        }
Exemple #6
0
        /// <summary>
        /// 根据拐点计算法获得导航网格的下一个拐点
        /// </summary>
        /// <param name="way"></param>
        /// <param name="triPathList"></param>
        /// <param name="endPos"></param>
        /// <param name="offSet"></param>
        /// <returns></returns>
        private WayPoint GetFurthestWayPoint(WayPoint way, List<NavTriangle> triPathList, Vector2 endPos, int offSet)
        {
            WayPoint nextWay = null;
            Vector2 currPnt = way.GetPoint();
            NavTriangle currTri = way.GetTriangle();
            NavTriangle lastTriA = currTri;
            NavTriangle lastTriB = currTri;
            int startIndex = triPathList.IndexOf(currTri);//开始路点所在的网格索引
            Line2D outSide = currTri.GetSide(currTri.GetOutWallIndex());//路径线在网格中的穿出边?
            Vector2 lastPntA = outSide.GetStartPoint();
            Vector2 lastPntB = outSide.GetEndPoint();
            Line2D lastLineA = new Line2D(currPnt, lastPntA);
            Line2D lastLineB = new Line2D(currPnt, lastPntB);
            Vector2 testPntA, testPntB;

            for (int i = startIndex + 1; i < triPathList.Count; i++)
            {
                currTri = triPathList[i];
                outSide = currTri.GetSide(currTri.GetOutWallIndex());
                if (i == triPathList.Count - 1)
                {
                    testPntA = endPos;
                    testPntB = endPos;
                }
                else
                {
                    testPntA = outSide.GetStartPoint();
                    testPntB = outSide.GetEndPoint();
                }

                if (lastPntA != testPntA)
                {
                    if (lastLineB.ClassifyPoint(testPntA) == PointSide.RIGHT_SIDE)
                    {
                        nextWay = new WayPoint(lastPntB, lastTriB);
                        return nextWay;
                    }
                    else if (lastLineA.ClassifyPoint(testPntA) != PointSide.LEFT_SIDE)
                    {
                        lastPntA = testPntA;
                        lastTriA = currTri;
                        //重设直线
                        lastLineA = new Line2D(lastLineA.GetStartPoint(), lastPntA);
                    }
                }

                if (lastPntB != testPntB)
                {
                    if (lastLineA.ClassifyPoint(testPntB) == PointSide.LEFT_SIDE)
                    {
                        nextWay = new WayPoint(lastPntA, lastTriA);
                        return nextWay;
                    }
                    else if (lastLineB.ClassifyPoint(testPntB) != PointSide.RIGHT_SIDE)
                    {
                        lastPntB = testPntB;
                        lastTriB = currTri;
                        //重设直线
                        lastLineB = new Line2D(lastLineB.GetStartPoint(), lastPntB);
                    }
                }
            }

            //到达终点
            nextWay = new WayPoint(endPos, triPathList[triPathList.Count - 1]);

            return nextWay;
        }
Exemple #7
0
        /// <summary>
        /// 找到指定边的约束边DT
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        private bool FindDT(Line2D line, out Vector2 dtPoint)
        {
            dtPoint = new Vector2();
            if (line == null)
                return false;

            Vector2 ptA = line.GetStartPoint();
            Vector2 ptB = line.GetEndPoint();

            List<Vector2> visiblePnts = new List<Vector2>();
            foreach (Vector2 point in allPoints)
            {
                if (IsPointVisibleOfLine(line, point))
                    visiblePnts.Add(point);
            }

            if (visiblePnts.Count == 0)
                return false;

            bool bContinue = false;
            dtPoint = visiblePnts[0];

            do
            {
                bContinue = false;
                //Step1.构造三角形的外接圆,以及外接圆的包围盒
                Circle circle = NMath.CreateCircle(ptA, ptB, dtPoint);
                Rect boundBox = NMath.GetCircleBoundBox(circle);

                //Step2. 依次访问网格包围盒内的每个网格单元:
                //若某个网格单元中存在可见点 p, 并且 ∠p1pp2 > ∠p1p3p2,则令 p3=p,转Step1;
                //否则,转Step3.
                float angOld = (float)Math.Abs(NMath.LineRadian(ptA, dtPoint, ptB));
                foreach (Vector2 pnt in visiblePnts)
                {
                    if (pnt == ptA || pnt == ptB || pnt == dtPoint)
                        continue;
                    if (!boundBox.Contains(pnt))
                        continue;

                    float angNew = (float)Math.Abs(NMath.LineRadian(ptA, pnt, ptB));
                    if (angNew > angOld)
                    {
                        dtPoint = pnt;
                        bContinue = true;
                        break;
                    }
                }

                //false 转Step3
            } while (bContinue);

            //Step3. 若当前网格包围盒内所有网格单元都已被处理完,
            // 也即C(p1,p2,p3)内无可见点,则 p3 为的 p1p2 的 DT 点
            return true;
        }
Exemple #8
0
        //         void SplitBigTriangle(ref List<Triangle> triangles)
        //         {
        //             // 将面积过大的三角形拆分成三个小三角形
        //             for (int i = 0; i < triangles.Count; i++)
        //             {
        //                 if (triangles[i].Area() > NeedSplitSize)
        //                 {
        //                 }
        //             }
        //         }

        /// <summary>
        /// 判断点是否是线段的可见点,组成的三角形没有和其他边相交
        /// </summary>
        /// <param name="line"></param>
        /// <param name="point"></param>
        /// <returns></returns>
        private bool IsPointVisibleOfLine(Line2D line, Vector2 point)
        {
            if (line == null)
                return false;

            Vector2 sPnt = line.GetStartPoint();
            Vector2 ePnt = line.GetEndPoint();

            // 是否是线段端点
            if (point == sPnt || point == ePnt)
                return false;
            //点不在线段的右侧(多边形顶点顺序为顺时针)
            if (line.ClassifyPoint(point) != PointSide.RIGHT_SIDE)
                return false;

            if (!IsVisibleIn2Point(sPnt, point))
                return false;

            if (!IsVisibleIn2Point(ePnt, point))
                return false;

            return true;
        }
        /// <summary>
        /// 找到指定边的约束边DT
        /// </summary>
        /// <param name="line"></param>
        /// <returns></returns>
        private bool FindDT(Line2D line, out Vector2 dtPoint)
        {
            dtPoint = new Vector2();
            if (line == null)
            {
                return(false);
            }

            Vector2 ptA = line.GetStartPoint();
            Vector2 ptB = line.GetEndPoint();

            List <Vector2> visiblePnts = new List <Vector2>();

            foreach (Vector2 point in allPoints)
            {
                if (IsPointVisibleOfLine(line, point))
                {
                    visiblePnts.Add(point);
                }
            }

            if (visiblePnts.Count == 0)
            {
                return(false);
            }

            bool bContinue = false;

            dtPoint = visiblePnts[0];

            do
            {
                bContinue = false;
                //Step1.构造三角形的外接圆,以及外接圆的包围盒
                Circle circle   = NMath.CreateCircle(ptA, ptB, dtPoint);
                Rect   boundBox = NMath.GetCircleBoundBox(circle);

                //Step2. 依次访问网格包围盒内的每个网格单元:
                //若某个网格单元中存在可见点 p, 并且 ∠p1pp2 > ∠p1p3p2,则令 p3=p,转Step1;
                //否则,转Step3.
                float angOld = (float)Math.Abs(NMath.LineRadian(ptA, dtPoint, ptB));
                foreach (Vector2 pnt in visiblePnts)
                {
                    if (pnt == ptA || pnt == ptB || pnt == dtPoint)
                    {
                        continue;
                    }
                    if (!boundBox.Contains(pnt))
                    {
                        continue;
                    }

                    float angNew = (float)Math.Abs(NMath.LineRadian(ptA, pnt, ptB));
                    if (angNew > angOld)
                    {
                        dtPoint   = pnt;
                        bContinue = true;
                        break;
                    }
                }

                //false 转Step3
            } while (bContinue);

            //Step3. 若当前网格包围盒内所有网格单元都已被处理完,
            // 也即C(p1,p2,p3)内无可见点,则 p3 为的 p1p2 的 DT 点
            return(true);
        }
        /// <summary>
        /// 创建导航网格
        /// </summary>
        /// <param name="polyAll">所有阻挡区域</param>
        /// <param name="triAll">输出的导航网格</param>
        /// <returns></returns>
        public NavResCode CreateNavMesh(List <Polygon> polyAll, ref int id, int groupid, ref List <Triangle> triAll)
        {
            triAll.Clear();
            List <Line2D> allLines = new List <Line2D>();  //线段堆栈

            //Step1 保存顶点和边
            NavResCode initRes = InitData(polyAll);

            if (initRes != NavResCode.Success)
            {
                return(initRes);
            }

            int      lastNeighborId = -1;
            Triangle lastTri        = null;

            //Step2.遍历边界边作为起点
            {
                Line2D sEdge = startEdge;
                allLines.Add(sEdge);
                Line2D edge = null;

                do
                {
                    //Step3.选出计算出边的DT点,构成约束Delaunay三角形
                    edge = allLines[allLines.Count - 1];
                    allLines.Remove(edge);

                    Vector2 dtPoint;
                    bool    isFindDt = FindDT(edge, out dtPoint);
                    if (!isFindDt)
                    {
                        continue;
                    }
                    Line2D lAD = new Line2D(edge.GetStartPoint(), dtPoint);
                    Line2D lDB = new Line2D(dtPoint, edge.GetEndPoint());

                    //创建三角形
                    Triangle delaunayTri = new Triangle(edge.GetStartPoint(), edge.GetEndPoint(), dtPoint, id++, groupid);
                    // 保存邻居节点
                    //                     if (lastNeighborId != -1)
                    //                     {
                    //                         delaunayTri.SetNeighbor(lastNeighborId);
                    //                         if(lastTri != null)
                    //                             lastTri.SetNeighbor(delaunayTri.ID);
                    //                     }
                    //save result triangle
                    triAll.Add(delaunayTri);

                    // 保存上一次的id和三角形
                    lastNeighborId = delaunayTri.GetID();
                    lastTri        = delaunayTri;

                    int lineIndex;
                    //Step4.检测刚创建的的线段ad,db;如果如果它们不是约束边
                    //并且在线段堆栈中,则将其删除,如果不在其中,那么将其放入
                    if (!Line2D.CheckLineIn(allEdges, lAD, out lineIndex))
                    {
                        if (!Line2D.CheckLineIn(allLines, lAD, out lineIndex))
                        {
                            allLines.Add(lAD);
                        }
                        else
                        {
                            allLines.RemoveAt(lineIndex);
                        }
                    }

                    if (!Line2D.CheckLineIn(allEdges, lDB, out lineIndex))
                    {
                        if (!Line2D.CheckLineIn(allLines, lDB, out lineIndex))
                        {
                            allLines.Add(lDB);
                        }
                        else
                        {
                            allLines.RemoveAt(lineIndex);
                        }
                    }

                    //Step5.如果堆栈不为空,则转到第Step3.否则结束循环
                } while (allLines.Count > 0);
            }

            // 计算邻接边和每边中点距离
            for (int i = 0; i < triAll.Count; i++)
            {
                Triangle tri = triAll[i];
                //// 计算每个三角形每边中点距离
                //tri.calcWallDistance();

                // 计算邻居边
                for (int j = 0; j < triAll.Count; j++)
                {
                    Triangle triNext = triAll[j];
                    if (tri.GetID() == triNext.GetID())
                    {
                        continue;
                    }

                    int result = tri.isNeighbor(triNext);
                    if (result != -1)
                    {
                        tri.SetNeighbor(result, triNext.GetID());
                    }
                }
            }

            return(NavResCode.Success);
        }
Exemple #11
0
		/// <summary>
		/// Checks the cross.
		/// </summary>
		/// <returns><c>true</c>, if cross was checked, <c>false</c> otherwise.</returns>
		/// <param name="line">Line.</param>
		/// <param name="pos">Position.</param>
		/// <param name="radius">Radius.</param>
		public static bool CheckCross( Line2D line , Vector2 pos , float radius )
		{
			float fDis = line.GetLength();
			
			Vector2 d;
			d.x = (line.GetEndPoint().x - line.GetStartPoint().x) / fDis;
			d.y = (line.GetEndPoint().y - line.GetStartPoint().y) / fDis;
			
			Vector2 E;
			E.x = pos.x - line.GetStartPoint().x;
			E.y = pos.y - line.GetStartPoint().y;
			
			float a = E.x * d.x + E.y * d.y;
			float a2 = a * a;
			
			float e2 = E.x * E.x + E.y * E.y;
			
			float r2 = radius * radius;
			
			if ((r2 - e2 + a2) < 0)  
			{  
				return false;  
			}
			return true;
		}
Exemple #12
0
		/// <summary>
		/// Checks the cross.
		/// </summary>
		/// <returns><c>true</c>, if cross was checked, <c>false</c> otherwise.</returns>
		/// <param name="line">Line.</param>
		/// <param name="tri">Tri.</param>
		public static bool CheckCross( Line2D line , Triangle tri )
		{
			for(int i = 0 ; i < 3 ; i++ )
			{
				Line2D lineTri = tri.GetSide(i);
				if( CheckCross(line.GetStartPoint() , line.GetEndPoint() ,
				               lineTri.GetStartPoint() , lineTri.GetEndPoint())
				   )
				{
					return true;
				}
			}
			return false;
		}
Exemple #13
0
        /// <summary>
        /// 根据线段生成矩形
        /// </summary>
        /// <param name="linePath">线段</param>
        /// <returns>矩形</returns>
        public static Rect LineRect(Line2D linePath)
        {
            Rect lineRect = new Rect();

            if (linePath.GetStartPoint().x < linePath.GetEndPoint().x)
                lineRect.xMin = linePath.GetStartPoint().x;
            else
                lineRect.xMin = linePath.GetEndPoint().x;

            if (linePath.GetStartPoint().y < linePath.GetEndPoint().y)
                lineRect.yMin = linePath.GetStartPoint().y;
            else
                lineRect.yMin = linePath.GetEndPoint().y;

            lineRect.width = Math.Abs(linePath.GetEndPoint().x - linePath.GetStartPoint().x);
            lineRect.height = Math.Abs(linePath.GetEndPoint().y - linePath.GetStartPoint().y);

            return lineRect;
        }