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_getNewPixelOrigingetSize<-- 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 ?
mapPropsobject you are using in your example? – TomazicM Mar 21 '20 at 18:07