예제 #1
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="dirEdgeList"></param>
        public void FindEdge(IList dirEdgeList)
        {
            /*
             * Check all forward DirectedEdges only.  This is still general,
             * because each edge has a forward DirectedEdge.
             */
            for (IEnumerator i = dirEdgeList.GetEnumerator(); i.MoveNext(); )
            {
                DirectedEdge de = (DirectedEdge) i.Current;
                if (!de.IsForward) continue;
                CheckForRightmostCoordinate(de);
            }

            /*
             * If the rightmost point is a node, we need to identify which of
             * the incident edges is rightmost.
             */
            Assert.IsTrue(minIndex != 0 || minCoord.Equals(minDe.Coordinate), "inconsistency in rightmost processing");
            if (minIndex == 0)            
                 FindRightmostEdgeAtNode();            
            else FindRightmostEdgeAtVertex();            

            /*
             * now check that the extreme side is the R side.
             * If not, use the sym instead.
             */
            orientedDe = minDe;
            Positions rightmostSide = GetRightmostSide(minDe, minIndex);
            if (rightmostSide == Positions.Left)            
                orientedDe = minDe.Sym;
        }
 /// <summary>
 /// 
 /// </summary>
 /// <param name="start"></param>
 protected void VisitLinkedDirectedEdges(DirectedEdge start)
 {
     DirectedEdge startDe = start;
     DirectedEdge de = start;
     do
     {
         Assert.IsTrue(de != null, "found null Directed Edge");
         de.Visited = true;
         de = de.Next;
     } 
     while (de != startDe);
 }
예제 #3
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="de"></param>
 public void ComputeDepths(DirectedEdge de)
 {
     int edgeIndex = FindIndex(de);
     int startDepth = de.GetDepth(Positions.Left);
     int targetLastDepth = de.GetDepth(Positions.Right);
     // compute the depths from this edge up to the end of the edge array
     int nextDepth = ComputeDepths(edgeIndex + 1, edgeList.Count, startDepth);
     // compute the depths for the initial part of the array
     int lastDepth = ComputeDepths(0, edgeIndex, nextDepth);        
     if (lastDepth != targetLastDepth)
         throw new TopologyException("depth mismatch at " + de.Coordinate);            
 }
예제 #4
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="start"></param>
 /// <param name="geometryFactory"></param>
 public EdgeRing(DirectedEdge start, IGeometryFactory geometryFactory)
 {
     this.geometryFactory = geometryFactory;
     ComputePoints(start);
     ComputeRing();
 }
예제 #5
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 /// <param name="er"></param>
 abstract public void SetEdgeRing(DirectedEdge de, EdgeRing er);
예제 #6
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="de"></param>
 /// <param name="opCode"></param>
 /// <param name="edges"></param>
 public void CollectLineEdge(DirectedEdge de, SpatialFunctions opCode, IList edges)
 {
     Label label = de.Label;
     Edge e = de.Edge;
     // include Curve edges which are in the result
     if (de.IsLineEdge)
     {                
         if (!de.IsVisited && OverlayOp.IsResultOfOp(label, opCode) && !e.IsCovered)
         {                    
             edges.Add(e);                    
             de.VisitedEdge = true;
         }
     }
 }
예제 #7
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="de"></param>
 /// <returns></returns>
 public override DirectedEdge GetNext(DirectedEdge de)
 {
     return de.Next;
 }
예제 #8
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="de"></param>
 private void CopySymDepths(DirectedEdge de)
 {
     DirectedEdge sym = de.Sym;
     sym.SetDepth(Positions.Left, de.GetDepth(Positions.Right));
     sym.SetDepth(Positions.Right, de.GetDepth(Positions.Left));
 }
예제 #9
0
 /// <summary>
 /// 
 /// </summary>
 private void FindRightmostEdgeAtNode()
 {
     Node node = minDe.Node;
     DirectedEdgeStar star = (DirectedEdgeStar) node.Edges;
     minDe = star.GetRightmostEdge();
     // the DirectedEdge returned by the previous call is not
     // necessarily in the forward direction. Use the sym edge if it isn't.
     if (!minDe.IsForward)
     {
         minDe = minDe.Sym;
         minIndex = minDe.Edge.Coordinates.Length - 1;
     }
 }
