Determining whether the end user WEB Baidu map within the grid range

Disposed in the pc distribution range business end next single user, according to the delivery location set by the user determines whether the distributable range, and a prompt to the user.

I realized at the idea said the following:

1. PC side is provided with a distribution range Baidu map, you can drag the selected

2. According to whether the distribution of the range set by the user determines the delivery address

First, Baidu PC clients to obtain the map range

Changes to the official website of the demo Baidu map, set the distribution range.

Ideas: Get the vertices of the polygon, saved to the database in the form of json.

About Baidu API covering polygon:

Constructor:

Polygon (points: Array [, opts: PolygonOptions]) to create the covering polygon

method:

setPath (path: Array) none of the polygon set of points (from 1.2 new)
getPath () Returns the Array group polygon points (from 1.2 new)

achieve:

//设置配送范围
function setRange(_point, _ppoints) {
    var polygon = new BMap.Polygon(_ppoints, {
        strokeColor: "blue",
        strokeWeight: 2,
        strokeOpacity: 0.5
    }); //创建多边形
    map.addOverlay(polygon); //增加多边形
    polygon.enableEditing(); //允许编辑
    polygon.addEventListener("lineupdate",
    function(e) {
        var rangeArr = polygon.getPath();
        $("#distributeRange").val(JSON.stringify(rangeArr));
    });
}

The above code is mainly listening lineupdate event, each drag vertices of a polygon Baidu callback function returns the map, then there is a tag by which type string into JSON.stringify method to be subsequent form submission.

Second, determine the point in the range

Go online to read about, a lot of methods to determine whether a point within the distribution range, probably using a ray method.
But there are some ways not considered comprehensive, resulting in some cases inaccurate judgment.
In Baidu map GeoUtils inside to find this method "to determine whether the polygon points inside."
Because I need to make a judgment on the back end, and then directly converted into js java, test crack shot, joy! (Hereinafter appended Test Method)

/**
* 判断点是否在多边形内
* @param point 检测点
* @param pts 多边形的顶点
* @return 点在多边形内返回true,否则返回false
*/
public static boolean IsPtInPoly(Point2D.Double point, List < Point2D.Double > pts) {
   int N = pts.size();
   boolean boundOrVertex = true; //如果点位于多边形的顶点或边上,也算做点在多边形内,直接返回true
   int intersectCount = 0; //cross points count of x
   double precision = 2e-10; //浮点类型计算时候与0比较时候的容差
   Point2D.Double p1,
   p2; //neighbour bound vertices
   Point2D.Double p = point; //当前点
   p1 = pts.get(0); //left vertex
   for (int i = 1; i <= N; ++i) { //check all rays
       if (p.equals(p1)) {
           return boundOrVertex; //p is an vertex
       }
       p2 = pts.get(i % N); //right vertex
       if (p.x < Math.min(p1.x, p2.x) || p.x > Math.max(p1.x, p2.x)) { //ray is outside of our interests
           p1 = p2;
           continue; //next ray left point
       }
       if (p.x > Math.min(p1.x, p2.x) && p.x < Math.max(p1.x, p2.x)) { //ray is crossing over by the algorithm (common part of)
           if (p.y <= Math.max(p1.y, p2.y)) { //x is before of ray
               if (p1.x == p2.x && p.y >= Math.min(p1.y, p2.y)) { //overlies on a horizontal ray
                   return boundOrVertex;
               }
               if (p1.y == p2.y) { //ray is vertical
                   if (p1.y == p.y) { //overlies on a vertical ray
                       return boundOrVertex;
                   } else { //before ray
                       ++intersectCount;
                   }
               } else { //cross point on the left side
                   double xinters = (p.x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y; //cross point of y
                   if (Math.abs(p.y - xinters) < precision) { //overlies on a ray
                       return boundOrVertex;
                   }
                   if (p.y < xinters) { //before ray
                       ++intersectCount;
                   }
               }
           }
       } else { //special case when ray is crossing through the vertex
           if (p.x == p2.x && p.y <= p2.y) { //p crossing over p2
               Point2D.Double p3 = pts.get((i + 1) % N); //next vertex
               if (p.x >= Math.min(p1.x, p3.x) && p.x <= Math.max(p1.x, p3.x)) { //p.x lies between p1.x & p3.x
                   ++intersectCount;
               } else {
                   intersectCount += 2;
               }
           }
       }
       p1 = p2; //next ray left point
   }
   if (intersectCount % 2 == 0) { //偶数在多边形外
       return false;
   } else { //奇数在多边形内
       return true;
   }
}

The main judge and feasibility of this approach.

To this end I wrote a test method.

Ideas: Get the vertices of a polygon, a random point and point

1. Call Baidu map method to determine whether the point is within the range
according to the shop's Baidu map acquisition of latitude and longitude, to determine whether its own program within the scope of

Call Baidu map method:

<html>
<head>
<meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
<title>GeoUtils示例</title>
<script src="http://api.map.baidu.com/api?v=1.2" type="text/javascript"></script>
<script src="http://api.map.baidu.com/library/GeoUtils/1.2/src/GeoUtils_min.js" type="text/javascript"></script>
<style type="text/css">
    table {
      font-size: 14px;
    }
</style>
</head>
<body>
<div id="container" style="float:left;width:600px;height:500px;border:1px solid gray">
</div>
<div id="control" style="float:left;width:300px;height:500px;border:1px solid gray">
    <table style="width:100%;">
    <tr>
        <td colspan="2">
            判断点是否在多边形内:
        </td>
    </tr>
    <tr>
        <td>
            <input onclick="polygon1()" type="button" value="多边形1"/>
        </td>
    </tr>
    <tr>
        <td>
            <input onclick="polygon2()" type="button" value="多边形2"/>
        </td>
    </tr>
    <tr>
        <td>
            经度<input id="lng" type="text" value="">
        </td>
    </tr>
    <tr>
        <td>
            纬度<input id="lat" type="text" value="">
        </td>
    </tr>
    <tr>
        <td>
            结果:
        </td>
    </tr>
    <tr>
        <td>
            <p id="result" style="color:red">
            </p>
        </td>
    </tr>
    <table>
</div>
</body>
</html>
<script type="text/javascript">
  var map = new BMap.Map('container')
  var pt = new BMap.Point(116.404, 39.915)
  var mkr = new BMap.Marker(pt)
  var ply //多边形
  map.centerAndZoom(pt, 16)
  map.enableScrollWheelZoom() //开启滚动缩放
  map.enableContinuousZoom() //开启缩放平滑
  //初始化为多边形1
  polygon1()
  //生成多边形1
  function polygon1 () {
    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)
    ply = new BMap.Polygon(pts)
//演示:将面添加到地图上
    map.clearOverlays()
    map.addOverlay(ply)
  }
  //生成多边形2
  function polygon2 () {
    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.396, 39.919)
    var pt4 = new BMap.Point(116.406, 39.920)
    var pt5 = new BMap.Point(116.410, 39.913)
    pts.push(pt1)
    pts.push(pt2)
    pts.push(pt3)
    pts.push(pt4)
    pts.push(pt5)
    ply = new BMap.Polygon(pts)
