/// <summary> /// 判断两条线段是否相交 /// </summary> /// <param name="a"></param> /// <param name="b"></param> /// <returns></returns> static public bool IsCross ( Segment a, Segment b ) { return Math.Max( a.startPoint.X, a.endPoint.X ) >= Math.Min( b.startPoint.X, b.endPoint.X ) && Math.Max( b.startPoint.X, b.endPoint.X ) >= Math.Min( a.startPoint.X, a.endPoint.X ) && Math.Max( a.startPoint.Y, a.endPoint.Y ) >= Math.Min( b.startPoint.Y, b.endPoint.Y ) && Math.Max( b.startPoint.Y, b.endPoint.Y ) >= Math.Min( a.startPoint.Y, a.endPoint.Y ) && MathTools.Vector2Cross( a.endPoint - b.startPoint, a.startPoint - a.endPoint ) * MathTools.Vector2Cross( b.endPoint - a.endPoint, a.startPoint - b.endPoint ) > 0 && MathTools.Vector2Cross( b.endPoint - a.startPoint, b.startPoint - b.endPoint ) * MathTools.Vector2Cross( a.endPoint - b.endPoint, b.startPoint - a.endPoint ) > 0; }
private void AddCurPosToNaviMap ( GraphPoint<NaviPoint>[] map, GraphPoint<NaviPoint> curNaviP, int prePointSum, List<Segment> guardLines, List<Segment> borderLines ) { map[prePointSum] = curNaviP; for (int i = 0; i < prePointSum; i++) { Segment seg = new Segment( curNaviP.value.Pos, map[i].value.Pos ); bool cross = false; foreach (Segment guardLine in guardLines) { if (Segment.IsCross( guardLine, seg )) { cross = true; break; } } if (!cross) { foreach (Segment borderLine in borderLines) { if (Segment.IsCross( borderLine, seg )) { cross = true; break; } } } if (!cross) { float weight = Vector2.Distance( curNaviP.value.Pos, map[i].value.Pos ); GraphPoint<NaviPoint>.Link( map[i], curNaviP, weight ); } } }
private void AddAimPosToNaviMap ( GraphPoint<NaviPoint>[] map, GraphPoint<NaviPoint> aimNaviP, GraphPoint<NaviPoint> curNaviP, int prePointSum, List<Segment> guardLines, List<Segment> borderLines ) { map[prePointSum + 1] = aimNaviP; for (int i = 0; i < prePointSum; i++) { Segment seg = new Segment( aimNaviP.value.Pos, map[i].value.Pos ); bool cross = false; foreach (Segment guardLine in guardLines) { if (Segment.IsCross( guardLine, seg )) { cross = true; break; } } if (!cross) { foreach (Segment borderLine in borderLines) { if (Segment.IsCross( borderLine, seg )) { cross = true; break; } } } if (!cross) { float weight = Vector2.Distance( aimNaviP.value.Pos, map[i].value.Pos ); GraphPoint<NaviPoint>.Link( map[i], aimNaviP, weight ); } } Segment curToAim = new Segment( curNaviP.value.Pos, aimNaviP.value.Pos ); bool link = true; foreach (Segment guardLine in guardLines) { if (Segment.IsCross( guardLine, curToAim )) { if (MathTools.Vector2Cross( guardLine.endPoint - guardLine.startPoint, curNaviP.value.Pos - guardLine.endPoint ) < 0) { link = false; break; } } } if (link) { foreach (Segment borderLine in borderLines) { if (Segment.IsCross( borderLine, curToAim )) { link = false; break; } } } if (link) { float weight = Vector2.Distance( curNaviP.value.Pos, aimNaviP.value.Pos ); GraphPoint<NaviPoint>.Link( curNaviP, aimNaviP, weight ); } }
public void BuildMap ( EyeableBorderObjInfo[] objInfos, Rectanglef mapBorder, float spaceForTank ) { #region 对每一个BorderObj生成逻辑坐标上的凸包点集,并向外扩展 borderLines = new List<Segment>(); convexs = new List<GuardConvex>(); foreach (EyeableBorderObjInfo obj in objInfos) { if (obj.ConvexHall == null || obj.IsDisappeared || obj.ConvexHall.Points == null) continue; Matrix matrix = obj.EyeableInfo.CurTransMatrix; GraphPoint<NaviPoint>[] convexHall; List<VisiBordPoint> bordPoints = obj.ConvexHall.Points; if (bordPoints.Count > 2) { List<GraphPoint<NaviPoint>> list = new List<GraphPoint<NaviPoint>>(); for (int i = 0; i < bordPoints.Count; i++) { Vector2 lastPos = Vector2.Transform( ConvertHelper.PointToVector2( bordPoints[i - 1 < 0 ? bordPoints.Count - 1 : i - 1].p ), matrix ); Vector2 curPos = Vector2.Transform( ConvertHelper.PointToVector2( bordPoints[i].p ), matrix ); Vector2 nextPos = Vector2.Transform( ConvertHelper.PointToVector2( bordPoints[(i + 1) % bordPoints.Count].p ), matrix ); Vector2 v1 = curPos - lastPos; Vector2 v2 = curPos - nextPos; float ang = MathTools.AngBetweenVectors( v1, v2 ); if (ang >= MathHelper.PiOver2) { float halfDes = (float)(spaceForTank / Math.Sin( ang )); Vector2 delta = halfDes * Vector2.Normalize( v1 ) + halfDes * Vector2.Normalize( v2 ); list.Add( new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[i].index, curPos + delta ), new List<GraphPath<NaviPoint>>() ) ); } else { v1.Normalize(); v2.Normalize(); Vector2 cenV = Vector2.Normalize( v1 + v2 ); Vector2 vertiV = new Vector2( cenV.Y, -cenV.X ); float ang2 = MathHelper.PiOver4 - 0.25f * ang; float vertiL = (float)(spaceForTank * Math.Tan( ang2 )); list.Add( new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[i].index, curPos + spaceForTank * cenV + vertiL * vertiV ), new List<GraphPath<NaviPoint>>() ) ); list.Add( new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[i].index, curPos + spaceForTank * cenV - vertiL * vertiV ), new List<GraphPath<NaviPoint>>() ) ); } // 添加borderLine borderLines.Add( new Segment( curPos, nextPos ) ); } convexHall = list.ToArray(); convexs.Add( new GuardConvex( convexHall ) ); } else if (bordPoints.Count == 2) { convexHall = new GraphPoint<NaviPoint>[4]; Vector2 startPos = Vector2.Transform( ConvertHelper.PointToVector2( bordPoints[0].p ), matrix ); Vector2 endPos = Vector2.Transform( ConvertHelper.PointToVector2( bordPoints[1].p ), matrix ); Vector2 dir = endPos - startPos; dir.Normalize(); Vector2 normal = new Vector2( dir.Y, -dir.X ); convexHall[0] = new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[0].index, startPos - dir * spaceForTank ), new List<GraphPath<NaviPoint>>() ); convexHall[1] = new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[0].index, startPos + spaceForTank * normal ), new List<GraphPath<NaviPoint>>() ); convexHall[2] = new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[1].index, endPos + spaceForTank * normal ), new List<GraphPath<NaviPoint>>() ); convexHall[3] = new GraphPoint<NaviPoint>( new NaviPoint( obj, bordPoints[1].index, endPos + dir * spaceForTank ), new List<GraphPath<NaviPoint>>() ); //if (float.IsNaN( convexHall[0].value.Pos.X ) || float.IsNaN( convexHall[1].value.Pos.X )) //{ //} // 添加borderLine borderLines.Add( new Segment( startPos, endPos ) ); convexs.Add( new GuardConvex( convexHall ) ); } } #endregion #region 得到警戒线 guardLines = new List<Segment>(); foreach (GuardConvex convex in convexs) { for (int i = 0; i < convex.points.Length; i++) { guardLines.Add( new Segment( convex[i].value.Pos, convex[(i + 1) % convex.Length].value.Pos ) ); //if (float.IsNaN( convex[i].value.Pos.X )) //{ //} } } mapBorder = new Rectanglef( mapBorder.X + spaceForTank, mapBorder.Y + spaceForTank, mapBorder.Width - 2 * spaceForTank, mapBorder.Height - 2 * spaceForTank ); guardLines.Add( new Segment( mapBorder.UpLeft, mapBorder.UpRight ) ); guardLines.Add( new Segment( mapBorder.UpRight, mapBorder.DownRight ) ); guardLines.Add( new Segment( mapBorder.DownRight, mapBorder.DownLeft ) ); guardLines.Add( new Segment( mapBorder.DownLeft, mapBorder.UpLeft ) ); #endregion #region 检查凸包内部连线是否和警戒线相交,如不相交则连接该连线并计算权值 foreach (GuardConvex convex in convexs) { for (int i = 0; i < convex.Length; i++) { // 检查连线是否超出边界 if (!mapBorder.Contains( convex[i].value.Pos )) continue; Segment link = new Segment( convex[i].value.Pos, convex[(i + 1) % convex.Length].value.Pos ); bool isCross = false; foreach (Segment guardLine in guardLines) { if (link.Equals( guardLine )) continue; if (Segment.IsCross( link, guardLine )) { isCross = true; break; } } if (!isCross) { float weight = Vector2.Distance( convex[i].value.Pos, convex[(i + 1) % convex.Length].value.Pos ); //if (float.IsNaN( weight )) //{ //} GraphPoint<NaviPoint>.Link( convex[i], convex[(i + 1) % convex.Length], weight ); } } } #endregion #region 检查凸包之间连线是否与警戒线以及边界线相交,如不相交则连接并计算权值 for (int i = 0; i < convexs.Count - 1; i++) { for (int j = i + 1; j < convexs.Count; j++) { foreach (GraphPoint<NaviPoint> p1 in convexs[i].points) { // 检查连线是否超出边界 if (!mapBorder.Contains( p1.value.Pos )) continue; foreach (GraphPoint<NaviPoint> p2 in convexs[j].points) { Segment link = new Segment( p1.value.Pos, p2.value.Pos ); bool isCross = false; foreach (Segment guardLine in guardLines) { if (Segment.IsCross( link, guardLine )) { isCross = true; break; } } if (!isCross) { foreach (Segment borderLine in borderLines) { if (Segment.IsCross( link, borderLine )) { isCross = true; break; } } } if (!isCross) { float weight = Vector2.Distance( p1.value.Pos, p2.value.Pos ); //if (float.IsNaN( weight )) //{ //} GraphPoint<NaviPoint>.Link( p1, p2, weight ); } } } } } #endregion #region 整理导航图 List<GraphPoint<NaviPoint>> points = new List<GraphPoint<NaviPoint>>(); foreach (GuardConvex convex in convexs) { foreach (GraphPoint<NaviPoint> p in convex.points) { points.Add( p ); } } naviGraph = points.ToArray(); #endregion }