///////////////////////////////////////////////////////////////////////////////////////////////////////// #region LOS视线检测相关 //--------------------------------------------------------------------------------------------------------- //松弛疗法,微调pos,直到该点真正地处于某个多边形中为止 //【遗留问题】没有考虑松弛过程中发生进入不可进入区域的情况 Belong_Status RelaxPostion(ref Vector2 pos, out Polygon poly) { Vector2 p = pos; Object obj = null; Belong_Status ret = GetPointLocation(p, out obj); //第一次 if (ret == Belong_Status.Invalid) { poly = null; return(ret); //不用松弛了,直接返回 } Random rand = new Random((int)DateTime.Now.Ticks); bool ok = (ret == Belong_Status.Polygon); while (!ok) { p.X = pos.X + (float)(rand.NextDouble() - 0.5d) / 10f; p.Y = pos.Y + (float)(rand.NextDouble() - 0.5d) / 10f; ret = GetPointLocation(p, out obj); ok = (ret == Belong_Status.Polygon); } pos = p; poly = (Polygon)obj; return(ret); }
//点与单个多边形的关系检测 //- 如果点在多边形内部,retobj返回该多边形 //- 如果点在多边形的边上,retobj返回该边 //- 如果点在多边形的顶点上,retobj返回该点 //- 如果点在多边形之外,retobj返回null public Belong_Status PointPolygonRelationshipTest(Vector2 pos, Polygon poly, out Object retobj) { //默认情况:点处于多边形以内 retobj = poly; Belong_Status result = Belong_Status.Polygon; foreach (Edge e in poly.edges) { Vector2 between = new Vector2(e.to.x - e.from.x, e.to.y - e.from.y); Vector2 from = new Vector2(pos.X - e.from.x, pos.Y - e.from.y); float test = Vector2.Ccw(between, from); if (FloatEqual(test, 0)) //在边上或在顶点上 { Vector2 to = new Vector2(pos.X - e.to.x, pos.Y - e.to.y); if (FloatEqual(from.LengthSq(), 0)) //在顶点e.from上 { retobj = e.from; result = Belong_Status.Vertex; } else if (FloatEqual(to.LengthSq(), 0)) //在顶点e.to上 { retobj = e.to; result = Belong_Status.Vertex; } else //在边上 { retobj = e; result = Belong_Status.Edge; } break; } if (test < 0) //点处于polygon之外 { retobj = null; result = Belong_Status.OutOfPolygon; break; } } return(result); }
///////////////////////////////////////////////////////////////////////////////////////////////////////// #region 快速检测点处于哪个多边形中 //快速检测点的位置 //- retobj: 要么返回一个多边形,要么返回一条边,要么返回一个点 //- 返回值: true,成功检测出了点的位置;false,点处于不合法位置 public Belong_Status GetPointLocation(Vector2 p, out Object retobj) { retobj = null; Belong_Status ret = Belong_Status.Invalid; for (int i = 0; i < polys.Length; i++) { Polygon poly = polys[i]; if ((p.X >= poly.min.X && p.X <= poly.max.X) && (p.Y >= poly.min.Y && p.Y <= poly.max.Y)) { Object obj; Belong_Status result = PointPolygonRelationshipTest(p, poly, out obj); if (result == Belong_Status.Polygon) { ret = result; retobj = obj; Debug.WriteLine(string.Format("(点位置检测) P:{0}", poly.idx)); break; } else if (result == Belong_Status.Edge) { ret = result; retobj = obj; Edge e = (Edge)obj; Debug.WriteLine(string.Format("(点位置检测) P:{0} E:({1}-{2})", poly.idx, e.belong_poly, e.neighbor_poly)); break; } else if (result == Belong_Status.Vertex) { ret = result; retobj = obj; FPoint pos = (FPoint)obj; Debug.WriteLine(string.Format("(点位置检测) P:{0} V:({1},{2})", poly.idx, pos.x, pos.y)); break; } } } return(ret); }