Leaflet LatLng coordinates to xy map - leaflet

How leaflet does to calculate the x y coordinates of the tiles from zoom z, latitude and longitude coordinates ?
what is the formula please?
Thank you

You can use map.latlngtoContainerPoint(latlng) but when you want the formular you can look into the src
Leafet/Map.js#L1071 --> Leafet/Map.js#L1014

In case you are referring to computation of tile z x y "coordinates" / names, then there is a very simple algorithm, as described on OpenStreetMap wiki about slippy maps: https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
Lon./lat. to tile numbers
n = 2 ^ zoom
xtile = n * ((lon_deg + 180) / 360)
ytile = n * (1 - arsinh(tan(lat_rad)) / π)) / 2
With arsinh being the Inverse hyperbolic sine
Some background explanation:
X goes from 0 (left edge is 180 °W) to 2zoom − 1 (right edge is 180 °E)
Y goes from 0 (top edge is 85.0511 °N) to 2zoom − 1 (bottom edge is 85.0511 °S) in a Mercator projection
See the wiki page for further explanation and details, as well as some code in different programming languages.

Related

How to correctly find UV on sphere

I have a sphere and a texture for it.
Texture consist of 16 tiles of zoom = 2 from OSM. Tile size is 256x256.
At top and bottom I added space to cover area in ranges [90, 85.0511] and [-85.0511, -90], proportionally. So texture size was 1024x1083.
I also tried texture without these two spaces, its size was 1024x1024 (map tiles only).
The problem is that after UV mapping on Y-axis objects are smaller on equator and bigger on poles.
There are two types of formulas
u = (lon + 180) / 360; // lon = [-180, 180]
v = (lat + 90) / 180; // lat = [-85.0511, 85.0511]
----
u = Math.atan2(z, x) / (2 * Math.PI) + 0.5; // x, y, z are vertex coordinates
v = Math.asin(y) / Math.PI + 0.5;
I tried all 8 variations: two textures, two u-formulas and two v-formulas.
The result is like on image above, or worse.
What am I doing wrong? Is it about texture, or UV-formulas, or something else?
P.S.: for poles (vertices in lat range = [-90, -85.0511], [85.0511, 90]) in fragment shader I don't use color from texture, but just solid color
OSM uses the Web Mercator projection. See also on OSM wiki.
The conversion from world (x,y,z) to texture (u,v) coordinates would be:
lon = atan2(y, x)
lat = atan2(z, sqrt(x*x+y*y))
u = (lon + pi)/(2*pi)
v = (log(tan(lat/2 + pi/4)) + pi)/(2*pi)
(I assume that z points north like in WGS-84 and all coordinates are right-handed.)
This projection doesn't cover the entire sphere: as the latitude approaches the poles, the v coordinate blows up to infinity. Therefore extending the map to the north or south direction is not going to be helpful.
Instead keep the original square 1024x1024 texture and render a texture mapped sphere capped at the ±85.051129° latitute (that's where v = 0,1) using the above coordinate mapping.
Alternatively (and this is more in-line with Web Mercator spirit), render each tile regular in the UV coordinates, and calculate the XYZ coordinates by reversing the above transformation.

Compute coordinates position with projection

Given 2 coordinates (point 1 and 2 in red) in WGS84 I need to find the coordinates of the point perpendicular (point 3) to the line at a given distance.
I could manage to make the math to compute this perpendicular point, but when displayed on the map, the point seems to be at a wrong place, probably because of the projection.
What I want on a map:
And what I have instead on the map:
How can I take into account the projection so that the point on the map appears perpendicular to the line? The algorithm below to compute the point comes from here: https://math.stackexchange.com/questions/93424/calculate-rectangle-coordinates-from-line-and-height
public static Coords ComputePerpendicularPoint(Coords first, Coords last, double distance)
{
double slope = -(last.Lon.Value - first.Lon.Value) / (last.Lat.Value - first.Lat.Value);
// number of km per degree = ~111km (111.32 in google maps, but range varies between 110.567km at the equator and 111.699km at the poles)
// 1km in degree = 1 / 111.32km = 0.0089
// 1m in degree = 0.0089 / 1000 = 0.0000089
distance = distance * 0.0000089 / 100; //0.0000089 => represents around 1m in wgs84. /100 because distance is in cm
double t = distance / Math.Sqrt(1 + (slope * slope));
Coords perp_coord = new Coords();
perp_coord.Lon = first.Lon + t;
perp_coord.Lat = first.Lat + (t * slope);
return perp_coord;
}
Thank you in advance!

Get XY Tile Coordinate at Z Zoom Level with Leaflet

I have figured out how to get XYZ coordinates by extending Leaflet with a createTile function.
But what I'm wanting to know is how do I access the XY tile name/coordinate for a fixed Z zoom level around my GPS coordinates, even if I'm not zoomed in.
Why? I'm working on a P2P/decentralized version of Uber, and the XY coordinates are a good common/shared location index for users to lookup/subscribe/query against. As in, everybody within that X mile radius all will know the same XY coordinate name and use that as a deterministic key to find each other with.
This project will "Convert lon, lat to screen pixel x, y from 0, 0 origin, at a certain zoom level." https://github.com/mapbox/sphericalmercator
UPDATED:
function lng2tile(lon,z) { return (Math.floor((lon+180)/360*Math.pow(2,z))) }
function lat2tile(lat,z) { return (Math.floor((1-Math.log(Math.tan(lat*Math.PI/180) + 1/Math.cos(lat*Math.PI/180))/Math.PI)/2 *Math.pow(2,z))) }
Or try this:
var row = Math.floor((location.lng + 180) / (360 / Math.pow(2, zoomLevel)));
var col = Math.floor((90 + (location.lat * -1)) / (180 / Math.pow(2, (zoomLevel - 1))));

Find Position based on signal strength (intersection area between circles)

I'm trying to estimate a position based on signal strength received from 4 Wi-Fi Access Points. I measure the signal strength from 4 access points located in each corner of a square room with 100 square meters (10x10). I recorded the signal strengths in a known position (x, y) = (9.5, 1.5) using an Android phone. Now I want to check how accurate can a multilateration method be under the circumstances.
Using MATLAB, I applied a formula to calculate distance using the signal strength. The following MATLAB function shows the application of the formula:
function [ d_vect ] = distance( RSS )
% Calculate distance from signal strength
result = (27.55 - (20 * log10(2400)) + abs(RSS)) / 20;
d_vect = power(10, result);
end
The input RSS is a vector with the four signal strengths measured in the test point (x,y) = (9.5, 1.5). The RSS vector looks like this:
RSS =
-57.6000
-60.4000
-44.7000
-54.4000
and the resultant vector with all the estimated distances to each access points looks like this:
d_vect =
7.5386
10.4061
1.7072
5.2154
Now I want to estimate my position based on these distances and the access points position in order to find the error between the estimated position and the known position (9.5, 1.5). I want to find the intersection area (In order to estimate a position) between four circles where each access point is the center of one of the circles and the distance is the radius of the circle.
I want to find the grey area as shown in this image :
http://www.biologycorner.com/resources/venn4.gif
If you want an alternative way of estimating the location without estimating the intersection of circles you can use trilateration. It is a common technique in navigation (e.g. GPS) to estimate a position given a set of distance measurements.
Also, if you wanted the area because you also need an estimate of the uncertainty of the position I would recommend solving the trilateration problem using least squares which will easily give you an estimate of the parameters involved and an error propagation to yield an uncertainty of the location.
I found an answear that solved perfectly the question. It is explained in detail in this link:
https://gis.stackexchange.com/questions/40660/trilateration-algorithm-for-n-amount-of-points
I also developed some MATLAB code for the problem. Here it goes:
Estimate distances from the Access Points:
function [ d_vect ] = distance( RSS )
result = (27.55 - (20 * log10(2400)) + abs(RSS)) / 20;
d_vect = power(10, result);
end
The trilateration function:
function [] = trilat( X, d, real1, real2 )
cla
circles(X(1), X(5), d(1), 'edgecolor', [0 0 0],'facecolor', 'none','linewidth',4); %AP1 - black
circles(X(2), X(6), d(2), 'edgecolor', [0 1 0],'facecolor', 'none','linewidth',4); %AP2 - green
circles(X(3), X(7), d(3), 'edgecolor', [0 1 1],'facecolor', 'none','linewidth',4); %AP3 - cyan
circles(X(4), X(8), d(4), 'edgecolor', [1 1 0],'facecolor', 'none','linewidth',4); %AP4 - yellow
axis([0 10 0 10])
hold on
tbl = table(X, d);
d = d.^2;
weights = d.^(-1);
weights = transpose(weights);
beta0 = [5, 5];
modelfun = #(b,X)(abs(b(1)-X(:,1)).^2+abs(b(2)-X(:,2)).^2).^(1/2);
mdl = fitnlm(tbl,modelfun,beta0, 'Weights', weights);
b = mdl.Coefficients{1:2,{'Estimate'}}
scatter(b(1), b(2), 70, [0 0 1], 'filled')
scatter(real1, real2, 70, [1 0 0], 'filled')
hold off
end
Where,
X: matrix with APs coordinates
d: distance estimation vector
real1: real position x
real2: real position y
If you have three sets of measurements with (x,y) coordinates of location and corresponding signal strength. such as:
m1 = (x1,y1,s1)
m2 = (x2,y2,s2)
m3 = (x3,y3,s3)
Then you can calculate distances between each of the point locations:
d12 = Sqrt((x1 - x2)^2 + (y1 - y2)^2)
d13 = Sqrt((x1 - x3)^2 + (y1 - y3)^2)
d23 = Sqrt((x2 - x3)^2 + (y2 - y3)^2)
Now consider that each signal strength measurement signifies an emitter for that signal, that comes from a location somewhere at a distance. That distance would be a radius from the location where the signal strength was measured, because one would not know at this point the direction from where the signal came from. Also, the weaker the signal... the larger the radius. In other words, the signal strength measurement would be inversely proportional to the radius. The smaller the signal strength the larger the radius, and vice versa. So, calculate the proportional, although not yet accurate, radius's of our three points:
r1 = 1/s1
r2 = 1/s2
r3 = 1/s3
So now, at each point pair, set apart by their distance we can calculate a constant (C) where the radius's from each location will just touch one another. For example, for the point pair 1 & 2:
Ca * r1 + Ca * r2 = d12
... solving for the constant Ca:
Ca = d12 / (r1 + r2)
... and we can do this for the other two pairs, as well.
Cb = d13 / (r1 + r3)
Cc = d23 / (r2 + r3)
All right... select the largest C constant, either Ca, Cb, or Cc. Then, use the parametric equation for a circle to find where the coordinates meet. I will explain.
The parametric equation for a circle is:
x = radius * Cos(theta)
y = radius * Sin(theta)
If Ca was the largest constant found, then you would compare points 1 & 2, such as:
Ca * r1 * Cos(theta1) == Ca * r2 * Cos(theta2) &&
Ca * r1 * Sin(theta1) == Ca * r2 * Sin(theta2)
... iterating theta1 and theta2 from 0 to 360 degrees, for both circles. You might write code like:
for theta1 in 0 ..< 360 {
for theta2 in 0 ..< 360 {
if( abs(Ca*r1*cos(theta1) - Ca*r2*cos(theta2)) < 0.01 && abs(Ca*r1*sin(theta1) - Ca*r2*sin(theta2)) < 0.01 ) {
print("point is: (", Ca*r1*cos(theta1), Ca*r1*sin(theta1),")")
}
}
}
Depending on what your tolerance was for a match, you wouldn't have to do too many iterations around the circumferences of each signal radius to determine an estimate for the location of the signal source.
So basically you need to intersect 4 circles. There can be many approaches to it, and there are two that will generate the exact intersection area.
First approach is to start with one circle, intersect it with the second circle, then intersect the resulting area with the third circle and so on. that is, on each step you know current intersection area, and you intersect it with a new circle. The intersection area will always be a region bounded by circle arcs, so to intersect it with a new circle you walk along the boundary of the area and check whether each bounding arc intersects with a new circle. If it does, then you leave only the part of the arc that lies inside a new circle, remember that you should continue with an arc from a new circle, and continue traversing the boundary until you find the next intersection.
Another approach that seems to result in a worse time complexity, but in your case of 4 circles this will not be important, is to find all the intersection points of two circles and choose only those points that are of interest for you, that is which lie inside all other circles. These points will be the corners of your area, and then it is rather easy to reconstruct the area. After googling a bit, I have even found a live demo of this approach.

Draw circle using latitude and longitude

I want to plot a latitude and longitude using matlab. Using that latitude and longitude as center of the circle, I want to plot a circle of radius 5 Nm.
r = 5/60;
nseg = 100;
x = 25.01;
y = 55.01;
theta = 0 : (2 * pi / nseg) : (2 * pi);
pline_x = r * cos(theta) + x;
pline_y = r * sin(theta) + y;
hold all
geoshow(pline_x, pline_y)
geoshow(x, y)
The circle does not look of what I expected.
Drawing a circle on earth is more complex that it looks like.
Drawing a line or a poly line is simple, because the vertices are defined.
Not so on circle.
a circle is defined by all points having the same distance from center (in meters! not in degrees!!!)
Unfortuantley lat and lon coordinates have not the same scale.
(The distance between two degrees of latidtude is always approx. 111.3 km, while for longitude this is only true at the equator. At the poles the distance between two longitudes approach zero. In Europe the factor is about 0.6. (cos(48deg))
There are two solution, the first is more universal, usefull for nearly all problems.
convert spherical coordinate (of circle center) to cartesian plane with unit = 1m, using a transformation (e.g equidistant transformation, also called equirectangular transf., this transformation works with the cos(centerLat) compensation factor)
calculate points (e.g circle points) in x,y plane using school mathematics.
transform all (x,y) points back to spherical (lat, lon) coordinates, using the inverse transformation of point 1.
Other solution
1. write a function which draws an ellipse in defined rectangle (all cartesian x,y)
2. define bounding of the circle to draw:
2a: calculate north-south diameter of circle/ in degrees: this a bit tricky: the distance is define in meters, you need a transformation to get the latitudeSpan: one degrees of lat is approx 111.3 km (eart circumence / 360.0): With this meters_per_degree value calc the N-S disatcne in degrees.
2b: calculate E-W span in degrees: now more tricky: calculate like 2a, but now divide by cos(centerLatitude) to compensate that E-W distances need more degrees when moving north to have the same meters.
Now draw ellipseInRectangle using N-S and E_W span for heigh and width.
But a circle on a sphere looks on the projected monitor display (or paper) only like a circle in the center of the projection. This shows:
Tissot's Error Ellipse