Leaflet custom projection - leaflet

I'm starting with Leaflet and I'm trying make a example with custom projection (EPSG:23030) to show a layer from WMS service. If I do not know the resolutions, how can I make it? I have this code, using the plugin Proj4Leaflet, but it doesn't work:
var crs23030 = new L.Proj.CRS('EPSG:23030','+proj=utm +zone=30 +ellps=intl +units=m +no_defs');
var map = new L.Map('map', {
crs: crs23030
});
L.tileLayer.wms('http://www.juntadeandalucia.es/servicios/mapas/callejero/wms', {
layers: 'CallejeroCompleto',
format: 'image/jpeg',
maxZoom: 13,
minZoom: 0
}).addTo(map);
map.setView(new L.LatLng(37.24344,-4.23522), 7);

If resolutions/scales are left out, it will default to the ones used by Leaflet's spherical Mercator implementation, which most likely will be a very bad fit for other projections.
What resolutions you use depends on the underlying tile server:
If it's a "true" WMS server, like GeoServer or similar, you can make up any resolutions that you like and are useful for your users. The WMS server will handle anything.
If it's a tile cache with a WMS interface, like GeoWebCache, you need to provide the resolutions defined in the tile server's configuration (the gridset in GWC terminology)
Also note that for a tile cache, you must also provide the gridset's origin, or Leaflet's request will not align with the cache's grid.

Ok, I understand you and I have tried this:
var crs23030 = new L.Proj.CRS('EPSG:23030','+proj=utm +zone=30 +ellps=intl +units=m +no_defs',
{
resolutions: [1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 1, 0.5]
}
);
and it works. I have concluded that if I doesn't know the resolutions, I must put it aproximately.
Thanks

Related

How to change projection for L.imageOverlay in leaflet [duplicate]

I have implemented the following piece of code where I need to fit a layer over a map, that I made using QGIS. But the coordinates are not working correctly, what should I do? The problem are the wrong coordinates or there is a way to fit the layer in the map correctly using overlay?
var L;
var initialCoordinates = [-14.91, -43.20];
var initialZoomLevel = 4;
// create a map in the "map" div, set the view to a given place and zoom
map = L.map('heatmap').setView(initialCoordinates, initialZoomLevel);
L.map('map', {
crs: L.CRS.EPSG4326
});
// add an OpenStreetMap tile layer
// L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}{r}.png', {
// attribution: '© OpenStreetMap © CartoDB',
// maxZoom: 19
// }).addTo(map);
L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}{r}.{ext}', {
attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap',
subdomains: 'abcd',
minZoom: 0,
maxZoom: 18,
ext: 'png'
}).addTo(map);
// [[5.32, -28.95], [-33.1999, -73.9]]
var imageUrl = '/images/temperatureMapDefault.png', //temperatureMapDefault.png
imageBounds = [[5.32, -28.95], [-33.1999, -73.9]]; // [[ymin, xmin][ymax, xmax]]
L.imageOverlay(imageUrl, imageBounds).addTo(map);
The coordinates for the bounding box are working just fine; the problem is in the projections.
Your QGIS project, and your output image, are using EPSG:4326. Leaflet uses EPSG:3857 (spherical mercator) for display. If you try to overlay a stretched EPSG:4326 image over a EPSG:3957 one, the top and bottom edges will fit but you'll experience a vertical shift.
You can see this more clearly by creating a bigger image in EPSG:4326 with country boundaries. I encourage you to experiment.
Please read https://docs.qgis.org/2.18/en/docs/user_manual/working_with_projections/working_with_projections.html and related documentation in order to configure your QGIS project to use a different CRS.

How to fit layer correctly in map using leaflet overlay?

