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