Example #1
0
        public void Test_S2RegionEncodeDecodeTest_S2Cap()
        {
            S2Cap cap_from_point         = S2Cap.FromPoint(new S2Point(3, 2, 1).Normalize());
            var   cap_from_center_height = S2Cap.FromCenterHeight(new S2Point(0, 0, 1).Normalize(), 5);

            var cap = TestEncodeDecode(kEncodedCapEmpty, S2Cap.Empty);

            Assert.True(S2Cap.Empty.ApproxEquals(cap));
            cap = TestEncodeDecode(kEncodedCapFull, S2Cap.Full);
            Assert.True(S2Cap.Full.ApproxEquals(cap));
            cap = TestEncodeDecode(kEncodedCapFromPoint, cap_from_point);
            Assert.True(cap_from_point.ApproxEquals(cap));
            cap = TestEncodeDecode(kEncodedCapFromCenterHeight, cap_from_center_height);
            Assert.True(cap_from_center_height.ApproxEquals(cap));
        }
Example #2
0
        public void Test_S2PointRegionTest_Basic()
        {
            S2Point       p  = new(1, 0, 0);
            S2PointRegion r0 = new(p);

            Assert.Equal(r0.Point, p);
            Assert.True(r0.Contains(p));
            Assert.True(r0.Contains(r0.Point));
            Assert.False(r0.Contains(new S2Point(1, 0, 1)));
            S2PointRegion r0_clone = (S2PointRegion)r0.CustomClone();

            Assert.Equal(r0_clone.Point, r0.Point);
            Assert.Equal(r0.GetCapBound(), S2Cap.FromPoint(p));
            S2LatLng ll = new(p);

            Assert.Equal(r0.GetRectBound(), new S2LatLngRect(ll, ll));

            // The leaf cell containing a point is still much larger than the point.
            S2Cell cell = new(p);

            Assert.False(r0.Contains(cell));
            Assert.True(r0.MayIntersect(cell));
        }
Example #3
0
    private void TestRandomCaps(S2RegionTermIndexer.Options options, QueryType query_type)
    {
        // This function creates an index consisting either of points (if
        // options.index_contains_points_only() is true) or S2Caps of random size.
        // It then executes queries consisting of points (if query_type == POINT)
        // or S2Caps of random size (if query_type == CAP).
        var indexer = new S2RegionTermIndexer(options);
        var coverer = new S2RegionCoverer(options);
        var caps = new List <S2Cap>();
        var coverings = new List <S2CellUnion>();
        var index = new Dictionary <string, List <int> >();
        int index_terms = 0, query_terms = 0;

        for (int i = 0; i < iters; ++i)
        {
            // Choose the region to be indexed: either a single point or a cap
            // of random size (up to a full sphere).
            S2Cap         cap;
            List <string> terms;
            if (options.IndexContainsPointsOnly)
            {
                cap   = S2Cap.FromPoint(S2Testing.RandomPoint());
                terms = indexer.GetIndexTerms(cap.Center, "");
            }
            else
            {
                cap = S2Testing.GetRandomCap(
                    0.3 * S2Cell.AverageArea(options.MaxLevel),
                    4.0 * S2Cell.AverageArea(options.MinLevel));
                terms = indexer.GetIndexTerms(cap, "");
            }
            caps.Add(cap);
            coverings.Add(coverer.GetCovering(cap));
            foreach (var term in terms)
            {
                if (!index.ContainsKey(term))
                {
                    index.Add(term, new List <int>());
                }

                index[term].Add(i);
            }
            index_terms += terms.Count;
        }
        for (int i = 0; i < iters; ++i)
        {
            // Choose the region to be queried: either a random point or a cap of
            // random size.
            S2Cap         cap;
            List <string> terms;
            if (query_type == QueryType.CAP)
            {
                cap   = S2Cap.FromPoint(S2Testing.RandomPoint());
                terms = indexer.GetQueryTerms(cap.Center, "");
            }
            else
            {
                cap = S2Testing.GetRandomCap(
                    0.3 * S2Cell.AverageArea(options.MaxLevel),
                    4.0 * S2Cell.AverageArea(options.MinLevel));
                terms = indexer.GetQueryTerms(cap, "");
            }
            // Compute the expected results of the S2Cell query by brute force.
            S2CellUnion covering = coverer.GetCovering(cap);
            var         expected = new List <int>();
            var         actual   = new List <int>();
            for (int j = 0; j < caps.Count; ++j)
            {
                if (covering.Intersects(coverings[j]))
                {
                    expected.Add(j);
                }
            }
            foreach (var term in terms)
            {
                actual.AddRange(index[term]);
            }
            Assert.Equal(expected, actual);
            query_terms += terms.Count;
        }
        _logger.WriteLine($"Index terms/doc: {((double)index_terms) / iters:2f},  Query terms/doc: {((double)query_terms) / iters:2f}");
    }
