我正在将具有半径的中心点(纬度,经度)传递给此函数,以获取圆周点(纬度,经度),以便我从中创建几何并将其存储在MYSQL中,以便稍后执行ST_Contains函数上。
在Google地图上绘制时,这使我得到的是椭圆形而不是圆形。
public static function convert($center, $radius, $numberOfSegments = 360)
{
$n = $numberOfSegments;
$flatCoordinates = [];
$coordinates = [];
for ($i = 0; $i < $n; $i++) {
$flatCoordinates = array_merge($flatCoordinates, static::offset($center, $radius, 2 * pi() * $i / $n));
}
$flatCoordinates[] = $flatCoordinates[0];
$flatCoordinates[] = $flatCoordinates[1];
for ($i = 0, $j = 0; $j < count($flatCoordinates); $j += 2) {
$coordinates[$i++] = array_slice($flatCoordinates, $j, 2);
}
return [
'type' => 'Polygon',
'coordinates' => [array_reverse($coordinates)]
];
}
public static function toRadians($angleInDegrees = null)
{
return $angleInDegrees * pi() / 180;
}
public static function toDegrees($angleInRadians = null)
{
return $angleInRadians * 180 / pi();
}
public static function offset($c1, $distance, $bearing)
{
$lat1 = static::toRadians($c1[1]);
$lon1 = static::toRadians($c1[0]);
$dByR = $distance / 6378137; // distance divided by 6378137 (radius of the earth) wgs84
$lat = asin(
sin($lat1) * cos($dByR) +
cos($lat1) * sin($dByR) * cos($bearing)
);
$lon = $lon1 + atan2(
sin($bearing) * sin($dByR) * cos($lat1),
cos($dByR) - sin($lat1) * sin($lat)
);
return [static::toDegrees($lon), static::toDegrees($lat)];
}
考虑到WGS84,我真的不需要像地球曲率那样精确,因为半径很小(25m-150m)。
答案 0 :(得分:1)
我通过变量名猜测您是从this question获得函数的,但是您忘记了代码的一行,特别是引起该人问题的那一行。
此外,第一个函数中的数组代码比所需的要冗长得多。我在这里对此进行了概括,并使用内置的PHP函数进行弧度/度转换:
<?php
function convert($center, $radius, $numberOfSegments = 360)
{
$n = $numberOfSegments;
$flatCoordinates = [];
$coordinates = [];
for ($i = 0; $i < $n; $i++) {
$bearing = 2 * M_PI * $i / $n;
$flatCoordinates[] = offset($center, $radius, $bearing);
}
$flatCoordinates[] = $flatCoordinates[0];
return [
'type' => 'Polygon',
'coordinates' => [$flatCoordinates]
];
}
function offset($c1, $distance, $bearing) {
$lat1 = deg2rad($c1[0]);
$lon1 = deg2rad($c1[1]);
$dByR = $distance/6378137; // convert dist to angular distance in radians
$lat = asin(
sin($lat1) * cos($dByR) +
cos($lat1) * sin($dByR) * cos($bearing)
);
$lon = $lon1 + atan2(
sin($bearing) * sin($dByR) * cos($lat1),
cos($dByR) - sin($lat1) * sin($lat)
);
$lon = fmod(
$lon + 3 * M_PI,
2 * M_PI
) - M_PI;
return [rad2deg($lon), rad2deg($lat)];
}
$result = convert([49, -122], 5000, 20);
foreach ($result['coordinates'][0] as $v) echo "$v[1]\t$v[0]\n";
输出:
49.044915764206 -122
49.042715494198 -121.97882560793
49.036330613043 -121.9597290805
49.026387559463 -121.94458290688
49.01386140937 -121.93486968973
48.999979747353 -121.93153702633
48.986101953242 -121.93490597976
48.973585929464 -121.94464162541
48.963655392709 -121.95978779908
48.957280637886 -121.97886189803
48.955084235794 -122
48.957280637886 -122.02113810197
48.963655392709 -122.04021220092
48.973585929464 -122.05535837459
48.986101953242 -122.06509402024
48.999979747353 -122.06846297367
49.01386140937 -122.06513031027
49.026387559463 -122.05541709312
49.036330613043 -122.0402709195
49.042715494198 -122.02117439207
49.044915764206 -122
我使用了this site for testing,它按预期绘制了一个圆圈。