Leaflet JS: Custom 2D projection that uses meters instead of lat,long - maps

I am working on a custom game map. This map is basically a raster image, overlayed with some paths and markers. I want to use Leaflet to display the map.
What I am struggling with, is that Leaflet uses Latitude and Longitude to calculate positions, while it uses meters for distances (path lengths, radii of circles, etc).
This is very understandable when dealing with a spherical world like our Earth, but it complicates the custom map, which is flat a lot.
I would like to be able to specify the positions in the same unit as the distances.
Now, by default Leaflet uses a Spherical Mercator projection. According to the Docs, it is possible to define your own projections and coordinate reference systems, but I have been unable to do this thus far.
How would this be possible? Or is there a simpler way?

You should take a look at the simple coordinate reference system (L.CRS.Simple) included with Leaflet:
A simple CRS that maps longitude and latitude into x and y directly. May be used for maps of flat surfaces (e.g. game maps).
You can define the CRS of your L.Map instead upon initialization like so:
new L.Map('myDiv', {
crs: L.CRS.Simple
});
Some further elaboration: As #ghybs pointed out in the comment below and the comment to your question the default sperical mercator projection (L.CRS.EPSG3857) already works in meters. When you calculate the distance between two coordinates, Leaflet returns meters, example:
var startCoordinate = new L.LatLng(0, -1);
var endCoordinate = new L.LatLng(0, 1);
var distance = startCoordinate.distanceTo(endCoordinate);
console.log(distance);
The above will print 222638.98158654713 to your console which is the distance between those two coordinates in meters. Problem is that when using spherical projection, distance between two coordinates will become less the further you get from the equator which will become problematic when creating a flat gameworld. That's why you should use L.CRS.Simple, you won't have said problem.

Related

How to efficiently find co-planar point in array of 3D points (Terrain)

I am representing a terrain using a two dimensional array height map (500x500) where points are 1 unit apart (1 unit = 1 meter in this case).
I am also representing a player using a 3D-point which is represented as (x-float,y-float,z-float). Since the players positioning allows for fine-tuned positioning while the height map is lower resolution, i need a method to find the approximation of the height (z-axis) of the character based on the x/y coordinates that he falls within the terrain height-map (co-planar point).
Therefore my question comes in two parts:
How to find co-planar point where the x/y portion of the co-planar point is already solved for?
Is there a recommended library that can handle this in C#?

How to create a grid of 50sq km Rectangles or Hexagons in React Map GL(Mapbox) and Deck.gl, that covers an entire country

I'm trying to create a Grid Layer of Either Rectangles or Hexagons in React Map GL(Map Box) and Deck GL, that cover an entire country.
This is what I'm trying to achieve: http://webcoveragemap.rootmetrics.com/en-US
These are the Solutions I've found:
https://deck.gl/#/documentation/deckgl-api-reference/layers/s2-layer
https://deck.gl/#/documentation/deckgl-api-reference/layers/h3-cluster-layer
The problem I'm facing with is that s2-layer uses S2 Cell token (Which I can't seem to understand how to calculate and similarly h3-cluster-layer uses H3 and for that too I can't find any code samples for React. So can anybody explain me either how to use H3, S2 and calculate 50sq km boxes that can be viewed on React Map Gl with Deck GL (if needed). Or suggest another Solution?
Turns out there's java script version of H3-Core Library (A hexagon-based geographic grid system). https://www.npmjs.com/package/h3-js
All it require's to convert a lat/lng point to a hexagon index at some resolution is following code:
const h3Index = h3.geoToH3(37.3615593, -122.0553238, 7);
// -> '87283472bffffff'

Converting pixels to coordinates on a Mapbox map

I have the lat and lon coordinates to a location on a Mapbox map. The map is set to zoom level 15 and is of bearing 30 degrees. I need to travel +500px horizontally and +300px vertically as the map is displayed on the screen. How do I work out what the destination is in lat and lon coordinates?
I need to do this calculation (and many like it) in a ruby script.
Whilst I've found some information describing how to achieve the reverse of what I want its difficult for me to understand how it works and thus I can't reverse the calculations.
Can someone help me?
There's a method named project and unproject.
project converts LngLat into pixel and unproject converts pixel into LngLat.
You can use something like:
const currentCenterPixel = map.project(map.getCenter());
currentCenterPixel.x += 500;
currentCenterPixel.y += 300;
map.once("idle", () => {
map.panTo(map.unproject(currentCenterPixel));
});
https://jsfiddle.net/cs09g/q3x1ohun/8/

