ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
~~~ <?php namespace app\common\library; use think\Config; class Geo { private $point;//当前经纬度 private $point_array;//围栏经纬度 const EARTH_RADIUS = 6378137; const PI = 3.1415926; /** * Constructor */ public function __construct($point,$point_array) { $this->point = $point; $this->point_array = $point_array; } public function GetAllDistance() { $distance=array(); $point_array=$this->point_array; $len = Count($point_array); $maxIndex = $len - 1; for ($i = 0; $i < $len; $i++) { //多边形中当前点 $currentPoint = $point_array[$i]; $nearPoint = $maxIndex == $i ? $point_array[0] : $point_array[$i + 1]; $a = $this->GetDistance($this->point, $currentPoint);//经纬坐标系中求两点的距离公式 $b = $this->GetDistance($this->point, $nearPoint);//经纬坐标系中求两点的距离公式 $c = $this->GetDistance($currentPoint, $nearPoint);//经纬坐标系中求两点的距离公式 if ($a * $a >= $c * $c + $b * $b) { $distance[]=$b; continue; } if ($b*$b >= $c * $c + $a * $a) { $distance[]=$a; continue; } $l = ($a + $b + $c) / 2; //周长的一半 $s = sqrt($l * ($l - $a) * ($l - $b) * ($l - $c)); //海伦公式求面积 $distance[]=2 * $s / $a; } return min($distance); } /// <summary> /// 计算两点位置的距离,返回两点的距离,单位:米 /// 该公式为GOOGLE提供,误差小于0.2米 /// </summary> /// <param name="lng1">第一点经度</param> /// <param name="lat1">第一点纬度</param> /// <param name="lng2">第二点经度</param> /// <param name="lat2">第二点纬度</param> /// <returns></returns> public function GetDistance($point1, $point2) { $radLat1 = $this->Rad($point1['lat']); $radLng1 = $this->Rad($point1['lng']); $radLat2 = $this->Rad($point2['lat']); $radLng2 = $this->Rad($point2['lng']); $a = $radLat1 - $radLat2; $b = $radLng1 - $radLng2; $result = 2 * asin(sqrt(pow(sin($a / 2), 2) + cos($radLat1) * cos($radLat2) * pow(sin($b / 2), 2))) * self::EARTH_RADIUS; return $result; } public function Rad($d) { return $d * self::PI / 180; } //检测经纬度是不是在范围内 public function is_point_in_polygon() { $point=$this->point; $pts=$this->point_array; $N = count($pts); $boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true $intersectCount = 0;//cross points count of x $precision = 2e-10; //浮点类型计算时候与0比较时候的容差 $p1 = 0;//neighbour bound vertices $p2 = 0; $p = $point; //测试点 $p1 = $pts[0];//left vertex for ($i = 1; $i <= $N; ++$i) {//check all rays // dump($p1); if ($p['lng'] == $p1['lng'] && $p['lat'] == $p1['lat']) { return $boundOrVertex;//p is an vertex } $p2 = $pts[$i % $N];//right vertex if ($p['lat'] < min($p1['lat'], $p2['lat']) || $p['lat'] > max($p1['lat'], $p2['lat'])) {//ray is outside of our interests $p1 = $p2; continue;//next ray left point } if ($p['lat'] > min($p1['lat'], $p2['lat']) && $p['lat'] < max($p1['lat'], $p2['lat'])) {//ray is crossing over by the algorithm (common part of) if($p['lng'] <= max($p1['lng'], $p2['lng'])){//x is before of ray if ($p1['lat'] == $p2['lat'] && $p['lng'] >= min($p1['lng'], $p2['lng'])) {//overlies on a horizontal ray return $boundOrVertex; } if ($p1['lng'] == $p2['lng']) {//ray is vertical if ($p1['lng'] == $p['lng']) {//overlies on a vertical ray return $boundOrVertex; } else {//before ray ++$intersectCount; } } else {//cross point on the left side $xinters = ($p['lat'] - $p1['lat']) * ($p2['lng'] - $p1['lng']) / ($p2['lat'] - $p1['lat']) + $p1['lng'];//cross point of lng if (abs($p['lng'] - $xinters) < $precision) {//overlies on a ray return $boundOrVertex; } if ($p['lng'] < $xinters) {//before ray ++$intersectCount; } } } } else {//special case when ray is crossing through the vertex if ($p['lat'] == $p2['lat'] && $p['lng'] <= $p2['lng']) {//p crossing over p2 $p3 = $pts[($i+1) % $N]; //next vertex if ($p['lat'] >= min($p1['lat'], $p3['lat']) && $p['lat'] <= max($p1['lat'], $p3['lat'])) { //p.lat lies between p1.lat & p3.lat ++$intersectCount; } else { $intersectCount += 2; } } } $p1 = $p2;//next ray left point } if ($intersectCount % 2 == 0) {//偶数在多边形外 return false; } else { //奇数在多边形内 return true; } } } ~~~