setting map boundary / edge when nowrap is engaged - leaflet

Is there any way to adjust the bounds of the map so that the right-edge of Russia doesn't appear over to the left? You can see in the image I have a MultiPolygon area overlaying Russia but the map and the overlay are split. I'd like that tiny piece of the country to be on the right if possible!
Edge of Russia on the wrong side of the map:

A workaround I can think of is using the maxBounds property, where you would shift the default bounds slightly to the right, along with minZoom: 1. This won't prevent the user from seeing the world several times for a short time if zoomed out far / panning outside, as it says there:
... bouncing the user back when he tries to pan outside the view
var map = L.map('map',{
maxBounds:[ [-90, -160], [90, 200] ],
minZoom: 1
}).setView([66.058, 189.459], 4);
Demo

Welcome to SO!
If your multi polygon is the blueish area, then I am afraid you have to refactor your data in order to achieve what you want (shifting the left area onto the right, as if it were stitched back to Russia main land).
Your data (probably GeoJSON?) contains a separate polygon which longitudes are in the [-180, -120] range. Leaflet has no choice but to display it on the left of your map, independently from the noWrap option.
So you would need to dig into your data, and add 360 degrees longitude to every node of this polygon, so that they now sit in the range [180, 300].
Or somehow introduce a "detection" in your code that would perform the longitude addition automatically for shapes which bounds and/or center are far away (let's say in the [-180, -120] longitude range). Leaflet does not perform that operation automatically out-of-the-box.
Note: the noWrap option is for your Tile Layer not to load tiles outside that "central" world (in order to avoid showing multiple copies of the world). But in your case, you want to show a part of Russia / Siberia on an "adjacent copy of the world", so you might want to remove that option, or you will have your polygon not sitting over any basemap.

Related

How to show building floors in Deck.gl/react-map-gl

So I'm currently working on Deck.gl and React and I need to load a geojson file which has an additional property named "floors" or something similar which tells how many floors the building has.
Is there any way to extrude alternating floors horizontally just a little bit so that it looks like a floor edge like some of the buildings in this image (although most of them just go thinner at the top). I tried searching the deck.gl but there is no such thing. I looked up and found MapBox-gl-js has something called an extrusion-base-height which lets you add polygon above another but there is no such thing as extruding horizontally to make 1 floor thinner and then back to the original size. This would give and edge whenever a new floor starts.
I have scoured the docs for deck.gl but couldn't find any thing on extruding horizontally or in another sense changing the polygon area/size so that I can draw multiple size polygons on the same spot.
Another clear picture of what I'm trying
Things I want to do.
The red polygon is tilted. Need to make it's orientation the same as the green one and reducing it's area at the same time.
Move the red polygon base at the top of the green polygon.
The test data I'm using is given below,
var offset = 0.00001;
var data = [{
polygon: [
[-77.014904,38.816248],
[-77.014842,38.816395],
[-77.015056,38.816449],
[-77.015117,38.816302],
[-77.014904,38.816248]
],
height: 30
},
{
polygon: [
[-77.014904 + offset ,38.816248],
[-77.014842 - offset, 38.816395 - offset],
[-77.015056 - offset, 38.816449 - offset],
[-77.015117 + offset, 38.816302],
[-77.014904 + offset, 38.816248]
],
height: 40
}
];
EDIT:- I think the proper way would be to convert longitude/latitude to Cartesian Coordinates, get the vectors to the 4 corners of the polygon translate the vectors to move towards the center by the offset amount then convert back. But this would only work with quad/rectangle polygon, for buildings that are made up of multiple quads I'd need another way.
If I'm understanding correctly, your problem boils down to: given a polygon (the footprint of the lower part of the building), generate a slightly smaller version of the same polygon, centered within it.
Fortunately, this is really easy using Turf's transformScale method.
So your steps will be:
Convert your polygon data into GeoJSON. (Which I assume you have some mechanism to do, in order to display it in Mapbox-GL-JS in the first place.)
Generate a smaller polygon using turf.transformScale(base, 0.9)
Add the new polygon with map.addSource
Display the new polygon with map.addLayer, setting the extrusion base height etc as required.

Wrong geometry with mapbox queryRenderedFeatures

I am trying to get the geometry of the polygon with queryRenderedFeatures
On zoom level 12 is ok, but on 15 I got the wrong geomentry.
Here is my code, and I everytime on mouse over I get the different coordinates.
Here https://codepen.io/benderlidze/pen/qPXNJv - hover the mouse from the top on the poly and from the bottom. The red poly is a geometry returned by queryRenderedFeatures and it is always different.
map.on("mousemove", "seatRowsFill", function(e) {
map.getCanvas().style.cursor = 'pointer';
map.setFilter("seatRowsFill-hover", ["==", "rowNumber", e.features[0].properties.rowNumber]);
var relatedFeatures = map.queryRenderedFeatures(e.point, { layers: ['seatRowsFill'],"filter": ["==", "rowNumber", e.features[0].properties.rowNumber] } )
console.log(relatedFeatures["0"].geometry.coordinates["0"][2])
At zoom 15, the geometry crosses a tile boundary. You can see this by adding map.showTileBoundaries = true: https://codepen.io/stevebennett/pen/XezJNB
From the documentation for queryRenderedFeatures():
Because features come from tiled vector data or GeoJSON data that is converted to tiles internally, feature geometries may be split or duplicated across tile boundaries and, as a result, features may appear multiple times in query results. For example, suppose there is a highway running through the bounding rectangle of a query. The results of the query will be those parts of the highway that lie within the map tiles covering the bounding rectangle, even if the highway extends into other tiles, and the portion of the highway within each map tile will be returned as a separate feature. Similarly, a point feature near a tile boundary may appear in multiple tiles due to tile buffering.
Instead of retrieving the geometry and then displaying that, it's usually better to have a separate layer which is just used for highlighting, then update the filter on that layer to match some property.
So, if you update the highlight layer's filter to be ['==', id, 500], then all the different pieces of that polygon will display correctly.
See the "Create a hover effect" example.

Specifying Lat & Long for Leaflet TileLayer

Seems like a simple question, but I have been tearing my hair out for hours now.
I have a series of files ie.
kml_image_L1_0_0.jpg
kml_image_L2_0_0.jpg
kml_image_L2_0_1.jpg
kml_image_L2_1_0.jpg
kml_image_L2_1_1.jpg
etc. However just plotting them on the leaflet map surface understandibly puts the images at 0,0 on the earths surface, and the 0 zoom level inferred by the files should really be about 15 or so.
So I want to specify the latitude and longitude where the images should originate , and what zoom level they should start at. I have tried bounds (which doesn't display anything) and I have tried playing with offsetting the zoom level.
I need this because a user needs to click on an offline map to specify where they are and I need the GPS coordinates.
I also have a KML file but it seems to be of more help for plotting vector data on the map.
Any help is much appreciated, cheers.
If I understand correctly, the "kml_image_Lz_x_y.jpg" images that you have are actually tiles, with zoom, horizontal and vertical indices in their file name?
And your issue is that they use (z,x,y) numbers as if they started from the top-most level (zoom 0, single tile for entire world), but in fact they are just a small portion of the pyramid of tiles?
And you cannot use them as is because you still want to get actual geographic coordinates (latitude, longitude), which would be totally wrong if you used the tiles as if they were showing the entire world?
In that case, you have several options as workarounds:
The most simple and reliable would probably be to simply write a small script to rename all your tiles to their true (z,x,y) numbers.
Another option would be to modify the (z,x,y) numbers before they are written in the tile src attribute, and apply the appropriate offset (constant for z, scaled by z for x and y). That should probably happen in L.TileLayer.getTileUrl() method.
Good luck! :-)

Longitude, Latitude to XY coordinate conversion

I want to now how to convert longitude, latitude to its equivalent xy coordinate components in iPhone programming. (I am using only CoreLocation programming, and want to show a point on iPhone screen without any map).
thanks
Well the exact conversion depends on exactly which part of the Earth you want to show, and the stretching along longitude varies according to latitude, at least in Mercator.
That being said, even if you don't want to display an actual MapKit map, it would probably be easiest to create an MKMapView and keep it to one side. If you set the area you want to display appropriately on that (by setting the region property), you can use convertCoordinate:toPointToView: to map from longitude and latitude to a 2d screen location.
Note that MKMapView adjusts the region you set so as to make sense for the viewport its been given (eg, if you gave it a region that was a short fat rectangle, but the view it had was a tall thin rectangle, it'd pick the smallest region that covers the entire short fat rectangle but is the shape of a tall thin rectangle), so don't get confused if you specify a region with the top left being a particular geolocation, but then that geolocation isn't at the exact top left of the view.

Change annotations inside MapKit view

I have a lot of annotations to manage inside the mapkit view.
The rules are :
1 -only show annotations when the mapView.region.span.longitudeDelta is above 0.042
2 -only show annotations inside the visible area.
3- remove the annotations when they comes out the visible area...
How I can do that ... Share your experience...
Thanks
You need a few things. One is to search your database for the pins with latitudes and longitudes inside the map's view. This is called a bounding box. The next is to remove the annotations when they move outside the visible rect of the map. Each time the map is moved, you'll have to recalculate what pins are in the box and what pins are outside but still on the map.
One hint I can give you is to divide the visible rect of the map into squares (maybe 17 x 23 squares of 20 x 20) and figure out if a pin goes into that square. If it does, mark that square as filled, and if another pin wants to go into that square, don't let it. This will allow you to filter the pins so there aren't too many on screen at one time.
It's not an easy problem, but if you do some search around you'll find your way through it. This cluster marker code for Google Maps might help.