Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undoing the last point in OL3 removes the last segment

I need a functionality in my web app for undoing the last point. There has been some solutions such as this for the given problem which can handle it to some extent:

var undo = false; // set this to true in the Esc key handler
var draw = new ol.interaction.Draw({
// ...
geometryFunction: function(coords, geom) {
    if (!geom) {
        geom = new ol.geom.LineString(null);
    }
    if (undo) {
        if (coords.length > 1) {
            coords.pop();
        }
        undo = false;
    }
    geom.setCoordinates(coords);
    return geom;
    }
});

But there seems to be a bug or something that I cannot figure out.

Using this plunker you can try what I am gonna explain:

If you draw a line with some vertices and then undo (hit ESC) till the last point on the line is removed, and then finish the line at (or close enough to) the same point just being undone, the last segment will be removed, why?

explained by figures:

1- Drawing a line feature

enter image description here

2- undoing the last (third) point enter image description here

3- finishing the line at (or close) the same point. enter image description here

4-the last segment is removed. enter image description here

I tried it several times and it happens. It wont happen if you add a point not close to the removed one or add more than one point.

Edit

Seems that OL3 checks the last two coordinates of the geometry and if they are the same then decides to finish the drawing session, and removes the last one. I tried the below code:

function geometryChange(coordinates, geometry){
if (!geometry) {
    geometry = new ol.geom.LineString(null);   
} 
if (undo){
    var coords = geometry.getCoordinates();
    console.info(coords);
    console.info(coordinates);
    var diff = coordinates.length - coords.length;
    if (diff > 0) {
        var lastCoordinates= coordinates[coordinates.length-1];
        console.info(coordinates);
        coordinates.splice(coordinates.length - (diff+1), diff,lastCoordinates);
        console.info(coordinates);
        coordinates.pop();
        console.info(coordinates);
        undo=false;
        if (coords.length === 1){
            undone=true;
            lineStringdraw.finishDrawing();
            undone=false;
            var emptyFeature = vector2.getSource().getFeatures()[vector2.getSource().getFeatures().length-1];
            vector2.getSource().removeFeature(emptyFeature);
            featureID-=1;
        }
    }
}
//console.info(coordinates);
geometry.setCoordinates(coordinates);
//coordinates= geometry.getCoordinates();
return geometry;    
}

the results are even more interesting. As I undo the last point, when I want to just add a point close to that (not finishing the line with double click), the OL assumes the drawing is finished and triggers the drawend event (I have this event for some purposes but amazingly is triggered for no reason).

like image 694
msc87 Avatar asked Dec 28 '15 09:12

msc87


1 Answers

try to change this piece of your code:

var keydown = function(evt){
var charCode = (evt.which) ? evt.which : evt.keyCode;
if (charCode === 27 && drawing === true){ //esc key
    var geom = drawing_feature.getGeometry();
    geom.setCoordinates(geom.getCoordinates().slice(0, -1));
}
};

to this:

var keydown = function(evt){
var charCode = (evt.which) ? evt.which : evt.keyCode;
if (charCode === 27 && drawing === true){ //esc key
    var geom = drawing_feature.getGeometry();
    var coordsLength = geom.getCoordinates().length;
    geom.setCoordinates(geom.getCoordinates().slice(0, coordsLength-1));
}
};

If you can use the removeLastPoint method then try the following

var keydown = function(evt){
var charCode = (evt.which) ? evt.which : evt.keyCode;
if (charCode === 27 && drawing === true){ //esc key
draw.removeLastPoint();
}
};
like image 85
pavlos Avatar answered Nov 04 '22 12:11

pavlos