/// <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> /// 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> /// /// </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> /// 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 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> /// 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="eSearch"></param> /// <returns></returns> public 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> /// /// </summary> /// <param name="ee"></param> /// <returns></returns> public EdgeEnd GetNextCW(EdgeEnd ee) { IList temp = Edges; temp = null; // Hack for calling property int i = edgeList.IndexOf(ee); int iNextCW = i - 1; if (i == 0) { iNextCW = edgeList.Count - 1; } return((EdgeEnd)edgeList[iNextCW]); }
/// <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 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; Locations startLoc = startLabel.GetLocation(geomIndex, Positions.Left); Assert.IsTrue(startLoc != Locations.Null, "Found unlabelled area edge"); Locations 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"); Locations leftLoc = label.GetLocation(geomIndex, Positions.Left); Locations rightLoc = label.GetLocation(geomIndex, Positions.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(Locations.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++) { Locations eLoc = eLabel.GetLocation(i); if (eLoc == Locations.Interior || eLoc == Locations.Boundary) { label.SetLocation(i, Locations.Interior); } } } }
/// <summary> /// /// </summary> /// <param name="e"></param> public void Add(EdgeEnd e) { nodes.Add(e); edgeEndList.Add(e); }
/// <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> /// Add the edge to the list of edges at this node. /// </summary> /// <param name="e"></param> public void Add(EdgeEnd e) { // Assert: start pt of e is equal to node point edges.Insert(e); e.Node = this; }
/// <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) { edgeMap[e] = obj; edgeList = null; // edge list has changed - clear the cache }
/// <summary> /// /// </summary> /// <param name="obj"></param> /// <returns></returns> public int CompareTo(object obj) { EdgeEnd e = (EdgeEnd)obj; return(CompareDirection(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 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; ICoordinate 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> /// Add the edge to the list of edges at this node. /// </summary> /// <param name="e"></param> public void Add(EdgeEnd e) { // Assert: start pt of e is equal to node point edges.Insert(e); e.Node = this; }
/// <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 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="e"></param> public void Insert(EdgeEnd e) { // Assert: start point is the same // Assert: direction is the same edgeEnds.Add(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> /// /// </summary> /// <param name="geomIndex"></param> public 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 Locations startLoc = Locations.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, Positions.Left) != Locations.Null) { startLoc = label.GetLocation(geomIndex, Positions.Left); } } // no labelled sides found, so no labels to propagate if (startLoc == Locations.Null) { return; } Locations 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, Positions.On) == Locations.Null) { label.SetLocation(geomIndex, Positions.On, currLoc); } // set side labels (if any) if (label.IsArea(geomIndex)) { Locations leftLoc = label.GetLocation(geomIndex, Positions.Left); Locations rightLoc = label.GetLocation(geomIndex, Positions.Right); // if there is a right location, that is the next location to propagate if (rightLoc != Locations.Null) { if (rightLoc != currLoc) { throw new TopologyException("side location conflict", e.Coordinate); } if (leftLoc == Locations.Null) { Assert.ShouldNeverReachHere("found single null side (at " + 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, Positions.Left) == Locations.Null, "found single null side"); label.SetLocation(geomIndex, Positions.Right, currLoc); label.SetLocation(geomIndex, Positions.Left, currLoc); } } } }
/// <summary> /// /// </summary> /// <param name="e"></param> public void Add(EdgeEnd e) { nodes.Add(e); edgeEndList.Add(e); }
/// <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> /// /// </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. * * Note 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) == Locations.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)) { Locations loc = Locations.Null; if (hasDimensionalCollapseEdge[geomi]) { loc = Locations.Exterior; } else { ICoordinate p = e.Coordinate; loc = GetLocation(geomi, p, geom); } label.SetAllLocationsIfNull(geomi, loc); } } } }
/// <summary> /// /// </summary> /// <param name="eSearch"></param> /// <returns></returns> public 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> /// 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 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--; } ICoordinate 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 a EdgeEnd into this EdgeEndStar. /// </summary> /// <param name="e"></param> abstract public void Insert(EdgeEnd 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) { edgeMap[e] = obj; edgeList = null; // edge list has changed - clear the cache }
/// <summary> /// Insert a EdgeEnd into this EdgeEndStar. /// </summary> /// <param name="e"></param> abstract public void Insert(EdgeEnd 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 void Add(EdgeEnd e) { ICoordinate p = e.Coordinate; Node n = AddNode(p); n.Add(e); }
/// <summary> /// /// </summary> /// <param name="ee"></param> /// <returns></returns> public EdgeEnd GetNextCW(EdgeEnd ee) { IList temp = Edges; temp = null; // Hack for calling property int i = edgeList.IndexOf(ee); int iNextCW = i - 1; if (i == 0) iNextCW = edgeList.Count - 1; return (EdgeEnd) edgeList[iNextCW]; }