Exemplo n.º 1
0
 public void Test_GetCentroid_Polygon()
 {
     // GetCentroid returns the centroid multiplied by the area of the polygon.
     Assert.True(S2.ApproxEquals(
                     new S2Point(S2.M_PI_4, S2.M_PI_4, S2.M_PI_4),
                     S2.GetCentroid(MakeLaxPolygonOrDie("0:0, 0:90, 90:0"))));
 }
Exemplo n.º 2
0
    // Returns the centroid of all shapes whose dimension is maximal within the
    // index, multiplied by the measure of those shapes.  For example, if the
    // index contains points and polylines, then the result is defined as the
    // centroid of the polylines multiplied by the total length of those
    // polylines.  The points would be ignored when computing the centroid.
    //
    // The measure of a given shape is defined as follows:
    //
    //  - For dimension 0 shapes, the measure is shape.num_edges().
    //  - For dimension 1 shapes, the measure is GetLength(shape).
    //  - For dimension 2 shapes, the measure is GetArea(shape).
    //
    // Note that the centroid is not unit length, so you may need to call
    // Normalize() before passing it to other S2 functions.  Note that this
    // function returns (0, 0, 0) if the index contains no geometry.
    //
    // The centroid is scaled by the total measure of the shapes for two reasons:
    // (1) it is cheaper to compute this way, and (2) this makes it easier to
    // compute the centroid of a collection of shapes (since the individual
    // centroids can simply be summed).
    public static S2Point GetCentroid(S2ShapeIndex index)
    {
        int dim      = GetDimension(index);
        var centroid = S2Point.Empty;

        for (int i = 0; i < index.NumShapeIds(); ++i)
        {
            var shape = index.Shape(i);
            if (shape != null && shape.Dimension() == dim)
            {
                centroid += S2.GetCentroid(shape);
            }
        }
        return(centroid);
    }
Exemplo n.º 3
0
    public void Test_LoopTestBase_GetAreaAndCentroid()
    {
        Assert.Equal(S2.M_4_PI, S2.GetArea(full_));
        Assert.Equal(S2Point.Empty, S2.GetCentroid(full_));

        Assert2.DoubleEqual(S2.GetArea(north_hemi_), S2.M_2_PI);
        Assert2.Near(S2.M_2_PI, S2.GetArea(east_hemi_), 1e-12);

        // Construct spherical caps of random height, and approximate their boundary
        // with closely spaces vertices.  Then check that the area and centroid are
        // correct.
        for (int iter = 0; iter < 50; ++iter)
        {
            // Choose a coordinate frame for the spherical cap.
            S2Testing.GetRandomFrame(out var x, out var y, out var z);

            // Given two points at latitude phi and whose longitudes differ by dtheta,
            // the geodesic between the two points has a maximum latitude of
            // atan(tan(phi) / cos(dtheta/2)).  This can be derived by positioning
            // the two points at (-dtheta/2, phi) and (dtheta/2, phi).
            //
            // We want to position the vertices close enough together so that their
            // maximum distance from the boundary of the spherical cap is kMaxDist.
            // Thus we want Math.Abs(atan(tan(phi) / cos(dtheta/2)) - phi) <= kMaxDist.
            const double kMaxDist   = 1e-6;
            double       height     = 2 * S2Testing.Random.RandDouble();
            double       phi        = Math.Asin(1 - height);
            double       max_dtheta = 2 * Math.Acos(Math.Tan(Math.Abs(phi)) / Math.Tan(Math.Abs(phi) + kMaxDist));
            max_dtheta = Math.Min(Math.PI, max_dtheta);  // At least 3 vertices.

            S2PointLoopSpan loop = new();
            for (double theta = 0; theta < S2.M_2_PI;
                 theta += S2Testing.Random.RandDouble() * max_dtheta)
            {
                loop.Add(Math.Cos(theta) * Math.Cos(phi) * x +
                         Math.Sin(theta) * Math.Cos(phi) * y +
                         Math.Sin(phi) * z);
            }
            double  area          = S2.GetArea(loop);
            S2Point centroid      = S2.GetCentroid(loop);
            double  expected_area = S2.M_2_PI * height;
            Assert.True(Math.Abs(area - expected_area) <= S2.M_2_PI * kMaxDist);
            S2Point expected_centroid = expected_area * (1 - 0.5 * height) * z;
            Assert.True((centroid - expected_centroid).Norm() <= 2 * kMaxDist);
        }
    }
Exemplo n.º 4
0
 public void Test_GetCentroid_Points()
 {
     // GetCentroid() returns the centroid multiplied by the number of points.
     Assert.Equal(new S2Point(1, 1, 0),
                  S2.GetCentroid(MakeIndexOrDie("0:0 | 0:90 # #").Shape(0)));
 }