Exemplo n.º 1
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 private static void CopySymDepths(DirectedEdge de)
 {
     DirectedEdge sym = de.Sym;
     sym.SetDepth(PositionType.Left, de.GetDepth(PositionType.Right));
     sym.SetDepth(PositionType.Right, de.GetDepth(PositionType.Left));
 }
Exemplo n.º 2
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="start"></param>
 /// <param name="geometryFactory"></param>
 public MaximalEdgeRing(DirectedEdge start, IGeometryFactory geometryFactory)
     : base(start, geometryFactory) { }
Exemplo n.º 3
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 public virtual void ComputeDepths(DirectedEdge de)
 {
     int edgeIndex = FindIndex(de);
     int startDepth = de.GetDepth(PositionType.Left);
     int targetLastDepth = de.GetDepth(PositionType.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);
 }
Exemplo n.º 4
0
        /// <summary>
        /// Traverse the star of 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 virtual void FindCoveredLineEdges()
        {
            // 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
             */
            LocationType startLoc = LocationType.Null;

            for (IEnumerator it = GetEnumerator(); it.MoveNext();)
            {
                DirectedEdge nextOut = (DirectedEdge)it.Current;
                DirectedEdge nextIn  = nextOut.Sym;
                if (!nextOut.IsLineEdge)
                {
                    if (nextOut.IsInResult)
                    {
                        startLoc = LocationType.Interior;
                        break;
                    }
                    if (nextIn.IsInResult)
                    {
                        startLoc = LocationType.Exterior;
                        break;
                    }
                }
            }
            // no A edges found, so can't determine if Curve edges are covered or not
            if (startLoc == LocationType.Null)
            {
                return;
            }

            /*
             * move around ring, keeping track of the current location
             * (Interior or Exterior) for the result area.
             * If Curve edges are found, mark them as covered if they are in the interior
             */
            LocationType currLoc = startLoc;

            for (IEnumerator it = GetEnumerator(); it.MoveNext();)
            {
                DirectedEdge nextOut = (DirectedEdge)it.Current;
                DirectedEdge nextIn  = nextOut.Sym;
                if (nextOut.IsLineEdge)
                {
                    nextOut.Edge.IsCovered = (currLoc == LocationType.Interior);
                }
                else
                {
                    // edge is an Area edge
                    if (nextOut.IsInResult)
                    {
                        currLoc = LocationType.Exterior;
                    }
                    if (nextIn.IsInResult)
                    {
                        currLoc = LocationType.Interior;
                    }
                }
            }
        }
Exemplo n.º 5
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 /// <param name="er"></param>
 public abstract void SetEdgeRing(DirectedEdge de, EdgeRing er);
Exemplo n.º 6
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="start"></param>
 /// <param name="geometryFactory"></param>
 protected EdgeRing(DirectedEdge start, IGeometryFactory geometryFactory)
 {
     _innerGeometryFactory = geometryFactory;
     ComputePoints(start);
     ComputeRing();
 }
Exemplo n.º 7
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 virtual void CollectBoundaryTouchEdge(DirectedEdge de, SpatialFunction 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 == SpatialFunction.Intersection)
            {
                edges.Add(de.Edge);
                de.VisitedEdge = true;
            }
        }
Exemplo n.º 8
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 virtual 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);
            }
        }
Exemplo n.º 9
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="start"></param>
 /// <param name="geometryFactory"></param>
 protected EdgeRing(DirectedEdge start, IGeometryFactory geometryFactory)
 {
     _innerGeometryFactory = geometryFactory;
     ComputePoints(start);
     ComputeRing();
 }
Exemplo n.º 10
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 /// <param name="opCode"></param>
 /// <param name="edges"></param>
 public void CollectLineEdge(DirectedEdge de, SpatialFunction 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;
         }
     }
 }
Exemplo n.º 11
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 /// <param name="er"></param>
 public abstract void SetEdgeRing(DirectedEdge de, EdgeRing er);
Exemplo n.º 12
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 /// <returns></returns>
 public abstract DirectedEdge GetNext(DirectedEdge de);
Exemplo n.º 13
0
        /// <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);
        }
