public void testDisjoint()
        {
            var builder = new S2PolygonBuilder(S2PolygonBuilderOptions.UndirectedXor);

            builder.AddPolygon(adj0);
            builder.AddPolygon(unAdj);
            var ab = new S2Polygon();

            assertTrue(builder.AssemblePolygon(ab, null));

            var union = new S2Polygon();

            union.InitToUnion(adj0, unAdj);
            assertEquals(2, union.NumLoops);

            checkEqual(ab, union);
            tryUnion(adj0, unAdj);
        }
        private void checkEqual(S2Polygon a, S2Polygon b)
        {
            var MAX_ERROR = 1e-31;

            if (a.IsNormalized && b.IsNormalized)
            {
                var r = a.BoundaryApproxEquals(b, MAX_ERROR);
                assertTrue(r);
            }
            else
            {
                var builder = new S2PolygonBuilder(S2PolygonBuilderOptions.UndirectedXor);
                var a2      = new S2Polygon();
                var b2      = new S2Polygon();
                builder.AddPolygon(a);
                assertTrue(builder.AssemblePolygon(a2, null));
                builder.AddPolygon(b);
                assertTrue(builder.AssemblePolygon(b2, null));
                assertTrue(a2.BoundaryApproxEquals(b2, MAX_ERROR));
            }
        }
