Ejemplo n.º 1
0
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},
		}
	}
}
Ejemplo n.º 2
0
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()),
	}
}