Closed RayLarone closed 3 months ago
Ok, so I've been looking through the glify code and it looks like this loss of precision is happening once the lat/lng coordinates get converted to pixel coordinates (latLonToPixel
) and then these pixel coordinates are converted to a Float32Array
.
As these pixel coordinates are pretty long decimals, any precision below a few meters gets lost by the Float32Array
.
One solution would be to use a Float64Array
although I don't think WebGL supports this and it might affect performance.
Another way to solve this would be to reduce the size of these pixel coordinates. If you are creating a map that needs precision down the to meter or centimetre, you are unlikely to be mapping anything bigger than a city, district or country. So, it should be possible to normalise these pixel coordinates around your area of interest, which would solve the polygon rendering issue above, and give you centimetre or even millimetre precision.
Just by way of explanation, if you go to this article (https://leafletjs.com/examples/extending/extending-2-layers.html) and scroll down to section about "The Pixel Origin" you will see that the pixel origin (0, 0) is located in the top left corner of the map, and all geometries are plotted in relation to this pixel origin. This means anything close to this origin will be plotted by glify with a much higher precision than things far away from it. (again due to the Float32Array
conversion)
Note that the black border is the correct polygon plotted with base leaflet and the blue fill is plotted by glify. From the above map, you can see that the polygons which are closer to the Pixel Center are much more accurate when compared to the polygons which are far way.
One way to solve this would be to move the pixel origin to the centre of the area we are plotting. First we could calculate the centroid of the GeoJson passed as an argument coord_centroid = getCentroid(geojson)
. Or if this takes too much time we could just pick the first set of coordinates in the geojson (or the map center with map.getCenter()
), as this will likely be a better guess than the default pixel centre of (0, 0). Alternatively, the user could just pass the geojson centroid manually as an optional argument.
The next step would be to convert this centroid to pixel coordinates: latLonToPixel(coord_centroid)
.
Using these centroid pixel coordinates we then translate our geojson so it is as close to the Pixel Origin as possible:
//shapes.ts lines 224-234 for (let i = 0, iMax = triangles.length; i < iMax; i) { pixel = map.project(new LatLng(triangles[i++], triangles[i++]), 0); vertices.push( pixel.x - centroid.x, pixel.y - centroid.y, chosenColor.r, chosenColor.g, chosenColor.b, alpha ); }
We can then offset the mapMatrix
so the polygons get set back to their original place on the map:
// shapes.ts lines 266-269 mapMatrix .setSize(canvas.width, canvas.height) .scaleTo(scale) .translateTo(-offset.x + centroid.x, -offset.y + centroid.y);
If this gets applied to my original question, we can pass in a centroid of around (51.524730, -0.181100)
and the output of these changes gives the following:
If you look at the scale bar below you can see this now has an accuracy of centimetres or even millimeters (which might address this issue https://github.com/robertleeplummerjr/Leaflet.glify/issues/54):
As well as this, the polygons also don't "jitter" as you pan around. (i.e. it should solves issues like this https://github.com/robertleeplummerjr/Leaflet.glify/issues/119)
This solution could also be applied to points and lines.
Do you think this could be implemented? And thanks for the great library :)
I have a dataset containing thousands of Car Parking Spaces I want to show on a map. However when I use the
L.glify.shapes
function the polygons do not render correctly? Is there any way I can resolve this issue? Many thanksYou can see the code here: https://codepen.io/RayL1/pen/WNzbddJ
This is what is should look like:
This is how it comes out:
Difference: