Example #1
0
    private static void TestInterpolate(S2Point a, S2Point b, double t, S2Point expected)
    {
        a        = a.Normalize();
        b        = b.Normalize();
        expected = expected.Normalize();

        // We allow a bit more than the usual 1e-15 error tolerance because
        // interpolation uses trig functions.
        S1Angle kError = S1Angle.FromRadians(3e-15);

        Assert.True(new S1Angle(S2.Interpolate(a, b, t), expected) <= kError);

        // Now test the other interpolation functions.
        S1Angle r = t * new S1Angle(a, b);

        Assert.True(new S1Angle(S2.GetPointOnLine(a, b, r), expected) <= kError);
        if (a.DotProd(b) == 0)
        {  // Common in the test cases below.
            Assert.True(new S1Angle(S2.GetPointOnRay(a, b, r), expected) <= kError);
        }
        if (r.Radians >= 0 && r.Radians < 0.99 * S2.M_PI)
        {
            S1ChordAngle r_ca = new(r);
            Assert.True(new S1Angle(S2.GetPointOnLine(a, b, r_ca), expected) <= kError);
            if (a.DotProd(b) == 0)
            {
                Assert.True(new S1Angle(S2.GetPointOnRay(a, b, r_ca), expected) <= kError);
            }
        }
    }
Example #2
0
    public void Test_S2_InterpolateCanExtrapolate()
    {
        S2Point i = new(1, 0, 0);
        S2Point j = new(0, 1, 0);

        // Initial vectors at 90 degrees.
        TestInterpolate(i, j, 0, new S2Point(1, 0, 0));
        TestInterpolate(i, j, 1, new S2Point(0, 1, 0));
        TestInterpolate(i, j, 1.5, new S2Point(-1, 1, 0));
        TestInterpolate(i, j, 2, new S2Point(-1, 0, 0));
        TestInterpolate(i, j, 3, new S2Point(0, -1, 0));
        TestInterpolate(i, j, 4, new S2Point(1, 0, 0));

        // Negative values of t.
        TestInterpolate(i, j, -1, new S2Point(0, -1, 0));
        TestInterpolate(i, j, -2, new S2Point(-1, 0, 0));
        TestInterpolate(i, j, -3, new S2Point(0, 1, 0));
        TestInterpolate(i, j, -4, new S2Point(1, 0, 0));

        // Initial vectors at 45 degrees.
        TestInterpolate(i, new S2Point(1, 1, 0), 2, new S2Point(0, 1, 0));
        TestInterpolate(i, new S2Point(1, 1, 0), 3, new S2Point(-1, 1, 0));
        TestInterpolate(i, new S2Point(1, 1, 0), 4, new S2Point(-1, 0, 0));

        // Initial vectors at 135 degrees.
        TestInterpolate(i, new S2Point(-1, 1, 0), 2, new S2Point(0, -1, 0));

        // Take a small fraction along the curve.
        S2Point p = S2.Interpolate(i, j, 0.001);

        // We should get back where we started.
        TestInterpolate(i, p, 1000, j);
    }
Example #3
0
        public void Test_S2Cell_GetMaxDistanceToEdge()
        {
            // Test an edge for which its antipode crosses the cell. Validates both the
            // standard and brute force implementations for this case.
            S2Cell  cell = S2Cell.FromFacePosLevel(0, 0, 20);
            S2Point a    = -S2.Interpolate(2.0, cell.Center(), cell.Vertex(0));
            S2Point b    = -S2.Interpolate(2.0, cell.Center(), cell.Vertex(2));

            S1ChordAngle actual   = cell.MaxDistance(a, b);
            S1ChordAngle expected = GetMaxDistanceToEdgeBruteForce(cell, a, b);

            Assert2.Near(expected.Radians(), S1ChordAngle.Straight.Radians(), S2.DoubleError);
            Assert2.Near(actual.Radians(), S1ChordAngle.Straight.Radians(), S2.DoubleError);
        }
Example #4
0
 public void Test_S2_RepeatedInterpolation()
 {
     // Check that points do not drift away from unit length when repeated
     // interpolations are done.
     for (int i = 0; i < 100; ++i)
     {
         S2Point a = S2Testing.RandomPoint();
         S2Point b = S2Testing.RandomPoint();
         for (int j = 0; j < 1000; ++j)
         {
             a = S2.Interpolate(a, b, 0.01);
         }
         Assert.True(a.IsUnitLength());
     }
 }
Example #5
0
        public void Test_S2Cell_ConsistentWithS2CellIdFromPoint()
        {
            // Construct many points that are nearly on an S2Cell edge, and verify that
            // S2Cell(S2CellId(p)).Contains(p) is always true.

            for (int iter = 0; iter < 1000; ++iter)
            {
                S2Cell  cell = new(S2Testing.GetRandomCellId());
                int     i    = S2Testing.Random.Uniform(4);
                S2Point v1   = cell.Vertex(i);
                S2Point v2   = S2Testing.SamplePoint(
                    new S2Cap(cell.Vertex(i + 1), S1Angle.FromRadians(1e-15)));
                S2Point p = S2.Interpolate(S2Testing.Random.RandDouble(), v1, v2);
                Assert.True(new S2Cell(new S2CellId(p)).Contains(p));
            }
        }
