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