Mapbox Geocoding API: reverseMode not working with limit>1 - mapbox

In reverse geocoding, the results for an API call with reverseMode = score and reverseMode = distance are exactly same (order and values) when limit is greater than 1. I have tried this with several coordinates.
When I try the same coordinates with limit = 1 and reverseMode = score, I get a different result compared with limit = 5 and reverseMode = score. This is not expected behavior.
It is almost as if reverseMode is always "distance" when limit>1, even when specified otherwise.
The coordinates I have been using: -73.9860900000000 (long), 40.7482390000000 (lat)
Is this expected? How can I get results ranked by score with limit>1?

Related

Adding up doubles result in NaN while trying to calculate distance between two positions?

I'm working on a program in which i want to store the distance the user walked since pressing a button. I retrieve the distance via geolocator package and display it on screen which works just fine.
I know there are some distanceBetween-Function for locations, but as far as i noticed, they are just calculating the distance between 2 points and not the actual distance the user walked (For example, if the user starts at one point X, walks over to Point Y and back to X would end in comparing start-and endpoint (X to X), which results in distance: 0, but i want the distance X -> Y -> X.
I added following function that calculated the distance based on longitude/latitude.
double distance(Position start, Position current){
return double.parse((acos(sin(start.latitude)*sin(current.latitude)+cos(start.latitude)*cos(current.latitude)*cos(current.longitude-start.longitude))*6371).toStringAsFixed(2));
}
I call it every frame and store the distance between the current and last gps position.
Works slowly but fine, except one Problem:
Somewhen, the double suddenly turns into "NaN", and i can't figure out why.
It's completely random when this occurs - At the beginning, it was always around 0.6, but it also occurred around 4.5 and 0.2, so i think the problem may be somewhere else.
Can anybody help?
Or does anybody knows a built-in-function that can solve the same problem?
I tried parsing the double to only have 2 decimal spaces (Didn't round it before) because i thought the number might just got too many decimal spaces to be displayed, but error still occured.
I have a second task that is happening at the same time each time stamp, so i thought it was hindering retrieving the GPS, so i tried disabling it, but it didn't change anything.
It's possible that you are getting numerical stability issues with the spherical law of cosines since you're calculating the distance on every frame? It is known that the formula has conditioning issues for very small distances (less than one meter).
Note that the domain for
arccosine(x) is given by -1 <= x <= 1. If in your case you were to supply a value greater than 1 (or smaller than -1) you would get a NaN result.
If you are still debugging this you can add a simple print statement:
double distance(Position start, Position current){
double x = sin(start.latitude)*sin(current.latitude)+cos(start.latitude)*cos(current.latitude)*cos(current.longitude-start.longitude);
if (x > 1 || x < -1) {
print("error");
}
return ((acos(sin(start.latitude)*sin(current.latitude)+cos(start.latitude)*cos(current.latitude)*cos(current.longitude-start.longitude))*6371));
}
If this is indeed the case, then you have a few options, use the Haversine formula because it is better conditioned for small distances, or simply set x to 1 if it's above 1. This anyway just means that the distance is zero.
For more information (and the Haversine formula) see also: Great circle distance
I really didn't think about the arccosines domain...
So i updated my code with your proposition to:
double distance(Position start, Position current) {
double x = sin(start.latitude) * sin(current.latitude) + cos(start.latitude) * cos(current.latitude) * cos(current.longitude - start.longitude);
if (x > 1 || x < -1) {
if (kDebugMode) {
print("error");
}
return 0;
}
return double.parse((acos(x) * 6371).toStringAsFixed(2));
}
It works fine, thank you for your help!

Calculate walking times across route

I am trying to calculate travel distances across a walkable street network I've downloaded using OSMNX. I have generated a route from an origin to a destination using NetworkX's nx.shortest_path function. However, whenever I calculate my route setting "travel_time" as weight, I get inaccurate results. I was wondering if this might have to do with the "speed_kph" attribute in the network. Is there a way to manually set speeds to equate walking speeds (e.g. 5 kph?)?
You are using the nx.shortest_path_length function and the travel_time attribute. Note the travel_time attribute is not present by default in your graph. In order to add it you need to use ox.add_edge_travel_times.
The Networkx function shortest_path_length states in it's documentation:
weight -
If None, every edge has weight/distance/cost 1. If a string, use this edge attribute as the edge weight. Any edge attribute not present defaults to 1.
Since the travel_time is not present you get the shortest path which has the minimum edges.
This can be verified by trying:
weight = nx.shortest_path_length(walk_network, origin_nn, destination_nn, weight = 'fake_key')
Since usually in walking you assume a constant speed, a possible solution would be to use the edge length and calculate the speed separately.
For example:
import osmnx as ox
import networkx as nx
WALKING_SPEED = 1.4 # m/s average walkihg speed
walk_network = ox.graph.graph_from_address('Piccadilly Circus, London', dist = 1000, network_type = 'walk')
origin = (-0.13492669985021463, 51.51016491413415)
destination = (-0.12516, 51.51112)
origin_nn = ox.distance.nearest_nodes(walk_network, origin[0], origin[1])
destination_nn = ox.distance.nearest_nodes(walk_network, destination[0], destination[1])
length = nx.shortest_path_length(walk_network, origin_nn, destination_nn, weight = 'length')
duration = length / WALKING_SPEED / 60
print('The shortest walking route is {:.2f} meters and will take {:.2f} minutes'.format(length, duration))

Understanding MATLAB Graticules in Meshgrat and Pcolorm

I'm having trouble understanding what precisely the output of meshgrat means and how this relates to the lat and lon parameters of pcolorm(lat,lon,Z). I have a grid of global data, I'll call Z, at a 1.5 degree latitude x 1.5 degree longitude spatial resolution. Thus I have a matrix that's 120 x 240 (180 degrees of latitude / 1.5 = 120, 360 degrees of longitude / 1.5 = 240). Row 1 is 90 N and column 1 is 180 W (-180).
If I follow the MATLAB documentation, I can use meshgrat to produce the lat and lon arguments that I need to supply to pcolorm as follows.
latlim = [-90 90];
lonlim = [-180 180];
[lat,lon] = meshgrat(latlim,lonlim,[120 240]);
However, I don't understand why the spacing of the output is the way it is. For example, the first five values of lat are [-90.0000, -88.4874, -86.9748,-85.4622,-83.9496...]. The lon values follow the same spacing. The spacing is very close to 1.5 degrees, but it isn't. Why is there a discrepancy? The documentation claims that the paired lat and lon values are the location of the graticule vertices. In that case, these values make some sense, since there will always be one more vertex than actual grid cells. To test this, I made the following adjustment to the meshgrat code by adding one extra row and column:
latlim2 = [-90 90];
lonlim2 = [-180 180];
[lat2,lon2] = meshgrat(latlim2,lonlim2,[121 241]);
This did, indeed, produce the expected output, with the spacing now exactly at 1.5 degrees (i.e [-90.0000, -88.5000, -87.0000, -85.5000, -84.0000...]). Again, this is logical if these are viewed as vertices. But under this scenario lat and lon no longer match Z in size, which goes against how the documentation says to treat lat and lon in this case.
There seems to be a mismatch here: either the spacing in the lat lon grids are not accurate, or the girds are not the same size as the data, which would be fine in my mind as long as MATLAB knows how to interpret them accordingly, but the documentation does not seem to suggest using it this way. I have no detailed knowledge of how the MATLAB functions work at a finer level. Can someone explain to me what I'm missing?
Thus I have a matrix that's 120 x 240 (180 degrees of latitude / 1.5 = 120, 360 degrees of longitude / 1.5 = 240).
180/1.5 is indeed 120. But you also have an element at 0deg (presumably). That's 121.

Reading Data from Firestore

I am creating an app where a user can create an event and see other events created by other users only if there are in a 10Km Radius. I am storing all the data in firestore.
This is how the app works, from the user side all the events are fetched and only those events are displayed whose distance is less than 10km.
The problem is if there are 10,000 events in the database and the user is in the 10km radius of only 10 events then obviously it will count as 10,000 reads which is too expensive.
Any suggestions for this problem?
One solution that I have in mind is to store data according to the geographical area but how to implement it is another problem.
You won't be charge for 10 000 reads but only the documents retrieved by your query, ten in your example.
Here's a good video from Firebase explaining their billing system : https://www.youtube.com/watch?time_continue=224&v=6NegFl9p_sE
Also keep in mind that for queries other than document reads, such as a request for a list of collection IDs, you are billed for one document read.
I suggest computing min and max longitude corresponding to 10 km distance from user longitude. You do the same with latitude and use those limits in Firestore query. Doing so You will have less events/reads and you can compute the exact distance to suppress events between 10 and 14 km radius... if necessary.
To compute your limit you can use the following formula from https://www.movable-type.co.uk/scripts/latlong.html (Destination point given distance and bearing from start point) and there's an online javascript calculator you can study.
φ2 = asin( sin φ1 ⋅ cos δ + cos φ1 ⋅ sin δ ⋅ cos θ )
λ2 = λ1 + atan2( sin θ ⋅ sin δ ⋅ cos φ1, cos δ − sin φ1 ⋅ sin φ2 )
where φ is latitude, λ is longitude, θ is the bearing (clockwise from north), δ is the angular distance d/R; d being the distance traveled in meters, R the earth’s radius (6371e3).
With bearing 0° you obtain LatitudeMax
With bearing 90° you obtain longitudeEast
With bearing 180° you obtain LatitudeMin
With bearing 270° you obtain longitudewest
Since earth is a sphere with longitude between -180° and 180°
longitudeMin = Min(longitudeEast, longitudeWest)
longitudeMax = Max(longitudeEast, longitudeWest)
And The Firestore part is like :
CollectionReference col = Firestore.instance.collection("mycollection");
Query latitudeMinQuery = col.where('latitude', isGreaterThan: LatitudeMin);
Query latitudeMaxQuery = latitudeMinQuery.where('latitude', isLessThan: LatitudeMin);
Query longitudeMinQuery = latitudeMaxQuery.where('longitude', isGreaterThan: LongitudeMin);
Query longitudeMaxQuery = longitudeMinQuery.where('latitude', isLessThan: LongitudeMax);
https://stackoverflow.com/a/43804487/9139407 (answers by #alex-mamo)
Hopes it helps!

Wrong distance calculation with MongoDB

I am executing the following raw query with MongoDB:
qry = {"position" : SON([("$near", [52.497309,13.39385]), ("$maxDistance", distance/111.12 )])}
locations = Locations.objects(__raw__=qry)
The position in the database is set to [52.473266, 13.45494].
I get a result once I set the distance to 7.3 or higher, so it seems the two locations must at least be 7.3 kilometer away from each other.
When I calculate the distance of those two geo locations with Google Maps (for example going by car) it's telling me it's only 5.2 kilometer away from each other.
I tested it with loads of different locations and there is always a big difference in the distance calculation of google and Mongodb
Am i missing anything or can somebody explain please where this difference is coming from?
I already checked this answer but it's not working for me...
MongoDB assumes that coordinates are in (long, lat) format. If you compute distances by hand using Great-circle distance you'll see what is going on:
> from math import acos, sin, cos, radians
>
> long_x, lat_x = [radians(y) for y in [52.473266, 13.45494]]
> long_y, lat_y = [radians(y) for y in [52.497309, 13.39385]]
>
> acos(sin(lat_x) * sin(lat_y) + cos(lat_x) * cos(lat_y) * cos(long_x - long_y)) * 6371.0
7.27362435031
Google takes coordinates in (lat, long) format so if you provide the same input Google interpretation will be like below:
> acos(sin(long_x) * sin(long_y) + cos(long_x) * cos(long_y) * cos(lat_x - lat_y)) * 6371.0
4.92535867182