PHP calculate lat/lng of the square around a given point on the surface?
Given latitude/longitude of a point of earth surface (and a distance, say in kilometers) i need to compute the top-left, top-right, bottom-right and bottom-left coordinates. No matter the orientation of the square.
I've f开发者_开发技巧ound a nice PHP class for computing the distance between two point on the surface but unfortunately there is no function about a square (or even a circle) around a point.
This may work for you. The approach here is to find the destination points from the given point from due north, due east, due west, and due south. The function getSquareAroundPoint
returns an array specifying these four points, and the function getMinMaxCoords
returns the minimum and maximum coordinates of these points, as required by the REST API you mention (it's returned as an array of an array, in case the input coordinate is near the 180-degree meridian.) It's placed in the public domain.
The approach includes finding a destination point given coordinates, distance, and bearing. This calculation is called solving the "direct geodesic problem", and this is discussed in C.F.F. Karney's article "Algorithms for geodesics", 2012. The getDestinationPoint
method below uses a technique that is less accurate than the algorithms presented in Karney's article, especially because the technique assumes Earth is a perfect sphere.
// Distance is in km, alat and alon are in degrees
function getDestinationPoint($alat, $alon, $distance, $bearing){
$pi=3.14159265358979;
$alatRad=$alat*$pi/180;
$alonRad=$alon*$pi/180;
$bearing=$bearing*$pi/180;
$alatRadSin=sin($alatRad);
$alatRadCos=cos($alatRad);
// Ratio of distance to earth's radius
$angularDistance=$distance/6370.997;
$angDistSin=sin($angularDistance);
$angDistCos=cos($angularDistance);
$xlatRad = asin( $alatRadSin*$angDistCos +
$alatRadCos*$angDistSin*cos($bearing) );
$xlonRad = $alonRad + atan2(
sin($bearing)*$angDistSin*$alatRadCos,
$angDistCos-$alatRadSin*sin($xlatRad));
// Return latitude and longitude as two element array in degrees
$xlat=$xlatRad*180/$pi;
$xlon=$xlonRad*180/$pi;
if($xlat>90)$xlat=90;
if($xlat<-90)$xlat=-90;
while($xlat>180)$xlat-=360;
while($xlat<=-180)$xlat+=360;
while($xlon>180)$xlon-=360;
while($xlon<=-180)$xlon+=360;
return array($xlat,$xlon);
}
// Distance is in km, lat and lon are in degrees
function getSquareAroundPoint($lat,$lon,$distance){
return array(
getDestinationPoint($lat,$lon,$distance,0), // Get north point
getDestinationPoint($lat,$lon,$distance,90), // Get east point
getDestinationPoint($lat,$lon,$distance,180), // Get south point
getDestinationPoint($lat,$lon,$distance,270) // Get west point
);
}
// Returns array containing an array with min lat, max lat, min lon, max lon
// If the square defining these points crosses the 180-degree meridian, two
// such arrays are returned. Otherwise, one such array (within another array)
// is returned.
function getMinMaxCoords($lat,$lon,$distance){
$s=getSquareAroundPoint($lat,$lon,$distance);
if($s[3][1]>$s[1][1]){// if west longitude is greater than south longitude
// Crossed the 180-degree meridian
return array(
array($s[2][0],$s[0][0],$s[3][1],180),
array($s[2][0],$s[0][0],-180,$s[1][1])
);
} else {
// Didn't cross the 180-degree meridian (usual case)
return array(
array($s[2][0],$s[0][0],$s[3][1],$s[1][1])
);
}
}
// Example: Gets extreme coordinates around point at (10.0,20.0)
print_r(getSquareAroundPoint(10.0,180,100));
print_r(getMinMaxCoords(10.0,180,100));
精彩评论