Undoing the last point in OL3 removes the last segment
Asked Answered
A

1

15

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).

Arabelle answered 28/12, 2015 at 9:17 Comment(7)
I can't reproduce this behavior, it would be easier if you show a screen video. Your image sequence doesn't look like the same linestring.Standing
@JonatasWalker: hope this help...youtube.com/watch?v=BYrWWlNRYM4Arabelle
@JonatasWalker: did you have time to take a look at the video? I am still struggling with this issue. would appreciate any insight!Arabelle
Yes, I did and I thought you and @pavlos have reached the solution. I'll try a deeper look.Standing
At the time that plunker was created there wasn't removeLastPoint. You should rely on it. A forked plunker to demonstrate.Standing
Did you check my last plunker?Standing
@JonatasWalker: I just did... seems it has the same problem.Arabelle
R
2

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();
}
};
Reactive answered 28/12, 2015 at 11:12 Comment(12)
What should the geometryFunction be then?Arabelle
I managed to reproduce your case. slice(0,-1) didnt seem correct to me as slice needs start end point. so -1 it is not a proper end point unless I am missing something. I have changed this within your plunker and seems to do the job. Did you try it? Maybe you dont need geometryFunctionReactive
+1 because I was also thinking of removing geometryFunction, but yet I am not sure if I should since I need it for other issues. Otherwise, -1 and length-1 are not different in slice function.Arabelle
thats correct. Just read it on w3schools Use negative numbers to select from the end of an array sorry for that I wasnt aware. At least we have learned something :))))))). Aparently , did you manage to solve it????Reactive
I'll try to remove geometryFunction to see if the results are correct. I need some geometry changes for , e.g. snapping the first or/and the last point of a lineString, so I should make sure I can handle them without the geometryFunction.Arabelle
No, without geometryFunction, the line wont change. In fact, the change is temporarily and as soon as the pointer moves, the lines returns to the same geometry as before undoing it.Arabelle
You can always use the removeLastPoint method. I ll try to update my answer to show you this option.Reactive
It did not work.... I dont know why but seems as it is experimental, it can be expected...Arabelle
the error is happening only if you have pressed the esc key once. Just an info might help youReactive
I'm using OL 3.8.2 but it does not know removeLastPoint as a function. Strange! I also didn't quite get what you said about the error.Arabelle
It is strange indeed. removeLastPoint was working within the supplied plunker. Though didnt have the expected result. Aparently plunker comes with a timeout error right now. So I cannt test it again. The error is happening only if the remaining points of digitising line is two. If you have more than 2 points remaining no such error occurs. It seems to be an ol3 bug.Reactive
forget about the two points, what I meant is that if you press esk key (undo action) once and go for adding a point close to the one moved you get the error. But if you press esc twice or more you have to click close to the very first point moved to reproduce the errorReactive

© 2022 - 2024 — McMap. All rights reserved.