Or *_*ger 6 php spatial geospatial
假设我有这个lon/lat: 33.33333,22.22222
如何在X英里/公里范围内随机选择另一个lon/lat?
谢谢,
Ste*_*ris 11
@MikeLewis答案是迄今为止更简单的方法,但它只给你一个纬度和经度范围,从中随机绘制可能会给你超出给定半径的点.
以下是有点复杂,但应该给你'更好'的结果.(这可能是没有必要的,但我想要去:)).
与@MikeLewis的回答一样,这里的假设是地球是一个球体.我们不仅在公式中使用它,而且在我们利用旋转对称时也使用它.
首先,我们采取明显的方法来选择随机距离$distance(少于$radius几英里)并尝试在数$distance英里之外找到一个随机点.这些点在球体上形成一个圆圈,你可以很快说服自己一个简单的圆形参数化很难.我们改为考虑一个特例:北极.
距离北极一定距离的点在固定纬度(90-($distance/(pi*3959)*180)的球体上形成一个圆.这给了我们一个非常采摘这个圆上任意一点的简单方法:将有知纬度和随机经度.
然后我们简单地旋转球体,使我们的北极位于我们最初给定的点.旋转后我们随机点的位置给出了我们想要的点.
注意:此处使用的笛卡尔坐标 - 球面坐标转换与文献中的常规坐标转换不同.我唯一的动机是让z轴(0,0,1)指向北方,y轴(0,1,0)指向你,朝向纬度和经度等于0的点.所以如果你想想象地球你正在看海湾几内亚
/**
* Given a $centre (latitude, longitude) co-ordinates and a
* distance $radius (miles), returns a random point (latitude,longtitude)
* which is within $radius miles of $centre.
*
* @param array $centre Numeric array of floats. First element is
* latitude, second is longitude.
* @param float $radius The radius (in miles).
* @return array Numeric array of floats (lat/lng). First
* element is latitude, second is longitude.
*/
function generate_random_point( $centre, $radius ){
$radius_earth = 3959; //miles
//Pick random distance within $distance;
$distance = lcg_value()*$radius;
//Convert degrees to radians.
$centre_rads = array_map( 'deg2rad', $centre );
//First suppose our point is the north pole.
//Find a random point $distance miles away
$lat_rads = (pi()/2) - $distance/$radius_earth;
$lng_rads = lcg_value()*2*pi();
//($lat_rads,$lng_rads) is a point on the circle which is
//$distance miles from the north pole. Convert to Cartesian
$x1 = cos( $lat_rads ) * sin( $lng_rads );
$y1 = cos( $lat_rads ) * cos( $lng_rads );
$z1 = sin( $lat_rads );
//Rotate that sphere so that the north pole is now at $centre.
//Rotate in x axis by $rot = (pi()/2) - $centre_rads[0];
$rot = (pi()/2) - $centre_rads[0];
$x2 = $x1;
$y2 = $y1 * cos( $rot ) + $z1 * sin( $rot );
$z2 = -$y1 * sin( $rot ) + $z1 * cos( $rot );
//Rotate in z axis by $rot = $centre_rads[1]
$rot = $centre_rads[1];
$x3 = $x2 * cos( $rot ) + $y2 * sin( $rot );
$y3 = -$x2 * sin( $rot ) + $y2 * cos( $rot );
$z3 = $z2;
//Finally convert this point to polar co-ords
$lng_rads = atan2( $x3, $y3 );
$lat_rads = asin( $z3 );
return array_map( 'rad2deg', array( $lat_rads, $lng_rads ) );
}
Run Code Online (Sandbox Code Playgroud)
您可以使用此帖子来指导您:
http://blog.fedecarg.com/2009/02/08/geo-proximity-search-the-haversine-equation/
因此,在您的示例中,您只需选择1到10英里之间的随机数,其中10是"在一定范围内".
$longitude = (float) 33.33333;
$latitude = (float) 22.22222;
$radius = rand(1,10); // in miles
$lng_min = $longitude - $radius / abs(cos(deg2rad($latitude)) * 69);
$lng_max = $longitude + $radius / abs(cos(deg2rad($latitude)) * 69);
$lat_min = $latitude - ($radius / 69);
$lat_max = $latitude + ($radius / 69);
echo 'lng (min/max): ' . $lng_min . '/' . $lng_max . PHP_EOL;
echo 'lat (min/max): ' . $lat_min . '/' . $lat_max;
Run Code Online (Sandbox Code Playgroud)
更新:
正如托马拉克在下面的评论中所说,这是在假设地球是一个球而不是一个不均匀的大地水准面的情况下工作的.因此,您将获得近似值,而不是可能(接近)精确结果.