1

I am working with OpenLayers/Turfjs to detect self intersection in users manually drawn polygons on a web map. The function that detects the self intersection is a property of the condition of the draw control.

 var selfIintersectFeature = function (e) {
    var OLDrawEndFeature = e.target.getFeaturesAtPixel(e.pixel)[0];
    if (OLDrawEndFeature.getGeometry().getType() !== 'Point') {
        if (OLDrawEndFeature.getGeometry().getCoordinates().length > 3) {
            var intTestCoords = OLDrawEndFeature.getGeometry().getCoordinates();
            var intTestLinearRing = new ol.geom.LinearRing(intTestCoords, 'XY');
            var intTestPolygon = new ol.geom.Polygon([]);
            intTestPolygon.appendLinearRing(intTestLinearRing);
            var intTestPolygonList = [intTestPolygon]
            var intMultiPolygonGeometry = new ol.geom.MultiPolygon(intTestPolygonList)
            var intTestFeature = new ol.Feature(intMultiPolygonGeometry);
            var geoJsonFeature = JSON.parse(formatGEOJSON.writeFeature(intTestFeature));
            var kinks = turf.kinks(geoJsonFeature);
            console.log(kinks);
            if (kinks.features.length > 0) {
                $('#self-intersect-modal').modal();
                return false
            }
        }
    }
    return true

The kinks function of Turf detects the self-intersections only when The polygon has more than 4 vertices and the vertex of the polygon causing the self intersection is defined with a higher value on the X-Axis in comparison to the first vertex that started the polygon drawing (is located at its left/west).

The problem is that turf does not detect a self-intersection when a polygon has 4 vertices and the vertex causing the polygon to self-intersect has a lower x value than the first vertex that initiated the polygon linear ring (is located at its right/east).

How could I detect when vertex that causes a self intersection is located both at east and west of the first drawing vertex of the polygon in a polygon with 4 vertices?

I tried JSTS and got the same problem, I am working on legacy code and only can use ES5 Javascript with no package support.

3
  • 2
    Since you are testing OLDrawEndFeature.getGeometry().getCoordinates().length > 3 I presume OLDrawEndFeature is a linestring? (for a polygon getCoordinates().length would return the number of linear rings) If you are converting a linestring to polygon are the start and end coordinates equal (a 4 vertex polygon has 5 coordinates in its linear ring).
    – Mike
    Oct 9, 2019 at 8:49
  • Yes, That was the reason why it was not picking up the self intersection. When a user draws a polygon that has 4 or more vertices and the last coordinates are not the same as the first one in the list (which means the polygon appears closed on the map but it isn't coordinate-wise) then kinks aren't detected. What I did was to create a function that checks the number of coords vertices and if they 4 or more check if the first one ans last one are the same, if they are not add push the first coords at the end of the coords array. Maybe there is a better way of checking this Oct 9, 2019 at 10:12
  • If you resolved your problem, publish it as answer so others may profit from it.
    – TomazicM
    Oct 9, 2019 at 12:35

1 Answer 1

1

The solution I adopted isn't working because putting the self intersection check on the condition doesn't always lead to check for a complete Polygon feature (until the drawing is finished the feature is of type MULTILINESTRING). What I did was to put the self-intersect checks on the drawend, the feature will be added to the layer anyway and I handle validation through the web page rather than while drawing. In this way, the Polygon type of geometry generated from the interaction will follow the correct number and order of coordinates and will be parsed by turf with no errors. Here is how I did it.

   function convertToTurfFeature(feature) {
        var featureGeometry = feature.getGeometry();
        var geometryType = featureGeometry.getType();
        var featureCoords = geometryType.startsWith("Multi") ? 
featureGeometry.getCoordinates()[0][0] : featureGeometry.getCoordinates()[0];
        var turfFeature = turf.polygon([featureCoords]);
        return turfFeature;
    }

    function selfIntersectOnDraw(editedFeature) {
        var turfPolygon = convertToTurfFeature(editedFeature);
        var kinks = turf.kinks(turfPolygon);
        return kinks;
    }

ol.Interaction.Draw.on('drawend', function (e) {
        var drawnFeature = e.feature;
        var kinks = selfIntersectOnDraw(drawnFeature);
        var intersectionPoints = kinks.features;
        if (intersectionPoints.length > 0) {
            //handle self-intersections points features here
    }
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.