private void TryAddLink() { // A link be between exactly two polygons. if (_intersectedEdges.Count != 2) { return; } // A polygon can't connect with itself if (_intersectedEdges[0].Polygon == _intersectedEdges[1].Polygon) { return; } // Can make a connection. PolygonLink polyLink = new PolygonLink( _intersectedEdges[0].Polygon, _intersectedEdges[0].Edge, _intersectedEdges[1].Polygon, _intersectedEdges[1].Edge); _navMesh.AddLink(polyLink); }
/// <summary> /// This function will look up the polygon index right away. /// This could potentially cause problems if the XML has the polygon defs later in the file. /// The values should really be cached and it should be done after. /// (or thrown in a closure but the C# syntax is a little too messy for that) /// </summary> /// <param name="xmlReader"></param> /// <param name="navMesh"></param> private static void LoadSingleLink(XmlTextReader xmlReader, NavMesh navMesh) { int startPolygonIndex = -1; int startEdgeStart = -1; int startEdgeEnd = -1; int endPolygonIndex = -1; int endEdgeStart = -1; int endEdgeEnd = -1; xmlReader.MoveToContent(); while (xmlReader.Read()) { if ("start" == xmlReader.Name) { startPolygonIndex = int.Parse(xmlReader.GetAttribute("polygon")); startEdgeStart = int.Parse(xmlReader.GetAttribute("edgestart")); startEdgeEnd = int.Parse(xmlReader.GetAttribute("edgeend")); } else if ("end" == xmlReader.Name) { endPolygonIndex = int.Parse(xmlReader.GetAttribute("polygon")); endEdgeStart = int.Parse(xmlReader.GetAttribute("edgestart")); endEdgeEnd = int.Parse(xmlReader.GetAttribute("edgeend")); } else if ("link" == xmlReader.Name) { PolygonLink polygonLink = new PolygonLink( navMesh.PolygonList[startPolygonIndex], new IndexedEdge(startEdgeStart, startEdgeEnd), navMesh.PolygonList[endPolygonIndex], new IndexedEdge(endEdgeStart, endEdgeEnd)); navMesh.AddLink(polygonLink); return; } } }
/// <summary> /// Defines links for this face. A prior call to <c>SetLine</c> is required. /// </summary> /// <param name="prev">The preceding face (after it has been processed via a call to /// <c>SetLine</c>, Must refer to the same polygon as this face.</param> /// <returns>The links (the number of array elements will equal the value that came /// back from the <c>SetLine</c> call)</returns> internal PolygonLink[] CreateLinks(PolygonFace prev) { Debug.Assert(m_Polygon!=null); Debug.Assert(m_Divider!=null); Debug.Assert(prev.Divider!=null); Debug.Assert(Object.ReferenceEquals(prev.Polygon, m_Polygon)); // Try to obtain a point feature at the beginning of this face. ISpatialIndex index = CadastralMapModel.Current.Index; PointFeature beginPoint = new FindPointQuery(index, m_Begin).Result; // If the polygon to the left of the this face? (if so, curve-related // things may need to be reversed below) bool isPolLeft = (m_Divider.Left == m_Polygon); // Default geometric info we need to define bool isCurveEnd = false; bool isRadial = false; double bearing = 0.0; double angle = 0.0; // Is the position at the beginning of this face the start // or end of a circular arc (points between 2 curves (on // compound curve) are NOT considered to be curve ends). Note // that the line could either be a CircularArc, or a topological // section based on a circular arc. ICircularArcGeometry prevArc = (prev.Divider.LineGeometry as ICircularArcGeometry); ICircularArcGeometry thisArc = (m_Divider.LineGeometry as ICircularArcGeometry); bool isPrevCurve = (prevArc!=null); bool isThisCurve = (thisArc!=null); isCurveEnd = (isPrevCurve!=isThisCurve); // If we are dealing with a point between two curves try to // set the curve parameters and, if successful, we will treat // the point as a radial point. if (isPrevCurve && isThisCurve) { isRadial = true; // Get the curve parameters... IPosition prevcen = prevArc.Circle.Center; double prevrad = prevArc.Circle.Radius; IPosition thiscen = thisArc.Circle.Center; double thisrad = thisArc.Circle.Radius; // We only need to know the sense for one of the arcs bool iscw = thisArc.IsClockwise; // If the 2 curves do not have the same centre and radius, // see if they are really close (to the nearest centimeter // on the ground). In that case, use the average values for // the 2 curves. If they really are different curves, don't // treat this as a radial curve point -- treat it as a // curve end instead. IPosition centre = null; // The centre to actually use if (!(prevcen==thiscen && Math.Abs(prevrad-thisrad)<Constants.TINY)) { double xc1 = prevcen.X; double yc1 = prevcen.Y; double xc2 = thiscen.X; double yc2 = thiscen.Y; double dxc = xc2-xc1; double dyc = yc2-yc1; if (Math.Abs(dxc)<0.01 && Math.Abs(dyc)<0.01 && Math.Abs(prevrad-thisrad)<0.01) { // Close enough centre = new Position(xc1+dxc*0.5, yc1+dyc*0.5); } else { isRadial = false; isCurveEnd = true; } } else centre = prevcen; // If the centre and radius were the same (or close enough), // define the radial bearing from the centre of the circle. // If the polygon is actually on the other side, reverse the // bearing so that it's directed INTO the polygon. if (isRadial) { Debug.Assert(centre!=null); bearing = Geom.BearingInRadians(centre, m_Begin); angle = 0.0; if (iscw != isPolLeft) bearing += Constants.PI; } } // If we're not dealing with a radial curve (or we have curves that // don't appear to be radial) if (!isRadial) { // Get the clockwise angle from the last position of the // preceding face to the first position after the start // of this face. Since info is held in a clockwise cycle // around the polygon, this will always give us the exterior // angle. Turn reference = new Turn(m_Begin, prev.TailReference); angle = reference.GetAngleInRadians(this.HeadReference); // Define the bearing to use for projecting the point. It's // in the middle of the angle, but projected into the polygon. bearing = reference.BearingInRadians + angle*0.5 + Constants.PI; } // Initialize the link at the start of the face List<PolygonLink> links = new List<PolygonLink>(); PolygonLink link = new PolygonLink(beginPoint, isCurveEnd, isRadial, bearing, angle); links.Add(link); // Initialize links for any extra points if (m_ExtraPoints!=null) { // Intermediate points can never be curve ends isCurveEnd = false; // If the face is a curve, they're radial points isRadial = isThisCurve; // Note any curve info double radius; IPosition centre = null; bool iscw = false; if (isRadial) { Debug.Assert(m_Divider.Line.LineGeometry is ICircularArcGeometry); ICircularArcGeometry arc = (m_Divider.Line.LineGeometry as ICircularArcGeometry); centre = arc.Circle.Center; radius = arc.Circle.Radius; iscw = arc.IsClockwise; angle = 0.0; } for (uint i=0; i<m_ExtraPoints.Length; i++) { //IPointGeometry loc = m_ExtraPoints[i].Geometry; PointFeature loc = m_ExtraPoints[i]; // Figure out the orientation bearing for the point if (isRadial) { Debug.Assert(centre!=null); bearing = Geom.BearingInRadians(centre, loc); if (iscw != isPolLeft) bearing += Constants.PI; } else { // Get the exterior clockwise angle IPointGeometry back; IPointGeometry fore; if (i==0) back = m_Begin; else back = m_ExtraPoints[i-1].Geometry; if (i==(m_ExtraPoints.Length-1)) fore = m_End; else fore = m_ExtraPoints[i+1].Geometry; Turn reference = new Turn(loc, back); angle = reference.GetAngleInRadians(fore); // Define the bearing to use for projecting the point. It's // in the middle of the angle, but projected into the polygon. bearing = reference.BearingInRadians + angle*0.5 + Constants.PI; } link = new PolygonLink(m_ExtraPoints[i], isCurveEnd, isRadial, bearing, angle); links.Add(link); } } return links.ToArray(); }