I have implemented the following piece of code where I need to fit a layer over a map, that I made using QGIS. But the coordinates are not working correctly, what should I do? The problem are the wrong coordinates or there is a way to fit the layer in the map correctly using overlay?
var L;
var initialCoordinates = [-14.91, -43.20];
var initialZoomLevel = 4;
// create a map in the "map" div, set the view to a given place and zoom
map = L.map('heatmap').setView(initialCoordinates, initialZoomLevel);
L.map('map', {
crs: L.CRS.EPSG4326
});
// add an OpenStreetMap tile layer
// L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}{r}.png', {
// attribution: '© OpenStreetMap © CartoDB',
// maxZoom: 19
// }).addTo(map);
L.tileLayer('https://stamen-tiles-{s}.a.ssl.fastly.net/toner-lite/{z}/{x}/{y}{r}.{ext}', {
attribution: 'Map tiles by Stamen Design, CC BY 3.0 — Map data © OpenStreetMap',
subdomains: 'abcd',
minZoom: 0,
maxZoom: 18,
ext: 'png'
}).addTo(map);
// [[5.32, -28.95], [-33.1999, -73.9]]
var imageUrl = '/images/temperatureMapDefault.png', //temperatureMapDefault.png
imageBounds = [[5.32, -28.95], [-33.1999, -73.9]]; // [[ymin, xmin][ymax, xmax]]
L.imageOverlay(imageUrl, imageBounds).addTo(map);
The coordinates for the bounding box are working just fine; the problem is in the projections.
Your QGIS project, and your output image, are using EPSG:4326. Leaflet uses EPSG:3857 (spherical mercator) for display. If you try to overlay a stretched EPSG:4326 image over a EPSG:3957 one, the top and bottom edges will fit but you'll experience a vertical shift.
You can see this more clearly by creating a bigger image in EPSG:4326 with country boundaries. I encourage you to experiment.
Please read https://docs.qgis.org/2.18/en/docs/user_manual/working_with_projections/working_with_projections.html and related documentation in order to configure your QGIS project to use a different CRS.

How to load WMS tiles only inside a bounding box in Leaflet?