예제 #10
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="de"></param>
        /// <param name="i"></param>
        /// <returns></returns>
        private Positions GetRightmostSideOfSegment(DirectedEdge de, int i)
        {
            Edge e = de.Edge;
            ICoordinate[] coord = e.Coordinates;

            if (i < 0 || i + 1 >= coord.Length) 
                return Positions.Parallel;
            if (coord[i].Y == coord[i + 1].Y)
                return Positions.Parallel;    

            Positions pos = Positions.Left;
            if (coord[i].Y < coord[i + 1].Y) 
                pos = Positions.Right;

            return pos;
        }
예제 #11
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="de"></param>
 /// <param name="index"></param>
 /// <returns></returns>
 private Positions GetRightmostSide(DirectedEdge de, int index)
 {
     Positions side = GetRightmostSideOfSegment(de, index);
     if (side < 0)
         side = GetRightmostSideOfSegment(de, index - 1);
     if (side < 0)
     {
         // reaching here can indicate that segment is horizontal                
         minCoord = null;
         CheckForRightmostCoordinate(de);
     }
     return side;
 }
예제 #12
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="de"></param>
 private void CheckForRightmostCoordinate(DirectedEdge de)
 {
     ICoordinate[] coord = de.Edge.Coordinates;
     for (int i = 0; i < coord.Length - 1; i++)
     {
         // only check vertices which are the start or end point of a non-horizontal segment
         // <FIX> MD 19 Sep 03 - NO!  we can test all vertices, since the rightmost must have a non-horiz segment adjacent to it
         if (minCoord == null || coord[i].X > minCoord.X)
         {
             minDe = de;
             minIndex = i;
             minCoord = coord[i];
         }
     }
 }
예제 #13
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="start"></param>
 /// <param name="geometryFactory"></param>
 public EdgeRing(DirectedEdge start, IGeometryFactory geometryFactory)
 {
     this.geometryFactory = geometryFactory;
     ComputePoints(start);
     ComputeRing();
 }
예제 #14
0
        /// <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(IList edgesToAdd)
        {
            // create all the nodes for the edges
            for (IEnumerator it = edgesToAdd.GetEnumerator(); it.MoveNext(); )
            {
                Edge e = (Edge) it.Current;
                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);
            }
        }
예제 #15
0
        /// <summary>
        /// Finds all non-horizontal segments intersecting the stabbing line
        /// in the input dirEdge.
        /// The stabbing line is the ray to the right of stabbingRayLeftPt.
        /// </summary>
        /// <param name="stabbingRayLeftPt">The left-hand origin of the stabbing line.</param>
        /// <param name="dirEdge"></param>
        /// <param name="stabbedSegments">The current list of DepthSegments intersecting the stabbing line.</param>
        private void FindStabbedSegments(ICoordinate stabbingRayLeftPt, DirectedEdge dirEdge, IList stabbedSegments)
        {
            ICoordinate[] pts = dirEdge.Edge.Coordinates;
            for (int i = 0; i < pts.Length - 1; i++)
            {
                seg.P0 = pts[i];
                seg.P1 = pts[i + 1];
                // ensure segment always points upwards
                if (seg.P0.Y > seg.P1.Y)
                    seg.Reverse();

                // skip segment if it is left of the stabbing line
                double maxx = Math.Max(seg.P0.X, seg.P1.X);
                if (maxx < stabbingRayLeftPt.X) continue;

                // skip horizontal segments (there will be a non-horizontal one carrying the same depth info
                if (seg.IsHorizontal) continue;

                // skip if segment is above or below stabbing line
                if (stabbingRayLeftPt.Y < seg.P0.Y || stabbingRayLeftPt.Y > seg.P1.Y) continue;

                // skip if stabbing ray is right of the segment
                if (CGAlgorithms.ComputeOrientation(seg.P0, seg.P1, stabbingRayLeftPt) == CGAlgorithms.Right) continue;

                // stabbing line cuts this segment, so record it
                int depth = dirEdge.GetDepth(Positions.Left);
                // if segment direction was flipped, use RHS depth instead
                if (! seg.P0.Equals(pts[i]))
                    depth = dirEdge.GetDepth(Positions.Right);
                DepthSegment ds = new DepthSegment(seg, depth);
                stabbedSegments.Add(ds);
            }
        }
