func RectFromPointPair(p1, p2 LatLng) Rect { return Rect{ Lat: r1.IntervalFromPointPair(p1.Lat.Radians(), p2.Lat.Radians()), Lng: s1.IntervalFromPointPair(p1.Lng.Radians(), p2.Lng.Radians()), } }
func (c Cell) RectBound() Rect { if c.level > 0 { // Except for cells at level 0, the latitude and longitude // extremes are attained at the vertices. Furthermore, the // latitude range is determined by one pair of diagonally // opposite vertices and the longitude range is determined by // the other pair. // // We first determine which corner (i,j) of the cell has the // largest absolute latitude. To maximize latitude, we want to // find the point in the cell that has the largest absolute // z-coordinate and the smallest absolute x- and y-coordinates. // To do this we look at each coordinate (u and v), and // determine whether we want to minimize or maximize that // coordinate based on the axis direction and the cell's (u,v) // quadrant. u := c.uv.X.Lo + c.uv.X.Hi v := c.uv.Y.Lo + c.uv.Y.Hi i, j := ijFromFaceZ(c.face, u, v) // We grow the bounds slightly to make sure that the bounding // rectangle also contains the normalized versions of the // vertices. Note that the maximum result magnitude is Pi, with // a floating-point exponent of 1. Therefore adding or // subtracting 2**-51 will always change the result. lat := r1.IntervalFromPointPair(c.Latitude(i, j), c.Latitude(1-i, 1-j)) lat = lat.Expanded(maxError).Intersection(validRectLatRange) if lat.Lo == -M_PI_2 || lat.Hi == M_PI_2 { return Rect{lat, s1.FullInterval()} } lng := s1.IntervalFromPointPair(c.Longitude(i, 1-j), c.Longitude(1-i, j)) return Rect{lat, lng.Expanded(maxError)} } // The 4 cells around the equator extend to +/-45 degrees latitude at // the midpoints of their top and bottom edges. The two cells covering // the poles extend down to +/-35.26 degrees at their vertices. // // The face centers are the +X, +Y, +Z, -X, -Y, -Z axes in that order. switch c.face { case 0: return Rect{ r1.Interval{-M_PI_4, M_PI_4}, s1.Interval{-M_PI_4, M_PI_4}, } case 1: return Rect{ r1.Interval{-M_PI_4, M_PI_4}, s1.Interval{M_PI_4, 3 * M_PI_4}, } case 2: return Rect{ r1.Interval{poleMinLat, M_PI_2}, s1.Interval{-math.Pi, math.Pi}, } case 3: return Rect{ r1.Interval{-M_PI_4, M_PI_4}, s1.Interval{3 * M_PI_4, -3 * M_PI_4}, } case 4: return Rect{ r1.Interval{-M_PI_4, M_PI_4}, s1.Interval{-3 * M_PI_4, -M_PI_4}, } default: return Rect{ r1.Interval{-M_PI_2, -poleMinLat}, s1.Interval{-math.Pi, math.Pi}, } } }