Example #6
0
    public void Test_S2_CollinearEdgesThatDontTouch()
    {
        int kIters = 500;

        for (int iter = 0; iter < kIters; ++iter)
        {
            S2Point a = S2Testing.RandomPoint();
            S2Point d = S2Testing.RandomPoint();
            S2Point b = S2.Interpolate(0.05, a, d);
            S2Point c = S2.Interpolate(0.95, a, d);
            Assert.True(0 > S2.CrossingSign(a, b, c, d));
            Assert.True(0 > S2.CrossingSign(a, b, c, d));
            S2EdgeCrosser crosser = new(a, b, c);
            Assert.True(0 > crosser.CrossingSign(d));
            Assert.True(0 > crosser.CrossingSign(c));
        }
    }
Example #7
0
    public void Test_S2_Interpolate()
    {
        // Choose test points designed to expose floating-point errors.
        S2Point p1 = new S2Point(0.1, 1e-30, 0.3).Normalize();
        S2Point p2 = new S2Point(-0.7, -0.55, -1e30).Normalize();

        // A zero-length edge.
        TestInterpolate(p1, p1, 0, p1);
        TestInterpolate(p1, p1, 1, p1);

        // Start, end, and middle of a medium-length edge.
        TestInterpolate(p1, p2, 0, p1);
        TestInterpolate(p1, p2, 1, p2);
        TestInterpolate(p1, p2, 0.5, 0.5 * (p1 + p2));

        // Test that interpolation is done using distances on the sphere rather than
        // linear distances.
        TestInterpolate(new S2Point(1, 0, 0), new S2Point(0, 1, 0), 1.0 / 3,
                        new S2Point(Math.Sqrt(3), 1, 0));
        TestInterpolate(new S2Point(1, 0, 0), new S2Point(0, 1, 0), 2.0 / 3,
                        new S2Point(1, Math.Sqrt(3), 0));

        // Test that interpolation is accurate on a long edge (but not so long that
        // the definition of the edge itself becomes too unstable).
        {
            double  kLng = Math.PI - 1e-2;
            S2Point a    = S2LatLng.FromRadians(0, 0).ToPoint();
            S2Point b    = S2LatLng.FromRadians(0, kLng).ToPoint();
            for (double f = 0.4; f > 1e-15; f *= 0.1)
            {
                TestInterpolate(a, b, f, S2LatLng.FromRadians(0, f * kLng).ToPoint());
                TestInterpolate(a, b, 1 - f, S2LatLng.FromRadians(0, (1 - f) * kLng).ToPoint());
            }
        }

        // Test that interpolation on a 180 degree edge (antipodal endpoints) yields
        // a result with the correct distance from each endpoint.
        for (double t = 0; t <= 1; t += 0.125)
        {
            S2Point actual = S2.Interpolate(p1, -p1, t);
            Assert2.Near(new S1Angle(actual, p1).Radians, t * Math.PI, 3e-15);
        }
    }
Example #8
0
    private S1ChordAngle EstimateMaxError(R2Point pa, S2Point a, R2Point pb, S2Point b)
    {
        // See the algorithm description at the top of this file.

        // We always tessellate edges longer than 90 degrees on the sphere, since the
        // approximation below is not robust enough to handle such edges.
        if (a.DotProd(b) < -1e-14)
        {
            return(S1ChordAngle.Infinity);
        }

        const double t1    = kInterpolationFraction;
        const double t2    = 1 - kInterpolationFraction;
        S2Point      mid1  = S2.Interpolate(a, b, t1);
        S2Point      mid2  = S2.Interpolate(a, b, t2);
        S2Point      pmid1 = proj_.Unproject(Projection.Interpolate(t1, pa, pb));
        S2Point      pmid2 = proj_.Unproject(Projection.Interpolate(t2, pa, pb));

        return(S1ChordAngle.Max(new S1ChordAngle(mid1, pmid1), new S1ChordAngle(mid2, pmid2)));
    }
Example #9
0
        public void Test_S2Cell_RectBoundIsLargeEnough()
        {
            // Construct many points that are nearly on an S2Cell edge, and verify that
            // whenever the cell contains a point P then its bound contains S2LatLng(P).

            for (int iter = 0; iter < 1000; /* advanced in loop below */)
            {
                S2Cell  cell = new(S2Testing.GetRandomCellId());
                int     i    = S2Testing.Random.Uniform(4);
                S2Point v1   = cell.Vertex(i);
                S2Point v2   = S2Testing.SamplePoint(
                    new S2Cap(cell.Vertex(i + 1), S1Angle.FromRadians(1e-15)));
                S2Point p = S2.Interpolate(S2Testing.Random.RandDouble(), v1, v2);
                if (new S2Loop(cell).Contains(p))
                {
                    Assert.True(cell.GetRectBound().Contains(new S2LatLng(p)));
                    ++iter;
                }
            }
        }