Point Selection, Circle Selection and Polygon Selection Elements in Openlayers 4

Click-on, circle-selection and polygon-selection are also the basic functions in maps, but there has been no demand for them. In the last two days, the function has been completed from page to function. The method I use is to use the ol4 API plus some js algorithm, which is recorded here.

1, demand

Click on a point, pop-up modal box set radius, after setting, draw points and radius circles on the map, select the equipment in the circle, and display these devices in the search results box.

Circle selection: Draw a circle selection directly, select the devices in the circle, and display them in the search results box.

Polygon Selection: Draw a polygon, select the devices in the polygon, and display them in the search results box.

2. Steps (approximate):

This is done by drawing draws.

Point selection: Set the type of draw as Point, after drawing, get the coordinates of the drawn points, draw a circle with the radius input in the modal box, traverse the element layer, and judge whether the elements are within the circle according to the algorithm point Inside Circle (point, circle, r), and screen out the elements within the circle.

Circle selection: Set type as Circle, after drawing, get the circle drawn, traverse the element layer, and then select the elements in the circle according to the algorithm point Inside Circle (point, circle, r).

Polygon selection: Set the type to Polygon, after drawing, get the drawn polygon, traverse the element layer, and then select the elements within the polygon range according to the algorithm inside Polygon (points, testPoint).

Box Selection: Set the type of draw to Circle, and set geometryFunction to ol.interaction.Draw.createBox(), after drawing, get the feature.getExtent() of the drawing elements, and get the elements in the elements layer according to the source. getFeatures InExtent (extent) of API.

Note: If there are too many elements in the layer, the extent of drawing elements can be obtained first, then according to source. getFeatures InExtent (extent), the elements in the extension box of drawing elements can be obtained, and then the elements in the graph range can be screened according to their own algorithm.

Take circle selection as an example:

var draw = new ol.interaction.Draw({
    source: drawSource,
    type:"Circle",
    style:drawStyle
});
map.addInteraction(draw);

draw.on('drawend',function(evt){
    var polygon = evt.feature.getGeometry();
    setTimeout(function(){              //If no delay is set, the selected elements in the range will be automatically cancelled after selection. The specific reason is unknown.
        var center = polygon.getCenter(),radius = polygon.getRadius(),extent = polygon.getExtent();
        var features = vectorLayer.getSource().getFeaturesInExtent(extent); //First narrow down the scope of feature s
        var str = "";
        for(var i=0;i<features.length;i++){
            var newCoords = features[i].getGeometry().getCoordinates();
            if(pointInsideCircle(newCoords,center,radius)){
                selectedFeatures.push(features[i]);
                str += "<div class=\"selectedItem\" onclick='showDeviceOnMap(\""+features[i].getId()+"\");'>"+features[i].get("name")+"</div>";
            }
        }
        $("#selectedInfoContent").html(str);
    },300)
})

3. Algorithms: Judging whether a point is in the polygon range and whether a point is in the circle range

/**
     *  Judging whether a point is inside a polygon
     *  @param points Polygon coordinate set
     *  @param testPoint Test point coordinates
     *  Return true to true and false to false
     *  */
    function insidePolygon(points, testPoint){
        var x = testPoint[0], y = testPoint[1];
        var inside = false;
        for (var i = 0, j = points.length - 1; i < points.length; j = i++) {
            var xi = points[i][0], yi = points[i][1];
            var xj = points[j][0], yj = points[j][1];

            var intersect = ((yi > y) != (yj > y))
                    && (x < (xj - xi) * (y - yi) / (yj - yi) + xi);
            if (intersect) inside = !inside;
        }
        return inside;
    }

    /**
     *  Judging whether a point is inside a circle
     *  @param point  Test point coordinates
     *  @param circle Center coordinates
     *  @param r Circle radius
     *  Return true to true and false to false
     *  */
    function pointInsideCircle(point, circle, r) {
        if (r===0) return false
        var dx = circle[0] - point[0]
        var dy = circle[1] - point[1]
        return dx * dx + dy * dy <= r * r
    }

4. Final results




Posted by djBuilder on Fri, 31 May 2019 13:58:52 -0700