suppose tiles are store in file system like below image
roughly seen this url http://build-failed.blogspot.in/2012/11/zoomable-image-with-leaflet.html
see the code
var map = L.map('map').setView([0, 0], 2);
L.tileLayer('http://localhost/tiles/eso/0/0/0.png', {
minZoom: 1,
maxZoom: 6,
attribution: 'Testing',
tms: true
}).addTo(map);
from the above code it seems that loading tile 0/0/0.png means refer one tile. so my question is how leaflet will load so many tiles because this url http://localhost/tiles/eso/0/0/0.png refer one tile.
the above code is right?
the above code can load bunch of tiles ?
what setView([0, 0], 2); doing ? what is the meaning of 0,0 and 2 what does it mean ?
also tell me what the below code is trying to say
var map = L.map('map').setView([0, 0], 2);
L.tileLayer('eso/{z}/{x}/{y}.jpg', {
minZoom: 1,
maxZoom: 6,
attribution: 'ESO/INAF-VST/OmegaCAM',
tms: true
}).addTo(map);
in the above code we do not mention any value for z or for y or x ?
what approach i need to follow in real life ?
do i need to specify value or leaf will provider value for z,y, and x at run time ?
please let me know. thanks
1) Above code is wrong. Test it and you will see always the same repeated 0/0/0 tile.
2) Above code cannot load bunch of tiles, or actually it creates bunch of tiles all having the same image.
3) setView([0, 0], 2) centers the map view on coordinates point latitude 0 degree, longitude 0 degree, and with zoom level 2 (zoom level 0 being the entire planet in 1 tile).
4) Refer to Leaflet documentation about raster Tile Layer:
{z} — zoom level, {x} and {y} — tile coordinates.
The first argument of L.tileLayeris the urlTemplate. The {z}, {x} and {y} texts are replaced by Leaflet by the target tile coordinates. For example, you can go to OpenStreetMap and right click on any tile (anywhere on the base map), select "Open image" (or "View image") and the browser will show only the particular tile with its exact URL, where z, x and y have been adjusted by Leaflet to point to that particular tile.
The background system is that tiles are arranged in a Quadtree structure, assuming zoom level 0 corresponds to the entire map fitting in a single tile (i.e. 0/0/0). Then for the next higher zoom level, each tile is subdivided into 4 child tiles. And so on.
So in the example folder structure you exhibit in your question, tiles 1/0/0 and 1/0/1 are the left half of tile 0/0/0. Tile 1/0/0 is the top left corner, tile 1/0/1 is the bottom left corner.
Again, all this is automatically managed by Leaflet, provided that your tiles follow this Quadtree arrangement (whether in folders or within their file name, like for Zoomify).
ghyb's answer for 1,2, and 3 are completely correct, you might want to vote that answer up.
...also tell me what the below code is trying to say
On your second question, ghybs is also completely correct - I will add to it from the perspective of someone who needed a simpler introduction. In addition to diving into the TileLayer code, you might start by googling 'slippy map' to get many intro-level conceptual overviews. A good and popular technical intro to slippy map tilenames and how to derive them from map coordinates, along with code examples in several languages, can be found in the openstreetmap documentation here. These will definitely help you wrap your head around the TileLayer code.
what approach i need to follow in real life ? do i need to specify
value or leaf will provider value for z,y, and x at run time ?
Leaflet and other libraries plug in the value of x,y,z as described by ghybs, based on the where you move and zoom on the map. They produce the values, and the request is made to the appropriate folders. In real life, you only need the folders with the right images (produced by a program that generates tiled images into those folder structures) - either on your computer, on a server - or, what is far more common, by using a web map server that delivers the images requested at x/y/z. Examples include geoserver, mapserver, mapnik, and many online services like google maps, openstreetmap, bing, etc.
Related
I am new to leaflet and I want the restrict the panning of a world map horizontally and not vertically (longitude but not latitude) because this map will display pictures when I click on them and I cant see well the image when i restrict the panning horizontally AND vertically. The map by itself it not a picture, it's a real world map. But when I click on certain location, a small picture will appear on the map.
I try to play with maxBounds and setMaxbounds. The normal maxBounds (to view the world map) is :
maxBounds: [[-85, -180.0],[85, 180.0]],
When i try to put the latitude to
[[-150, -180.0],[150, 180.0]]
, the vertical panning is still restricted. Can somebody help please? Thank you.
This sounds similar to a (quite obscure) issue in the Leaflet issue tracker a
while back: see https://github.com/Leaflet/Leaflet/issues/3081
However, that issue was dealing with infinite horizontal bounds, not vertical bounds in a CRS that already has some preset limits.
If you set the map's maxBounds to a value larger than 85 (the value for MAX_LATITUDE of L.Projection.Spherical) and run a debugger, the call stack goes through the map's _panInsideMapBounds(), then panInsideBounds(), then _limitCenter(), then _getBoundsOffset, then project(), then through the map CRS's latLngToPoint, then untimately L.Projection.Spherical's project(). L.Projection.Spherical.project() projects the bounds' limits into pixel coordinates, and clamps the projected point to be inside the projection's limits.
There are a lot of reasons behind this, one of them being to prevent users from putting markers outside the area covered with tiles:
(This is particularly important when a user confuses lat-lng with lng-lat and tries to use a value outside the [-90,90] range for latitude, and the projection code starts returning Infinity values everywhere)
How to get around this? Well, we can always specify the map's CRS, and we can create a CRS with a hacked projection which enforces a different limit. Please be aware that this changes how the pixelOrigin works internally (as explained in the Leaflet tutorial about extending layers), so stuff (particularly plugins) might break.
So something like:
var hackedSphericalMercator = L.Util.extend(L.Projection.SphericalMercator, {
MAX_LATITUDE: 89.999
});
var hackedEPSG3857 = L.Util.extend(L.CRS.EPSG3857, {
projection: hackedSphericalMercator
});
var map = new L.Map('mapcontainer', {
crs: hackedEPSG3857,
});
Of course, then you can set up your own maxBounds:
var map = new L.Map('mapcontainer', {
crs: hackedEPSG3857,
maxBounds: [[-Infinity, -10], [Infinity, 10]]
});
In this case, the bounds' limits would still be clamped to hackedSphericalMercator.MAX_LATITUDE, but you should have enough wiggle room for your application.
As a side note: A radically different approach to this problem would be to use a different map projection. We're used to a spherical cylindrical projection, but that's not the only way to flatten the earth.
In particular, a Transverse Mercator projection (or pretty much any other transverse cylindrical projection, for that matter) works pretty much in the same way, but wraps vertically instead of horizontally, and it's the projected longitudes, not latitudes, the ones which approach infinity asymptotically when approaching the [-180, 180] range. Let me borrow an image from its wikipedia article:
This implies a different set of challenges (namely finding some raster tiles appropriate for your application, including which prime meridian to use, and making proj4leaflet play nice), but it's definitely doable.
I have a map and a lot of markers are displayed on it. Sometimes markers are so close to each-other that they overlap. To remedy this, I have implemented a spiderfier library to remedy this situation.
The idea is to group the markers being close-enough upwards on the screen (downwards mathematically) in such a way that they will not intersect each-other.
Markers are displayed as rectangles.
Implementation:
traverses the markers and markers which intersect each-other are included into a group with the center of ((minX + maxX) / 2, maxY) and the radius is just large-enough to display the markers on the periphery without intersecting each-other
while there are semi-circles which intersect each-other, we merge them into a larger half-circle
we sort the markers by a comparator, placing "smaller" markers to the left on the periphery of the circle compared to their "greater" counterparts
we display the markers on the top-half circle, but we display a line from their modified location to their real location
So far, so good.
Problem: These lines are intersecting each-other too often and we need a comparator function with which the number of marker line intersection is minimalized.
Tries:
P1.x <= P2.x => P1 <= P2
arctan((P1.y - C.y) / (R * (P1.x - C.x))) <= arctan((P2.y - C.y) / (R * (P2.x - C.x))) => P1 <= P2
I had high hopes tied to the second try, but had to acknowledge that it is not a good idea, since the translation line and the line between the real location and the center of the circle are not necessarily collinear, in fact, their angle can become fairly big if there are many markers having their real location very close to each-other, whilst the half-circle's surface except this sub-region is fairly barren. So, this leads to intersections as well and it is much more complex than the first try. I believe Javascript's Math.atan is implemented either with Taylor series or Fourier series, which involves derivatives in the first case and integral in the second case. Or, there might be a third approach, which is highly complex as well. I would think about optimizations and stuff like that if this second approach would have significantly reduced the number of intersections, but since the improvement is barely observable if at all, I returned to the first approach.
I am thinking about the following approach:
calculate the locations of the marker slots on the periphery
try to translate all the markers to their closest possible slot
find the conflicting groups and solve all conflicts by finding the optimum, which is the translation-set with the smallest total translation
Is this idea leading to a state where spider line intersection number is minimalized and if not, how could I minimalize the number of such intersections?
This is a difficult problems, studied for a long time now.
It is sometimes called
automatic label placement.
The work cited below is typical of what is available in the literature.
Van Kreveld, Marc, Tycho Strijk, and Alexander Wolff. "Point set labeling with sliding labels." Proceedings of the fourteenth annual symposium on Computational geometry. ACM, 1998. ACM link.
I need to zoom my OpenLayers map (which uses a Google Maps baselayer) to fit all of a given list of coordinates into the view.
I've stored the coordinates in an array of longitude and latitude pairs named pointsDecimal which looks like this:
pointsDecimal: Array[50]
0: 148.77638
1: -34.491728
2: 148.77896
3: -34.492302
4: 148.778090711323
...
Even-numbered indices (0, 2, 4 etc) are longitude, and odd-numbered indices (1, 3, 5 etc) are latitude.
This is the code I'm trying to use:
map.getView().fit(pointsDecimal, map.getSize());
But for some reason this puts me at maximum zoom level at the coordinates [0,0] - in the Gulf of Guinea, not in southeastern New South Wales where I'd like to be!
I know this would be much easier if I was using an OpenLayers source (e.g. source.getExtent()) in place of my pointsDecimal array, but this is not an option in this case for reasons I won't go into right now - I can only use the array.
Can anyone give me any hints please?
EDIT: I think I'm nearly there, thanks to Anupam. This is what I have now:
var extent = [pointsLongMin,pointsLatMin,pointsLongMax,pointsLatMax];
map.getView().fit(extent,map.getSize());
The values I'm passing to the array are as follows:
pointsLongMin: 148.771162
pointsLatMin: -34.5029736405108
pointsLongMax: 148.77896
pointsLatMax: -34.491728
But I'm still getting dumped out in the ocean at [0,0]. What am I doing wrong here?
In order to use map.getView().fit(extent,size).
extent denotes four points as [minx, miny, maxx,maxy].
It is actually a rectangle. try
var extent=[148.77638,-34.491728,148.77896,-34.492302];
map.getView().fit(extent,map.getSize());
most propable reason is that your map is projected on EPSG:3857while your extent EPSG:4326. So you need to transform your extent to your map projection.
var coordMin = ol.proj.fromLonLat([148.77638,-34.491728], 'EPSG:3857');
var coordMax = ol.proj.fromLonLat([148.77896,-34.492302], 'EPSG:3857');
var extent=[coordMin[0],coordMin[1],coordMax[0],coordMax[1]];
map.getView().fit(extent,map.getSize());
You may find a more elegand way to do the extent transformation. Unless you provide your full code we can only guess what is your map projection. I am just guessing is EPSG:3857 cause thats the default ol3 use.
I'm learning Leaflet and I can't seem to figure out what I did (or didn't do) to make negative coordinate tiles not load.
My code currently looks like this:
var map = L.map('map', {
crs: L.CRS.Simple
}).setView([0,0]);
L.tileLayer('img/tile_{x}_{y}.png', {
tileSize: 100,
noWrap: true,
format: 'image/png',
}).addTo(map);
Any help is appreciated.
It's not the most intuitive description, but it's probably the tileLayer continuousWorld option you're looking for.
If set to true, the tile coordinates won't be wrapped by world width (-180 to 180 longitude) or clamped to lie within world height (-90 to 90). Use this if you use Leaflet for maps that don't reflect the real world (e.g. game, indoor or photo maps).
At least for me this worked with tiles that using the scheme "{z}_{y}_{x}.png" e.g. 1_0_-1.png, 1_-2_0.png 1_1_-1.png for a ¬ shaped map that's left of the 0,0 coordinates.
Beware that by default negative y is up and positive is down. To reverse this behavior use the tms option.
I just want to clarify whether my way of understanding is correct. In my Google Maps app I would like to show to my users markers from particular continents.
Question: Am I right that a bound in Google Map API is an area made from NOT MORE AND NOT LESS than two points (markers)?
From math lessons, to draw 2D area I just need two points. Right? So to show to my users all markers from Europe should I just find two coordinates, one from Iceland (top, left) and second from let's say south-east Turkey? (For USA I would pick Seattle and Miami).
So, below JS code works perfectly. My question is - could you confirm that my way of understanding and the approach I've chosen is correct? Does it make any sense?
var bounds = new google.maps.LatLngBounds();
bounds.extend(new google.maps.LatLng('66.057878', '-22.579047')); // Iceland
bounds.extend(new google.maps.LatLng('37.961952', '43.878878')); // Turkey
this.map.fitBounds(bounds);
Yes, you are mostly correct. Except a 'bound' in Google maps case can include multiple points, for example if you had a point to the far right in the middle of the square in your image above and another at the bottom of the square in the middle you would still get an area the same as you have drawn above but with 3 points as in the edited map.
Obligatory link to the docs :)
https://developers.google.com/maps/documentation/javascript/reference?hl=en
You should not think about "top-left" and "bottom-right" but as south-west and north-east (so bottom-left and top-right if you like), as these are the coordinates used to create and/or retrieve the bounds object.
See the documentation and the getNorthEast and getSouthWest methods.
These two points are LatLng objects, and not markers. As an example, a marker is positioned on the map using a LatLng object.
I don't know your use case and your way of storing the data, but there might be a more precise way to display "Europe" markers. You could for example save the region along with each marker so that you can just query for "EU" markers and not others...