public void Test_S1ChordAngle_ArithmeticPrecision() { // Verifies that S1ChordAngle is capable of adding and subtracting angles // extremely accurately up to Pi/2 radians. (Accuracy continues to be good // well beyond this value but degrades as angles approach Pi.) S1ChordAngle kEps = S1ChordAngle.FromRadians(1e-15); S1ChordAngle k90 = S1ChordAngle.Right; S1ChordAngle k90MinusEps = k90 - kEps; S1ChordAngle k90PlusEps = k90 + kEps; double kMaxError = 2 * S2.DoubleEpsilon; Assert2.Near(k90MinusEps.Radians(), S2.M_PI_2 - kEps.Radians(), kMaxError); Assert2.Near(k90PlusEps.Radians(), S2.M_PI_2 + kEps.Radians(), kMaxError); Assert2.Near((k90 - k90MinusEps).Radians(), kEps.Radians(), kMaxError); Assert2.Near((k90PlusEps - k90).Radians(), kEps.Radians(), kMaxError); Assert2.Near((k90MinusEps + kEps).Radians(), S2.M_PI_2, kMaxError); }
private static void CheckMaxDistance(S2Point x, S2Point a, S2Point b, double distance_radians) { x = x.Normalize(); a = a.Normalize(); b = b.Normalize(); S1ChordAngle max_distance = S1ChordAngle.Straight; Assert.False(S2.UpdateMaxDistance(x, a, b, ref max_distance)); max_distance = S1ChordAngle.Negative; Assert.True(S2.UpdateMaxDistance(x, a, b, ref max_distance)); Assert2.Near(distance_radians, max_distance.Radians(), S2.DoubleError); }
// Given two edges a0a1 and b0b1, check that the maximum distance between them // is "distance_radians". Parameters are passed by value so that this // function can normalize them. private static void CheckEdgePairMaxDistance(S2Point a0, S2Point a1, S2Point b0, S2Point b1, double distance_radians) { a0 = a0.Normalize(); a1 = a1.Normalize(); b0 = b0.Normalize(); b1 = b1.Normalize(); S1ChordAngle max_distance = S1ChordAngle.Straight; Assert.False(S2.UpdateEdgePairMaxDistance(a0, a1, b0, b1, ref max_distance)); max_distance = S1ChordAngle.Negative; Assert.True(S2.UpdateEdgePairMaxDistance(a0, a1, b0, b1, ref max_distance)); Assert2.Near(distance_radians, max_distance.Radians(), S2.DoubleError); }
public void Test_S2Cell_GetMaxDistanceToEdge() { // Test an edge for which its antipode crosses the cell. Validates both the // standard and brute force implementations for this case. S2Cell cell = S2Cell.FromFacePosLevel(0, 0, 20); S2Point a = -S2.Interpolate(2.0, cell.Center(), cell.Vertex(0)); S2Point b = -S2.Interpolate(2.0, cell.Center(), cell.Vertex(2)); S1ChordAngle actual = cell.MaxDistance(a, b); S1ChordAngle expected = GetMaxDistanceToEdgeBruteForce(cell, a, b); Assert2.Near(expected.Radians(), S1ChordAngle.Straight.Radians(), S2.DoubleError); Assert2.Near(actual.Radians(), S1ChordAngle.Straight.Radians(), S2.DoubleError); }
public void Test_S2Cell_GetMaxDistanceToCell() { for (int i = 0; i < 1000; i++) { S2Cell cell = new(S2Testing.GetRandomCellId()); S2Cell test_cell = new(S2Testing.GetRandomCellId()); S2CellId antipodal_leaf_id = new(-test_cell.Center()); S2Cell antipodal_test_cell = new(antipodal_leaf_id.Parent(test_cell.Level)); S1ChordAngle dist_from_min = S1ChordAngle.Straight - cell.Distance(antipodal_test_cell); S1ChordAngle dist_from_max = cell.MaxDistance(test_cell); Assert2.Near(dist_from_min.Radians(), dist_from_max.Radians(), 1e-8); } }
// Given two edges a0a1 and b0b1, check that the minimum distance between them // is "distance_radians", and that GetEdgePairClosestPoints() returns // "expected_a" and "expected_b" as the points that achieve this distance. // S2Point.Empty may be passed for "expected_a" or "expected_b" to indicate // that both endpoints of the corresponding edge are equally distant, and // therefore either one might be returned. // // Parameters are passed by value so that this function can normalize them. private static void CheckEdgePairMinDistance(S2Point a0, S2Point a1, S2Point b0, S2Point b1, double distance_radians, S2Point expected_a, S2Point expected_b) { a0 = a0.Normalize(); a1 = a1.Normalize(); b0 = b0.Normalize(); b1 = b1.Normalize(); expected_a = expected_a.Normalize(); expected_b = expected_b.Normalize(); var closest = S2.GetEdgePairClosestPoints(a0, a1, b0, b1); S2Point actual_a = closest.Item1; S2Point actual_b = closest.Item2; if (expected_a == S2Point.Empty) { // This special value says that the result should be a0 or a1. Assert.True(actual_a == a0 || actual_a == a1); } else { Assert.True(S2.ApproxEquals(expected_a, actual_a)); } if (expected_b == S2Point.Empty) { // This special value says that the result should be b0 or b1. Assert.True(actual_b == b0 || actual_b == b1); } else { Assert.True(S2.ApproxEquals(expected_b, actual_b)); } S1ChordAngle min_distance = S1ChordAngle.Zero; Assert.False(S2.UpdateEdgePairMinDistance(a0, a1, b0, b1, ref min_distance)); min_distance = S1ChordAngle.Infinity; Assert.True(S2.UpdateEdgePairMinDistance(a0, a1, b0, b1, ref min_distance)); Assert2.Near(distance_radians, min_distance.Radians(), S2.DoubleError); }