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