/** * Return true if the edge AB intersects the given edge of constant longitude. */ private static bool IntersectsLngEdge(S2Point a, S2Point b, R1Interval lat, double lng) { // Return true if the segment AB intersects the given edge of constant // longitude. The nice thing about edges of constant longitude is that // they are straight lines on the sphere (geodesics). return(S2.SimpleCrossing(a, b, S2LatLng.FromRadians(lat.Lo, lng) .ToPoint(), S2LatLng.FromRadians(lat.Hi, lng).ToPoint())); }
public void AddPoint(S2Point b) { // assert (S2.isUnitLength(b)); var bLatLng = new S2LatLng(b); if (bound.IsEmpty) { bound = bound.AddPoint(bLatLng); } else { // We can't just call bound.addPoint(bLatLng) here, since we need to // ensure that all the longitudes between "a" and "b" are included. bound = bound.Union(S2LatLngRect.FromPointPair(aLatLng, bLatLng)); // Check whether the Min/Max latitude occurs in the edge interior. // We find the normal to the plane containing AB, and then a vector // "dir" in this plane that also passes through the equator. We use // RobustCrossProd to ensure that the edge normal is accurate even // when the two points are very close together. var aCrossB = S2.RobustCrossProd(a, b); var dir = S2Point.CrossProd(aCrossB, new S2Point(0, 0, 1)); var da = dir.DotProd(a); var db = dir.DotProd(b); if (da * db < 0) { // Minimum/maximum latitude occurs in the edge interior. This affects // the latitude bounds but not the longitude bounds. var absLat = Math.Acos(Math.Abs(aCrossB[2] / aCrossB.Norm)); var lat = bound.Lat; if (da < 0) { // It's possible that absLat < lat.lo() due to numerical errors. lat = new R1Interval(lat.Lo, Math.Max(absLat, bound.Lat.Hi)); } else { lat = new R1Interval(Math.Min(-absLat, bound.Lat.Lo), lat.Hi); } bound = new S2LatLngRect(lat, bound.Lng); } } a = b; aLatLng = bLatLng; }
/** * Construct a rectangle from minimum and maximum latitudes and longitudes. If * lo.Lng > hi.Lng, the rectangle spans the 180 degree longitude line. */ public S2LatLngRect(S2LatLng lo, S2LatLng hi) { _lat = new R1Interval(lo.Lat.Radians, hi.Lat.Radians); _lng = new S1Interval(lo.Lng.Radians, hi.Lng.Radians); // assert (isValid()); }
/** Construct a rectangle from latitude and longitude intervals. */ public S2LatLngRect(R1Interval lat, S1Interval lng) { _lat = lat; _lng = lng; // assert (isValid()); }
/** * Convenience method to construct the minimal bounding rectangle containing * the two given points. This is equivalent to starting with an empty * rectangle and calling AddPoint() twice. Note that it is different than the * S2LatLngRect(lo, hi) constructor, where the first point is always used as * the lower-left corner of the resulting rectangle. */ public static S2LatLngRect FromPointPair(S2LatLng p1, S2LatLng p2) { // assert (p1.isValid() && p2.isValid()); return(new S2LatLngRect(R1Interval.FromPointPair(p1.Lat.Radians, p2.Lat.Radians), S1Interval.FromPointPair(p1.Lng.Radians, p2.Lng.Radians))); }