/** Erases all edges of the given loop and marks them as unused. */

        private void RejectLoop(S2Loop v, int n, System.Collections.Generic.IList <S2Edge> unusedEdges)
        {
            for (int i = n - 1, j = 0; j < n; i = j++)
            {
                unusedEdges.Add(new S2Edge(v.Vertex(i), v.Vertex(j)));
            }
        }
 private void EraseLoop(S2Loop v, int n)
 {
     for (int i = n - 1, j = 0; j < n; i = j++)
     {
         EraseEdge(v.Vertex(i), v.Vertex(j));
     }
 }
        /**
         * Copy constructor.
         */

        public S2Polygon(S2Loop loop)
        {
            _loops       = new List <S2Loop>();
            _bound       = loop.RectBound;
            _hasHoles    = false;
            _numVertices = loop.NumVertices;

            _loops.Add(loop);
        }
        private static void InsertLoop(S2Loop newLoop, S2Loop parent, System.Collections.Generic.IDictionary <NullObject <S2Loop>, List <S2Loop> > loopMap)
        {
            List <S2Loop> children = null;

            if (loopMap.ContainsKey(parent))
            {
                children = loopMap[parent];
            }

            if (children == null)
            {
                children        = new List <S2Loop>();
                loopMap[parent] = children;
            }

            foreach (var child in children)
            {
                if (child.ContainsNested(newLoop))
                {
                    InsertLoop(newLoop, child, loopMap);
                    return;
                }
            }

            // No loop may contain the complement of another loop. (Handling this case
            // is significantly more complicated.)
            // assert (parent == null || !newLoop.containsNested(parent));

            // Some of the children of the parent loop may now be children of
            // the new loop.
            List <S2Loop> newChildren = null;

            if (loopMap.ContainsKey(newLoop))
            {
                newChildren = loopMap[newLoop];
            }
            for (var i = 0; i < children.Count;)
            {
                var child = children[i];
                if (newLoop.ContainsNested(child))
                {
                    if (newChildren == null)
                    {
                        newChildren      = new List <S2Loop>();
                        loopMap[newLoop] = newChildren;
                    }
                    newChildren.Add(child);
                    children.RemoveAt(i);
                }
                else
                {
                    ++i;
                }
            }
            children.Add(newLoop);
        }
        /**
         * Add all edges in the given loop. If the sign() of the loop is negative
         * (i.e. this loop represents a hole), the reverse edges are added instead.
         * This implies that "shells" are CCW and "holes" are CW, as required for the
         * directed edges convention described above.
         *
         * This method does not take ownership of the loop.
         */

        public void AddLoop(S2Loop loop)
        {
            var sign = loop.Sign;

            for (var i = loop.NumVertices; i > 0; --i)
            {
                // Vertex indices need to be in the range [0, 2*num_vertices()-1].
                AddEdge(loop.Vertex(i), loop.Vertex(i + sign));
            }
        }
        /** Return true if any loop contains the given loop. */

        private bool AnyLoopContains(S2Loop b)
        {
            for (var i = 0; i < NumLoops; ++i)
            {
                if (Loop(i).Contains(b))
                {
                    return(true);
                }
            }
            return(false);
        }
        /**
         * If this method returns false, the region does not intersect the given cell.
         * Otherwise, either region intersects the cell, or the intersection
         * relationship could not be determined.
         */

        public bool MayIntersect(S2Cell cell)
        {
            if (NumLoops == 1)
            {
                return(Loop(0).MayIntersect(cell));
            }
            var cellBound = cell.RectBound;

            if (!_bound.Intersects(cellBound))
            {
                return(false);
            }

            var cellLoop = new S2Loop(cell, cellBound);
            var cellPoly = new S2Polygon(cellLoop);

            return(Intersects(cellPoly));
        }
        /**
         * If this method returns true, the region completely contains the given cell.
         * Otherwise, either the region does not contain the cell or the containment
         * relationship could not be determined.
         */

        public bool Contains(S2Cell cell)
        {
            if (NumLoops == 1)
            {
                return(Loop(0).Contains(cell));
            }
            var cellBound = cell.RectBound;

            if (!_bound.Contains(cellBound))
            {
                return(false);
            }

            var cellLoop = new S2Loop(cell, cellBound);
            var cellPoly = new S2Polygon(cellLoop);

            return(Contains(cellPoly));
        }
        private int ContainsOrCrosses(S2Loop b)
        {
            var inside = false;

            for (var i = 0; i < NumLoops; ++i)
            {
                var result = Loop(i).ContainsOrCrosses(b);
                if (result < 0)
                {
                    return(-1); // The loop boundaries intersect.
                }
                if (result > 0)
                {
                    inside ^= true;
                }
            }
            return(inside ? 1 : 0); // True if loop B is contained by the polygon.
        }
        private void InitLoop(S2Loop loop, int depth, System.Collections.Generic.IDictionary <NullObject <S2Loop>, List <S2Loop> > loopMap)
        {
            if (loop != null)
            {
                loop.Depth = depth;
                _loops.Add(loop);
            }
            List <S2Loop> children = null;

            if (loopMap.ContainsKey(loop))
            {
                children = loopMap[loop];
            }
            if (children != null)
            {
                foreach (var child in children)
                {
                    InitLoop(child, depth + 1, loopMap);
                }
            }
        }
