/// <summary> /// /// </summary> /// <param name="outstream"></param> public virtual void Write(StreamWriter outstream) { for (IEnumerator it = GetEnumerator(); it.MoveNext();) { EdgeEnd e = (EdgeEnd)it.Current; e.Write(outstream); } }
/// <summary> /// /// </summary> private void ComputeEdgeEndLabels() { // Compute edge label for each EdgeEnd for (IEnumerator it = GetEnumerator(); it.MoveNext();) { EdgeEnd ee = (EdgeEnd)it.Current; ee.ComputeLabel(); } }
/// <summary> /// Insert an EdgeEnd into the map, and clear the edgeList cache, /// since the list of edges has now changed. /// </summary> /// <param name="e"></param> /// <param name="obj"></param> protected void InsertEdgeEnd(EdgeEnd e, object obj) { // Diego Guidi says: i have inserted this line because if i try to add an object already present // in the list, a System.ArgumentException was thrown. if (_edgeMap.Contains(e)) { return; } _edgeMap.Add(e, obj); _edgeList = null; // edge list has changed - clear the cache }
/// <summary> /// Insert a EdgeEnd in order in the list. /// If there is an existing EdgeStubBundle which is parallel, the EdgeEnd is /// added to the bundle. Otherwise, a new EdgeEndBundle is created /// to contain the EdgeEnd. /// </summary> /// <param name="e"></param> public override void Insert(EdgeEnd e) { EdgeEndBundle eb = (EdgeEndBundle)EdgeMap[e]; if (eb == null) { eb = new EdgeEndBundle(e); InsertEdgeEnd(e, eb); } else eb.Insert(e); }
/// <summary> /// /// </summary> /// <param name="ee"></param> /// <returns></returns> public virtual EdgeEnd GetNextCw(EdgeEnd ee) { InitializeEdges(); int i = _edgeList.IndexOf(ee); int iNextCw = i - 1; if (i == 0) { iNextCw = _edgeList.Count - 1; } return((EdgeEnd)_edgeList[iNextCw]); }
/// <summary> /// Returns the EdgeEnd which has edge e as its base edge /// (MD 18 Feb 2002 - this should return a pair of edges). /// </summary> /// <param name="e"></param> /// <returns> The edge, if found <c>null</c> if the edge was not found.</returns> public virtual EdgeEnd FindEdgeEnd(Edge e) { for (IEnumerator i = EdgeEnds.GetEnumerator(); i.MoveNext();) { EdgeEnd ee = (EdgeEnd)i.Current; if (ee.Edge == e) { return(ee); } } return(null); }
/// <summary> /// /// </summary> /// <param name="eSearch"></param> /// <returns></returns> public virtual int FindIndex(EdgeEnd eSearch) { GetEnumerator(); // force edgelist to be computed for (int i = 0; i < _edgeList.Count; i++) { EdgeEnd e = (EdgeEnd)_edgeList[i]; if (e == eSearch) { return(i); } } return(-1); }
/// <summary> /// Implements the total order relation: /// a has a greater angle with the positive x-axis than b. /// Using the obvious algorithm of simply computing the angle is not robust, /// since the angle calculation is obviously susceptible to roundoff. /// A robust algorithm is: /// - first compare the quadrant. If the quadrants /// are different, it it trivial to determine which vector is "greater". /// - if the vectors lie in the same quadrant, the computeOrientation function /// can be used to decide the relative orientation of the vectors. /// </summary> /// <param name="e"></param> public virtual int CompareDirection(EdgeEnd e) { if (_dx == e._dx && _dy == e._dy) { return(0); } // if the rays are in different quadrants, determining the ordering is trivial if (_quadrant > e._quadrant) { return(1); } if (_quadrant < e._quadrant) { return(-1); } // vectors are in the same quadrant - check relative orientation of direction vectors // this is > e if it is CCW of e return(CgAlgorithms.ComputeOrientation(e._p0, e._p1, _p1)); }
/// <summary> /// /// </summary> /// <param name="geomIndex"></param> /// <returns></returns> private bool CheckAreaLabelsConsistent(int geomIndex) { // Since edges are stored in CCW order around the node, // As we move around the ring we move from the right to the left side of the edge IList edges = Edges; // if no edges, trivially consistent if (edges.Count <= 0) { return(true); } // initialize startLoc to location of last Curve side (if any) int lastEdgeIndex = edges.Count - 1; Label startLabel = ((EdgeEnd)edges[lastEdgeIndex]).Label; LocationType startLoc = startLabel.GetLocation(geomIndex, PositionType.Left); Assert.IsTrue(startLoc != LocationType.Null, "Found unlabelled area edge"); LocationType currLoc = startLoc; for (IEnumerator it = GetEnumerator(); it.MoveNext();) { EdgeEnd e = (EdgeEnd)it.Current; Label label = e.Label; // we assume that we are only checking a area Assert.IsTrue(label.IsArea(geomIndex), "Found non-area edge"); LocationType leftLoc = label.GetLocation(geomIndex, PositionType.Left); LocationType rightLoc = label.GetLocation(geomIndex, PositionType.Right); // check that edge is really a boundary between inside and outside! if (leftLoc == rightLoc) { return(false); } // check side location conflict if (rightLoc != currLoc) { return(false); } currLoc = leftLoc; } return(true); }
/// <summary> /// Compute the labelling for all dirEdges in this star, as well /// as the overall labelling. /// </summary> /// <param name="geom"></param> public override void ComputeLabelling(GeometryGraph[] geom) { base.ComputeLabelling(geom); // determine the overall labelling for this DirectedEdgeStar // (i.e. for the node it is based at) _label = new Label(LocationType.Null); IEnumerator it = GetEnumerator(); while (it.MoveNext()) { EdgeEnd ee = (EdgeEnd)it.Current; Edge e = ee.Edge; Label eLabel = e.Label; for (int i = 0; i < 2; i++) { LocationType eLoc = eLabel.GetLocation(i); if (eLoc == LocationType.Interior || eLoc == LocationType.Boundary) { _label.SetLocation(i, LocationType.Interior); } } } }
/// <summary> /// /// </summary> /// <param name="obj"></param> /// <returns></returns> public virtual int CompareTo(object obj) { EdgeEnd e = (EdgeEnd)obj; return(CompareDirection(e)); }
/// <summary> /// /// </summary> /// <param name="geom"></param> public virtual void ComputeLabelling(GeometryGraph[] geom) { ComputeEdgeEndLabels(); // Propagate side labels around the edges in the star // for each parent Geometry PropagateSideLabels(0); PropagateSideLabels(1); /* * If there are edges that still have null labels for a point * this must be because there are no area edges for that point incident on this node. * In this case, to label the edge for that point we must test whether the * edge is in the interior of the point. * To do this it suffices to determine whether the node for the edge is in the interior of an area. * If so, the edge has location Interior for the point. * In all other cases (e.g. the node is on a line, on a point, or not on the point at all) the edge * has the location Exterior for the point. * * Notice that the edge cannot be on the Boundary of the point, since then * there would have been a parallel edge from the Geometry at this node also labelled Boundary * and this edge would have been labelled in the previous step. * * This code causes a problem when dimensional collapses are present, since it may try and * determine the location of a node where a dimensional collapse has occurred. * The point should be considered to be on the Exterior * of the polygon, but locate() will return Interior, since it is passed * the original Geometry, not the collapsed version. * * If there are incident edges which are Line edges labelled Boundary, * then they must be edges resulting from dimensional collapses. * In this case the other edges can be labelled Exterior for this Geometry. * * MD 8/11/01 - NOT True! The collapsed edges may in fact be in the interior of the Geometry, * which means the other edges should be labelled Interior for this Geometry. * Not sure how solve this... Possibly labelling needs to be split into several phases: * area label propagation, symLabel merging, then finally null label resolution. */ bool[] hasDimensionalCollapseEdge = { false, false }; for (IEnumerator it = GetEnumerator(); it.MoveNext();) { EdgeEnd e = (EdgeEnd)it.Current; Label label = e.Label; for (int geomi = 0; geomi < 2; geomi++) { if (label.IsLine(geomi) && label.GetLocation(geomi) == LocationType.Boundary) { hasDimensionalCollapseEdge[geomi] = true; } } } for (IEnumerator it = GetEnumerator(); it.MoveNext();) { EdgeEnd e = (EdgeEnd)it.Current; Label label = e.Label; for (int geomi = 0; geomi < 2; geomi++) { if (label.IsAnyNull(geomi)) { LocationType loc; if (hasDimensionalCollapseEdge[geomi]) { loc = LocationType.Exterior; } else { Coordinate p = e.Coordinate; loc = GetLocation(geomi, p, geom); } label.SetAllLocationsIfNull(geomi, loc); } } } }
/// <summary> /// /// </summary> /// <param name="ee"></param> /// <returns></returns> public virtual EdgeEnd GetNextCw(EdgeEnd ee) { InitializeEdges(); int i = _edgeList.IndexOf(ee); int iNextCw = i - 1; if (i == 0) iNextCw = _edgeList.Count - 1; return (EdgeEnd)_edgeList[iNextCw]; }
/// <summary> /// /// </summary> /// <param name="eSearch"></param> /// <returns></returns> public virtual int FindIndex(EdgeEnd eSearch) { GetEnumerator(); // force edgelist to be computed for (int i = 0; i < _edgeList.Count; i++) { EdgeEnd e = (EdgeEnd)_edgeList[i]; if (e == eSearch) return i; } return -1; }
/// <summary> /// Insert a EdgeEnd into this EdgeEndStar. /// </summary> /// <param name="e"></param> public abstract void Insert(EdgeEnd e);
/// <summary> /// /// </summary> /// <param name="e"></param> public EdgeEndBundle(EdgeEnd e) : base(e.Edge, e.Coordinate, e.DirectedCoordinate, new Label(e.Label)) { Insert(e); }
/// <summary> /// Add the edge to the list of edges at this node. /// </summary> /// <param name="e"></param> public virtual void Add(EdgeEnd e) { // Assert: start pt of e is equal to node point _edges.Insert(e); e.Node = this; }
/// <summary> /// Insert a directed edge in the list. /// </summary> /// <param name="ee"></param> public override void Insert(EdgeEnd ee) { DirectedEdge de = (DirectedEdge)ee; InsertEdgeEnd(de, de); }
/// <summary> /// Adds a new EdgeEnd to the planar graph /// </summary> /// <param name="e">The EdgeEnd to add</param> public virtual void Add(EdgeEnd e) { _nodes.Add(e); _edgeEndList.Add(e); }
/// <summary> /// /// </summary> /// <param name="de"></param> /// <param name="i"></param> /// <returns></returns> private static PositionType GetRightmostSideOfSegment(EdgeEnd de, int i) { Edge e = de.Edge; IList<Coordinate> coord = e.Coordinates; if (i < 0 || i + 1 >= coord.Count) return PositionType.Parallel; if (coord[i].Y == coord[i + 1].Y) return PositionType.Parallel; PositionType pos = PositionType.Left; if (coord[i].Y < coord[i + 1].Y) pos = PositionType.Right; return pos; }
/// <summary> /// /// </summary> /// <param name="e"></param> public void Insert(EdgeEnd e) { // Assert: start point is the same // Assert: direction is the same _edgeEnds.Add(e); }
/// <summary> /// Create a StubEdge for the edge after the intersection eiCurr. /// The next intersection is provided /// in case it is the endpoint for the stub edge. /// Otherwise, the next point from the parent edge will be the endpoint. /// eiCurr will always be an EdgeIntersection, but eiNext may be null. /// </summary> /// <param name="edge"></param> /// <param name="l"></param> /// <param name="eiCurr"></param> /// <param name="eiNext"></param> public virtual void CreateEdgeEndForNext(Edge edge, IList l, EdgeIntersection eiCurr, EdgeIntersection eiNext) { int iNext = eiCurr.SegmentIndex + 1; // if there is no next edge there is nothing to do if (iNext >= edge.NumPoints && eiNext == null) return; Coordinate pNext = edge.GetCoordinate(iNext); // if the next intersection is in the same segment as the current, use it as the endpoint if (eiNext != null && eiNext.SegmentIndex == eiCurr.SegmentIndex) pNext = eiNext.Coordinate; EdgeEnd e = new EdgeEnd(edge, eiCurr.Coordinate, pNext, new Label(edge.Label)); l.Add(e); }
/// <summary> /// Adds a node for the start point of this EdgeEnd /// (if one does not already exist in this map). /// Adds the EdgeEnd to the (possibly new) node. /// </summary> /// <param name="e"></param> public virtual void Add(EdgeEnd e) { Coordinate p = e.Coordinate; Node n = AddNode(p); n.Add(e); }
/// <summary> /// Create a EdgeStub for the edge before the intersection eiCurr. /// The previous intersection is provided /// in case it is the endpoint for the stub edge. /// Otherwise, the previous point from the parent edge will be the endpoint. /// eiCurr will always be an EdgeIntersection, but eiPrev may be null. /// </summary> /// <param name="edge"></param> /// <param name="l"></param> /// <param name="eiCurr"></param> /// <param name="eiPrev"></param> public virtual void CreateEdgeEndForPrev(Edge edge, IList l, EdgeIntersection eiCurr, EdgeIntersection eiPrev) { int iPrev = eiCurr.SegmentIndex; if (eiCurr.Distance == 0.0) { // if at the start of the edge there is no previous edge if (iPrev == 0) return; iPrev--; } Coordinate pPrev = edge.GetCoordinate(iPrev); // if prev intersection is past the previous vertex, use it instead if (eiPrev != null && eiPrev.SegmentIndex >= iPrev) pPrev = eiPrev.Coordinate; Label label = new Label(edge.Label); // since edgeStub is oriented opposite to it's parent edge, have to flip sides for edge label label.Flip(); EdgeEnd e = new EdgeEnd(edge, eiCurr.Coordinate, pPrev, label); l.Add(e); }
/// <summary> /// Insert an EdgeEnd into the map, and clear the edgeList cache, /// since the list of edges has now changed. /// </summary> /// <param name="e"></param> /// <param name="obj"></param> protected void InsertEdgeEnd(EdgeEnd e, object obj) { // Diego Guidi says: i have inserted this line because if i try to add an object already present // in the list, a System.ArgumentException was thrown. if (_edgeMap.Contains(e)) return; _edgeMap.Add(e, obj); _edgeList = null; // edge list has changed - clear the cache }
/// <summary> /// Implements the total order relation: /// a has a greater angle with the positive x-axis than b. /// Using the obvious algorithm of simply computing the angle is not robust, /// since the angle calculation is obviously susceptible to roundoff. /// A robust algorithm is: /// - first compare the quadrant. If the quadrants /// are different, it it trivial to determine which vector is "greater". /// - if the vectors lie in the same quadrant, the computeOrientation function /// can be used to decide the relative orientation of the vectors. /// </summary> /// <param name="e"></param> public virtual int CompareDirection(EdgeEnd e) { if (_dx == e._dx && _dy == e._dy) return 0; // if the rays are in different quadrants, determining the ordering is trivial if (_quadrant > e._quadrant) return 1; if (_quadrant < e._quadrant) return -1; // vectors are in the same quadrant - check relative orientation of direction vectors // this is > e if it is CCW of e return CgAlgorithms.ComputeOrientation(e._p0, e._p1, _p1); }
/// <summary> /// /// </summary> /// <param name="geomIndex"></param> public virtual void PropagateSideLabels(int geomIndex) { // Since edges are stored in CCW order around the node, // As we move around the ring we move from the right to the left side of the edge LocationType startLoc = LocationType.Null; // initialize loc to location of last Curve side (if any) for (IEnumerator it = GetEnumerator(); it.MoveNext();) { EdgeEnd e = (EdgeEnd)it.Current; Label label = e.Label; if (label.IsArea(geomIndex) && label.GetLocation(geomIndex, PositionType.Left) != LocationType.Null) { startLoc = label.GetLocation(geomIndex, PositionType.Left); } } // no labelled sides found, so no labels to propagate if (startLoc == LocationType.Null) { return; } LocationType currLoc = startLoc; for (IEnumerator it = GetEnumerator(); it.MoveNext();) { EdgeEnd e = (EdgeEnd)it.Current; Label label = e.Label; // set null On values to be in current location if (label.GetLocation(geomIndex, PositionType.On) == LocationType.Null) { label.SetLocation(geomIndex, PositionType.On, currLoc); } // set side labels (if any) // if (label.IsArea()) //ORIGINAL if (label.IsArea(geomIndex)) { LocationType leftLoc = label.GetLocation(geomIndex, PositionType.Left); LocationType rightLoc = label.GetLocation(geomIndex, PositionType.Right); // if there is a right location, that is the next location to propagate if (rightLoc != LocationType.Null) { if (rightLoc != currLoc) { throw new TopologyException(TopologyText.SideLocationConflict, e.Coordinate); } if (leftLoc == LocationType.Null) { throw new TopologyException(TopologyText.SingleNullSide, e.Coordinate); } currLoc = leftLoc; } else { /* RHS is null - LHS must be null too. * This must be an edge from the other point, which has no location * labelling for this point. This edge must lie wholly inside or outside * the other point (which is determined by the current location). * Assign both sides to be the current location. */ Assert.IsTrue(label.GetLocation(geomIndex, PositionType.Left) == LocationType.Null, "found single null side"); label.SetLocation(geomIndex, PositionType.Right, currLoc); label.SetLocation(geomIndex, PositionType.Left, currLoc); } } } }