Problem of tiling with GeoWebCache: most tiles are missing - javascript

I set up a PostGIS database that I added in GeoServer via a parameterized SQL view. I used Leaflet to display this layer via wms.
It worked fine until I add GeoWebCache using the url "/geoserver/gwc/service/wms" instead of "/geoserver/wms". I can still see my polygons when I'm at the minimal zoom. But then when I zoom I see only a red polygon and a half of a green polygon and if I zoom again I see only the red polygon. You can see these 3 states on the images below:
I guess this is a problem of tiling: I get the minimal tiles and also some tiles around the red polygon for further zooms but for some reason it seems that the other tiles are not sent.
Here is the code I use to get my wms layer with leaflet:
geoJSONlayer = L.tileLayer.wms("/geoserver/gwc/service/wms", {
layers: 'cartowiki:choix',
format: 'image/png',
transparent: true,
viewparams: 'year:'+(annee+3000)
}).addTo(map);
geoJSONlayer.addTo(map);
Do you have an idea of the problem here ?
Thanks in advance,

The bounding box was the problem indeed. In Geoserver, I had to modify the properties of the layer in 2 places :
I clicked 'Compute from SRS bounds' and then 'Compute from native bounds' in the Bounding Boxes part of the Data section
I erased and created again the available gridsets in the Tile Caching section so that the grid subset bounds would update with the new Bounding Boxes
I hope it can help someone in the future!

Related

Leaflet overlay order (points, lines, and polygons)

I'm working with the Leaflet.StyledLayerControl plugin and would like to set my layers so that polygons always get pushed to the back, lines above the polygons, and points above the lines.
I have searched for solutions here but most refer to tilelayers or map panes (which I think only work with another version of leaflet 1.0).
I want to be able to toggle lines on and off and have them always be below points (same with polygons below polylines).
I'm guessing I have to do something with setZIndex or bringToFront() but i'm not sure where to start.
Any help would be appreciated. Thanks.
The easy solution is really to use Leaflet 1.0, which provides you with map.createPane("paneName") functionality. So you create like "polygonsPane", "linesPane" and "pointsPane", that you specify to each of your vector / shape layers using their pane option.
Once set, you can add / remove them to / from map, and they will always be inserted in the specified pane, hence respecting the pane's order.
// Create necessary panes in correct order (i.e. "bottom-most" first).
map.createPane("polygonsPane");
map.createPane("linesPane");
map.createPane("pointsPane");
L.polygon([/* coords */], { pane: "polygonsPane" }).addTo(map);
L.polyline([/* coords */], { pane: "linesPane" }).addTo(map);
L.circleMarker([/* coords */], { pane: "pointsPane" }).addTo(map);
Demo: https://jsfiddle.net/3v7hd2vx/51/
With Leaflet 0.7, you know that all vector layers are part of the same SVG container, being appended when added to map, hence they appear on top of all previously added vectors. Then you have to use bringToFront() and/or bringToBack() to re-sort them to whatever order you need.
You might be interested in that post for that case: https://gis.stackexchange.com/questions/166252/geojson-layer-order-in-leaflet-0-7-5/167904#167904

leaflet fixed size circle on map

