在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
如何判断一个点是否在一个多边形内,何时会用到这个场景。 我们就模拟一个真是场景。我们公司是快递公司,在本地区域有6个分点。每个分点有3-5个工人负责附近的快递派遣发送,所以根据每个点的服务区域我们就能大概知道我们的服务范围。如果客户要收发快递我们会告知是否在服务范围内,且那个点离的最近,应派谁去收发快递。…… 网上其实找了好多判断点是否在经纬度的多边形内,但都是Javascript版: http://www.voidcn.com/blog/jq_develop/article/p-3221513.html http://www.html-js.com/article/1528 http://api.map.baidu.com/library/GeoUtils/1.2/examples/simple.html google算法: https://en.wikipedia.org/wiki/Geohash 其中第三个是百度官网的一个示例
查看源码,百度里面有一个http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils_min.js文件 其中isPointInPolygon方法就是判断点是否在多边形内部 //点在多边形内 function ptInPolygon(){ var pts = []; var pt1 = new BMap.Point(116.395, 39.910); var pt2 = new BMap.Point(116.394, 39.914); var pt3 = new BMap.Point(116.403, 39.920); var pt4 = new BMap.Point(116.402, 39.914); var pt5 = new BMap.Point(116.410, 39.913); pts.push(pt1); pts.push(pt2); pts.push(pt3); pts.push(pt4); pts.push(pt5); var ply = new BMap.Polygon(pts); var pt =new BMap.Point(116.400, 39.914); var result = BMapLib.GeoUtils.isPointInPolygon(pt, ply); if(result == true){ alert("点在多边形内"); } else { alert("点在多边形外") } //演示:将面添加到地图上 map.clearOverlays(); var mkr = new BMap.Marker(pt); map.addOverlay(mkr); map.addOverlay(ply); }
PHP版的也有好几个,都是翻译Javascript但试了下,几乎没一个可以判断验证的。后来在一个论坛中找到了一个很精准的计算多边形内代码,贴出来和大家分享 $point=[ 'lng'=>121.427417, 'lat'=>31.20357 ]; $arr=[ [ 'lng'=>121.23036, 'lat'=>31.218609 ], [ 'lng'=>121.233666, 'lat'=>31.210579 ], [ 'lng'=>121.247177, 'lat'=>31.206749 ], [ 'lng'=>121.276353, 'lat'=>31.190811 ], [ 'lng'=>121.267442, 'lat'=>31.237383 ], ]; $a= is_point_in_polygon($point, $arr); var_dump($a); /** * 判断一个坐标是否在一个多边形内(由多个坐标围成的) * 基本思想是利用射线法,计算射线与多边形各边的交点,如果是偶数,则点在多边形外,否则 * 在多边形内。还会考虑一些特殊情况,如点在多边形顶点上,点在多边形边上等特殊情况。 * @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; } } 打印:bool(false) 将 $point=[ 'lng'=>121.427417, 'lat'=>31.20357 ]; 替换为 $point=[ 'lng'=>121.257428, 'lat'=>31.222481 ]; 打印:bool(true)
------------- 扩展 ------------------------- 在百度地图上绘制多边形并保存绘制的点的经纬度 <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta name="viewport" content="initial-scale=1.0, user-scalable=no" /> <style type="text/css"> body, html{width: 100%;height: 100%;margin:0;font-family:"微软雅黑";} #allmap {width: 100%; height:500px; overflow: hidden;} #result {width:100%;font-size:12px;} dl,dt,dd,ul,li{ margin:0; padding:0; list-style:none; } p{font-size:12px;} dt{ font-size:14px; font-family:"微软雅黑"; font-weight:bold; border-bottom:1px dotted #000; padding:5px 0 5px 5px; margin:5px 0; } dd{ padding:5px 0 0 5px; } li{ line-height:28px; } </style> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=25eb303c9c5df0ec2424fa86816437da"></script> <!--加载鼠标绘制工具--> <script type="text/javascript" src="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.js"></script> <link rel="stylesheet" href="http://api.map.baidu.com/library/DrawingManager/1.4/src/DrawingManager_min.css" /> <!--加载检索信息窗口--> <script type="text/javascript" src="http://api.map.baidu.com/library/SearchInfoWindow/1.4/src/SearchInfoWindow_min.js"></script> <link rel="stylesheet" href="http://api.map.baidu.com/library/SearchInfoWindow/1.4/src/SearchInfoWindow_min.css" /> <script src="http://apps.bdimg.com/libs/jquery/1.10.2/jquery.min.js"></script> <title>鼠标绘制工具</title> </head> <body> <div id="allmap" style="overflow:hidden;zoom:1;position:relative;"> <div id="map" style="height:100%;-webkit-transition: all 0.5s ease-in-out;transition: all 0.5s ease-in-out;"></div> </div> <div> <input type="button" class="btn_gray" value="添加多边形" onclick="addPolyline()"> <input type="button" class="btn_gray" value="保存数据" onclick="saveData()"> </div> <script type="text/javascript"> //记录marker、label、polyline的个数 var NUM_MARKER = 0, NUM_LABEL = 0, NUM_POLYLINE = 0; var polyDefaultStyle = { strokeColor: "#f00", strokeOpacity: 0.6, strokeWeight: 4 } /* *用于存储地图各个配置项的数据结构 *包括:地图中心点、地图的监听事件、地图的控件、地图上的覆盖物等信息 *用于获取代码的时候绘制地图 */ var config = { city: "北京", center_point: new BMap.Point(116.403874, 39.914889), zoom: 12, container_width: 700, container_height: 550, enableScrollWheelZoom: true, enableKeyboard: true, enableDragging: true, enableDoubleClickZoom: true, scale_control: { added: true, anchor: "BMAP_ANCHOR_BOTTOM_LEFT", type: "BMAP_UNIT_IMPERIAL" }, nav_control: { added: true, anchor: "BMAP_ANCHOR_TOP_LEFT", type: "BMAP_NAVIGATION_CONTROL_LARGE" }, overview_control: { added: true, anchor: "BMAP_ANCHOR_BOTTOM_RIGHT", isopen: true }, label_array: [], label_config: [], marker_array: [], marker_config: [], polyline_config: [], polyline_array: [], polyline_name_array: [] } // 百度地图API功能 var map = new BMap.Map('map'); var poi = new BMap.Point(116.307852, 40.057031); map.centerAndZoom(poi, 16); map.enableScrollWheelZoom(); function drawMap(areaStr) { var areaObj = JSON.parse(areaStr); if (areaObj) { //清空服务范围缓存 config.polyline_array = []; //对服务范围数据进行遍历 for (var len = 0; len < areaObj.service_area.length; len++) { var area_item = areaObj.service_area[len]; if (area_item) { var polyPoint = []; var name = area_item.name; var points = area_item.points; for (var p_num = 0; p_num < points.length; p_num++) { var point = new BMap.Point(points[p_num].lng, points[p_num].lat); polyPoint.push(point); if (p_num == 0) { map.centerAndZoom(point, 12); } } //在地图上绘制服务范围区域 var polygon = new BMap.Polygon(polyPoint, { strokeColor: polyDefaultStyle.strokeColor, strokeWeight: polyDefaultStyle.strokeWeight, strokeOpacity: polyDefaultStyle.strokeOpacity}); map.addOverlay(polygon); //将服务范围加入到缓存中 config.polyline_array.push(polygon); config.polyline_name_array.push(name); } } } } var ranges = '{"service_area":[{"name":"多边形1","points":[{"lng":121.23036,"lat":31.218609},{"lng":121.233666,"lat":31.210579},{"lng":121.247177,"lat":31.206749},{"lng":121.276353,"lat":31.190811},{"lng":121.267442,"lat":31.237383}]}]}'; setTimeout(function () { drawMap(ranges); }, 1000); </script> <script> // 此变量在添加标注功能时,用于记录当前的click事件的处理函数 var clickHandler; //鼠标样式 var cursorStyle = { "ol_marker": "hand", "ol_polygen": "crosshair", "ol_label": "text", "default": "auto" }; //添加标注时,鼠标的label信息 var 全部评论
专题导读
上一篇:php项目打包(php项目打包一般用什么)发布时间:2022-07-10下一篇:piwik流量统计系统搭建(apache2.4+piwik+mysql5.6+php5.6.14)发布时间:2022-07-10热门推荐
热门话题
阅读排行榜
|
请发表评论