Example #4
0
        public void Test_S2Cap_Basic()
        {
            // Test basic properties of empty and full caps.
            S2Cap empty = S2Cap.Empty;
            S2Cap full  = S2Cap.Full;

            Assert.True(empty.IsValid());
            Assert.True(empty.IsEmpty());
            Assert.True(empty.Complement().IsFull());
            Assert.True(full.IsValid());
            Assert.True(full.IsFull());
            Assert.True(full.Complement().IsEmpty());
            Assert.Equal(2, full.Height());
            Assert2.DoubleEqual(180.0, full.Radius.Degrees());

            // Test ==/!=.
            Assert.Equal(full, full);
            Assert.Equal(empty, empty);
            Assert.NotEqual(full, empty);

            // Test the S1Angle constructor using out-of-range arguments.
            Assert.True(new S2Cap(new S2Point(1, 0, 0), S1Angle.FromRadians(-20)).IsEmpty());
            Assert.True(new S2Cap(new S2Point(1, 0, 0), S1Angle.FromRadians(5)).IsFull());
            Assert.True(new S2Cap(new S2Point(1, 0, 0), S1Angle.Infinity).IsFull());

            // Check that the default S2Cap is identical to Empty().
            var default_empty = S2Cap.Empty;

            Assert.True(default_empty.IsValid());
            Assert.True(default_empty.IsEmpty());
            Assert.Equal(empty.Center, default_empty.Center);
            Assert.Equal(empty.Height(), default_empty.Height());

            // Containment and intersection of empty and full caps.
            Assert.True(empty.Contains(empty));
            Assert.True(full.Contains(empty));
            Assert.True(full.Contains(full));
            Assert.False(empty.InteriorIntersects(empty));
            Assert.True(full.InteriorIntersects(full));
            Assert.False(full.InteriorIntersects(empty));

            // Singleton cap containing the x-axis.
            S2Cap xaxis = S2Cap.FromPoint(new S2Point(1, 0, 0));

            Assert.True(xaxis.Contains(new S2Point(1, 0, 0)));
            Assert.False(xaxis.Contains(new S2Point(1, 1e-20, 0)));
            Assert.Equal(0, xaxis.Radius.Radians());

            // Singleton cap containing the y-axis.
            S2Cap yaxis = S2Cap.FromPoint(new S2Point(0, 1, 0));

            Assert.False(yaxis.Contains(xaxis.Center));
            Assert.Equal(0, xaxis.Height());

            // Check that the complement of a singleton cap is the full cap.
            S2Cap xcomp = xaxis.Complement();

            Assert.True(xcomp.IsValid());
            Assert.True(xcomp.IsFull());
            Assert.True(xcomp.Contains(xaxis.Center));

            // Check that the complement of the complement is *not* the original.
            Assert.True(xcomp.Complement().IsValid());
            Assert.True(xcomp.Complement().IsEmpty());
            Assert.False(xcomp.Complement().Contains(xaxis.Center));

            // Check that very small caps can be represented accurately.
            // Here "kTinyRad" is small enough that unit vectors perturbed by this
            // amount along a tangent do not need to be renormalized.
            S2Cap tiny    = new(new S2Point(1, 2, 3).Normalize(), S1Angle.FromRadians(kTinyRad));
            var   tangent = tiny.Center.CrossProd(new S2Point(3, 2, 1)).Normalize();

            Assert.True(tiny.Contains(tiny.Center + 0.99 * kTinyRad * tangent));
            Assert.False(tiny.Contains(tiny.Center + 1.01 * kTinyRad * tangent));

            // Basic tests on a hemispherical cap.
            S2Cap hemi = S2Cap.FromCenterHeight(new S2Point(1, 0, 1).Normalize(), 1);

            Assert.Equal(-hemi.Center, hemi.Complement().Center);
            Assert.Equal(1, hemi.Complement().Height());
            Assert.True(hemi.Contains(new S2Point(1, 0, 0)));
            Assert.False(hemi.Complement().Contains(new S2Point(1, 0, 0)));
            Assert.True(hemi.Contains(new S2Point(1, 0, -(1 - kEps)).Normalize()));
            Assert.False(hemi.InteriorContains(new S2Point(1, 0, -(1 + kEps)).Normalize()));

            // A concave cap.  Note that the error bounds for point containment tests
            // increase with the cap angle, so we need to use a larger error bound
            // here.  (It would be painful to do this everywhere, but this at least
            // gives an example of how to compute the maximum error.)
            S2Point      center    = GetLatLngPoint(80, 10);
            S1ChordAngle radius    = new(S1Angle.FromDegrees(150));
            double       max_error =
                radius.GetS2PointConstructorMaxError() +
                radius.S1AngleConstructorMaxError +
                3 * S2.DoubleEpsilon;  // GetLatLngPoint() error
            S2Cap concave     = new(center, radius);
            S2Cap concave_min = new(center, radius.PlusError(-max_error));
            S2Cap concave_max = new(center, radius.PlusError(max_error));

            Assert.True(concave_max.Contains(GetLatLngPoint(-70, 10)));
            Assert.False(concave_min.Contains(GetLatLngPoint(-70, 10)));
            Assert.True(concave_max.Contains(GetLatLngPoint(-50, -170)));
            Assert.False(concave_min.Contains(GetLatLngPoint(-50, -170)));

            // Cap containment tests.
            Assert.False(empty.Contains(xaxis));
            Assert.False(empty.InteriorIntersects(xaxis));
            Assert.True(full.Contains(xaxis));
            Assert.True(full.InteriorIntersects(xaxis));
            Assert.False(xaxis.Contains(full));
            Assert.False(xaxis.InteriorIntersects(full));
            Assert.True(xaxis.Contains(xaxis));
            Assert.False(xaxis.InteriorIntersects(xaxis));
            Assert.True(xaxis.Contains(empty));
            Assert.False(xaxis.InteriorIntersects(empty));
            Assert.True(hemi.Contains(tiny));
            Assert.True(hemi.Contains(new S2Cap(new S2Point(1, 0, 0), S1Angle.FromRadians(S2.M_PI_4 - kEps))));
            Assert.False(hemi.Contains(new S2Cap(new S2Point(1, 0, 0), S1Angle.FromRadians(S2.M_PI_4 + kEps))));
            Assert.True(concave.Contains(hemi));
            Assert.True(concave.InteriorIntersects(hemi.Complement()));
            Assert.False(concave.Contains(S2Cap.FromCenterHeight(-concave.Center, 0.1)));
        }