public function getRectBound() { if ($this->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 = $this->uv[0][0] + $this->uv[0][1]; $v = $this->uv[1][0] + $this->uv[1][1]; $i = S2Projections::getUAxis($this->face)->z == 0 ? $u < 0 ? 1 : 0 : ($u > 0 ? 1 : 0); $j = S2Projections::getVAxis($this->face)->z == 0 ? $v < 0 ? 1 : 0 : ($v > 0 ? 1 : 0); $lat = R1Interval::fromPointPair($this->getLatitude($i, $j), $this->getLatitude(1 - $i, 1 - $j)); $lat = $lat->expanded(self::MAX_ERROR)->intersection(S2LatLngRect::fullLat()); if ($lat->lo() == -S2::M_PI_2 || $lat->hi() == S2::M_PI_2) { return new S2LatLngRect($lat, S1Interval::full()); } $lng = S1Interval::fromPointPair($this->getLongitude($i, 1 - $j), $this->getLongitude(1 - $i, $j)); return new S2LatLngRect($lat, $lng->expanded(self::MAX_ERROR)); } // The face centers are the +X, +Y, +Z, -X, -Y, -Z axes in that order. // assert (S2Projections.getNorm(face).get(face % 3) == ((face < 3) ? 1 : -1)); switch ($this->face) { case 0: return new S2LatLngRect(new R1Interval(-S2::M_PI_4, S2::M_PI_4), new S1Interval(-S2::M_PI_4, S2::M_PI_4)); case 1: return new S2LatLngRect(new R1Interval(-S2::M_PI_4, S2::M_PI_4), new S1Interval(S2::M_PI_4, 3 * S2::M_PI_4)); case 2: return new S2LatLngRect(new R1Interval(POLE_MIN_LAT, S2::M_PI_2), new S1Interval(-S2::M_PI, S2::M_PI)); case 3: return new S2LatLngRect(new R1Interval(-S2::M_PI_4, S2::M_PI_4), new S1Interval(3 * S2::M_PI_4, -3 * S2::M_PI_4)); case 4: return new S2LatLngRect(new R1Interval(-S2::M_PI_4, S2::M_PI_4), new S1Interval(-3 * S2::M_PI_4, -S2::M_PI_4)); default: return new S2LatLngRect(new R1Interval(-S2::M_PI_2, -POLE_MIN_LAT), new S1Interval(-S2::M_PI, S2::M_PI)); } }