示例#1
0
    private static S1Angle BruteForceDistance(S2LatLngRect a, S2LatLngRect b)
    {
        if (a.Intersects(b))
        {
            return(S1Angle.FromRadians(0));
        }

        // Compare every point in 'a' against every latitude edge and longitude edge
        // in 'b', and vice-versa, for a total of 16 point-vs-latitude-edge tests and
        // 16 point-vs-longitude-edge tests.
        var pnt_a = new S2LatLng[4];
        var pnt_b = new S2LatLng[4];

        pnt_a[0] = new S2LatLng(a.LatLo(), a.LngLo());
        pnt_a[1] = new S2LatLng(a.LatLo(), a.LngHi());
        pnt_a[2] = new S2LatLng(a.LatHi(), a.LngHi());
        pnt_a[3] = new S2LatLng(a.LatHi(), a.LngLo());
        pnt_b[0] = new S2LatLng(b.LatLo(), b.LngLo());
        pnt_b[1] = new S2LatLng(b.LatLo(), b.LngHi());
        pnt_b[2] = new S2LatLng(b.LatHi(), b.LngHi());
        pnt_b[3] = new S2LatLng(b.LatHi(), b.LngLo());

        // Make arrays containing the lo/hi latitudes and the lo/hi longitude edges.
        var lat_a = new S1Angle[2] {
            a.LatLo(), a.LatHi()
        };
        var lat_b = new S1Angle[2] {
            b.LatLo(), b.LatHi()
        };
        var lng_edge_a = new S2Point[][] { new S2Point[] { pnt_a[0].ToPoint(), pnt_a[3].ToPoint() },
                                           new S2Point[] { pnt_a[1].ToPoint(), pnt_a[2].ToPoint() } };
        var lng_edge_b = new S2Point[][] { new S2Point[] { pnt_b[0].ToPoint(), pnt_b[3].ToPoint() },
                                           new S2Point[] { pnt_b[1].ToPoint(), pnt_b[2].ToPoint() } };

        S1Angle min_distance = S1Angle.FromDegrees(180.0);

        for (int i = 0; i < 4; ++i)
        {
            // For each point in a and b.
            var current_a = pnt_a[i];
            var current_b = pnt_b[i];

            for (int j = 0; j < 2; ++j)
            {
                // Get distances to latitude and longitude edges.
                S1Angle a_to_lat = GetDistance(current_a, lat_b[j], b.Lng);
                S1Angle b_to_lat = GetDistance(current_b, lat_a[j], a.Lng);
                S1Angle a_to_lng = S2.GetDistance(current_a.ToPoint(), lng_edge_b[j][0], lng_edge_b[j][1]);
                S1Angle b_to_lng = S2.GetDistance(current_b.ToPoint(), lng_edge_a[j][0], lng_edge_a[j][1]);

                min_distance = new[] { min_distance, a_to_lat, b_to_lat, a_to_lng, b_to_lng }.Min();
            }
        }
        return(min_distance);
    }
示例#2
0
    private static S1Angle BruteForceRectPointDistance(S2LatLngRect a, S2LatLng b)
    {
        if (a.Contains(b))
        {
            return(S1Angle.FromRadians(0));
        }

        S1Angle b_to_lo_lat = GetDistance(b, a.LatLo(), a.Lng);
        S1Angle b_to_hi_lat = GetDistance(b, a.LatHi(), a.Lng);
        S1Angle b_to_lo_lng = S2.GetDistance(b.ToPoint(), new S2LatLng(a.LatLo(), a.LngLo()).ToPoint(), new S2LatLng(a.LatHi(), a.LngLo()).ToPoint());
        S1Angle b_to_hi_lng = S2.GetDistance(b.ToPoint(), new S2LatLng(a.LatLo(), a.LngHi()).ToPoint(), new S2LatLng(a.LatHi(), a.LngHi()).ToPoint());

        return(new[] { b_to_lo_lat, b_to_hi_lat, b_to_lo_lng, b_to_hi_lng }.Min());
    }
示例#3
0
    public void Test_S2LatLngRect_Accessors()
    {
        // Check various accessor methods.
        S2LatLngRect d1 = RectFromDegrees(-90, 0, -45, 180);

        Assert2.DoubleEqual(d1.LatLo().GetDegrees(), -90);
        Assert2.DoubleEqual(d1.LatHi().GetDegrees(), -45);
        Assert2.DoubleEqual(d1.LngLo().GetDegrees(), 0);
        Assert2.DoubleEqual(d1.LngHi().GetDegrees(), 180);
        Assert.Equal(d1.Lat, new(-S2.M_PI_2, -S2.M_PI_4));
        Assert.Equal(d1.Lng, new(0, Math.PI));
    }