I am using leaflet.js to create few markers and circles. I am using the below given code to draw circles : -
L.circle([ lat, lng ], 1000, {
color : colorCode,
stroke : false,
fillColor : colorCode,
fillOpacity : 0.7
});
Now if I edit this circle on UI and drag this circle vertically downwards, the circle size increases and vice a versa. Similar issue is with calling the above given method with different lat lngs. The same radius (1000) sized circle get plotted with different sizes on map.
My requirement is to place marker with same radius with same size on map everywhere.
I checked L.circleMarker but it takes radius in pixels and also circleMarkers does not scale in zoomin zoomout events. That is why I can't use circleMarkers.
I changed the crs option to 4326 but no success. I am using imageOverlay not tileset. I have created a fiddle.
http://jsfiddle.net/newBee_/88bdrzkr/12/
Try creating a circle on top area then edit and move it downwards. It's size increases. This is what I want to stop. This will resolve the problem of generating circle of same radius via code in different area of map with same size. Please help.
Please suggest.
Edit:
It looks like this is a bug deep into Leaflet 0.x: L.Circle radius computation uses hard-coded Earth projection rather than the specified CRS. Leaflet 1.0 seems to correctly check for the CRS before using the Earth-related computation.
For your case, simply overriding the faulty method seems to fix it, at least visually.
Demo: http://jsfiddle.net/88bdrzkr/13/
The "corrected" method to include in your script:
L.Circle.include({
_getLngRadius: function () {
return this._getLatRadius();
}
});
Regarding iH8's answer, the trick to override L.CRS.Simple.scale is similar to highly zooming (the 256 factor expands the latLng to much further pixels - any high number will do). At high zoom, you are moving your circle along a very short distance, for which the latitude does not change much. So you do not see any visible difference in radius, even though the bug is still there.
Demo of using just higher zoom, no method override at all: http://jsfiddle.net/kau6g8fk/1/
For your need where the circle looks to be more like a visual aid, any of these 3 solutions is enough.
Edit: the CRS is not the issue at all.
Previous message:
If you use Leaflet for indoor mapping, as your jsFiddle suggests (or any flat type map, as opposed to the projection of a sphere like Earth on to a plane), you could simply use L.CRS.Simple
Striked out this faulty solution as pointed out by Ghybs in his answer
Very weird issue, turns out that overloading L.CRS.Simple's scale method to return 256 * Math.pow(2, zoom) fixes this. Here's a fork of your JSFiddle: http://jsfiddle.net/kau6g8fk/ I'm unsure as to the cause of this issue, it would require more research. Will do if i find the time. Found the solution here: http://codepen.io/mike_beweb/pen/BymKGe
The answer below was given before the poster edited his/her question and showed that the used CRS was L.CRS.Simple while i presumed the default CRS. I'll leave it in tact because it might come in handy for some users:
The size change on drag of your L.Circle's is because of your map's default spherical mercator projection (EPSG:3857). Best explained with an image, here's a map with a graticule overlay on every 10 degrees:
Demo on Plunker: Leaflet 0.7.5 EPSG:3857 Spherical
As you move further from the equator every plane becomes higher. Thus your circle automaticly becomes higher the further north/south you drag it. You could use a equirectangular projection (EPSG:4326), in which every plane has the same size regardless of the distance from the equator:
Demo on Plunker: Leaflet 0.7.5 EPSG:4326 Equirectangular
With equirectangle projection you won't have the problem you're having now but you'll have to change your tileset to one with EPSG:4326 projection and those are hard to come by compared to EPSG:3857 tilesets.
If you're not willing or unable to change projection another solution could be to hack around L.CircleMarker and change the radius of your markers depended on current zoomlevel. But that's rather ugly in my opinion.

Leafletjs Cursor when hovering over WMS Layer

I am using Leafletjs. Currently its pretty straight forward, I have a streets view from open maps.
var streets = L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {
maxZoom: 18,
attribution: 'Map data © OpenStreetMap contributors'
});
I also have a WMS layer that is coming from a geoserver. It has the standard getFeatureInfo and everything shows up correctly.
L.tileLayer.wms("GEOSERVERURL", {
layers: 'layers',
format: 'image/png'
,transparent: true
}).addTo(map);
The wms layer is also clickable and I use getFeatureInfo to get the info for that layer. The issue is that the user doesn't know its clickable because the cursor never changes when they hover of the wms layer. My question is how do make the cursor change when hovering over the layer?
Has anyone implemented this feature before or have an idea to implement it? The only research I have stumbled across so far has using mouseover on the map and calling getFeatureInfo to tell if its over a layer. However, that seems like it would cause a lot of chatter just to identify cursor area.
EDIT: To clarify, I want the cursor to only change when its hovered over the wms layer that is populated. Although it technically gets applied to the whole map, it only has content on a part of it. Which kind of raises the question of 'Can I limit the wms layer to only the content area and then show a cursor?' Maybe a bounding area or something along those lines?
EDIT 2: Below is an example of what it looks like. The street map parts I want to keep the normal cursor but I want a pointer when hovering over the colored wms map parts.
Set an ID on the tileLayer's container and then use CSS to change the cursor:
Javascript:
var wms = L.tileLayer.wms("GEOSERVERURL", {
layers: 'layers',
format: 'image/png',
transparent: true
}).addTo(map);
wms.getContainer().setAttribute('id', 'wmsContainer');
Stylesheet:
#wmsContainer {
cursor: grab; /* or any other cursor: https://developer.mozilla.org/en-US/docs/Web/CSS/cursor */
}
Note: you need to do this after the layer is added to the map. Before you add it to the map the getContainer method will return undefined.
Edit after question edit and comments:
Unfortunatly that's not possible. At least not as far as i know. Because L.TileLayer.WMS is a layer of images, there is absolutely no way of deducting which tiles have features on them and which are transparent.
What you could do as a workaround is work out the boundaries of your object, use that to create a transparent polygon without stroke and put that over your WMS layer. Polygons are interactive thus you get the cursorchange included, plus as an extra bonus, you can do other fancy stuff like show the outline or something like that on mouseover. I've created a little demo from the WMS example you supplied in the comments.
http://plnkr.co/edit/1HGn6IUzdrn1N5KGazXQ?p=preview
Note that i'm using a GeoJSON layer with one feature instead of a polygon, because it was easier to find the outline of the US in GeoJSON format. But in your case a four point polygon would do the trick just as wel.
Hope that helps, let me know if something isn't clear.

