Relative position in PHP between two dots (Lat / Long)
I have a database of airports with latitude and longitude for each point. I want to run a PHP script to find all the airports near a given airport with their distance and relative direction.
those. for KLDJ airport (40-37-02.810N 074-14-40.539W)
Nearby airport
KJFK - John F. Kennedy Airport (21.2 nm NE) (40-38-23.104N 073-46-44.132W)
I used the code http://www.movable-type.co.uk/scripts/latlong.html to find the distance and tried to use it to find the prop, which might be wrong.
//BEARING RHUMB LINE
$phi = log(tan($lat2/2+pi/4)/tan($lat1/2+pi/4));
$distance['bearing'] = (rad2deg(atan2($theta, $phi)) +180) % 360;
I basically want to run all points through this script and find the distance I already have, but then the direction. (i.e. N, S, W, E, NW, SW, NE, SE)
a source to share
Heavy borrowing from the methods here and using the data here , I put together this example
<?php
$chicago = array(
'lat' => 41.9
, 'lng' => 87.65
);
$dallas = array(
'lat' => 32.73
, 'lng' => 96.97
);
$ftworth = array(
'lat' => 32.82
, 'lng' => 97.35
);
$bearing = getBearingBetweenPoints( $dallas, $chicago );
echo "Bearing: $bearing°<br>";
echo "Direction: " . getCompassDirection( $bearing );
function getBearingBetweenPoints( $point1, $point2 )
{
return getRhumbLineBearing( $point1['lat'], $point2['lng'], $point2['lat'], $point1['lng'] );
}
function getRhumbLineBearing($lat1, $lon1, $lat2, $lon2) {
//difference in longitudinal coordinates
$dLon = deg2rad($lon2) - deg2rad($lon1);
//difference in the phi of latitudinal coordinates
$dPhi = log(tan(deg2rad($lat2) / 2 + pi() / 4) / tan(deg2rad($lat1) / 2 + pi() / 4));
//we need to recalculate $dLon if it is greater than pi
if(abs($dLon) > pi()) {
if($dLon > 0) {
$dLon = (2 * pi() - $dLon) * -1;
}
else {
$dLon = 2 * pi() + $dLon;
}
}
//return the angle, normalized
return (rad2deg(atan2($dLon, $dPhi)) + 360) % 360;
}
function getCompassDirection( $bearing )
{
static $cardinals = array( 'N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N' );
return $cardinals[round( $bearing / 45 )];
}
a source to share
You can check if the latitude of position B is greater or less than the latitude of position A to determine if it is in the east or west. It's the same with longitude for north and south. Finally, you need a threshold to detect, in which case the drift is large enough to go in an intermediate direction.
a source to share
Check out another page from the same site :
$lat = 0; // latitude of centre of bounding circle in degrees
$lon = 0; // longitude of centre of bounding circle in degrees
$rad = 0; // radius of bounding circle in chosen units
// Choose your unit of measure...
$r = 6371; // earth radius in km
$r = 3959; // earth radius in miles
// or
$r = 3440; // earth radius in nautical miles
// convert point of origin to radians
$lat = deg2rad($lat);
$lon = deg2rad($lon);
// first-cut bounding box (in radians)
$maxLat = $lat + $rad / $r;
$minLat = $lat - $rad / $r;
// compensate for longitude getting smaller with increasing latitude
$maxLon = ( $lon + $rad / $r ) / cos( $lat );
$minLon = ( $lon - $rad / $r ) / cos( $lat );
combined with a request:
$query = 'SELECT
id
, lat
, lon
, ACOS(SIN('.$lat.') * SIN(RADIANS(lat)) + COS('.$lat.') * COS(RADIANS(lat)) * COS(RADIANS(lon) - '. $lon.')) * '.$r.' AS distance
FROM (
SELECT
id
, lat
, lon
FROM MyTable
WHERE
RADIANS(lat) > $minLat AND RADIANS(lat) < '.$maxLat.'
AND
RADIANS(lon) > $minLon AND RADIANS(lon) < '.$maxLon.'
) AS FirstCut
WHERE ACOS(SIN('.$lat.') * SIN(RADIANS(lat)) + COS('.$lat.') * COS(RADIANS(lat)) * COS(RADIANS(lon) - '. $lon.')) * '.$r.' < '.$rad;
Selects a list of locations (and their distance from the start of your circle) within the specified circle.
All that remains is to compute the bearing for the returned locations. What can you do with your line formula.
The above assumes your database is populated with coordinates in degrees.
If you had locations saved as geometry objects, you can use MySQL's built-in spatial functions . Though I'm pretty sure MySQL only includes bounding boxes.
a source to share