/// <summary> /// Visits all pairs of crossing edges in the given S2ShapeIndex, terminating /// early if the given EdgePairVisitor function returns false (in which case /// VisitCrossings returns false as well). "type" indicates whether all /// crossings should be visited, or only interior crossings. /// /// If "need_adjacent" is false, then edge pairs of the form (AB, BC) may /// optionally be ignored (even if the two edges belong to different edge /// chains). This option exists for the benefit of FindSelfIntersection(), /// which does not need such edge pairs (see below). /// </summary> private static bool VisitCrossings(S2ShapeIndex index, CrossingType type, bool need_adjacent, EdgePairVisitor visitor) { // TODO(ericv): Use brute force if the total number of edges is small enough // (using a larger threshold if the S2ShapeIndex is not constructed yet). var count = index.GetEnumerableCount(); for (var pos = 0; pos < count; pos++) { var shape_edges = new ShapeEdgeVector(); var icell = index.GetIndexCell(pos); var indexCell = icell.Value.Item2; GetShapeEdges(index, indexCell, shape_edges); if (!VisitCrossings(shape_edges, type, need_adjacent, visitor)) { return(false); } } return(true); }
/// <summary> /// Given a vector of edges within an S2ShapeIndexCell, visit all pairs of /// crossing edges (of the given CrossingType). /// </summary> private static bool VisitCrossings(ShapeEdgeVector shape_edges, CrossingType type, bool need_adjacent, EdgePairVisitor visitor) { var min_crossing_sign = type == CrossingType.INTERIOR ? 1 : 0; var num_edges = shape_edges.Count; for (int i = 0; i + 1 < num_edges; i++) { var a = shape_edges[i]; var j = i + 1; // A common situation is that an edge AB is followed by an edge BC. We // only need to visit such crossings if "need_adjacent" is true (even if // AB and BC belong to different edge chains). if (!need_adjacent && a.V1 == shape_edges[j].V0) { j++; if (j >= num_edges) { break; } } var crosser = new S2EdgeCrosser(a.V0, a.V1); for (; j < num_edges; j++) { var b = shape_edges[j]; if (crosser.C == S2Point.Empty || crosser.C != b.V0) { crosser.RestartAt(b.V0); } var sign = crosser.CrossingSign(b.V1); if (sign >= min_crossing_sign) { if (!visitor(a, b, sign == 1)) { return(false); } } } } return(true); }
// Visits all crossings of any edge in "a_edges" with any edge in "b_edges". private bool VisitEdgesEdgesCrossings(ShapeEdgeVector a_edges, ShapeEdgeVector b_edges) { // Test all edges of "a_edges" against all edges of "b_edges". foreach (var a in a_edges) { var crosser = new S2EdgeCrosser(a.V0, a.V1); foreach (var b in b_edges) { if (crosser.C == S2Point.Empty || crosser.C != b.V0) { crosser.RestartAt(b.V0); } int sign = crosser.CrossingSign(b.V1); if (sign >= min_crossing_sign_) { if (!VisitEdgePair(a, b, sign == 1)) { return(false); } } } } return(true); }
/// <summary> /// Returns a vector containing all edges in the given S2ShapeIndexCell vector. /// (The result is returned as an output parameter so that the same storage can /// be reused, rather than allocating a new temporary vector each time.) /// </summary> private static void GetShapeEdges(S2ShapeIndex index, List <S2ShapeIndexCell> cells, ShapeEdgeVector shape_edges) { shape_edges.Clear(); foreach (var cell in cells) { AppendShapeEdges(index, cell, shape_edges); } }
/// <summary> /// Returns a vector containing all edges in the given S2ShapeIndexCell. /// (The result is returned as an output parameter so that the same storage can /// be reused, rather than allocating a new temporary vector each time.) /// </summary> private static void GetShapeEdges(S2ShapeIndex index, S2ShapeIndexCell cell, ShapeEdgeVector shape_edges) { shape_edges.Clear(); AppendShapeEdges(index, cell, shape_edges); }
/// <summary> /// Appends all edges in the given S2ShapeIndexCell to the given vector. /// </summary> private static void AppendShapeEdges(S2ShapeIndex index, S2ShapeIndexCell cell, ShapeEdgeVector shape_edges) { for (int s = 0; s < cell.NumClipped(); ++s) { var clipped = cell.Clipped(s); var shape = index.Shape(clipped.ShapeId); var num_edges = clipped.NumEdges; for (int i = 0; i < num_edges; i++) { shape_edges.Add(new ShapeEdge(shape, clipped.Edge(i))); } } }