您现在的位置是: 网站首页>文章详情 文章详情

地图定位:计算两点地理坐标之间的距离,判断一个坐标是否在一个多边形内(由多个坐标围成的)

Heartless Wolf 1560906783 php 13782 收藏

简介 PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;



/**
* 计算两点地理坐标之间的距离
* @param Decimal $longitude1 起点经度
* @param Decimal $latitude1 起点纬度
* @param Decimal $longitude2 终点经度
* @param Decimal $latitude2 终点纬度
* @param Int   $unit    单位 1:米 2:公里
* @param Int   $decimal  精度 保留小数位数
* @return Decimal
*/
function getDistance($longitude1, $latitude1, $longitude2, $latitude2, $unit=1, $decimal=2){

   $EARTH_RADIUS = 6370.996; // 地球半径系数
   $PI = 3.1415926;

   $radLat1 = $latitude1 * $PI / 180.0;
   $radLat2 = $latitude2 * $PI / 180.0;

   $radLng1 = $longitude1 * $PI / 180.0;
   $radLng2 = $longitude2 * $PI /180.0;

   $a = $radLat1 - $radLat2;
   $b = $radLng1 - $radLng2;

   $distance = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1) * cos($radLat2) * pow(sin($b/2),2)));
   $distance = $distance * $EARTH_RADIUS * 1000;

   if($unit==2){
       $distance = $distance / 1000;
   }

   return round($distance, $decimal);

}


/**
* 判断一个坐标是否在一个多边形内(由多个坐标围成的)
* 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则
* 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。
* @param $point 指定点坐标
* @param $pts 多边形坐标 顺时针方向
*/
function is_point_in_polygon($point, $pts) {
   $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;
   }
}


文章评论

    点击加载更多评论

我的名片

网名:Hello World

职业:PHP开发

现居:福建省-福州市

Email:565554856@qq.com

  • 图片信息

站点信息

  • 建站时间:2019-04-20
  • 文章总计:69条
  • 笔记总计:4条
  • 文章评论:0条
  • 笔记评论:0条
  • 当前访问IP:3.146.255.249