百度坐标点计算
2017-11-24 22:54
218 查看
前段时间因项目需求,用到了关于坐标点计算的几个方法,就在这里整理下:
1. 计算两个坐标点之间的距离
2. 已知一个坐标点和最大距离,求另一坐标可能在的坐标区域
3. 判断一个坐标点是否在一个多边形内
在看具体的实现方法之前,建议先了解下射线法思路,参考文档:
http://blog.csdn.net/qq_27161673/article/details/52973866
1. 计算两个坐标点之间的距离
2. 已知一个坐标点和最大距离,求另一坐标可能在的坐标区域
3. 判断一个坐标点是否在一个多边形内
计算两个坐标点之间的距离
/** * 计算两个坐标之间的距离 * @param $lat1 坐标点1的纬度 * @param $lng1 坐标点1的经度 * @param $lat2 坐标点2的纬度 * @param $lng2 坐标点2的经度 * @return float */ function GetDistance($lat1, $lng1, $lat2, $lng2){ $PI = 3.1415926535898; $EARTH_RADIUS = 6378.137; $radLat1 = $lat1 * ($PI / 180); $radLat2 = $lat2 * ($PI / 180); $a = $radLat1 - $radLat2; $b = ($lng1 * ($PI / 180)) - ($lng2 * ($PI / 180)); $s = 2 * asin(sqrt(pow(sin($a/2),2) + cos($radLat1)*cos($radLat2)*pow(sin($b/2),2))); return round($s * $EARTH_RADIUS * 1000); }
已知一个坐标点和最大距离,求另一坐标可能在的坐标区域
/** * 已知一个坐标点和最大距离,求另一坐标的区域范围 * @param $lng 经度 * @param $lat 纬度 * @param int $distance 距离 * @return array */ function returnSquarePoint($lng,$lat,$distance = 1500){ $earthRadius = 6371000; //deg2rad()将角度转换为相应的弧度 //rad2deg()将弧度数转换为相应的角度数 $dlng = 2 * asin(sin($distance / (2 * $earthRadius)) / cos(deg2rad($lat))); $dlng = rad2deg($dlng); $dlat = $distance/$earthRadius; $dlat = rad2deg($dlat); return array( 'minLng'=>$lng - $dlng, 'maxLng'=>$lng + $dlng, 'minLat'=>$lat - $dlat, 'maxLat'=>$lat + $dlat ); //所以,经度范围在minLng和maxLng之间,纬度范围在minLat和maxLat之间 }
判断一个坐标点是否在一个多边形内
基本思想:利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况,特殊情况特殊处理。在看具体的实现方法之前,建议先了解下射线法思路,参考文档:
http://blog.csdn.net/qq_27161673/article/details/52973866
/** * 判断一个百度坐标是否在一个多边形内(由多个坐标围成的,可以是不规则的形状) * @param $point 指定点坐标,数组 * @param $pts 多边形坐标 顺时针方向 */ function isPointInPolygon($point, $pts){ //先判断是否在该多边形的外包矩形中 $latList = array_column($pts,'lat'); $lngList = array_column($pts,'lng'); if($point['lat'] > max($latList) || $point['lat'] < min($latList) || $point['lng'] > max($lngList) || $point['lng'] < min($lngList)){ return false; } $N = count($pts); $boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true $intersectCount = 0;//射线与多边形相交的次数 $precision = 2e-10; //浮点类型计算时候与0比较时候的容差 $p = $point; //测试点 $p1 = $pts[0];//初始左顶点 for ($i = 1; $i <= $N; ++$i) { //点落在多边形的顶点处,与p1重合 if ($p['lng'] == $p1['lng'] && $p['lat'] == $p1['lat']) { return $boundOrVertex;//p is an vertex } //选择与经度平行的线为射线 //p.lat不在p1.lat和p2.lat之间,即不会和p1与p2两点间的连线相交 $p2 = $pts[$i % $N];//右顶点 if ($p['lat'] < min($p1['lat'], $p2['lat']) || $p['lat'] > max($p1['lat'], $p2['lat'])) { $p1 = $p2; //移动左顶点到下一个坐标点 continue; } //p.lat在p1.lat和p2.lat之间,且不与顶点经度相同(通常情况) if ($p['lat'] > min($p1['lat'], $p2['lat']) && $p['lat'] < max($p1['lat'], $p2['lat'])) { if ($p['lng'] <= max($p1['lng'], $p2['lng'])) { //p1、p2在同一纬度,p的经度在p1与p2两点之间 if ($p1['lat'] == $p2['lat'] && $p['lng'] >= min($p1['lng'], $p2['lng'])) { return $boundOrVertex; } if ($p1['lng'] == $p2['lng']) { //p、p1、p2在同一经度,且p在p1与p2两点之间 if ($p1['lng'] == $p['lng']) { return $boundOrVertex; } else {//射线穿过p1、p2连线 ++$intersectCount; } } else { //$xinters是p1射线与p1、p2连线交点处的经度 $xinters = ($p['lat'] - $p1['lat']) * ($p2['lng'] - $p1['lng']) / ($p2['lat'] - $p1['lat']) + $p1['lng'];//cross point of lng //var_dump('p1_lat:'.$p1['lat'].'--p1_lng:'.$p1['lng'].'--p2_lat:'.$p2['lat'].'--p2_lng:'.$p2['lng'].'--'.$xinters); //p在p1、p2连线上 if (abs($p['lng'] - $xinters) < $precision) { return $boundOrVertex; } //射线穿过p1、p2连线 if ($p['lng'] < $xinters) { ++$intersectCount; } } } } else { //特殊情况:当射线穿过顶点p2时 if ($p['lat'] == $p2['lat'] && $p['lng'] <= $p2['lng']) { $p3 = $pts[($i + 1) % $N]; //下一个顶点 //若p.lat在p1.lat 和 p3.lat之间(p1、p3在p2的两侧,且射线穿过顶点p2) if ($p['lat'] >= min($p1['lat'], $p3['lat']) && $p['lat'] <= max($p1['lat'], $p3['lat'])) { ++$intersectCount; } else { //若p1、p3在p2的同一侧,且射线穿过顶点p2,则按照两次计算 $intersectCount += 2; } } } $p1 = $p2;//移动左顶点到下一个坐标点 } if ($intersectCount % 2 == 0) {//偶数在多边形外 return false; } else { //奇数在多边形内 return true; } } $pts = array( array('lat'=>39.910,'lng'=>116.395), array('lat'=>39.914,'lng'=>116.394), array('lat'=>39.920,'lng'=>116.403), array('lat'=>39.914,'lng'=>116.402), array('lat'=>39.913,'lng'=>116.410), ); $point = array('lat'=>$lat,'lng'=>$lng); if(isPointInPolygon($point, $pts)){ echo 1; //在多边形内 }else{ echo 0; //不在多边形内 }
相关文章推荐
- 根据经纬度计算距离的公式、百度坐标转换成GPS坐标(PHP版)
- 计算两个坐标点的距离(高德or百度)
- 仿谷歌,百度分页 计算分析
- 如何通过旋转坐标轴计算坐标系A中的点到坐标系B中的点的变换T
- 百度 计算广告学学习记录
- iOS开发UI篇章之应用管理的九宫格坐标计算
- Gps坐标转换成 百度坐标 高德坐标
- 折线图(四)计算坐标轴文字大小,确定准确位置
- WGS84、Web墨卡托、火星坐标、百度坐标互转
- 关于GDAL计算图像坐标的几个问题
- 根据角度计算圆的坐标点
- 【UGUI】计算UGUI层级较深的物体在屏幕上的坐标
- 计算两个坐标之间距离的函数
- 开发一个坐标计算工具, A表示向左移动,D表示向右移动,W表示向上移动,S表示向下移动。从(0,0)点开始移动,从输入字符串里面读取一些坐标,并将最终输入结果输出到输出文件里面。
- 高德地图计算两坐标之间距离
- 计算两个坐标之间的距离(米)
- 年份计算生肖(百度面试题)
- mongodb 计算坐标距离
- Bestcoder Pro.ID 2001 输入两点坐标(X1,Y1),(X2,Y2),计算并输出两点间的距离。
- 请问C++在坐标轴内怎么计算一个长方形和十字形状的面积,用数组保存的坐标点