Set Parent of Map Axes in Matlab GUI

I am programming a basic GUI in MATLAB that utilizes the mapping toolbox. The GUI will display a grayscale image and then plot discrete points over the data, all of this over the necessary map projection. It is important that I plot onto map axes (those created by the axesm command) rather than the vanilla cartesian space. I have no problem doing all this from the command line, but I cannot find a way to implement a GUI version and its driving me nuts.
The problem is that I need to specify the map axes as being the child of the parent figure. The normal axes has a property that can be set, doing something like:
axesHandle = axes('Parent', parentHandle, ...);
or
set(axesHandle, 'Parent', parentHandle);
However, there is no equivalent parent property for the map axes created by the axesm function, so I have no way to manipulate the axes within the figure. How can I do this?
Update: If I create a plot within the map axes in an empty figure, get(figureHandle, 'Children') returns the handle of the axesm object (thanks #slayton!), so the map axes object must be implicitly added to the children of the figure by MATLAB.
Should I be concerned that the map axes do not refer back to the parent figure, or should I just let it be? I wonder if this is a classic case of MATLAB forcing me to not comply with the standards the manual tells me to implement.
From reading your question what I think you are trying to do is grab the handle of the axes object. This can be done as the axes is created using either axes or subplot
a = axes();
a = subplot(x,y,z);
% both return an handle to the newly created axes object
Additionally if the axes is created automagically by a function call like plot or image you can get the axes handle that too:
p = plot(1:10); %returns a handle to a line object
a = get(p,'Parent');
i = image(); %returns a handle to an image object
a = get(i, 'Parent');
Finally, neither of those two options is available you can always get the axes handle from its containing figure with:
a = get(figureHandle, 'Children');
Remember though that this will return a vector of axes handles if your figure contains more than one axes.
Finally when it comes time to draw draw your points to the axes that contains your map image you simply need to call:
line(xPoints, yPoints, 'linestyle', 'none', 'marker', '.', 'color', 'r', 'size', 15)
This will draw the vertices of the line using large red dots.
I'm not sure if this answers your question because the code you provided doesn't line up with the question you asked.
The code you provided looks like you are trying to move an axes from one figure to another. You can totally do this!
f = figure('Position', [100 100 100 100]);
a = axes('Parent', f);
pause
f2 = figure('Position', [250 100 100 100]);
set(a,'Parent', f2);
After much trial and error and reading of documentation, I have found that there is no way to explicitly specify the parent of the map axes. Instead, they are implicitly added on top of the current axes. In the instance that no axes exist in the current figure, calling axesm creates an axes object and then places the axesm object inside. When you take this route, you have to grab the axes object handle by calling gca:
mapAxesHandle = axesm(...);
axesHandle = gca(...);
This makes it frustrating to use the mapping toolbox when writing a GUI from scratch, but that's the way Mathworks makes it happen. Thanks to #slayton for useful info. I'd upvote but my reputation is <15 :(

Configuring maxExtent and restrictExtent coordinates in OpenLayers

I'm very new to OpenLayers and working with GeoData; as such, I think I have a pretty noob question about configuring map bounds with OpenLayers. First, here's the map code I've made up...
function createMap(containerId){
return new OpenLayers.Map(containerId, {
projection: new OpenLayers.Projection("EPSG:900913"),
displayProjection: new OpenLayers.Projection("EPSG:4326"),
units: "m",
maxResolution:156543.0339,
numZoomLevels:4,
controls: [],
maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34),
restrictExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34)
});
}
I have my map and I've loaded a GeoJSON layer of vector country shapes on top of it. So far so good. However, if I call zoomToMaxExtent on the map, the map zooms out to be a little tiny thumbnail-sized graphic in the center of my viewport rather than filling the frame. Then if I zoom in on the map, I can (seemingly) pan the map indefinitely in any direction rather than being constrained at the edges of the map shapes.
So I assume I'm doing something wrong with my maxExtent and restrictExtent settings, although I have no idea what it is. To be honest, I'm not sure what those huge bounding numbers are (found them in sample code). Essentially, by Lon/Lat coordinates, I think I'm just trying to restrict bounding to -180, -90, 180, 90 – which should provide a tight frame around the map geography, right? Unfortunately setting those Lon/Lat's to the bounding params don't seem to do anything. Any insight would be greatly appreciated!

Resources