0

The short question

Given:

  • map center (in lat long)
  • map boundaries (in lat long)
  • position of the point A on the layout relative to the layout origin

How to compute: position of the point A in lat/long (not using map object only CRS)

Or simpler

Given:

  • map center (in lat long)
  • map boundaries (in lat long)

How to compute: position of the layout origin in pixels (not using map object only CRS)

If I had response for the second one I could figure out response for the first one.


Longer explanation

The whole task here is given: 1. map center (lat long) 2. map bounds (lat long) 3. point (px relative origin pixel) calculate point position (3) in lat long.

Consider zoom always constant here = 18

Why: I had map UX with properties : center and bounds all in lat long, then I have svg layout as a layer on lefalet map (SVGOverlay) , when I add some object on this svg layout it's position will be given relative to this layout origin, I want to display it as lat long.

I can use map.layerPointToLatLng to get exactly required result, but for this I had to have reference to already created leaflet map, but in some scenarios I don't have one, for example I store in db 3 parameters which describes the map and objects on it : map center, map bounds and svg object point relative to the layout origin and want to calculate lat long of the object without creating map instance.

So I was digging into leaflet library layerPointToLatLng implementation and flow from there:

  • getPixelOrigin
  • _getNewPixelOrigin
  • getSize <-- Probably issue is here
  • Given size, center & size calculate origin and then its straightforward unproject(origin + relative point position)

getSize here is just

                this._container.clientWidth || 0,
                this._container.clientHeight || 0);

So it was set up by image overlay, like this

    _reset: function () {
        var image = this._image,
            bounds = new Bounds(
                this._map.latLngToLayerPoint(this._bounds.getNorthWest()),
                this._map.latLngToLayerPoint(this._bounds.getSouthEast())),
            size = bounds.getSize();

        DomUtil.setPosition(image, bounds.min);

        image.style.width  = size.x + 'px';
        image.style.height = size.y + 'px';
    },

So I've tried replicate all this flow but with this _container ref like this


export interface MapEnv {
    zoom: number;
    crs: L.CRS;
}

export const defaultMapEnv: MapEnv = {
    zoom: 18,
    crs: CRS.EPSG3857
};

export const getMapOrigin = (
    bounds: LatLngBounds,
    center: Point,
    { crs, zoom } = defaultMapEnv
): Point => {
    //
    const lbounds = new L.LatLngBounds(bounds.southWest, bounds.northEast);
    const lcenter = new L.LatLng(center.x, center.y);

    const bounds1 = new L.Bounds(
        crs.latLngToPoint(lbounds.getNorthWest(), zoom),
        crs.latLngToPoint(lbounds.getSouthEast(), zoom)
    );

    const size = bounds1.getSize();

    const ppp = crs.latLngToPoint(lcenter, zoom);

    const orig = ppp
        .subtract(size.divideBy(2))
        .round();

    return { x: orig.x, y: orig.y };
};

export const mapPoint2LatLong = (
    orig: Point,
    point: Point,
    { crs, zoom } = defaultMapEnv
) => {

    const lorig = new L.Point(orig.x, orig.y);
    const lpoint = new L.Point(point.x, point.y);

    const res = crs.pointToLatLng(lorig.add(lpoint), zoom);

    return { x: res.lat, y: res.lng };
};

But this implementation always gives some small offset relative to the correct lat long coordinates Example:

            const pt = [57320, 43710];

            console.log('center', mapProps.center);
            console.log('bounds', mapProps.bounds);
            console.log(
                'map latlong',
                map.layerPointToLatLng(new L.Point(pt[0], pt[1]))
            );
            const orig = getMapOrigin(mapProps.bounds, mapProps.center);
            const ll = mapPoint2LatLong(orig, { x: pt[0], y: pt[1] });
            console.log('custom latlong', ll);


=====
center {x: 55.159897, y: 61.402554}
bounds 
{
northEast: (2) [55.293583, 61.804276]
southWest: (2) [55.018969, 61.094971]
}
map latlong {lat: 55.02665382398748, lng: 61.708027124404914} <-- Correct
custom latlong {x: 55.16323630220735, y: 61.35539174079896} <-- Incorrect (small offset always)

Some hints, suggestions how to correct this ?

  • 2
    I'm sure Leaflet has all the necessary methods to achieve what you want. Problem is that from this long question it's hard to guess what exactly you want/need. Can you formulate your need in two or three sentences (without hints to possible solutions and problems therein)? – TomazicM Mar 17 at 11:03
  • @TomazicM Thanks, reformulated – baio Mar 17 at 12:19
  • When you talk about "given map center" and "given map boundaries", what do you have in mind? Current view values obtained from Leaflet? Or your desired values that you want view to conform to? – TomazicM Mar 17 at 12:44
  • One more question. When you say "position of the point A on the layout relative to the layout origin", what do you have in mind? Current view, where upper left corner has coordinate [0, 0]? Or upper left corner of the whole map? There is also map container which a bit bigger than current map view. And there is also overlay container, which has exactly the same dimensions as map view. Thing can get quite complex. You can get a hint here: gis.stackexchange.com/questions/353250/… – TomazicM Mar 17 at 12:50
  • @TomazicM This : desired values that you want view to conform to – baio Mar 17 at 12:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.