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