PHP:基于中心经纬度和距离查找纬度和经度边界

8
我正在处理一个与类似问题的解决方案,并在实施中发现它返回的坐标是一个高矩形而不是正方形(请参见其他问题中Matthias的答案)。
我只需要返回一个数组,因为这是与WordPress一起使用的,其有自己首选的查询方法。
以下是我的实现:
function bar_get_nearby( $lat, $lng, $limit = 50, $distance = 50, $unit = 'mi' ) {
    
    // radius of earth; @note: the earth is not perfectly spherical, but this is considered the 'mean radius'
    if( $unit == 'km' ) { $radius = 6371.009; }
    elseif ( $unit == 'mi' ) { $radius = 3958.761; }

    // latitude boundaries
    $maxLat = ( float ) $lat + rad2deg( $distance / $radius );
    $minLat = ( float ) $lat - rad2deg( $distance / $radius );

    // longitude boundaries (longitude gets smaller when latitude increases)
    $maxLng = ( float ) $lng + rad2deg( $distance / $radius / cos( deg2rad( ( float ) $lat ) ) );
    $minLng = ( float ) $lng - rad2deg( $distance / $radius / cos( deg2rad( ( float ) $lat ) ) );

    $max_min_values = array(
        'max_latitude' => $maxLat,
        'min_latitude' => $minLat,
        'max_longitude' => $maxLng,
        'min_longitude' => $minLng
    );
    
    return $max_min_values;
    
}

如果我通过Google Maps API输入G2 1QX这个邮政编码并选择5英里的距离,我将得到经纬度为-4.2556347 / 55.8620472的坐标,并返回以下数组:

Array
(
    [max_latitude] => -4.18326890233
    [min_latitude] => -4.32800049767
    [max_longitude] => 55.9346130696
    [min_longitude] => 55.7894813304
)

有什么想法吗?非常感谢提前。

祝好, RS

3个回答

8

这是您的函数,经过我的修改,它将提供正方形坐标而不是高矩形:

function bar_get_nearby( $lat, $lng, $limit = 50, $distance = 50, $unit = 'mi' ) {
    // radius of earth; @note: the earth is not perfectly spherical, but this is considered the 'mean radius'
    if( $unit == 'km' ) { $radius = 6371.009; }
    elseif ( $unit == 'mi' ) { $radius = 3958.761; }

    // latitude boundaries
    $maxLat = ( float ) $lat + rad2deg( $distance / $radius );
    $minLat = ( float ) $lat - rad2deg( $distance / $radius );

    // longitude boundaries (longitude gets smaller when latitude increases)
    $maxLng = ( float ) $lng + rad2deg( $distance / $radius) / cos( deg2rad( ( float ) $lat ) );
    $minLng = ( float ) $lng - rad2deg( $distance / $radius) / cos( deg2rad( ( float ) $lat ) );

    $max_min_values = array(
        'max_latitude' => $maxLat,
        'min_latitude' => $minLat,
        'max_longitude' => $maxLng,
        'min_longitude' => $minLng
    );

    return $max_min_values;
}

Cheers,

Rupesh Kamble


1
非常感谢您的好方法。不过这里有一个小错误:在maxLng和minLng中,删除第一部分除法周围的括号。只需将rad2deg($distance/$radius)相除,而不是$lng,否则结果会偏差很大。 - Tim Bodeit
谢谢,Tim。正确的代码是:$maxLng = ( float ) $lng + rad2deg( $distance / $radius) / cos( deg2rad( ( float ) $lat ) ); $minLng = ( float ) $lng - rad2deg( $distance / $radius) / cos( deg2rad( ( float ) $lat ) ); - dsomnus

0

我曾经编写过这个函数,用于计算两点之间的距离,单位为公里(km),而不是英里。我对英里答案进行了快速修改。

/**
 * The Haversine function can be used to calculate the distance between 2 points on a map
 *
 * @param  float $lat1 The longtitude value of the first point
 * @param  float $lon1 The lattitude of the frist point
 * @param  float $lat2 The longtitude value of the second point
 * @param  float $lon2 The lattitude of the second point
 * @return float       The distance between the points in mile
 *
 * @access public
 **/
public function harversineDistance($lat1, $lon1, $lat2, $lon2)
{
    $latd = deg2rad($lat2 - $lat1);
    $lond = deg2rad($lon2 - $lon1);
    $a = sin($latd / 2) * sin($latd / 2) +
        cos(deg2rad($lat1)) * cos(deg2rad($lat2)) *
        sin($lond / 2) * sin($lond / 2);
    $c = 2 * atan2(sqrt($a), sqrt(1 - $a));

    // Original return for the km answer
    //return 6371.0 * $c;

    // Return for the mile answer on 2 digits percision
    return round(((6371.0 * $c) * 0.621371192), 2);
}

谢谢Bearwulf,一旦我缩小了查询范围,这将非常有用 :) - RS-

0

我需要将这个函数转换成SQL语句,以下是我们可以使用的SQL查询调用方式。

select bar_get_nearby(4.860416,-58.93018, 100 ,@"mi")

特别感谢Rupesh K

DELIMITER $$
CREATE FUNCTION bar_get_nearby(lat FLOAT,lng FLOAT,distance FLOAT,unit VARCHAR(3)) RETURNS TEXT
BEGIN

  DECLARE radius FLOAT;
  DECLARE maxLat FLOAT;
  DECLARE minLat FLOAT;
  DECLARE maxLng FLOAT;
  DECLARE minLng FLOAT;
  DECLARE max_min_values TEXT;

  CASE unit
    WHEN  'km' THEN
       SET radius = 6371.009;
    WHEN 'mi' THEN
       SET radius = 3958.761;
    ELSE
       SET radius = 3958.761;
  END CASE;

   SET maxLat = lat + degrees( distance / radius );
   SET minLat = lat - degrees( distance / radius );


   SET maxLng = lng + degrees( distance / radius) / COS( radians( lat ) );
   SET minLng = lng - degrees( distance / radius) / COS( radians( lat ) );

    SET max_min_values = concat('north=' , maxLat, '&south=' , minLat,'&east=' , maxLng, '&west=' , minLng);

  RETURN max_min_values;
END$$
DELIMITER ;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接