/** * <p>Computes the bounding coordinates of all points on the surface * of a sphere that have a great circle distance to the point represented * by this GeoLocation instance that is less or equal to the distance * argument.</p> * <p>For more information about the formulae used in this method visit * <a href="http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates"> * http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates</a>.</p> * * @param double $distance the distance from the point represented by this * GeoLocation instance. Must me measured in the same unit as the radius * argument. * @param string $unit_of_measurement * @throws \Exception * @internal param radius the radius of the sphere, e.g. the average radius for a * spherical approximation of the figure of the Earth is approximately * 6371.01 kilometers. * @return GeoLocation[] an array of two GeoLocation objects such that:<ul> * <li>The latitude of any point within the specified distance is greater * or equal to the latitude of the first array element and smaller or * equal to the latitude of the second array element.</li> * <li>If the longitude of the first array element is smaller or equal to * the longitude of the second element, then * the longitude of any point within the specified distance is greater * or equal to the longitude of the first array element and smaller or * equal to the longitude of the second array element.</li> * <li>If the longitude of the first array element is greater than the * longitude of the second element (this is the case if the 180th * meridian is within the distance), then * the longitude of any point within the specified distance is greater * or equal to the longitude of the first array element * <strong>or</strong> smaller or equal to the longitude of the second * array element.</li> * </ul> */ public function boundingCoordinates($distance, $unit_of_measurement) { $radius = $this->getEarthsRadius($unit_of_measurement); if ($radius < 0 || $distance < 0) throw new \Exception('Arguments must be greater than 0.'); // angular distance in radians on a great circle $this->angular = $distance / $radius; $minLat = $this->radLat - $this->angular; $maxLat = $this->radLat + $this->angular; $minLon = 0; $maxLon = 0; if ($minLat > self::$MIN_LAT && $maxLat < self::$MAX_LAT) { $deltaLon = asin(sin($this->angular) / cos($this->radLat)); $minLon = $this->radLon - $deltaLon; if ($minLon < self::$MIN_LON) $minLon += 2 * pi(); $maxLon = $this->radLon + $deltaLon; if ($maxLon > self::$MAX_LON) $maxLon -= 2 * pi(); } else { // a pole is within the distance $minLat = max($minLat, self::$MIN_LAT); $maxLat = min($maxLat, self::$MAX_LAT); $minLon = self::$MIN_LON; $maxLon = self::$MAX_LON; } return array( GeoLocation::fromRadians($minLat, $minLon), GeoLocation::fromRadians($maxLat, $maxLon) ); }
/** * <p>Computes the bounding coordinates of all points on the surface * of a sphere that have a great circle distance to the point represented * by this GeoLocation instance that is less or equal to the distance * argument.</p> * <p>For more information about the formulae used in this method visit * <a href="http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates"> * http://JanMatuschek.de/LatitudeLongitudeBoundingCoordinates</a>.</p> * @param distance the distance from the point represented by this * GeoLocation instance. Must me measured in the same unit as the radius * argument. * @param radius the radius of the sphere, e.g. the average radius for a * spherical approximation of the figure of the Earth is approximately * 6371.01 kilometers. * @return an array of two GeoLocation objects such that:<ul> * <li>The latitude of any point within the specified distance is greater * or equal to the latitude of the first array element and smaller or * equal to the latitude of the second array element.</li> * <li>If the longitude of the first array element is smaller or equal to * the longitude of the second element, then * the longitude of any point within the specified distance is greater * or equal to the longitude of the first array element and smaller or * equal to the longitude of the second array element.</li> * <li>If the longitude of the first array element is greater than the * longitude of the second element (this is the case if the 180th * meridian is within the distance), then * the longitude of any point within the specified distance is greater * or equal to the longitude of the first array element * <strong>or</strong> smaller or equal to the longitude of the second * array element.</li> * </ul> */ public function boundingCoordinates($distance, $radius) { if ($radius < 0 || $distance < 0) { throw new Exception('Arguments must be greater than 0.'); } // angular distance in radians on a great circle $radDist = $distance / $radius; $minLat = $this->radLat - $radDist; $maxLat = $this->radLat + $radDist; $minLon = 0; $maxLon = 0; if ($minLat > MIN_LAT && $maxLat < MAX_LAT) { $deltaLon = asin(sin($radDist) / cos($this->radLat)); $minLon = $this->radLon - $deltaLon; if ($minLon < MIN_LON) { $minLon += 2 * pi(); } $maxLon = $this->radLon + $deltaLon; if ($maxLon > MAX_LON) { $maxLon -= 2 * pi(); } } else { // a pole is within the distance $minLat = max($minLat, MIN_LAT); $maxLat = min($maxLat, MAX_LAT); $minLon = MIN_LON; $maxLon = MAX_LON; } return array(GeoLocation::fromRadians($minLat, $minLon), GeoLocation::fromRadians($maxLat, $maxLon)); }