Пример #3
0
        private void addChain(Chain chain,
                              S2Point x,
                              S2Point y,
                              S2Point z,
                              double maxPerturbation,
                              S2PolygonBuilder builder)
        {
            // Transform the given edge chain to the frame (x,y,z), perturb each vertex
            // up to the given distance, and add it to the builder.

            var vertices = new List <S2Point>();

            getVertices(chain.str, x, y, z, maxPerturbation, vertices);
            if (chain.closed)
            {
                vertices.Add(vertices[0]);
            }
            for (var i = 1; i < vertices.Count; ++i)
            {
                builder.AddEdge(vertices[i - 1], vertices[i]);
            }
        }
        private bool testBuilder(TestCase test)
        {
            for (var iter = 0; iter < 200; ++iter)
            {
                // Initialize to the default options, which are changed below
                var options = S2PolygonBuilderOptions.DirectedXor;

                options.UndirectedEdges = evalTristate(test.undirectedEdges);
                options.XorEdges = evalTristate(test.xorEdges);

                // Each test has a minimum and a maximum merge distance. The merge
                // distance must be at least the given minimum to ensure that all expected
                // merging will take place, and it must be at most the given maximum to
                // ensure that no unexpected merging takes place.
                //
                // If the minimum and maximum values are different, we have some latitude
                // to perturb the vertices as long as the merge distance is adjusted
                // appropriately. If "p" is the maximum perturbation distance, "min" and
                // "max" are the min/max merge distances, and "m" is the actual merge
                // distance for this test, we require that
                //
                // x >= min + 2*p and x <= max - 2*p .
                //
                // This implies that p <= 0.25 * (max - min). We choose "p" so that it is
                // zero half of the time, and otherwise chosen randomly up to this limit.

                var minMerge = S1Angle.FromDegrees(test.minMerge).Radians;
                var maxMerge = S1Angle.FromDegrees(test.maxMerge).Radians;
                var r = Math.Max(0.0, 2*rand.NextDouble() - 1);
                var maxPerturbation = r*0.25*(maxMerge - minMerge);

                // Now we set the merge distance chosen randomly within the limits above
                // (min + 2*p and max - 2*p). Half of the time we set the merge distance
                // to the minimum value.

                r = Math.Max(0.0, 2*rand.NextDouble() - 1);
                options.MergeDistance = S1Angle.FromRadians(
                    minMerge + 2*maxPerturbation + r*(maxMerge - minMerge - 4*maxPerturbation));

                options.Validate = true;
                var builder = new S2PolygonBuilder(options);

                // On each iteration we randomly rotate the test case around the sphere.
                // This causes the S2PolygonBuilder to choose different first edges when
                // trying to build loops.
                var x = randomPoint();
                var y = S2Point.Normalize(S2Point.CrossProd(x, randomPoint()));
                var z = S2Point.Normalize(S2Point.CrossProd(x, y));

                foreach (var chain in test.chainsIn)
                {
                    addChain(chain, x, y, z, maxPerturbation, builder);
                }
                var loops = new List<S2Loop>();
                var unusedEdges = new List<S2Edge>();
                if (test.xorEdges < 0)
                {
                    builder.AssembleLoops(loops, unusedEdges);
                }
                else
                {
                    var polygon = new S2Polygon();
                    builder.AssemblePolygon(polygon, unusedEdges);
                    polygon.Release(loops);
                }
                var expected = new List<S2Loop>();
                foreach (var loop in test.loopsOut)
                {
                    var vertices = new List<S2Point>();
                    getVertices(loop, x, y, z, 0, vertices);
                    expected.Add(new S2Loop(vertices));
                }
                // We assume that the vertex locations in the expected output polygon
                // are separated from the corresponding vertex locations in the input
                // edges by at most half of the minimum merge distance. Essentially
                // this means that the expected output vertices should be near the
                // centroid of the various input vertices.
                var maxError = 0.5*minMerge + maxPerturbation;

                // Note single "|" below so that we print both sets of loops.
                if (findMissingLoops(loops, expected, maxError, "Actual")
                    | findMissingLoops(expected, loops, maxError, "Expected"))
                {
                    Console.Error.WriteLine(
                        "During iteration " + iter + ", undirected: " + options.UndirectedEdges + ", xor: "
                        + options.XorEdges + "\n\n");
                    return false;
                }
                if (unusedEdges.Count != test.numUnusedEdges)
                {
                    Console.Error.WriteLine("Wrong number of unused edges: " + unusedEdges.Count + " (should be "
                                            + test.numUnusedEdges + ")\n");
                    return false;
                }
            }
            return true;
        }
        private void addChain(Chain chain,
                              S2Point x,
                              S2Point y,
                              S2Point z,
                              double maxPerturbation,
                              S2PolygonBuilder builder)
        {
            // Transform the given edge chain to the frame (x,y,z), perturb each vertex
            // up to the given distance, and add it to the builder.

            var vertices = new List<S2Point>();
            getVertices(chain.str, x, y, z, maxPerturbation, vertices);
            if (chain.closed)
            {
                vertices.Add(vertices[0]);
            }
            for (var i = 1; i < vertices.Count; ++i)
            {
                builder.AddEdge(vertices[i - 1], vertices[i]);
            }
        }
        public void testDisjoint()
        {
            var builder = new S2PolygonBuilder(S2PolygonBuilderOptions.UndirectedXor);
            builder.AddPolygon(adj0);
            builder.AddPolygon(unAdj);
            var ab = new S2Polygon();
            assertTrue(builder.AssemblePolygon(ab, null));

            var union = new S2Polygon();
            union.InitToUnion(adj0, unAdj);
            assertEquals(2, union.NumLoops);

            checkEqual(ab, union);
            tryUnion(adj0, unAdj);
        }
        private void checkEqual(S2Polygon a, S2Polygon b)
        {
            var MAX_ERROR = 1e-31;

            if (a.IsNormalized && b.IsNormalized)
            {
                var r = a.BoundaryApproxEquals(b, MAX_ERROR);
                assertTrue(r);
            }
            else
            {
                var builder = new S2PolygonBuilder(S2PolygonBuilderOptions.UndirectedXor);
                var a2 = new S2Polygon();
                var b2 = new S2Polygon();
                builder.AddPolygon(a);
                assertTrue(builder.AssemblePolygon(a2, null));
                builder.AddPolygon(b);
                assertTrue(builder.AssemblePolygon(b2, null));
                assertTrue(a2.BoundaryApproxEquals(b2, MAX_ERROR));
            }
        }
