// Given a point X and an edge AB, check that the distance from X to AB is // "distance_radians" and the closest point on AB is "expected_closest". private static void CheckDistance(S2Point x, S2Point a, S2Point b, double distance_radians, S2Point expected_closest) { x = x.Normalize(); a = a.Normalize(); b = b.Normalize(); expected_closest = expected_closest.Normalize(); Assert2.Near(distance_radians, S2.GetDistance(x, a, b).Radians, S2.DoubleError); S2Point closest = S2.Project(x, a, b); Assert.True(S2Pred.CompareEdgeDistance( closest, a, b, new S1ChordAngle(S2.kProjectPerpendicularErrorS1Angle)) < 0); // If X is perpendicular to AB then there is nothing further we can expect. if (distance_radians != S2.M_PI_2) { if (expected_closest == new S2Point()) { // This special value says that the result should be A or B. Assert.True(closest == a || closest == b); } else { Assert.True(S2.ApproxEquals(closest, expected_closest)); } } S1ChordAngle min_distance = S1ChordAngle.Zero; Assert.False(S2.UpdateMinDistance(x, a, b, ref min_distance)); min_distance = S1ChordAngle.Infinity; Assert.True(S2.UpdateMinDistance(x, a, b, ref min_distance)); Assert2.Near(distance_radians, min_distance.ToAngle().Radians, S2.DoubleError); }
private static S1Angle BruteForceDistance(S2LatLngRect a, S2LatLngRect b) { if (a.Intersects(b)) { return(S1Angle.FromRadians(0)); } // Compare every point in 'a' against every latitude edge and longitude edge // in 'b', and vice-versa, for a total of 16 point-vs-latitude-edge tests and // 16 point-vs-longitude-edge tests. var pnt_a = new S2LatLng[4]; var pnt_b = new S2LatLng[4]; pnt_a[0] = new S2LatLng(a.LatLo(), a.LngLo()); pnt_a[1] = new S2LatLng(a.LatLo(), a.LngHi()); pnt_a[2] = new S2LatLng(a.LatHi(), a.LngHi()); pnt_a[3] = new S2LatLng(a.LatHi(), a.LngLo()); pnt_b[0] = new S2LatLng(b.LatLo(), b.LngLo()); pnt_b[1] = new S2LatLng(b.LatLo(), b.LngHi()); pnt_b[2] = new S2LatLng(b.LatHi(), b.LngHi()); pnt_b[3] = new S2LatLng(b.LatHi(), b.LngLo()); // Make arrays containing the lo/hi latitudes and the lo/hi longitude edges. var lat_a = new S1Angle[2] { a.LatLo(), a.LatHi() }; var lat_b = new S1Angle[2] { b.LatLo(), b.LatHi() }; var lng_edge_a = new S2Point[][] { new S2Point[] { pnt_a[0].ToPoint(), pnt_a[3].ToPoint() }, new S2Point[] { pnt_a[1].ToPoint(), pnt_a[2].ToPoint() } }; var lng_edge_b = new S2Point[][] { new S2Point[] { pnt_b[0].ToPoint(), pnt_b[3].ToPoint() }, new S2Point[] { pnt_b[1].ToPoint(), pnt_b[2].ToPoint() } }; S1Angle min_distance = S1Angle.FromDegrees(180.0); for (int i = 0; i < 4; ++i) { // For each point in a and b. var current_a = pnt_a[i]; var current_b = pnt_b[i]; for (int j = 0; j < 2; ++j) { // Get distances to latitude and longitude edges. S1Angle a_to_lat = GetDistance(current_a, lat_b[j], b.Lng); S1Angle b_to_lat = GetDistance(current_b, lat_a[j], a.Lng); S1Angle a_to_lng = S2.GetDistance(current_a.ToPoint(), lng_edge_b[j][0], lng_edge_b[j][1]); S1Angle b_to_lng = S2.GetDistance(current_b.ToPoint(), lng_edge_a[j][0], lng_edge_a[j][1]); min_distance = new[] { min_distance, a_to_lat, b_to_lat, a_to_lng, b_to_lng }.Min(); } } return(min_distance); }
private static S1Angle BruteForceRectPointDistance(S2LatLngRect a, S2LatLng b) { if (a.Contains(b)) { return(S1Angle.FromRadians(0)); } S1Angle b_to_lo_lat = GetDistance(b, a.LatLo(), a.Lng); S1Angle b_to_hi_lat = GetDistance(b, a.LatHi(), a.Lng); S1Angle b_to_lo_lng = S2.GetDistance(b.ToPoint(), new S2LatLng(a.LatLo(), a.LngLo()).ToPoint(), new S2LatLng(a.LatHi(), a.LngLo()).ToPoint()); S1Angle b_to_hi_lng = S2.GetDistance(b.ToPoint(), new S2LatLng(a.LatLo(), a.LngHi()).ToPoint(), new S2LatLng(a.LatHi(), a.LngHi()).ToPoint()); return(new[] { b_to_lo_lat, b_to_hi_lat, b_to_lo_lng, b_to_hi_lng }.Min()); }