Exemplo n.º 14
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 /// <returns></returns>
 public override DirectedEdge GetNext(DirectedEdge de)
 {
     return de.Next;
 }
Exemplo n.º 15
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.Count - 1;
     }
 }
Exemplo n.º 16
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 /// <param name="er"></param>
 public override void SetEdgeRing(DirectedEdge de, EdgeRing er)
 {
     de.EdgeRing = er;
 }
Exemplo n.º 17
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 private void CheckForRightmostCoordinate(DirectedEdge de)
 {
     IList<Coordinate> coord = de.Edge.Coordinates;
     for (int i = 0; i < coord.Count - 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];
         }
     }
 }
Exemplo n.º 18
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 /// <returns></returns>
 public abstract DirectedEdge GetNext(DirectedEdge de);
Exemplo n.º 19
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="de"></param>
 /// <param name="index"></param>
 /// <returns></returns>
 private PositionType GetRightmostSide(DirectedEdge de, int index)
 {
     PositionType 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;
 }
Exemplo n.º 20
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 == null) continue;
                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);
        }
Exemplo n.º 21
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;
            PositionType rightmostSide = GetRightmostSide(_minDe, _minIndex);
            if (rightmostSide == PositionType.Left)
                _orientedDe = _minDe.Sym;
        }
Exemplo n.º 22
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(Coordinate stabbingRayLeftPt, DirectedEdge dirEdge, IList stabbedSegments)
        {
            IList<Coordinate> pts = dirEdge.Edge.Coordinates;
            for (int i = 0; i < pts.Count - 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(PositionType.Left);
                // if segment direction was flipped, use RHS depth instead
                if (!_seg.P0.Equals(pts[i]))
                    depth = dirEdge.GetDepth(PositionType.Right);
                DepthSegment ds = new DepthSegment(_seg, depth);
                stabbedSegments.Add(ds);
            }
        }
Exemplo n.º 23
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 static void ComputeDepths(DirectedEdge startEdge)
 {
     ISet nodesVisited = new HashedSet();
     Queue nodeQueue = new Queue();
     Node startNode = startEdge.Node;
     nodeQueue.Enqueue(startNode);
     nodesVisited.Add(startNode);
     startEdge.IsVisited = 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 = 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);
             }
         }
     }
 }
 /// <summary>
 ///
 /// </summary>
 /// <param name="start"></param>
 private static void VisitLinkedDirectedEdges(DirectedEdge start)
 {
     DirectedEdge startDe = start;
     DirectedEdge de = start;
     do
     {
         if (de == null) throw new NullEdgeException();
         de.IsVisited = true;
         de = de.Next;
     }
     while (de != startDe);
 }
Exemplo n.º 25
0
        /// <summary>
        /// Traverse the star of DirectedEdges, linking the included edges together.
        /// To link two dirEdges, the next pointer for an incoming dirEdge
        /// is set to the next outgoing edge.
        /// DirEdges are only linked if:
        /// they belong to an area (i.e. they have sides)
        /// they are marked as being in the result
        /// 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 virtual 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    = SCANNING_FOR_INCOMING;

            // 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())
                {
                    continue;
                }

                // record first outgoing edge, in order to link the last incoming edge
                if (firstOut == null && nextOut.IsInResult)
                {
                    firstOut = nextOut;
                }

                switch (state)
                {
                case SCANNING_FOR_INCOMING:
                    if (!nextIn.IsInResult)
                    {
                        continue;
                    }
                    incoming = nextIn;
                    state    = LINKING_TO_OUTGOING;
                    break;

                case LINKING_TO_OUTGOING:
                    if (!nextOut.IsInResult)
                    {
                        continue;
                    }
                    if (incoming != null)
                    {
                        incoming.Next = nextOut;
                    }
                    state = SCANNING_FOR_INCOMING;
                    break;

                default:
                    break;
                }
            }
            if (state == LINKING_TO_OUTGOING)
            {
                if (firstOut == null)
                {
                    throw new TopologyException("no outgoing dirEdge found", Coordinate);
                }
                Assert.IsTrue(firstOut.IsInResult, "unable to link last incoming dirEdge");
                if (incoming != null)
                {
                    incoming.Next = firstOut;
                }
            }
        }