~~~
<?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;
}
}
}
~~~
- 面试
- php
- laravel
- 安装
- 创建数据
- 创建控制器
- 错误
- 权限认证
- 图形验证码
- 管理员
- 无限分类
- 视频播放
- 推流
- pc页面
- thinkphp5
- 表单提交安全验证
- crontab
- 获取下级所有数据
- 过滤敏感词
- 二维码
- 邀请码
- jwt token
- 笛卡尔
- 高并发解决优化
- 设置多语言
- 计算经纬度两点距离
- 分片上传
- centos swoole
- 查看swoole版本
- centos 安装 redis
- 把整数随机分成n份或者红包
- 生成随机字符串
- 获取上级
- 宝塔搭建nginx推拉流
- 生成二维码海报
- 二维数组去重
- 经纬度 ---边距 和判断是不是范围内
- workerman
- 扩展
- redis
- mysql
- mysql 主从复制
- 定位问题语句
- 列的选择规则
- Enum介绍
- 索引介绍
- 延迟关联
- in 查询陷阱
- limit 优化
- 事务
- 读写分离
- mysql 权限错误
- mysql计算距离
- mysql数据导出导入
- 索引失效
- mysql 语句技巧
- linux
- 配置nginx 高可用
- Nginx内核参数优化
- 配置优化
- nginx-keepalived实现高可用负载
- lvs+keepalived
- centos5关闭防火墙
- nginx操作
- linux操作
- mysql 安装
- php
- 安装phpadmin
- php7安装mongodb
- 查看php位置
- 查找开启的进程端口
- 守护进程
- centos安装php7.2
- centos 错误解决
- 安装php7错误
- mysql 错误
- 支付宝支付
- html
- js 倒计时
- go vscode 配置
- go util
- 获取两个数之间随机数
- java
- lambda
- 随机抽取
- lombok
- springboot
- 常见注解
- 接受参数常用注解
- 文件上传
- 上传错误日志拦截
- 拦截器
- 定时任务
- mybatis
- 关联查询
- 全局配置
- 缓存
- git
- 微信相关
- 体现到零钱
- 服务商转账
- 公众号小程序相关
- 小程序二维码
- svn
- layui