I have an application in which I use mapbox.js to load basemap tiles for a location. Then user can load WMS tiles from a WMS server, of size 256X256 which get loaded on top of the basemap.
I am using mapbox and leaflet to display map as follow:
window.map = L.map('map', { 'minZoom': minZoomLevel(), 'maxZoom': maxZoomLevel(), reuseTiles: true, unloadInvisibleTiles: true }).setView(["35.7804", "-78.6391"], 17)
Then I am using Leaflet, to send requests to my server, and from there send request to WMS server to load tiles using this:
wms = L.tileLayer.wms('/viewers/wms', {
minZoom: 12,
maxZoom: 25,
layers: 'some layer name',
format: 'image/png',
updateWhenIdle: false,
transparent: true,
reuseTiles: true,
showTheRasterReturned: true,
COVERAGE_CQL_FILTER: 'featureId=\'' + featureId + '\''
});
By the time the request reaches my server, a BBOX attribute is added automatically by leaflet which has different co-ordinates (I think it is taking full viewport) i.e.
Started GET
"/viewers/wms?SERVICE=WMS&REQUEST=GetMap&VERSION=1.1.1&LAYERS=some
layer
name&STYLES=&FORMAT=image%2Fpng&TRANSPARENT=true&HEIGHT=256&WIDTH=256&REUSETILES=true&SHOWTHERASTERRETURNED=true&COVERAGE_CQL_FILTER=featureId%3D%279d3a23cba90680cecda337a926f563a6%27&SRS=EPSG%3A3857&**BBOX=-8755402.967897227,4285977.050006404,-8755097.219784087,4286282.798119542**" for 127.0.0.1 at 2018-06-27 16:51:01 -0400
A BBOX attribute is added by leaflet on the fly which are as follows
BBOX=-8755402.967897227,4285977.050006404,-8755097.219784087,4286282.798119542"
although, I want to get tiles only for these co-ordinates:
southWest ={lat: 35.77712238348847, lng: -78.64827990531921}
northEast {lat: 35.783693840245284, lng: -78.62991213798523}
setting up a BBOX option inside L.tileLayer.wms does not help either, as BBOX co-ordinates are added by leaflet.
Leaflet is working as expected.
You just have to remember that while Leaflet uses different Coordinate Reference Systems (CRSs) for the display projection and for L.LatLngs. You specify L.LatLngs (and bounds, etc) in EPSG:4326 (AKA equirectangular), and Leaflet will translate everything into EPSG:3857 (AKA Spherical Mercator).
Note how the URL for the WMS request includes a SRS=EPSG%3A3857 parameter (which means SRS=EPSG:3857 once URI-decoded). This means that Leaflet is providing coordinates in EPSG:3857, and expecting an image projected in EPSG:3857.
If you see no images, that likely means that your WMS server does not support EPSG:3857. Also, I encourage you to read through the Leaflet WMS/TMS tutorial, which highlights how to use different CRSs with WMS raster sources.
although, I want to get tiles only for these co-ordinates
Then use the bounds option of L.TileLayer.WMS. (If you don't see this option in the documentation, remember that L.TileLayer.WMS inherits options from L.TileLayer, which in turn inherits options from L.GridLayer)
Like so:
wms = L.tileLayer.wms('/viewers/wms', {
minZoom: 12,
maxZoom: 25,
layers: 'some layer name',
format: 'image/png',
updateWhenIdle: false,
transparent: true,
reuseTiles: true,
showTheRasterReturned: true,
COVERAGE_CQL_FILTER: 'featureId=\'' + featureId + '\''
bounds: L.latLngBounds([[35.77, -78.65],[35.78, -78.63]])
});

Leafletjs show a single wrapped map

I want to show a single world map and wrap it around so that each area is shown only once on the screen. Please refer the fiddle http://jsfiddle.net/8m13d6vs/
var osmUrl = 'http://{s}.tile.osm.org/{z}/{x}/{y}.png',
osm = L.tileLayer(osmUrl, {
noWrap: false,
attribution: "<a href='http://openstreetmap.org'>OpenStreetMap</a>"
});
var map = L.map('map').setView([0, 0], 1).addLayer(osm);
In the above fiddle, wrap is on, but the world map is duplicated. I want a single world map, and on left/right mouse drag, it should wrap around. It should be responsive to the area as well. Is there any way to achieve this? Hope my problem statement is understandable.
There's the Leaflet worldCopyJump option:
var map = L.map('map', {worldCopyJump: true}).setView([0, 0], 1).addLayer(osm);
It defaults to false, but setting this to true will copy the contents of the map over as the user pans beyond the map boundaries.
This sounds like a misunderstanding of the definition of "wrap":
In the context of Leaflet's Tile Layer / Grid Layer option noWrap, it says:
Whether the layer is wrapped around the antimeridian. If true, the GridLayer will only be displayed once at low zoom levels.
So it sounds like simply noWrap: true should achieve your objective.
Updated JSFiddle: http://jsfiddle.net/8m13d6vs/3/
BTW you should consider upgrading Leaflet version to 1+

Mapbox: How to continuously wrap a feature layer

Mapbox can continuously wrap tile layers such that you can scroll infinitely to the left and right over a repeating map of the world.
I have added a feature layer to a world map which displays some markers and, for some reason, this feature layer does not also wrap. The markers are only present on the original iteration of the world tiles layer.
I've tried using the noWrap: false options property that controls this characteristic on the tile layer when adding a feature layer, but it doesn't seem to have any effect.
Is there any way to do this?
Use the worldCopyJump option
example:
var map = L.mapbox.map('map', 'your.mapid', {center: [lat, long],
zoom: 4,
worldCopyJump: true
});
Not sure if I understand your question...
You can use
maxBounds: [[-90,-180],[90,180]]
for example
map = L.mapbox.map('map', '<some map id>',{minZoom: 0, maxZoom: 10, maxBounds: [[-90,-180],[90,180]]});
https://www.mapbox.com/mapbox.js/example/v1.0.0/maxbounds/