예제 #16
0
 /// <summary>
 /// Compute depths for all dirEdges via breadth-first traversal of nodes in graph.
 /// </summary>
 /// <param name="startEdge">Edge to start processing with.</param>
 // <FIX> MD - use iteration & queue rather than recursion, for speed and robustness
 private void ComputeDepths(DirectedEdge startEdge)
 {
     ISet nodesVisited = new HashedSet();
     Queue nodeQueue = new Queue();
     Node startNode = startEdge.Node;                 
     nodeQueue.Enqueue(startNode);   
     nodesVisited.Add(startNode);
     startEdge.Visited = true;
     while (nodeQueue.Count != 0)
     {
         Node n = (Node) nodeQueue.Dequeue();                
         nodesVisited.Add(n);
         // compute depths around node, starting at this edge since it has depths assigned
         ComputeNodeDepth(n);
         // add all adjacent nodes to process queue, unless the node has been visited already                
         IEnumerator i = ((DirectedEdgeStar)n.Edges).GetEnumerator();
         while (i.MoveNext()) 
         {
             DirectedEdge de = (DirectedEdge) i.Current;
             DirectedEdge sym = de.Sym;
             if (sym.IsVisited) continue;
             Node adjNode = sym.Node;
             if (!(nodesVisited.Contains(adjNode))) 
             {
                 nodeQueue.Enqueue(adjNode);
                 nodesVisited.Add(adjNode);
             }
         }                
     }
 }
예제 #17
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="de"></param>
 /// <returns></returns>
 abstract public DirectedEdge GetNext(DirectedEdge de);
예제 #18
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="start"></param>
 /// <param name="geometryFactory"></param>
 public MaximalEdgeRing(DirectedEdge start, IGeometryFactory geometryFactory) 
     : base(start, geometryFactory) { }
예제 #19
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="de"></param>
 /// <param name="er"></param>
 abstract public void SetEdgeRing(DirectedEdge de, EdgeRing er);
예제 #20
0
 /// <summary>
 /// 
 /// </summary>
 /// <param name="de"></param>
 /// <param name="er"></param>
 public override void SetEdgeRing(DirectedEdge de, EdgeRing er)
 {
     de.EdgeRing = er;
 }
예제 #21
0
        /// <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
            {
                Assert.IsTrue(de != null, "found null Directed Edge");
                if (de.EdgeRing == this)
                    throw new TopologyException("Directed Edge visited twice during ring-building at " + de.Coordinate);

                edges.Add(de);                
                Label label = de.Label;
                Assert.IsTrue(label.IsArea());
                MergeLabel(label);
                AddPoints(de.Edge, de.IsForward, isFirstEdge);
                isFirstEdge = false;
                SetEdgeRing(de, this);
                de = GetNext(de);
            } 
            while (de != startDe);
        }
예제 #22
0
        /// <summary>
        /// Collect edges from Area inputs which should be in the result but
        /// which have not been included in a result area.
        /// This happens ONLY:
        /// during an intersection when the boundaries of two
        /// areas touch in a line segment
        /// OR as a result of a dimensional collapse.
        /// </summary>
        /// <param name="de"></param>
        /// <param name="opCode"></param>
        /// <param name="edges"></param>
        public void CollectBoundaryTouchEdge(DirectedEdge de, SpatialFunctions opCode, IList edges)
        {            
            Label label = de.Label;            
            if (de.IsLineEdge)  
                return;         // only interested in area edges         
            if (de.IsVisited)   
                return;         // already processed
            if (de.IsInteriorAreaEdge)  
                return; // added to handle dimensional collapses            
            if (de.Edge.IsInResult) 
                return;     // if the edge linework is already included, don't include it again

            // sanity check for labelling of result edgerings
            Assert.IsTrue(!(de.IsInResult || de.Sym.IsInResult) || !de.Edge.IsInResult);            
            // include the linework if it's in the result of the operation
            if (OverlayOp.IsResultOfOp(label, opCode) && opCode == SpatialFunctions.Intersection)
            {
                edges.Add(de.Edge);
                de.VisitedEdge = true;
            }
        }
예제 #23
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 /// <returns></returns>
 abstract public DirectedEdge GetNext(DirectedEdge de);