private EdgeRing _shell; // if non-null, the ring is a hole and this EdgeRing is its containing shell #endregion Fields #region Constructors /// <summary> /// Initializes a new instance of the EdgeRing class. /// </summary> public EdgeRing( DirectedEdge start, GeometryFactory geometryFactory, CGAlgorithms cga ) { _geometryFactory = geometryFactory; _cga = cga; ComputePoints(start); ComputeRing(); }
public void ComputeDepths(DirectedEdge de) { int edgeIndex = FindIndex(de); Label label = de.Label; int startDepth = de.GetDepth( Position.Left ); // compute the depths from this edge up to the end of the edge array int nextDepth = ComputeDepths( edgeIndex + 1, _edgeList.Count - 1, startDepth ); // compute the depths for the initial part of the array int lastDepth = ComputeDepths( 0, edgeIndex, nextDepth ); //Trace.WriteLine( ToString() ); Trace.Assert( lastDepth == startDepth, "depth mismatch at " + de.Coordinate.ToString() ); }
public override DirectedEdge GetNext( DirectedEdge de ) { return de.Next; }
/// <summary> /// Initializes a new instance of the MaximalEdgeRing class. /// A MaximalEdgeRing is a ring of edges which may contain nodes of degree > 2. /// A MaximalEdgeRing may represent two different spatial entities: /// <ul> /// <li>a single polygon possibly containing inversions (if the ring is oriented CW) /// <li>a single hole possibly containing exversions (if the ring is oriented CCW) /// </ul> /// If the MaximalEdgeRing represents a polygon, /// the interior of the polygon is strongly connected. /// These are the form of rings used to define polygons under some spatial data models. /// However, under the OGC SFS model, {@link MinimalEdgeRings} are required. /// A MaximalEdgeRing can be converted to a list of MinimalEdgeRings using the /// { BuildMinimalRings() } method. /// </summary> public MaximalEdgeRing( DirectedEdge start, GeometryFactory geometryFactory, CGAlgorithms cga ) : base( start, geometryFactory, cga ) { }
/// <summary> /// Collect all the points from the DirectedEdges of this ring into a contiguous list. /// </summary> /// <param name="start"></param> protected void ComputePoints(DirectedEdge start) { _startDe = start; DirectedEdge de = start; bool isFirstEdge = true; do { if ( de == null ) { throw new InvalidOperationException("Found null Directed Edge."); } _edges.Add( de ); Label label = de.Label; // Java used an assert here... if ( !label.IsArea() ) { throw new InvalidOperationException("Label IsArea() is false when true is expected."); } MergeLabel( label ); AddPoints( de.Edge, de.IsForward, isFirstEdge ); isFirstEdge = false; SetEdgeRing( de, this ); de = GetNext( de ); // GetNext will be implemented in the inherited class...this class is abstract. } while ( de != _startDe ); }
public abstract void SetEdgeRing( DirectedEdge de, EdgeRing er );
public abstract DirectedEdge GetNext( DirectedEdge de );
} // public void LinkAllDirectedEdges() /// <summary> /// Traverse the star edges, maintaing the current location in the result area /// at this node (if any). If any L edges are found in the interior of the result, /// mark them as covered. /// </summary> public void FindCoveredLineEdges() { //Trace.WriteLine("findCoveredLineEdges"); //Trace.WriteLine( ToString() ); // 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 // Find first DirectedEdge of result area (if any). // The interior of the result is on the RHS of the edge, // so the start location will be: // - INTERIOR if the edge is outgoing // - EXTERIOR if the edge is incoming int startLoc = Location.Null; foreach (DirectedEdge de in Edges()) { DirectedEdge nextOut = de; DirectedEdge nextIn = nextOut.Sym; if (!nextOut.IsLineEdge) { if (nextOut.InResult) { startLoc = Location.Interior; break; } if (nextIn.InResult) { startLoc = Location.Exterior; break; } } } // foreach ( object obj in edges ) // no A edges found, so can't determine if L edges are covered or not if (startLoc == Location.Null) { return; } // move around ring, keeping track of the current location // (Interior or Exterior) for the result area. // If L edges are found, mark them as covered if they are in the interior int currLoc = startLoc; foreach (DirectedEdge de in Edges()) { DirectedEdge nextOut = de; DirectedEdge nextIn = nextOut.Sym; if (nextOut.IsLineEdge) { nextOut.Edge.SetCovered = (currLoc == Location.Interior); //Trace.WriteLine( nextOut.ToString() ); } else { // edge is an Area edge if (nextOut.InResult) { currLoc = Location.Exterior; } if (nextIn.InResult) { currLoc = Location.Interior; } } } // foreach ( object obj in edges ) } // public void FindCoveredLineEdges()
} // private void CollectLines( int opCode ) /// <summary> /// /// </summary> /// <param name="de"></param> /// <param name="opCode"></param> /// <param name="edges"></param> public void CollectLineEdge( DirectedEdge de, int opCode, ArrayList edges ) { Label label = de.Label; Edge e = de.Edge; // include L edges which are in the result if ( de.IsLineEdge ) { if ( !de.Visited && OverlayOp.IsResultOfOp( label, opCode ) && !e.IsCovered ) { //Trace.WriteLine("de: " + de.Label.ToString() ); //Trace.WriteLine("edge: " + e.Label.ToString() ); edges.Add( e ); de.SetVisitedEdge( true ); } // if ( !de.Visited && OverlayOp.IsResultOfOp( label, opCode ) && !e.IsCovered ) } // if ( de.IsLineEdge ) } // public void CollectLineEdge( DirectedEdge de, int opCode, ArrayList edges )
protected void VisitLinkedDirectedEdges(DirectedEdge start) { DirectedEdge startDe = start; DirectedEdge de = start; //Debug.println(de); do { de.Visited=true; de = de.Next; //Debug.println(de); } while (de != startDe); }
abstract public void SetEdgeRing(DirectedEdge de, EdgeRing er);
} // public void ComputeRing() abstract public DirectedEdge GetNext(DirectedEdge de);
/// <summary> /// Insert a directed edge in the list. /// </summary> /// <param name="ee">The EdgeEnd to be inserted into the list. Must be of type DirectedEdge.</param> public override void Insert(EdgeEnd ee) { DirectedEdge de = (DirectedEdge)ee; InsertEdgeEnd(de, de); }
public override void SetEdgeRing( DirectedEdge de, EdgeRing er ) { de.EdgeRing = er; }
} // public void CollectLineEdge( DirectedEdge de, int opCode, ArrayList edges ) /// <summary> /// Collect edges from Area input which should be in the result by which have not been included /// in a result area. This happens ONLY: /// <ul> /// <li>during an intersection when the boundaries of two areas touch in a line segment. /// <li>OR as a result of a dimensional collapse. /// </ul> /// </summary> /// <param name="de"></param> /// <param name="opCode"></param> /// <param name="edges"></param> public void CollectBoundaryTouchEdge( DirectedEdge de, int opCode, ArrayList edges ) { Label label = de.Label; // this smells like a bit of a hack, but it seems to work... if ( !de.IsLineEdge && !de.IsInteriorAreaEdge // added to handle dimensional collapses && !de.Edge.IsInResult && !de.Visited && OverlayOp.IsResultOfOp( label, opCode ) && opCode == OverlayOp.Intersection ) { edges.Add( de.Edge ); de.SetVisitedEdge( true ); } } // public void CollectBoundaryTouchEdge( DirectedEdge de, int opCode, ArrayList edges )
/// <summary> /// Add a set of edges to the graph. For each edge two DirectedEdges /// will be created. DirectedEdges are NOT linked by this method. /// </summary> /// <param name="edgesToAdd"></param> public void AddEdges( ArrayList edgesToAdd ) { // create all the nodes for the edges foreach( object objectEdge in edgesToAdd ) { Edge e = (Edge) objectEdge; _edges.Add( e ); DirectedEdge de1 = new DirectedEdge( e, true ); DirectedEdge de2 = new DirectedEdge( e, false ); de1.Sym = de2; de2.Sym = de1; Add( de1 ); Add( de2 ); } // foreach( object objectEdge in edgesToAdd ) }
} // private ArrayList GetResultAreaEdges() /// <summary> /// Traverse the star of DirectedEdges, linking the included edge together. /// To link two dirEdges, the next pointer for an incoming dirEdge is set to the next outgoing edge. /// /// DirEdges are only linked. If: /// <ul> /// <li>They belong to an area (i.e. they have sides) /// <li>They are marked as being in the result. /// </ul> /// Edges are linked in CCW order (the order they are stored.) This means that rings have /// their face on the Right ( in other words, the topological location of the face is given /// by the RHS label of the DirectedEdge) /// /// PRECONDITION: No pair of dirEdges are both marked as being in the result. /// </summary> public void LinkResultDirectedEdges() { // make sure edges are copied to resultAreaEdges list GetResultAreaEdges(); // find first area edge (if any) to start linking at DirectedEdge firstOut = null; DirectedEdge incoming = null; int state = ScanningForIncoming; // link edges in CCW order for (int i = 0; i < _resultAreaEdgeList.Count; i++) { DirectedEdge nextOut = (DirectedEdge)_resultAreaEdgeList[i]; DirectedEdge nextIn = nextOut.Sym; // skip de's that we're not interested in if (nextOut.Label.IsArea()) { // record first outgoing edge, in order to link the last incoming edge if (firstOut == null && nextOut.InResult) { firstOut = nextOut; } // assert: sym.isInResult() == false, since pairs of dirEdges should have been removed already switch (state) { case ScanningForIncoming: if (!nextIn.InResult) { continue; } incoming = nextIn; state = LinkingToOutGoing; break; case LinkingToOutGoing: if (!nextOut.InResult) { continue; } incoming.Next = nextOut; state = ScanningForIncoming; break; } // switch ( state ) } // if ( nextOut.Label.IsArea() ) } // for (int i = 0; i < _resultAreaEdgeList.Count; i++) //Trace.WriteLine( ToString() ); if (state == LinkingToOutGoing) { if (firstOut == null) { throw new TopologyException("No outgoing dirEdge found."); } if (!firstOut.InResult) { throw new TopologyException("Unable to link last incoming dirEdge."); } incoming.Next = firstOut; } } // public void LinkResultDirectedEdges()