示例#4
0
        static void TestSubdivide(S2Cell cell)
        {
            GatherStats(cell);
            if (cell.IsLeaf())
            {
                return;
            }

            var children = new S2Cell[4];

            Assert.True(cell.Subdivide(children));
            S2CellId child_id     = cell.Id.ChildBegin();
            double   exact_area   = 0;
            double   approx_area  = 0;
            double   average_area = 0;

            for (int i = 0; i < 4; ++i, child_id = child_id.Next())
            {
                exact_area   += children[i].ExactArea();
                approx_area  += children[i].ApproxArea();
                average_area += children[i].AverageArea();

                // Check that the child geometry is consistent with its cell ID.
                Assert.Equal(child_id, children[i].Id);
                Assert.True(S2.ApproxEquals(children[i].Center(), child_id.ToPoint()));
                S2Cell direct = new(child_id);
                Assert.Equal(direct.Face, children[i].Face);
                Assert.Equal(direct.Level, children[i].Level);
                Assert.Equal(direct.Orientation, children[i].Orientation);
                Assert.Equal(direct.CenterRaw(), children[i].CenterRaw());
                for (int k = 0; k < 4; ++k)
                {
                    Assert.Equal(direct.VertexRaw(k), children[i].VertexRaw(k));
                    Assert.Equal(direct.EdgeRaw(k), children[i].EdgeRaw(k));
                }

                // Test Contains() and MayIntersect().
                Assert.True(cell.Contains(children[i]));
                Assert.True(cell.MayIntersect(children[i]));
                Assert.False(children[i].Contains(cell));
                Assert.True(cell.Contains(children[i].CenterRaw()));
                for (int j = 0; j < 4; ++j)
                {
                    Assert.True(cell.Contains(children[i].VertexRaw(j)));
                    if (j != i)
                    {
                        Assert.False(children[i].Contains(children[j].CenterRaw()));
                        Assert.False(children[i].MayIntersect(children[j]));
                    }
                }

                // Test GetCapBound and GetRectBound.
                S2Cap        parent_cap  = cell.GetCapBound();
                S2LatLngRect parent_rect = cell.GetRectBound();
                if (cell.Contains(new S2Point(0, 0, 1)) || cell.Contains(new S2Point(0, 0, -1)))
                {
                    Assert.True(parent_rect.Lng.IsFull());
                }
                S2Cap        child_cap  = children[i].GetCapBound();
                S2LatLngRect child_rect = children[i].GetRectBound();
                Assert.True(child_cap.Contains(children[i].Center()));
                Assert.True(child_rect.Contains(children[i].CenterRaw()));
                Assert.True(parent_cap.Contains(children[i].Center()));
                Assert.True(parent_rect.Contains(children[i].CenterRaw()));
                for (int j = 0; j < 4; ++j)
                {
                    Assert.True(child_cap.Contains(children[i].Vertex(j)));
                    Assert.True(child_rect.Contains(children[i].Vertex(j)));
                    Assert.True(child_rect.Contains(children[i].VertexRaw(j)));
                    Assert.True(parent_cap.Contains(children[i].Vertex(j)));
                    Assert.True(parent_rect.Contains(children[i].Vertex(j)));
                    Assert.True(parent_rect.Contains(children[i].VertexRaw(j)));
                    if (j != i)
                    {
                        // The bounding caps and rectangles should be tight enough so that
                        // they exclude at least two vertices of each adjacent cell.
                        int cap_count  = 0;
                        int rect_count = 0;
                        for (int k = 0; k < 4; ++k)
                        {
                            if (child_cap.Contains(children[j].Vertex(k)))
                            {
                                ++cap_count;
                            }
                            if (child_rect.Contains(children[j].VertexRaw(k)))
                            {
                                ++rect_count;
                            }
                        }
                        Assert.True(cap_count <= 2);
                        if (child_rect.LatLo().Radians > -S2.M_PI_2 &&
                            child_rect.LatHi().Radians < S2.M_PI_2)
                        {
                            // Bounding rectangles may be too large at the poles because the
                            // pole itself has an arbitrary fixed longitude.
                            Assert.True(rect_count <= 2);
                        }
                    }
                }

                // Check all children for the first few levels, and then sample randomly.
                // We also always subdivide the cells containing a few chosen points so
                // that we have a better chance of sampling the minimum and maximum metric
                // values.  kMaxSizeUV is the absolute value of the u- and v-coordinate
                // where the cell size at a given level is maximal.
                double    kMaxSizeUV = 0.3964182625366691;
                R2Point[] special_uv =
                {
                    new R2Point(S2.DoubleEpsilon, S2.DoubleEpsilon), // Face center
                    new R2Point(S2.DoubleEpsilon, 1),                // Edge midpoint
                    new R2Point(1, 1),                               // Face corner
                    new R2Point(kMaxSizeUV, kMaxSizeUV),             // Largest cell area
                    new R2Point(S2.DoubleEpsilon, kMaxSizeUV),       // Longest edge/diagonal
                };
                bool force_subdivide = false;
                foreach (R2Point uv in special_uv)
                {
                    if (children[i].BoundUV.Contains(uv))
                    {
                        force_subdivide = true;
                    }
                }

                var debugFlag =
#if s2debug
                    true;
#else
                    false;
#endif

                if (force_subdivide ||
                    cell.Level < (debugFlag ? 5 : 6) ||
                    S2Testing.Random.OneIn(debugFlag ? 5 : 4))
                {
                    TestSubdivide(children[i]);
                }
            }

            // Check sum of child areas equals parent area.
            //
            // For ExactArea(), the best relative error we can expect is about 1e-6
            // because the precision of the unit vector coordinates is only about 1e-15
            // and the edge length of a leaf cell is about 1e-9.
            //
            // For ApproxArea(), the areas are accurate to within a few percent.
            //
            // For AverageArea(), the areas themselves are not very accurate, but
            // the average area of a parent is exactly 4 times the area of a child.

            Assert.True(Math.Abs(Math.Log(exact_area / cell.ExactArea())) <= Math.Abs(Math.Log((1 + 1e-6))));
            Assert.True(Math.Abs(Math.Log((approx_area / cell.ApproxArea()))) <= Math.Abs(Math.Log((1.03))));
            Assert.True(Math.Abs(Math.Log((average_area / cell.AverageArea()))) <= Math.Abs(Math.Log((1 + 1e-15))));
        }