You are here

function weather_get_nearest_station in Weather 7

Same name and namespace in other branches
  1. 7.3 weather.common.inc \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.

1 call to weather_get_nearest_station()
weather_block_view in ./weather.module
Implement hook_block_view().

File

./weather.module, line 627
Display current weather data from many places in the world.

Code

function weather_get_nearest_station($latitude, $longitude) {
  $sql = "SELECT icao, name AS real_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_icao} ORDER BY distance, real_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;
}