Search code examples
javascriptmathleafletreverse-engineeringmodulus

Leaflet reverse wrapLatLng operation


I've been stuck on this for a while now...

What I want to do is wrap a latLng when it crosses the w180 to store the coordinate so I do:

latLng = latLng.wrap()

And that works fine. But later I want to display that original value.

It basically comes down to reverse engineering these operations:

        var max = 180;
        var min = -180;
        var d = max - min;

        var lng = latLng.lng === max ? latLng.lng : ((latLng.lng - min) % d + d) % d + min;
        var lat = latLng.lat === max ? latLng.lat : ((latLng.lat - min) % d + d) % d + min;

        return new L.latLng(lat, lng);

I'm really struggling because of the modulo operations in this equation.

Any help would be greatly appreciated!


Solution

  • The operation ( a%d +d)%d computes the positive remainder of a.

    If a is positive, the repeated operation is redundant, as then the result stays a%d.

    If a is negative, by the usual conventions a%d will be a value between -d+1 and 0. Adding d shifts this result to 1,..,d and again computing the remainder reduces to the target range 0,..,d-1.

    The same could be achieved by

    r = a%d;
    if( r<0 ) {r=r+d;}
    

    but that is no longer a one-line formula.

    The way that operation is used in your code it makes sure that the result is in the range -180,..,179.999999.


    As to the first question, that is impossible. The remainder operation maps many arguments to one value, without further information one can not conclude from the value which of the infinitely many arguments it was computed from. You would have to store additional information like the effective divisor used in the totality of the remainder operations.

    You can shift the range to be from 0 to 360 by first shifting by one period to the range 180..540 and then reducing to the smallest non-negative remainder,

    ... = (a + 360) % 360
    

    which also could be achieved by

    ... = (a<0)?a+360:a