Ordering QuerySnapShot with calculated field - flutter

I am getting a Firestore collection as QuerySnapShot.
List userDocs = snapShot.data!.docs;
userDocs has a GeoPoint value and I am calculating the distance from the current user location to every userDocs GeoPoint item.
I am able to calculate the distance using a function, but I need to add this calculated distance as part of userDocs, in a way that I can sort the userDocs items from closest to farthest.
Here you have my attempt:
List userDocs = snapShot.data!.docs;
String distKm ="";
//iterate para calcular la distancia al spot
int i = 0;
userDocs.forEach((e) {
print("loop ${i}");
print(e['spot_id']);
//calculamos distancia
GeoPoint geoPoint = e['location'];
var latPost = geoPoint.latitude;
var lonPost = geoPoint.longitude;
var distancia = calculateDistance(
widget.latitud, widget.longitud, latPost, lonPost);
print("distancia ${distancia}");
distKm = distancia.toStringAsFixed(2);
print("distkm ${distKm}");
//update item in userDocs
i++;
});
Is there any way to add a new item to userDocs or update an existing (key,value) to be able to sort userDocs for nearest to farthest item?
EDIT
Function to calculate distances:
double calculateDistance(lat1, lon1, lat2, lon2) {
var p = 0.017453292519943295;
var c = cos;
var a = 0.5 -
c((lat2 - lat1) * p) / 2 +
c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p)) / 2;
return 12742 * asin(sqrt(a));
}

Firestore doesn't have a built-in operator for distance based filtering, and it can only order/filter on values that are stored in the documents that it returns.
If you know the lat/lon pairs for both locations when you write the document, you can indeed also add a field with the distance you calculate based on that, and then use that field in queries.
If either of the locations is not known at write time, that is not an option. Your only option at that point would be to use geohash (or similar) based querying, as explained in the Firebase documentation on geoqueries.

Related

how to find distance and time calculation between two location in flutter

I have multiple locations and current location, i want to find distance between my current location and other given location of google map flutter.
please provide any method or library which can easily calculate time and distance.I am Using this code but i can not find correct distance.
double _coordinateDistance(lat1, lon1, lat2, lon2) {
var p = 0.017453292519943295;
var c = cos;
var a = 0.5 - c((lat2 - lat1) * p) / 2 +
c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p)) / 2;
return 12742 * asin(sqrt(a));}
use https://pub.dev/packages/flutter_locations_distance package
add your multiple locations into lat and lon array and use this code
for(int i=0;i<locCount;i++){
double distance;
// Platform messages may fail, so we use a try/catch PlatformException.
try {
distance = await FlutterLocationsDistance().distanceBetween(currentLat,
currentLon, lat[i], lon[i]);
} on PlatformException {
distance = -1.0;
}
}
and for each multiple locations you can get the distance between current location and other locations.
to get your current location use https://pub.dev/packages/location package.
for the time you can use https://pub.dev/packages/stop_watch_timer package

is there any formula to get travel time between two locations or from distance in flutter without using google maps

I have two locations and I have the formula to get the distance between them but I want to calculate the travel time between them without using google maps or any API calling. Is there any formula to do that in flutter?
I think the real travel time depends on a lot of factors, for example the road you take or the speed limit.
Whitout some complex elaboration, which are usually perfomed by a backend, I don't think it is possible to calculate it.
Anyway, since you have got the distance, you could simply estimate it by giving a supposed speed and then using basic physics formulas.
time = distance / speed.
You cannot find the travel distance between two locations without using the Google API.
However you can get the air distance in meters using this formula in flutter.
double calculateDistance(
double lat1, double lon1, double lat2, double lon2) {
var p = 0.017453292519943295;
var c = cos;
var a = 0.5 -
c((lat2 - lat1) * p) / 2 +
c(lat1 * p) * c(lat2 * p) * (1 - c((lon2 - lon1) * p)) / 2;
var temp = 12742 * asin(sqrt(a));
return (temp * 1000);
}

how to calculate distance between two location on Flutter?(result should be meters)

