Setup projection on Leafletjs - leaflet

Im using an Leafletjs for an home project(This is have it looks, right now.
But i can't find have to setup the projection, i have found it for OpenLayers, which looks like this:
// Openlayers settings
//var defaultMaxExtent = new OpenLayers.Bounds(427304, 6032920, 927142, 6485144);
var defaultMaxExtent = new OpenLayers.Bounds(427304, 6032920, 927142, 6485144);
var defaultProjection = "EPSG:25832";
var defaultUnits = "Meters";
var defaultResolutions = new Array(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024);
var defaultExtent = new OpenLayers.Bounds(215446, 2103547, 706886, 6203897); //this extent is used when the page is loaded.
//var defaultExtent = new OpenLayers.Bounds(705446, 6203547, 706886, 6203897); //this extent is used when the page is loaded.
map = new OpenLayers.Map('map', { projection: defaultProjection, units: defaultUnits, maxExtent: defaultMaxExtent, resolutions: defaultResolutions, controls: [
// Hide controls by default
new OpenLayers.Control.Navigation({ wheelChange: HideInfoBox() }),
new OpenLayers.Control.ArgParser(),
new OpenLayers.Control.Attribution()]
});
layer = new OpenLayers.Layer.WMS("kort", "http://serverAddress?", { nbr: '', username: 'admin', password: 'adminadmin', layers: 'Overlayer', format: 'image/png' });
Anybody that can help me?
Update:
I have tried to take the standard projection from Leaflet and customized it, like so
L.CRS.EPSG25832 = L.extend({}, L.CRS, {
code: 'EPSG:25832',
projection: L.Projection.SphericalMercator,
transformation: new L.Transformation(0.5 / Math.PI, 0.5, -0.5 / Math.PI, 0.5),
project: function (latlng) { // (LatLng) -> Point
var projectedPoint = this.projection.project(latlng),
earthRadius = 6378137;
return projectedPoint.multiplyBy(earthRadius);
}
});
Now the projection is correct. But the problem now is the coordinates is wrong, so forexample if i get the coordinates from Leaflet, Kolding is now loacted in mid france not in Denmark.

I found the solution to the problem myself.
By doing this instead:
var crs = L.CRS.proj4js('EPSG:25832', '+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs', new L.Transformation(0.5 / (Math.PI * L.Projection.Mercator.R_MAJOR), 0.5, -0.5 / (Math.PI * L.Projection.Mercator.R_MINOR), 0.5));
var map = new L.Map('Krak-Map', { center: new L.LatLng(latitude, longitude), zoom: 17, crs: crs });

Related

Getting the map bounds of a GeoJson region in leaflet prior to zooming

I'm using leaflet and I'm loading up the regions of my map dynamically from a database, based on the bounding box coordinates of the currently viewed map. As I zoom in, the detail of each new layer increases. The same regions will exist in every layer of the map, and the same region on a different zoom level will have the same id.
I am currently attempting to calculate the target map bounds and target zoom level, so that I can load up all the intersecting regions within the new map bounding box. I currently have the following code.
zoomToFeature(e) {
//e.g. map zoom for currently visible map is 3
const layer = e.target;
let padding = [5, 5];
let layerBounds = layer.getBounds();
//e.g layerBounds returns:
//ne = lat: -37.770025, lng: 145.02439
//sw = lat: -37.834451, lng: 144.900952
let targetZoom = this.map.getBoundsZoom(layerBounds, false, padding);
targetZoom = Math.min(this.map.getMaxZoom(), targetZoom);
//e.g.targetZoom for this feature is 12
let center = layer.getCenter()
//e.g. center for this layer is lat: -37.78808138412046, lng: 144.93164062500003
let targetPixelBounds = this.map.getPixelBounds(center, targetZoom);
//e.g. targetPixelBounds: max: Point{x: 946751, y: 643578} min:{x:946114,y:643078}
//this looks very wrong, and so causes everything below to fail I think.
//am I supposed to reset the origin? am I meant to project the center and targetZoom?
let sw = this.map.unproject(targetPixelBounds.getBottomLeft());
let ne = this.map.unproject(targetPixelBounds.getTopRight());
let targetMapBounds = new L.LatLngBounds(sw, ne);
this.map.flyTo(center,targetZoom);
this.loadMapData(targetMapBounds, targetZoom).subscribe(() => {
this.removeOldRegions(); // deletes existing geojson
this.loadRegions(); // adds retrieved data to new geojson layer
//find the same region but in the new zoom layer
let newLayer = this.getLayerById(layer.feature.properties.id);
this.highlightFeature(newLayer);
});
}
It is going wrong at the
let targetPixelBounds = this.map.getPixelBounds(center, targetZoom)
line.
Any idea how I can fix this?
Ok, I've cracked the case.
The unproject lines in the original code above take zoom level as an argument, which I didn't put in the original code.. So I've refactored the code, which I have posted below.
Basically once I have the map bounding box, I can perform the fly to, and execute code to retrieve the new geojson at the new zoom level. By the time the animation has completed, the new geojson layer is already loaded. (Written in TypeScript. Sorry non TypeScript people)
zoomToFeature(e) {
const layer = e.target;
let padding = [5, 5];
let layerBounds = layer.getBounds();
let targetMapBoundsZoom = this.getTargetMapBoundsZoom(layerBounds, { padding: padding });
this.map.flyToBounds(targetMapBoundsZoom.bounds);
this.loadMapData(targetMapBoundsZoom.bounds, targetMapBoundsZoom.zoom).subscribe(() => {
this.removeOldRegions();
this.loadRegions();
//find the same region but in the new zoom layer
let newLayer = this.getLayerById(layer.feature.properties.id);
this.highlightFeature(newLayer);
});
}
getTargetMapBoundsZoom(bounds, options) {
let newBoundsCenterZoom = this._getBoundsCenterZoom(bounds, options);
let targetMapBoundsPixels = this.map.getPixelBounds(newBoundsCenterZoom.center, newBoundsCenterZoom.zoom);
let targetSw = this.map.unproject(targetMapBoundsPixels.getBottomLeft(), newBoundsCenterZoom.zoom);
let targetNe = this.map.unproject(targetMapBoundsPixels.getTopRight(), newBoundsCenterZoom.zoom);
let targetMapBounds = new L.LatLngBounds(targetSw, targetNe);
return {
bounds: targetMapBounds,
zoom: newBoundsCenterZoom.zoom
}
}
loadMapData(bounds, zoom): Observable<any[]> {
const boundingBox = Util.GetMapBounds(bounds);
const regionTypeId = this.regionTypeIds[this._regionType];
return this.mapService.getGeoJsonData("AU",
regionTypeId,
zoom,
boundingBox.n,
boundingBox.s,
boundingBox.e,
boundingBox.w).pipe(map((response: any) => {
this.mapGeoJsonData = this.createFeatureCollection(response.data);
return this.mapGeoJsonData;
}));
}
//this is a copy of the original _getBoundsCenterZoom that is internal to leaflet, with minor modifications.
_getBoundsCenterZoom(bounds, options) {
options = options || {};
bounds = bounds.getBounds ? bounds.getBounds() : L.latLngBounds(bounds);
var paddingTL = L.point(options.paddingTopLeft || options.padding || [0, 0]),
paddingBR = L.point(options.paddingBottomRight || options.padding || [0, 0]),
zoom = this.map.getBoundsZoom(bounds, false, paddingTL.add(paddingBR));
zoom = (typeof options.maxZoom === 'number') ? Math.min(options.maxZoom, zoom) : zoom;
if (zoom === Infinity) {
return {
center: bounds.getCenter(),
zoom: zoom
};
}
var paddingOffset = paddingBR.subtract(paddingTL).divideBy(2),
swPoint = this.map.project(bounds.getSouthWest(), zoom),
nePoint = this.map.project(bounds.getNorthEast(), zoom),
center = this.map.unproject(swPoint.add(nePoint).divideBy(2).add(paddingOffset), zoom);
return {
center: center,
zoom: zoom
};
}
createFeatureCollection(data: any) {
let featureCollection = {
type: "FeatureCollection",
features: data.map(r => {
const geoJson = JSON.parse(r.geoJson);
if (geoJson.type === "GeometryCollection") {
geoJson.geometries = geoJson.geometries.filter(r => r.type === "Polygon" || r.type === "MultiPolygon");
}
let feature = {
type: "Feature",
id: r.id,
properties: { id: r.id },
geometry: geoJson
}
return feature;
})
};
return featureCollection;
}
The default behaviour for this is to read out the bounds and pass it to the map:
map.fitBounds(e.target.getBounds());
Then you function can look like:
zoomToFeature(e) {
let padding = [5, 5];
let layerBounds = e.target.getBounds();
let targetZoom = this.map.getBoundsZoom(layerBounds, false, padding);
targetZoom = Math.min(this.map.getMaxZoom(), targetZoom);
//e.g.targetZoom for this feature is 12
map.fitBounds(layerBounds , {padding: padding, maxZoom: targetZoom });
this.loadMapData(layerBounds , targetZoom).subscribe(() => {
this.removeOldRegions(); // deletes existing geojson
this.loadRegions(); // adds retrieved data to new geojson layer
//find the same region but in the new zoom layer
let newLayer = this.getLayerById(layer.feature.properties.id);
this.highlightFeature(newLayer);
});
}
this moves the map and zoom it to the layer.

Leafletjs, overriding the max zoom in option

I have a standard leaflet map, for various reasons (high resolution data) I need to zoom in further than the default settings allow, to centimetres.
how do I override this max zoom setting?
My code is currently:
<script>
// Set the projection system using proj4js and proj4leafletjs(not sure this works yet)
var crs = new L.Proj.CRS('EPSG:32365',
'+proj=utm +zone=35 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs',
{
resolutions: [
8192, 4096, 2048, 1024, 512, 256, 128
],
origin: [0, 0]
})
// Creating map options
var mapOptions = {
center: [38.623162,27.9282893],
zoom: 10,
zoomSnap: 0.25
}
// Creating a map object
var map = new L.map('map', mapOptions);
// Creating a Layer object
var layer = new L.TileLayer('http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png');
// Adding layer to the map
map.addLayer(layer);
</script>

How to get the coordinates of a drawn box in OpenLayers?

I am a novice to OpenLayers, so sorry for an obvious (and perhaps dumb) question, for which I found different approaches for solutions, but none working. Tried this and that, a dozen different suggestions (here, here, here, here, here) but in vain.
Basically, I want to pass the coordinates of a drawn rectangle to another webservice. So, after having drawn the rectangle, it should spit me out the four corners of the bounding box.
What I have so far is the basic OL layers example for drawing a rectangle:
var source = new ol.source.Vector({wrapX: false});
vector = new ol.layer.Vector({
source: source,
style: new ol.style.Style({
fill: new ol.style.Fill({
color: 'rgba(0, 255, 0, 0.5)'
}),
stroke: new ol.style.Stroke({
color: '#ffcc33',
width: 2
}),
image: new ol.style.Circle({
radius: 7,
fill: new ol.style.Fill({
color: '#ffcc33'
})
})
})
});
var map = new ol.Map({
target: 'map',
layers: [
new ol.layer.Tile({
source: new ol.source.OSM()
}),
vector
],
view: new ol.View({
center: ol.proj.fromLonLat([37.41, 8.82]),
zoom: 4
})
});
var draw; // global so we can remove it later
function addInteraction()
{
var value = 'Box';
if (value !== 'None')
{
var geometryFunction, maxPoints;
if (value === 'Square')
{
value = 'Circle';
geometryFunction = ol.interaction.Draw.createRegularPolygon(4);
}
else if (value === 'Box')
{
value = 'LineString';
maxPoints = 2;
geometryFunction = function(coordinates, geometry)
{
if (!geometry)
{
geometry = new ol.geom.Polygon(null);
}
var start = coordinates[0];
var end = coordinates[1];
geometry.setCoordinates([
[start, [start[0], end[1]], end, [end[0], start[1]], start]
]);
return geometry;
};
}
draw = new ol.interaction.Draw({
source: source,
type: /** #type {ol.geom.GeometryType} */ (value),
geometryFunction: geometryFunction,
maxPoints: maxPoints
});
map.addInteraction(draw);
}
}
addInteraction();
Now, what comes next? What is a good way of extracting the bounding box?
Thanks for any hints!
You need to asign a listener to the draw interaction. Like so:
draw.on('drawend',function(e){
alert(e.feature.getGeometry().getExtent());
});
Here is a fiddle

Leaflet Circle radius changing dependant on y/lng coords

I am using mapbox/leaflet to display a picture of a human body rather than a regular map.
I am using leaflet draw and I need to be able to create a circle and move it around while maintaining its radius. However, when I move it towards the bottom of the map/screen, the size increases exponentialy. I want it to stay the same size.
I assume it's something to do with projection or CRS but I'm not sure what to do to stop it.
My code is :
var mapMinZoom = 0;
var mapMaxZoom = 4;
var map = L.map('map', {
maxZoom: mapMaxZoom,
minZoom: mapMinZoom,
crs: L.CRS.Simple,
noWrap: true,
continuousWorld: true
}).setView([0, 0], mapMaxZoom);
var mapBounds = new L.LatLngBounds(
map.unproject([0, 3840], mapMaxZoom),
map.unproject([4096, 0], mapMaxZoom));
map.fitBounds(mapBounds);
L.tileLayer('/tiles/{z}/{x}/{y}.png', {
minZoom: mapMinZoom, maxZoom: mapMaxZoom,
bounds: mapBounds,
attribution: 'Rendered with MapTiler',
noWrap: true,
continuousWorld: true
}).addTo(map);
var touches;
var featureGroup = L.featureGroup().addTo(map);
var drawControl = new L.Control.Draw({
edit: {
featureGroup: featureGroup
}
}).addTo(map);
map.on('draw:created', function (e) {
featureGroup.addLayer(e.layer);
});
Any ideas? I don't need to use leaflet draw, just the L.circle would do, but it has the same issue.
Gif of issue here :
Turns out there are a load of todos in the leaflet 0.7 code... including this little gem :
// TODO Earth hardcoded, move into projection code!
_getLatRadius: function () {
return (this._mRadius / 40075017) * 360;
},
_getLngRadius: function () {
return this._getLatRadius() / Math.cos(L.LatLng.DEG_TO_RAD * this._latlng.lat);
},
Updated to 0.8Dev and it has all been fixed!

Leaflet setMaxBonds causing error

My leaflet map with custom tiles is working properly until I try to set the max bounds for my map.
var SWCorner = new L.LatLng(-312, -180);
var NECorner = new L.LatLng(180, 312);
var MaxBounds = new L.LatLngBounds(southWest, northEast);
var map = L.map('map', { crs: L.CRS.EPSG4326, draggable: true }).setView([-63, 65], 1);
map.setMaxBounds(MaxBounds);
L.tileLayer('http://localhost:9000/CustomIcons/tile_{z}_{x}-{y}.png', {
boxZoom: false,
minZoom: 1,
maxZoom: 5,
tms: true,
noMoveStart: true,
keyboardPanOffset: 10,
noWrap: true,
tileSize: 350
}).addTo(map);
Things I have tried are:
var SOMmap = L.map('SOMmap', { crs: L.CRS.EPSG4326 maxBounds: new L.LatLngBounds([-312,-180],[180,312]}).setView([-63, 65], 1);
var SOMmap = L.map('SOMmap', { crs: L.CRS.EPSG4326,
draggable: true, maxBounds: MaxBounds }).setView([-63, 65], 1);
var SOMmap = L.map('SOMmap', { crs: L.CRS.EPSG4326,
draggable: true
}).setView([-63, 65], 1).setMaxBounds(MaxBounds);
Whenever I try to set the max bounds, the tiles always vanish. How do I need to call the setMaxBounds?
From http://spatialreference.org/ref/epsg/4326/
EPSG:4326
WGS 84
WGS84 Bounds: -180.0000, -90.0000, 180.0000, 90.0000
Projected Bounds: -180.0000, -90.0000, 180.0000, 90.0000
Scope: Horizontal component of 3D system. Used by the GPS satellite navigation system and for NATO military geodetic surveying.
Last Revised: Aug. 27, 2007
Area: World
So your values for the LatLngBounds are not valid in this projection lat should be between -180 and 180 , lng between -90 and 90