public void InitToIntersectionSloppy( S2Polygon a, S2Polygon b, S1Angle vertexMergeRadius) { Preconditions.CheckState(NumLoops == 0); if (!a._bound.Intersects(b._bound)) { return; } // We want the boundary of A clipped to the interior of B, // plus the boundary of B clipped to the interior of A, // plus one copy of any directed edges that are in both boundaries. var options = S2PolygonBuilderOptions.DirectedXor; options.MergeDistance = vertexMergeRadius; var builder = new S2PolygonBuilder(options); ClipBoundary(a, false, b, false, false, true, builder); ClipBoundary(b, false, a, false, false, false, builder); if (!builder.AssemblePolygon(this, null)) { // TODO (andriy): do something more meaningful here. Debug.WriteLine("Bad directed edges"); } }
/** * Clip the boundary of A to the interior of B, and add the resulting edges to * "builder". Shells are directed CCW and holes are directed clockwise, unless * "reverseA" or "reverseB" is true in which case these directions in the * corresponding polygon are reversed. If "invertB" is true, the boundary of A * is clipped to the exterior rather than the interior of B. If * "adSharedEdges" is true, then the output will include any edges that are * shared between A and B (both edges must be in the same direction after any * edge reversals are taken into account). */ private static void ClipBoundary(S2Polygon a, bool reverseA, S2Polygon b, bool reverseB, bool invertB, bool addSharedEdges, S2PolygonBuilder builder) { var bIndex = new S2PolygonIndex(b, reverseB); bIndex.PredictAdditionalCalls(a.NumVertices); var intersections = new List <ParametrizedS2Point>(); foreach (var aLoop in a._loops) { var n = aLoop.NumVertices; var dir = (aLoop.IsHole ^ reverseA) ? -1 : 1; var inside = b.Contains(aLoop.Vertex(0)) ^ invertB; for (var j = (dir > 0) ? 0 : n; n > 0; --n, j += dir) { var a0 = aLoop.Vertex(j); var a1 = aLoop.Vertex(j + dir); intersections.Clear(); ClipEdge(a0, a1, bIndex, addSharedEdges, intersections); if (inside) { intersections.Add(new ParametrizedS2Point(0.0, a0)); } inside = ((intersections.Count & 0x1) == 0x1); // assert ((b.contains(a1) ^ invertB) == inside); if (inside) { intersections.Add(new ParametrizedS2Point(1.0, a1)); } // Remove duplicates and produce a list of unique intersections. intersections.Sort(); for (int size = intersections.Count, i = 1; i < size; i += 2) { builder.AddEdge(intersections[i - 1].Point, intersections[i].Point); } } } }