[GIS] How to add vertices to a polygon on mouse click in OpenLayers

openlayers-2

I am pretty new to OpenLayers. I have a polygon drawn on a vector layer, along with ModifyFeature and SelectFeature, I need to implement a functionality when user clicks on the polygon, a new vertex should be added to the polygon at the position where use clicked. With the new vertex the user should be able to reshape the polygon. Is there any existing feature to do this? if not how can we implement this?

function init() {
    map = new OpenLayers.Map('map');

    var wms = new OpenLayers.Layer.WMS("OpenLayers WMS",
        "http://vmap0.tiles.osgeo.org/wms/vmap0?", { layers: 'basic' });

    OpenLayers.Feature.Vector.style['default']['strokeWidth'] = '2';

    var renderer = OpenLayers.Util.getParameters(window.location.href).renderer;
    renderer = (renderer) ? [renderer] : OpenLayers.Layer.Vector.prototype.renderers;

    vectors = new OpenLayers.Layer.Vector("Vector Layer", {
        renderers: renderer
    });

    map.events.register("mousemove", map, function (e) {
        var position = this.events.getMousePosition(e);
        OpenLayers.Util.getElement("coords").innerHTML = position;
    });

    map.addLayers([wms, vectors]);
    map.addControl(new OpenLayers.Control.LayerSwitcher());
    map.addControl(new OpenLayers.Control.MousePosition());

    if (console && console.log) {
        function report(event) {
            if (event.type === "beforefeaturemodified")
                controls.polygon.deactivate();
            console.log(event.type, event.feature ? event.feature.id : event.components);
        }
        vectors.events.on({
            "beforefeaturemodified": report,
            "featuremodified": report,
            "afterfeaturemodified": report,
            "vertexmodified": report,
            "sketchmodified": report,
            "sketchstarted": report,
            "sketchcomplete": report
        });
    }

    controls = {
        polygon: new OpenLayers.Control.DrawFeature(vectors,
                    OpenLayers.Handler.Polygon),
        modify: new OpenLayers.Control.ModifyFeature(vectors),
    };

    var featureSelect = new OpenLayers.Control.SelectFeature(vectors,
    {
        hover: false,
        clickout: false,
        multiple: false,
        toggle: true,
        //box: true,
        eventListeners: {
            featureunhighlighted: function () {
                //Do whatever you want here.
            }
        }
        //multipleKey: "shiftKey"
    });
    map.addControl(featureSelect);
    featureSelect.activate();

    for (var key in controls) {
        map.addControl(controls[key]);
        controls[key].activate();
    }

    map.setCenter(new OpenLayers.LonLat(0, 0), 3);

    //vectors.events.register('click', vectors, function (e) {
    //    console.log(e);
    //});

    vectors.events.register('sketchcomplete', vectors, function (e) {
        controls.polygon.deactivate();
    });
}

Thanks in advance

Best Answer

I did the similar work but a more complex algorithm for lines, and I think I get some inspiration from it. Your requirements are pretty much the same as what modifyFeature control can do, but you want to do it in a simpler way (from user point of view). It's possible but there's some trade off between the simplicity of manual work and that of computational work. It's actually often the case when it comes to computational geometry.

The modifyFeature control requires you to select one of the virtual vertices on edges, which implies that the new vertex will be inserted into that selected edge, so it's a deterministic process. Without this selecting process (by only clicking), you will need some extra computation to decide which edge (probably the nearest one, and the distance calculation to each edge is the extra work) to insert. For a simple polygon, the calculation is not a big problem, but the real use cases could be complex, e.g. a polygon has many edges and many of there's some cross over between edges. In such cases, it's possible when you want to insert the vertex to edge A, but end up with edge B. Moreover you will get some limitations on reshaping the polygon, following picture is a example (blue cross is where you clicked).

enter image description here

So I would suggest taking a deterministic way (maybe not exactly the same as how modifyFeature does), with less computation and you won't expect some 'special cases' (it's always about special cases). But if such special cases won't appear in your problem, then I don't see why not make users happy if it's a request from users or customers.