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