Пример #8
0
        private bool testBuilder(TestCase test)
        {
            for (var iter = 0; iter < 200; ++iter)
            {
                // Initialize to the default options, which are changed below
                var options = S2PolygonBuilderOptions.DirectedXor;

                options.UndirectedEdges = evalTristate(test.undirectedEdges);
                options.XorEdges        = evalTristate(test.xorEdges);

                // Each test has a minimum and a maximum merge distance. The merge
                // distance must be at least the given minimum to ensure that all expected
                // merging will take place, and it must be at most the given maximum to
                // ensure that no unexpected merging takes place.
                //
                // If the minimum and maximum values are different, we have some latitude
                // to perturb the vertices as long as the merge distance is adjusted
                // appropriately. If "p" is the maximum perturbation distance, "min" and
                // "max" are the min/max merge distances, and "m" is the actual merge
                // distance for this test, we require that
                //
                // x >= min + 2*p and x <= max - 2*p .
                //
                // This implies that p <= 0.25 * (max - min). We choose "p" so that it is
                // zero half of the time, and otherwise chosen randomly up to this limit.

                var minMerge        = S1Angle.FromDegrees(test.minMerge).Radians;
                var maxMerge        = S1Angle.FromDegrees(test.maxMerge).Radians;
                var r               = Math.Max(0.0, 2 * rand.NextDouble() - 1);
                var maxPerturbation = r * 0.25 * (maxMerge - minMerge);

                // Now we set the merge distance chosen randomly within the limits above
                // (min + 2*p and max - 2*p). Half of the time we set the merge distance
                // to the minimum value.

                r = Math.Max(0.0, 2 * rand.NextDouble() - 1);
                options.MergeDistance = S1Angle.FromRadians(
                    minMerge + 2 * maxPerturbation + r * (maxMerge - minMerge - 4 * maxPerturbation));

                options.Validate = true;
                var builder = new S2PolygonBuilder(options);

                // On each iteration we randomly rotate the test case around the sphere.
                // This causes the S2PolygonBuilder to choose different first edges when
                // trying to build loops.
                var x = randomPoint();
                var y = S2Point.Normalize(S2Point.CrossProd(x, randomPoint()));
                var z = S2Point.Normalize(S2Point.CrossProd(x, y));

                foreach (var chain in test.chainsIn)
                {
                    addChain(chain, x, y, z, maxPerturbation, builder);
                }
                var loops       = new List <S2Loop>();
                var unusedEdges = new List <S2Edge>();
                if (test.xorEdges < 0)
                {
                    builder.AssembleLoops(loops, unusedEdges);
                }
                else
                {
                    var polygon = new S2Polygon();
                    builder.AssemblePolygon(polygon, unusedEdges);
                    polygon.Release(loops);
                }
                var expected = new List <S2Loop>();
                foreach (var loop in test.loopsOut)
                {
                    var vertices = new List <S2Point>();
                    getVertices(loop, x, y, z, 0, vertices);
                    expected.Add(new S2Loop(vertices));
                }
                // We assume that the vertex locations in the expected output polygon
                // are separated from the corresponding vertex locations in the input
                // edges by at most half of the minimum merge distance. Essentially
                // this means that the expected output vertices should be near the
                // centroid of the various input vertices.
                var maxError = 0.5 * minMerge + maxPerturbation;

                // Note single "|" below so that we print both sets of loops.
                if (findMissingLoops(loops, expected, maxError, "Actual")
                    | findMissingLoops(expected, loops, maxError, "Expected"))
                {
                    Console.Error.WriteLine(
                        "During iteration " + iter + ", undirected: " + options.UndirectedEdges + ", xor: "
                        + options.XorEdges + "\n\n");
                    return(false);
                }
                if (unusedEdges.Count != test.numUnusedEdges)
                {
                    Console.Error.WriteLine("Wrong number of unused edges: " + unusedEdges.Count + " (should be "
                                            + test.numUnusedEdges + ")\n");
                    return(false);
                }
            }
            return(true);
        }