private static S2Point PerturbATowardsB(S2Point a, S2Point b) { var choice = S2Testing.Random.RandDouble(); if (choice < 0.1) { return(a); } if (choice < 0.3) { // Return a point that is exactly proportional to A and that still // satisfies S2.IsUnitLength(). for (; ;) { var b2 = (2 - a.Norm() + 5 * (S2Testing.Random.RandDouble() - 0.5) * S2.DoubleEpsilon) * a; if (b2 != a && b2.IsUnitLength()) { return(b2); } } } if (choice < 0.5) { // Return a point such that the distance squared to A will underflow. return(S2.InterpolateAtDistance(S1Angle.FromRadians(1e-300), a, b)); } // Otherwise return a point whose distance from A is near S2Constants.DoubleEpsilon such // that the log of the pdf is uniformly distributed. double distance = S2.DoubleEpsilon * 1e-5 * Math.Pow(1e6, S2Testing.Random.RandDouble()); return(S2.InterpolateAtDistance(S1Angle.FromRadians(distance), a, b)); }
public void Test_EdgeTrueCentroid_GreatCircles() { // Construct random great circles and divide them randomly into segments. // Then make sure that the centroid is approximately at the center of the // sphere. Note that because of the way the centroid is computed, it does // not matter how we split the great circle into segments. // // Note that this is a direct test of the properties that the centroid // should have, rather than a test that it matches a particular formula. for (int iter = 0; iter < 100; ++iter) { // Choose a coordinate frame for the great circle. S2Point centroid = S2Point.Empty; S2Testing.GetRandomFrame(out var x, out var y, out _); S2Point v0 = x; for (double theta = 0; theta < S2.M_2_PI; theta += Math.Pow(S2Testing.Random.RandDouble(), 10)) { S2Point v1 = Math.Cos(theta) * x + Math.Sin(theta) * y; centroid += S2Centroid.TrueCentroid(v0, v1); v0 = v1; } // Close the circle. centroid += S2Centroid.TrueCentroid(v0, x); Assert.True(centroid.Norm() <= 2e-14); } }
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); } }
public void Test_EdgeTrueCentroid_SemiEquator() { // Test the centroid of polyline ABC that follows the equator and consists // of two 90 degree edges (i.e., C = -A). The centroid (multiplied by // length) should point toward B and have a norm of 2.0. (The centroid // itself has a norm of 2/Pi, and the total edge length is Pi.) S2Point a = new(0, -1, 0), b = new(1, 0, 0), c = new(0, 1, 0); S2Point centroid = S2Centroid.TrueCentroid(a, b) + S2Centroid.TrueCentroid(b, c); Assert.True(S2.ApproxEquals(b, centroid.Normalize())); Assert2.DoubleEqual(2.0, centroid.Norm()); }