/** * Returns the shortest distance from a point P to this loop, given as the * angle formed between P, the origin and the nearest point on the loop to P. * This angle in radians is equivalent to the arclength along the unit sphere. */ public S1Angle GetDistance(S2Point p) { var normalized = S2Point.Normalize(p); // The furthest point from p on the sphere is its antipode, which is an // angle of PI radians. This is an upper bound on the angle. var minDistance = S1Angle.FromRadians(Math.PI); for (var i = 0; i < NumVertices; i++) { minDistance = S1Angle.Min(minDistance, S2EdgeUtil.GetDistance(normalized, Vertex(i), Vertex(i + 1))); } return(minDistance); }
/** * Return the area of the polygon interior, i.e. the region on the left side * of an odd number of loops (this value return value is between 0 and 4*Pi) * and the true centroid of the polygon multiplied by the area of the polygon * (see s2.h for details on centroids). Note that the centroid may not be * contained by the polygon. */ /** * Returns the shortest distance from a point P to this polygon, given as the * angle formed between P, the origin and the nearest point on the polygon to * P. This angle in radians is equivalent to the arclength along the unit * sphere. * * If the point is contained inside the polygon, the distance returned is 0. */ public S1Angle GetDistance(S2Point p) { if (Contains(p)) { return(S1Angle.FromRadians(0)); } // The furthest point from p on the sphere is its antipode, which is an // angle of PI radians. This is an upper bound on the angle. var minDistance = S1Angle.FromRadians(Math.PI); for (var i = 0; i < NumLoops; i++) { minDistance = S1Angle.Min(minDistance, Loop(i).GetDistance(p)); } return(minDistance); }
/** * Return the minimum distance (measured along the surface of the sphere) to * the given S2LatLngRect. Both S2LatLngRects must be non-empty. */ public S1Angle GetDistance(S2LatLngRect other) { var a = this; var b = other; Preconditions.CheckState(!a.IsEmpty); Preconditions.CheckArgument(!b.IsEmpty); // First, handle the trivial cases where the longitude intervals overlap. if (a.Lng.Intersects(b.Lng)) { if (a.Lat.Intersects(b.Lat)) { return(S1Angle.FromRadians(0)); // Intersection between a and b. } // We found an overlap in the longitude interval, but not in the latitude // interval. This means the shortest path travels along some line of // longitude connecting the high-latitude of the lower rect with the // low-latitude of the higher rect. S1Angle lo, hi; if (a.Lat.Lo > b.Lat.Hi) { lo = b.LatHi; hi = a.LatLo; } else { lo = a.LatHi; hi = b.LatLo; } return(S1Angle.FromRadians(hi.Radians - lo.Radians)); } // The longitude intervals don't overlap. In this case, the closest points // occur somewhere on the pair of longitudinal edges which are nearest in // longitude-space. S1Angle aLng, bLng; var loHi = S1Interval.FromPointPair(a.Lng.Lo, b.Lng.Hi); var hiLo = S1Interval.FromPointPair(a.Lng.Hi, b.Lng.Lo); if (loHi.Length < hiLo.Length) { aLng = a.LngLo; bLng = b.LngHi; } else { aLng = a.LngHi; bLng = b.LngLo; } // The shortest distance between the two longitudinal segments will include // at least one segment endpoint. We could probably narrow this down further // to a single point-edge distance by comparing the relative latitudes of the // endpoints, but for the sake of clarity, we'll do all four point-edge // distance tests. var aLo = new S2LatLng(a.LatLo, aLng).ToPoint(); var aHi = new S2LatLng(a.LatHi, aLng).ToPoint(); var aLoCrossHi = S2LatLng.FromRadians(0, aLng.Radians - S2.PiOver2).Normalized.ToPoint(); var bLo = new S2LatLng(b.LatLo, bLng).ToPoint(); var bHi = new S2LatLng(b.LatHi, bLng).ToPoint(); var bLoCrossHi = S2LatLng.FromRadians(0, bLng.Radians - S2.PiOver2).Normalized.ToPoint(); return(S1Angle.Min(S2EdgeUtil.GetDistance(aLo, bLo, bHi, bLoCrossHi), S1Angle.Min(S2EdgeUtil.GetDistance(aHi, bLo, bHi, bLoCrossHi), S1Angle.Min(S2EdgeUtil.GetDistance(bLo, aLo, aHi, aLoCrossHi), S2EdgeUtil.GetDistance(bHi, aLo, aHi, aLoCrossHi))))); }