示例#11
0
 public AnonS2EdgeIndex(S2Loop This)
 {
     _this = This;
 }
        /**
         * We start at the given edge and assemble a loop taking left turns whenever
         * possible. We stop the loop as soon as we encounter any vertex that we have
         * seen before *except* for the first vertex (v0). This ensures that only CCW
         * loops are constructed when possible.
         */

        private S2Loop AssembleLoop(S2Point v0, S2Point v1, System.Collections.Generic.IList <S2Edge> unusedEdges)
        {
            // The path so far.
            var path = new List <S2Point>();

            // Maps a vertex to its index in "path".
            var index = new Dictionary <S2Point, int>();

            path.Add(v0);
            path.Add(v1);

            index.Add(v1, 1);

            while (path.Count >= 2)
            {
                // Note that "v0" and "v1" become invalid if "path" is modified.
                v0 = path[path.Count - 2];
                v1 = path[path.Count - 1];

                var v2      = default(S2Point);
                var v2Found = false;
                HashBag <S2Point> vset;
                _edges.TryGetValue(v1, out vset);
                if (vset != null)
                {
                    foreach (var v in vset)
                    {
                        // We prefer the leftmost outgoing edge, ignoring any reverse edges.
                        if (v.Equals(v0))
                        {
                            continue;
                        }
                        if (!v2Found || S2.OrderedCcw(v0, v2, v, v1))
                        {
                            v2 = v;
                        }
                        v2Found = true;
                    }
                }
                if (!v2Found)
                {
                    // We've hit a dead end. Remove this edge and backtrack.
                    unusedEdges.Add(new S2Edge(v0, v1));
                    EraseEdge(v0, v1);
                    index.Remove(v1);
                    path.RemoveAt(path.Count - 1);
                }
                else if (!index.ContainsKey(v2))
                {
                    // This is the first time we've visited this vertex.
                    index.Add(v2, path.Count);
                    path.Add(v2);
                }
                else
                {
                    // We've completed a loop. Throw away any initial vertices that
                    // are not part of the loop.
                    var start = index[v2];
                    path = path.GetRange(start, path.Count - start);

                    if (_options.Validate && !S2Loop.IsValidLoop(path))
                    {
                        // We've constructed a loop that crosses itself, which can only happen
                        // if there is bad input data. Throw away the whole loop.
                        RejectLoop(path, path.Count, unusedEdges);
                        EraseLoop(path, path.Count);
                        return(null);
                    }
                    return(new S2Loop(path));
                }
            }
            return(null);
        }