How to use proj4lefleat in react-leaflet? - react-leaflet

I have a working react leaflet map that I need to re-define to hold a custom projection (ETRS89 / UTM zone 32N, EPSG:25832), since the default EPSG:3857 WMS request sent by Leaflet is producing a shifted map (so the city administration I am using the data of told me to use their native projection).
I can import proj4leaflet and derfine the projection like this:
import "proj4leaflet";
const crs = new Leaflet.Proj.CRS(
'EPSG:25832',
'+proj=utm +zone=32 +ellps=GRS80 +units=m +no_defs ',
{
resolutions: [
8192, 4096, 2048, 1024, 512, 256, 128,
64, 32, 16, 8, 4, 2, 1, 0.5
],
origin: [0, 0]
});
When I add this to my Map:
<Map
center={center}
zoom={zoom}
className="Map"
onClick={onClick}
crs={crs}
>
neither my WMSTileLayer nor my TileLayer will render afterwards. What is the best way of debugging this? Note that I do not have access to the servers I am querying since I am using Open Government Data WMSs, so I cannot see the logs there.

Thanks, Evan. While putting together a JSFiddle example I found the bug (I had a wrong reference in the Proj4 Library link).
const crs = new window.L.Proj.CRS
I add here the working example for others as a reference: JSFiddle Example of Proj4 Leaflet Map CRS

Related

gdal2tiles.py: Slice an image with its center being (0,0)

I made a map for my Minetest Game I play.
The project is here : https://github.com/amelaye/aiwMapping I created the map with the Python script gdal2tiles, like this : ./gdal2tiles.py -l -p raster -z 0-10 -w none ../map.png ../tiles
Here is the interesting part of code :
var minZoom = 0
var maxZoom = 9
var img = [
20000, // original width of image
20000 // original height of image
]
// create the map
var map = L.map(mapid, {
minZoom: minZoom,
maxZoom: maxZoom
})
var rc = new L.RasterCoords(map, img)
map.setView(rc.unproject([9000, 10554]), 7)
L.control.layers({
'Spawn': layerGeoGlobal(window.geoInfoSpawn, map, rc, 'red', 'star', 'fa'),
}, {
'Bounds': layerBounds(map, rc, img),
}).addTo(map)
L.tileLayer('./tiles/{z}/{x}/{y}.png', {
noWrap: true,
attribution: ''
}).addTo(map)
It works like a charm, but there is a problem : in Minetest, the coords (lat and lon) go to -10000 to 10000. In my Leaflet map, the coords still positive, then they go from 0 to 20000.
How can I solve this problem ?
CRS SIMPLE does not work.
PS : No relative questions have been posted, please read my message carefully.
When gdal2tiles is not given a georeferenced image (or a world file accompanying the image), it will assume that the (0,0) coordinate is at one of the corners of the image, and that one pixel equals one map unit (both horizontally and vertically).
Since your input image is a .png file, the most straightforward way of working around the issue will be creating an appropriate world file.
If your input image is map.png, create a new plain text file named map.pgw with the following contents...
1
0
0
1
-10000
-10000
...then run gdal2tiles.py again. Note that this worldfile assumes that one pixel equals one map unit, and the image's first corner is at the (-10000,-10000) coordinate.

CRS for HS2 snakegrid plotting in wrong location on Folium and Leaflet

