[GIS] Leaflet redraw() doesn’t trigger bounds update like setLatLngs()

leaflet

I'm the author of the geometry editing plugin leaflet.pm and I'm currently investigating a strange bug where editing a polygon sometimes won't update the bounds of the polygon even though the coordinates array changed.

I traced the issue down to two different functions I use to update the coordinates:

layer.setLatlngs().redraw();

and

layer._latlngs = [some new coords]
layer.redraw();

I guess the simple solution is to ALWAYS update a layers coords with setLatLng – and I'm currently changing my code to do that.

I still want to ask – shouldn't redraw() also update the bounds? Because it is visibly changing the layers appearance to the new coordinates too?

Best Answer

First things first: directly updating private members is never recommended, so API wise using setLatLngs() is the way to go.

I looked at the source code and the setLatLng() method in Polyline.js in order to see why the redraw won't cut it. Polygoncalls the Polyline setLatLngs() method so this is where I started.
1. setLatLngs method

// @method setLatLngs(latlngs: LatLng[]): this
    // Replaces all the points in the polyline with the given array of geographical points.
    setLatLngs: function (latlngs) {
        this._setLatLngs(latlngs);
        return this.redraw();
    },

This implicates that you don't need to call redraw() if you are using this method.
2. The private method _setLatLngs :

_setLatLngs: function (latlngs) {
        this._bounds = new LatLngBounds();
        this._latlngs = this._convertLatLngs(latlngs);
    },

Calls private method _convertLatLngs :

_convertLatLngs: function (latlngs) {
        var result = [],
            flat = LineUtil.isFlat(latlngs);

        for (var i = 0, len = latlngs.length; i < len; i++) {
            if (flat) {
                result[i] = toLatLng(latlngs[i]);
                this._bounds.extend(result[i]);
            } else {
                result[i] = this._convertLatLngs(latlngs[i]);
            }
        }

        return result;
    },

So, by not using setLatlngs(), leaflet did not get the instruction to rebuild the latLng array.