//演示:将多边形添加到地图上
    map.clearOverlays()
    map.addOverlay(ply)
  }
  map.addEventListener('click', function (e) {
    mkr.setPosition(e.point)
    map.addOverlay(mkr)
//将点击的点的坐标显示在页面上
    document.getElementById('lng').value = e.point.lng
    document.getElementById('lat').value = e.point.lat
    InOrOutPolygon(e.point.lng, e.point.lat)
  })
  function InOrOutPolygon (lng, lat) {
    var pt = new BMap.Point(lng, lat)
    var result = BMapLib.GeoUtils.isPointInPolygon(pt, ply)
    if (result == true) {
      document.getElementById('result').innerHTML = '点在多边形内'
    } else {
      document.getElementById('result').innerHTML = '点在多边形外'
    }
  }
</script>

Interface is as follows:

image-20190917234507139

On page after clicking on a point to get the coordinates of the point (for its own method of testing), and calls InOrOutPolygon to determine whether a store within this range.

image-20190917234838190

image-20190917234855187

Background test methods:

// 测试一个点是否在多边形内
public static void main(String[] args) {
    Point2D.Double point = new Point2D.Double(116.404072, 39.916605);
    List<Point2D.Double> pts = new ArrayList<Point2D.Double>();
    pts.add(new Point2D.Double(116.395, 39.910));
    pts.add(new Point2D.Double(116.394, 39.914));
    pts.add(new Point2D.Double(116.403, 39.920));
    pts.add(new Point2D.Double(116.402, 39.914));
    pts.add(new Point2D.Double(116.410, 39.913));
    if (IsPtInPoly(point, pts)) {
        System.out.println("点在多边形内");
    } else {
        System.out.println("点在多边形外");
    }
}

After testing with satisfactory results.

Summary, the process of implementing the most important is to save those vertex or vertices and stored in accordance with (a certain order), to determine whether a point is within the polygon vertices enclosed.

Feeling Baidu map or a good use. API is very wide, and is equipped with a demo, very beneficial to our developers.

Guess you like

Origin www.cnblogs.com/alterem/p/11539835.html