Exemple #1
0
    // Returns the centroid of the shape multiplied by the measure of the shape,
    // which 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 result is not unit length, so you may need to call
    // Normalize() before passing it to other S2 functions.
    //
    // The result is scaled by the measure defined above 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.  (This requires simply summing the
    // centroids of all shapes in the collection whose dimension is maximal.)
    public static S2Point GetCentroid(S2Shape shape)
    {
        var centroid = S2Point.Empty;

        S2Point[] vertices;
        int       dimension  = shape.Dimension();
        int       num_chains = shape.NumChains();

        for (int chain_id = 0; chain_id < num_chains; ++chain_id)
        {
            switch (dimension)
            {
            case 0:
                centroid += shape.GetEdge(chain_id).V0;
                break;

            case 1:
                GetChainVertices(shape, chain_id, out vertices);
                centroid += S2PolylineMeasures.GetCentroid(vertices);
                break;

            default:
                GetChainVertices(shape, chain_id, out vertices);
                centroid += S2.GetCentroid(vertices.ToList());
                break;
            }
        }
        return(centroid);
    }
        public void Test_GetLengthAndCentroid_GreatCircles()
        {
            // Construct random great circles and divide them randomly into segments.
            // Then make sure that the length and centroid are correct.  Note that
            // because of the way the centroid is computed, it does not matter how
            // we split the great circle into segments.

            for (int iter = 0; iter < 100; ++iter)
            {
                // Choose a coordinate frame for the great circle.
                S2Testing.GetRandomFrame(out var x, out var y, out _);

                var    lineList = new List <S2Point>();
                double theta    = 0;
                while (theta < S2.M_2_PI)
                {
                    lineList.Add(Math.Cos(theta) * x + Math.Sin(theta) * y);
                    theta += S2Testing.Random.RandDouble();
                }
                // Close the circle.
                lineList.Add(lineList[0]);
                var     line   = lineList.ToArray();
                S1Angle length = S2PolylineMeasures.GetLength(line);
                Assert.True(Math.Abs(length.Radians - S2.M_2_PI) <= 2e-14);
                S2Point centroid = S2PolylineMeasures.GetCentroid(line);
                Assert.True(centroid.Norm() <= 2e-14);
            }
        }
Exemple #3
0
    // For shapes of dimension 1, returns the sum of all polyline lengths on the
    // unit sphere.  Otherwise returns zero.  (See GetPerimeter for shapes of
    // dimension 2.)
    //
    // All edges are modeled as spherical geodesics.  The result can be converted
    // to a distance on the Earth's surface (with a worst-case error of 0.562%
    // near the equator) using the functions in s2earth.h.
    public static S1Angle GetLength(S2Shape shape)
    {
        if (shape.Dimension() != 1)
        {
            return(S1Angle.Zero);
        }
        var length     = S1Angle.Zero;
        int num_chains = shape.NumChains();

        for (int chain_id = 0; chain_id < num_chains; ++chain_id)
        {
            GetChainVertices(shape, chain_id, out var vertices);
            length += S2PolylineMeasures.GetLength(vertices);
        }
        return(length);
    }