I've been trying to plot some geographical date which is the HS2 snakegrid co-ordinate system
According to ESPG HS2 ESPG Geodetic Parameters Page I should be using CRS 9300 (although have also tried 9306)
When used, the location is not plotting correctly, example below uses folium to generate a basemap in WGS 84 and geopandas to add a point with the CRS changed to the HS2 9300.
The co-ordinates used should place the point just outside Euston Station but instead is plotting in Hyde Park
I've used Jupyter notebooks to run the below code, although i've also run in geodjango so i could use leaflet with proj4js string for HS2 and same thing
import folium
from folium import plugins
import geopandas as gpd
from shapely.geometry import Point
f = folium.Figure()
m = folium.Map(
location=[51.5091, -0.16006],
max_zoom = 22,
zoom_start = 16,
tiles = None,
control_scale = True,
prefer_canvas = True,
crs = 'EPSG3857',
)
folium.TileLayer('cartodbpositron', max_zoom = 22, detect_retina = True, name = 'Carto',).add_to(m)
s = gpd.GeoSeries([Point(292001.0182, 288039.0657),],)
s = s.set_crs('epsg:9300')
s.explore(name = "S", m = m, highlight = True, show = False, style_kwds={'color': 'green','fill': False},)
example output
UPDATE
I need to use HS2TN15_NTv2.gsb transformation file within pyproj
Reading the pyproj docs i should use pyproj.datadir.get_data_dir() to identify the data directory which gives \Lib\site-packages\pyproj\proj_dir\share\proj
However when i then run TransformerGroup("epsg:4258","epsg:9300") I still get the following warning
\lib\site-packages\pyproj\transformer.py:184: UserWarning: Best
transformation is not available due to missing
Grid(short_name=HS2TN15_NTv2.gsb, full_name=, package_name=, url=,
direct_download=False, open_license=False, available=False)
super().init(

How to show/hide labels according to zoom levels with expressions in mapbox-gl-js / maplibre-gl?

I have a point layer with an icon, and I would like to display the labels in addition to the icon only from a certain zoom level (9). I would like to avoid creating a dedicated label layer. Looking at the expression documentation, Stet and Zoom should give me the desired result, but it doesn't work.
Following this answer, I try to change the size of the text depending on the zoom level, but no matter the zoom, the text will always have the default size (here 7)
Am I missing something or is it a bug? I'm using Maplibre
layout: {
"icon-image": "border_crossing",
"icon-size": 0.5,
"icon-allow-overlap": true,
'text-field': ['get', 'loc_type'],
'text-variable-anchor': ['top'],
'text-radial-offset': 0.5,
'text-justify': 'auto',
"text-size": [ "step",
["zoom"],
0,0,
9,15,
7
]
}
There are various ways. One would be:
'text-field`: ["step", ["zoom"], "", 9, ["get", "loc_type"]]
It looks like you had a bug in your step code.

Highcharts Pyramid - same size of segments - despite the data value

I was wondering if it would be possible to ignore the sizes of segments in highcharts pyramid. I would like all segments to be of the same size despite the value. The reason is that sometimes differences between values may be quite significant and value of 1 - even being extremely important, becomes invisible when the next value is 500. Also, would like to be able to add a legend if possible. It would be nice to set a minimum size of a segment if not possible to get dynamic sizing disabled.
Thanks for your help!
Pawel
Yes, you can add additional data according to which the height of the segment will be calculated. Next, use keys option to map the values and show the right one in a tooltip and data label:
tooltip: {
pointFormat: '<span style="color:{point.color}">\u25CF</span> {series.name}: <b>{point.realY}</b><br/>'
},
series: [{
...
keys: ['name', 'realY', 'y'],
dataLabels: {
format: '<b>{point.name}</b> ({point.realY:,.0f})',
...
},
data: [
['Website visits', 15654, 1],
['Downloads', 4064, 1],
['Requested price list', 1987, 1],
['Invoice sent', 976, 1],
['Finalized', 846, 1]
]
}]
Live demo: https://jsfiddle.net/BlackLabel/e83fatk2/
API Reference: https://api.highcharts.com/highcharts/series.column.keys

Mapbox heatmap by point value

There is an example of the heatmap https://www.mapbox.com/mapbox-gl-js/example/heatmap/ by the number of markers/points on the area. But is there a way to display a heatmap by average pins/markers values? For example if I have 5 pins and their average prop value speed=3 then it will be shown as green cluster/heatmap and if their av. prop val is 6 then it will be red cluster/heatmap.
I found that "clusterAggregates" property can help, but can't find any example of using it.
Thanks
I'll leave my way to do so. Old question, which is sometimes risen, but there are no nice sollution, so... Turf's hexgrid (http://turfjs.org/docs/#hexGrid) can help:
const hexagons = hexGrid(bbox, size);
const collection = // collection of your points;
const hexagonsWithin = collect(hexagons, collection, "propertyToAgretateFrom", "propertyToAggregateIn");
const notEmptyHexagonValues = hexagonsWithin.features.filter(({ properties }) => properties.propertyToAggregateIn.length !== 0);
const notEmptyHexagons = {
"type": "FeatureCollection",
"features": notEmptyHexagonValues,
};
// at this point you're having not empty hexagons as a geojson, which you can add to the map
collect is another method from turf, whatcollection should be you can look up in the docs, because it's changing a lot.
The general idea behind is to "divide" visible part of map (bbox) into hexagons by hexGrid method and and aggregate some properties that you need from every marker inside of every hexagon you'll have into the array, so you can get an average value, for example. And assign a color based on it.
Let's say we have feature.properties.propertyToAgretateFrom as 4 and 5 in two markers. After the aggregation, if these markers were inside one polygon, you'll have it feature.properties.propertyToAggregateIn: [4, 5] - this feature is polygon. From this on you can do pretty much everything you want.