You are here

function weather_get_nearest_station in Weather 7.3

Same name and namespace in other branches
  1. 7 weather.module \weather_get_nearest_station()
  2. 7.2 weather.common.inc \weather_get_nearest_station()

Return ICAO code of the nearest weather station.

The distance calculation is based on the spherical law of cosines. The bearing is converted from radians to degrees and normalized to be between 0 and 360 degress. The returned value will range from -180° to 180°. All angles must be passed in radians for the trigonometry functions.

R = Earth's radius (using a mean radius of 6371 km) distance = R * acos(sin(lat1) * sin(lat2) + cos(lat1) * cos(lat2)

  • cos(long2 - long1))

bearing = atan2(sin(long2 - long1) * cos(lat2), cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2)

  • cos(long2- long1))

Note: The radius of the earth is multiplied by 10; afterwards, the distance is divided by 10 again. This is because of an implementation detail of ROUND() in PostgreSQL, see #1268844. On MySQL, this results in four digits after the decimal point, so a truncation is necessary.

The CAST(... AS DECIMAL) is necessary for calling the MOD() function in PostgreSQL, see also #1268844.

Parameters

float $latitude: Latitude to be searched.

float $longitude: Longitude to be searched.

Return value

object Object with ICAO code, name, distance, and bearing.

2 calls to weather_get_nearest_station()
weather_block_view in ./weather.module
Implements hook_block_view().
weather_update_7203 in ./weather.install
Convert old locations to new locations.

File

./weather.common.inc, line 288
Common functions in a separate file to reduce size of weather.module.

Code

function weather_get_nearest_station($latitude, $longitude) {
  $sql = "SELECT geoid, name AS displayed_name,\n    ROUND(63710 *\n      ACOS(\n        SIN(RADIANS(:lat)) * SIN(RADIANS(latitude)) +\n        COS(RADIANS(:lat)) * COS(RADIANS(latitude)) * COS(RADIANS(longitude - :long))\n      )) AS distance,\n    MOD(\n      CAST(ROUND(\n        DEGREES(\n          ATAN2(\n            SIN(RADIANS(longitude - :long)) * COS(RADIANS(latitude)),\n            COS(RADIANS(:lat)) * SIN(RADIANS(latitude)) - SIN(RADIANS(:lat)) * COS(RADIANS(latitude)) * COS(RADIANS(longitude - :long))\n          )\n        )\n      ) AS DECIMAL) + 360, 360\n    ) AS bearing\n    FROM {weather_places} ORDER BY distance, displayed_name";
  $result = db_query($sql, array(
    ':lat' => $latitude,
    ':long' => $longitude,
  ))
    ->fetchObject();

  // This cannot be done in the SQL query, because MySQL would return
  // four digits after the decimal point, resulting in an ugly display.
  $result->distance = $result->distance / 10;
  return $result;
}