php计算经纬度距离 及 某点是否在经纬度节点范围
js版 计算经纬度距离 及 某点是否在经纬度节点范围
本文档由 https://blog.csdn.net/AdminGuan/article/details/128118657 改版而来。
php 版 计算经纬度距离 及 某点是否在经纬度节点范围
public function index()
{
//1.计算两个点(经纬度)的距离
$staVal = ['lng' => '106.64647211048887', 'lat' => '26.619020177917346'];
$endVal = ['lng' => '106.65148784134672', 'lat' => '26.615442440608998'];
print_r($this->calcCoordsDistance($staVal, $endVal));
//2.判断某一点是否在某一区域范围内(lng.经度 lat.纬度)
$point1 = [121.65628910064697, 31.14649210398973]; //地点示例 1
$point2 = [106.64647211048887, 26.619020177917346]; //地点示例 2
$areaList = [
[121.64199829101561, 31.128897282106205],
[121.6805362701416, 31.128897282106205],
[121.685362701416, 31.157914133949994],
[121.64199829101561, 31.157914133949994],
[121.64199829101561, 31.128897282106205],
];
var_dump('point1=' . $this->judgeCoordsInArea($point1, $areaList)); // true
var_dump('point2=' . $this->judgeCoordsInArea($point2, $areaList)); // false
return 'test/index';
}
/**
* 计算两个点(经纬度)的距离
* @param array $startDot 开始点的经纬度(lng.经度 lat.纬度)
* @param array $endDot 结束点的经纬度(lng.经度 lat.纬度)
* @return ['mVal' => string, 'kmVal' => string, 'originVal' => '两点的经纬度为必传'] originVal.原始值单位为米
*/
protected function calcCoordsDistance(array $startDot, array $endDot) {
$result = ['mVal' => '', 'kmVal' => '', 'originVal' => '两点的经纬度为必传'];
if (empty($startDot) || empty($endDot)) {
return $result;
}
$earthRadius = 6378137.0; // 地球半径
$startRadianLat = $this->getRadian($startDot['lat']); // 纬度 - 开始
$endRadianLat = $this->getRadian($endDot['lat']); // 纬度 - 结束
//差值
$latDiffVal = $startRadianLat - $endRadianLat; // 维度差值
$lngDiffVal = $this->getRadian($startDot['lng']) - $this->getRadian($endDot['lng']); // 经度差值
//差值的正弦值
$latDiffSinVal = sin($latDiffVal / 2); // 维度差值的正弦值
$lngDiffSinVal = sin($lngDiffVal / 2); // 经度差值的正弦值
//余弦值乘积
$latCosProduct = cos($startRadianLat) * cos($endRadianLat); // 维度的余弦值乘积
$powVal = $latCosProduct * pow($lngDiffSinVal, 2);
$sqrtVal = pow($latDiffSinVal, 2) + $powVal; // 开平方根的值
// 结果值
$res = 2 * asin(sqrt($sqrtVal)) * $earthRadius;
$result['mVal'] = sprintf("%.2f", $res) . "m"; // 单位米
$result['kmVal'] = sprintf("%.5f", ($res / 1000)) . "km"; // 单位千米
$result['originVal'] = $res;
return $result;
}
protected function getRadian($d) {
return ($d * pi()) / 180.0; // 圆周率π
}
/** 判断某一点是否在某一区域范围内(lng.经度 lat.纬度)
* @param array $dot 需要判断的点(格式:[lng: "", lat: ""])
* @param array $range 区域范围(格式:[[lng: "", lat: ""], [lng: "", lat: ""]])
* @returns {boolean} true.存在 false.不存在
*/
protected function judgeCoordsInArea(array $dot, array $range) {
$count = 0;
$r1 = $range[0];
for ($i = 1; $i < count($range); $i++) {
$r2 = $range[$i % count($range)];
$t1 = $dot[0] > min($r1[0], $r2[0]) && $dot[0] <= max($r1[0], $r2[0]);
$t2 = $dot[1] <= max($r1[1], $r2[1]) && $r1[0] !== $r2[0];
if ($t1 && $t2) {
$term = (($dot[0] - $r1[0]) * ($r2[1] - $r1[1])) / ($r2[0] - $r1[0]) + $r1[1];
if ($r1[1] === $r2[1] || $dot[1] <= $term) $count++;
}
$r1 = $r2;
}
return $count % 2 !== 0;
}