How to calculate distance between two location in dart?
Without using plugin
double calculateDistance(lat1, lon1, lat2, lon2){
var p = 0.017453292519943295;
var c = cos;
var a = 0.5 - c((lat2 - lat1) * p)/2 +
c(lat1 * p) * c(lat2 * p) *
(1 - c((lon2 - lon1) * p))/2;
return 12742 * asin(sqrt(a));
}
result is KM. if you want meter just multiply by 1000. return 1000 * 12742 * asin(sqrt(a))
You can use geolocator plugin to calculate to distances between two coordinates:
An Example:
var _distanceInMeters = await Geolocator().distanceBetween(
_latitudeForCalculation,
_longitudeForCalculation,
_currentPosition.latitude,
_currentPosition.longitude,
);
Check out GeoLocator Plugin for more info.
Check out latlong. It's a package dedicated to work with coordinates and features sophisticated calculations.
Unlike packages like geolocator it does not come with integrated location services and can be used alongside packages specialized for that.
You can use latlong2 which is the continuation of latlong. It has features like distance calculation and path drawing. So you can get distance as path distance as well as direct distance.

Best Way for Search GPS points in a NOSQL Database

My questions is related on what is the best way to handle data related gps points in a database (in my case nosql DB MongoDB) in order to returns only closest points.
I have a collections of users in my database.
Now I need to create a new "table" which associate users with gps points (an user can have more points). For example:
User,lat,long
ALFA,40,50
ALFA,30,50
BETA,42,33
...
The server should makes available a function that, given a position in input, returns a list of users which are associated to points near the input.
For example:
function nearestUsers(lat,lon){
var mindif = 10000;
var closest;
users = getAllRecordsFromDataBase(); //query for MongoDB that returnst all records of the new table
for ( i = 0 ; i < users.length; i++){
if(this.distance(lat,lon,users[i].lat,users[i].lon)>mindif) delete users[i];
}
return users;
}
The distance function is the following:
function distance(lat1, lon1, lat2, lon2) {
lat1 = Deg2Rad(lat1);
lat2 = Deg2Rad(lat2);
lon1 = Deg2Rad(lon1);
lon2 = Deg2Rad(lon2);
var R = 6371;
var x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
var y = (lat2 - lat1);
var d = Math.sqrt(x * x + y * y) * R;
return d;
}
I'm afraid that, for big amount of data, this approch will result slow. Which is the best way to make more scalable the algorithm? Any suggestions?
Considering that this funcionality is inside my server in Node.js using a MongoDB, can I implement this function directly via query or using some special structure in my database?
You can use mongodb geospatial indexes and queries. Just store you points as GeoJSON points and perform queries using GeoJSON polylines as bbox-es and $geoWithin.

What NPM package should I use for finding the nearest city.

I am using Node.js and MongoDB.
Let say I have predefined few cities (e.g. Seattle, Miami, New York) with Lat & Lon. and there is a user click to my website and I know his IP address, and find out the lat & lon. Then I want to know which city that I've defined is the closest to the user.
I know I can do it using Mongo's geospatial feature. but it would be quite 'expensive' to use DB to calculate that for every web request.
Is there a Node.js NPM package that can do the geo feature as I described above?
How many "pre-defined" cities are you working with? If it's a small number, you could probably just store the list in memory and do a linear scan.
Also, you should probably just give the mongo geospatial query a try to get an idea of exactly how expensive it is, before assuming that it's unreasonable - if you index the city locations and the, it will be pretty fast..
If you are dealing with a lot of points, still don't want to rely on mongo geo-indexing, and need something really specialized, maybe an R-Tree would be worth experimenting with. Here's an r-tree implementation for javascript. https://github.com/imbcmdth/RTree
If you already have the user's location and the location of each city, it should be quite fast to compute the distance to the nearest. Check out this site: http://www.movable-type.co.uk/scripts/latlong.html
I have used the first algorithm a few times.
function getDistance(lat1,lat2,lon1,lon2){
var R = 6371; // km
var c = Math.PI / 180;
var dLat = (lat2-lat1) * c;
var dLon = (lon2-lon1) * c;
var lat1 = lat1 * c;
var lat2 = lat2 * c;
var a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(lat1) * Math.cos(lat2);
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
var d = R * c;
return d;
}
var closest, dist = Number.MAX_VALUE;
for(var i = 0, l=cities.length;i<l;++i){
if(getDistance(cities[i].longitude, cities[i].latitude, user.longitude, user.latitude) < max){
closest = cities[i];
}
}
alert(closest.name + ' is the winner :)');
You might want to add some exception handling here :)