How to add custom street names on Google Maps?

So you want to add custom street names or other labels on your Google Map? For example on this location. After learning current (3.6) google map js API you have these possible options:
KmlLayer (not works now)
GroundOverlay (works!)
OverlayView (should work)
KmlLayer "...adds geographic markup to the map from a KML, KMZ or GeoRSS file that is hosted on a publicly accessible web server...”. We can try this latest feature to add path with label. And it will work in Google Earth. But if path is too short – Google Earth will not show us a label. Workaround for short path is just make it long by adding start and end points few times:
<coordinates>
55.043196,82.907145 55.043473,82.909902
55.043196,82.907145 55.043473,82.909902
55.043196,82.907145 55.043473,82.909902
55.043196,82.907145 55.043473,82.909902
</coordinates>
Then we already see our nice custom label in Google Earth, but in Google Map not. Most possible reason is that google earth's latest feature is too latest. Currently it’s a fail way, but may be later, google map's KML renderer will take that feature into account.
GroundOverlay is "... a rectangular image overlay on the map ...". All is much simple.
Create image:
Open your Google Earth (make sure your latitude/longitude settings are Mercator) and go to your location
Add one pixel white image on your area and make it 33% transparent
Go to properties / place tab of your image overlay and copy latitudes/longitudes from there
Make screenshot in Google Earth and paste it to your favorite graphic editor
Crop image to the borders of your white transparent area
Add layer, where you will add your custom labels and add them
Switch off your base layer and save the result as png, for example overlay.png
Add the resulting image to your google map as:
google.maps.event.addDomListener(window, 'load', function() {
var mapDiv = document.getElementById('map'),
opts = {mapTypeId: google.maps.MapTypeId.HYBRID},
map = new google.maps.Map(mapDiv, opts),
area = new google.maps.LatLngBounds(
new google.maps.LatLng(55.042297, 82.906337),
new google.maps.LatLng(55.043862, 82.910473)
),
overlay = new google.maps.GroundOverlay(
'overlay.png', area, {map: map, clickable: false}
);
map.fitBounds(area);
});
OverlayView you can try by yourself.
ps: Is this a correct format for article? Or may be it should be a community wiki?
I created a MapLabel utility library a while ago. While it doesn't have any rotation or text-on-path capabilities (I'd love to see you add it!), it does let you put text on a map.

Google Maps Tile Overlay

I am currently working on google map and new to it..
I want to know is it possible to divide the map into certain tiles with definite height and width and to color them.. If yes then somebody can just explain how to do it as i am facing difficulties.
I think what you are referring to is known as overlays in the Google Maps API. Do you want to achieve something like this? (click to show overlay)
The polygons section in the Google Maps API documentation would be the place to go to learn more.
If there is a limited area (geographically) that you would like to color based on map tiles, then you could create a custom tile layer overlay for that area (with each tile colored appropriately).
You can read the documentation for Tile Layer Overlays, but the gist is that you create a GTileLayer object, then set a property on that object with a function, getTileUrl, that is called when Google maps need to insert a tile in Google Maps.
In your getTileUrl function, you can return your own version of the tile (which you can draw with a colored tint based on the origional tile):
tilelayer.getTileUrl = function(point, zoom) {
if (zoom == 17 && point.x == 38598 && point.y == 49259)
return "../pics/origional_tile_with_colored_tint.png";
};
Once you have a a GTileLayer object, you instantiate a GTileLayerOverlay (passing in your GTileLayer) and add it to the GMap2 object (with the addOverlay method).
You can find an example of this here.

Categories

Resources