/** 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); } } }
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); }