Reading Data from Firestore - flutter

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!

Related

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.

deg2km command does not calculate distance between two points in matlab

I am trying to calculate distance between two geographical coordinates and I want to convert geographical coordinates to the km. Therefore I used deg2km function. However, I realise that it is not convert points properly.
For instance, I used these two points.
p_x=[5; 10]; %degree
p_y=[8; 16]; %degree
pos_y=deg2km(p_y,6378);
pos_x=deg2km(p_x,6378);
It returns as:
pos_x= [556.58549846099 1113.17099692198]
pos_y= [890.536797537587 1781.07359507517]
When I calculate distance ( sqrt((556.5-1113.2)^2+(890.5368-1781.1)^2) ) between these points I obtained distance as : 1050.2464
However I checked it google map and also other websites it should be 1042 km.
Do you have any suggestion to calculate distance and also points as kilometers properly?
Thanks in advance!
edited as :
I've points(deg)and I need to convert them km and calculate distance between points.
LAT=[41.000173;41.010134]*pi/180;
LON=[28.995882;28.995584]*pi/180;
I used this code to calculate distance. It calculates properly.
But I can not convert my points to kilometers.
LAT=[41.000173;41.010134]*pi/180;
LON=[28.995882;28.995584]*pi/180;
R=6378; %km
for i=1:length(LAT)-1
psi(i,1) = atan2( sin (LON(i+1)-LON(i)) * cos (LAT(i+1)) , cos (LAT(i)) *sin (LAT(i+1)) - sin (LAT(i)) * cos (LAT(i+1)) * cos (LON(i+1)-LON(i)) );
a=(sin((LAT(i+1)-LAT(i))/2))^2+cos(LAT(i))*cos(LAT(i+1))*(sin((LON(i+1)-LON(i))/2))^2;
c=2*atan2(sqrt(a),sqrt(1-a));
d(i,1)=R*c;
end

Cartesian Coordinate System in Perspective Projection

I'm still implementing a perspective projection for my augmented reality application. I've already asked some questions about the viewport-calculation and other camera stuff, which is explained from Aldream in this thread
However, I don't get any useful value at the moment and I think this depends on my calculation of the cartesian coordinate space.
I had some different ways to transform latitude,longitude and altitude to a cartesian coordinate space, but nothing of them seems to work properly. Currently I'm using ECEF(earth centered), but I also tried different calculations like a combination of the haversine-formula and trigonometry (to calculate x and y from the distance and the bearing between two points).
So my question is:
How does the cartesian coordinate space affect my perspective projection? Where do I have to "compensate" my units?(When I'm using meter or centimeter for example)?
Lets say I'm using ECEF, than I get values in meter, so for example, my camera is at (0,0,2m height) and my point is at (10,10,0). Now I can easily use the function mentioned on wikipedia and afterwards using the conversion of dx,dy,dz explained in my other thread (mentioned above). What I still don't get: How does this projection "know" what my units in the coordinate system are? I think this is the mistake I'm currently doing. I don't handle the units of my coordinate system and therefore, cannot get any good value from my projection.
When I'm using a coordinate system with centimeter as unit, all of my values from my perspective projection are increasing. Where do I have to "resolve" this unit-problem? Do I have to "transform" my camera-width and camera-height from pixel to meter? Do I have to convert the coordinate system to pixel? Which coordinate-system should be used to handle this situation? I hope you can understand my problem.
Edit:I solved it myself.
I've changed my coordinate system from ecef to a own system (using haversine and bearing and then calculating x,y,z) and now I get good values! :)
I'll try another way to explain it here then. :)
The short answer is: the unit of your cartesian positions doesn't matter as long as you keep it homogeneous, ie as long as you apply this unit both to your scene and to your camera.
For the longer answer, let's go back to the formula you used...
With:
d the relative Cartesian coordinates
s the size of your printable surface
r the size of your "sensor" / recording surface (ie r_x and r_y the size of the sensor and r_z its focal length)
b the position on your printable surface
.. and do the pseudo dimensional analysis. We have:
[PIXEL] = (([LENGTH] x [PIXEL]) / ([LENGTH] * [LENGTH])) * [LENGTH]
Whatever you use as unit for LENGTH, it will be homogenized, ie only the proportion is kept.
Ex:
[PIXEL] = (([MilliM] x [PIXEL]) / ([MilliMeter] * [MilliMeter])) * [MilliMeter]
= (([Meter/1000] x [PIXEL]) / ([Meter/1000] * [Meter/1000])) * [Meter/1000]
= 1000 * 1000 / 1000 /1000 * (([Meter] x [PIXEL]) / ([Meter] * [Meter])) * [Meter]
= (([Meter] x [PIXEL]) / ([Meter] * [Meter])) * [Meter]
Back to my explanations on your other thread:
If we use those notations to express b_x:
b_x = (d_x * s_x) / (d_z * r_x) * r_z
= (d_x * w) / (d_z * 2 * f * tan(α)) * f
= (d_x * w) / (d_z * 2 * tan(α)) // with w in px
Wheter you use (d_x, d_y, d_z) = (X,Y,Z) or (d_x, d_y, d_z) = (1000*X,1000*Y,1000*Z), the ratio d_x / d_z won't change.
Now for the reasons behind your problem, you should maybe check if you apply the correct unit to the position of your camera / to its distance to the scene too. Check also your α or the unit of the focal length, depending on which one you use.
If think the later suggestion is the most likely. It can be easy to forget to also apply the right unit to the characteristics of your camera.

Figuring out distance and course between two coordinates

I have 2 coordinates and would like to do something seemingly straightforward. I want to figure out, given:
1) Coordinate A
2) Course provided by Core Location
3) Coordinate B
the following:
1) Distance between A and B (can currently be done using distanceFromLocation) so ok on that one.
2) The course that should be taken to get from A to B (different from course currently traveling)
Is there a simple way to accomplish this, any third party or built in API?
Apple doesn't seem to provide this but I could be wrong.
Thanks,
~Arash
EDIT:
Thanks for the fast responses, I believe there may have been some confusion, I am looking to get the course (bearing from point a to point b in degrees so that 0 degrees = north, 90 degrees = east, similar to the course value return by CLLocation. Not trying to compute actual turn by turn directions.
I have some code on github that does that. Take a look at headingInRadians here. It is based on the Spherical Law of Cosines. I derived the code from the algorithm on this page.
/*-------------------------------------------------------------------------
* Given two lat/lon points on earth, calculates the heading
* from lat1/lon1 to lat2/lon2.
*
* lat/lon params in radians
* result in radians
*-------------------------------------------------------------------------*/
double headingInRadians(double lat1, double lon1, double lat2, double lon2)
{
//-------------------------------------------------------------------------
// Algorithm found at http://www.movable-type.co.uk/scripts/latlong.html
//
// Spherical Law of Cosines
//
// Formula: θ = atan2( sin(Δlong) * cos(lat2),
// cos(lat1) * sin(lat2) − sin(lat1) * cos(lat2) * cos(Δlong) )
// JavaScript:
//
// var y = Math.sin(dLon) * Math.cos(lat2);
// var x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
// var brng = Math.atan2(y, x).toDeg();
//-------------------------------------------------------------------------
double dLon = lon2 - lon1;
double y = sin(dLon) * cos(lat2);
double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(dLon);
return atan2(y, x);
}
See How to get angle between two POI?
Depending on how much work you want to put in this one, I would suggest looking at Tree Traversal Algorithms (check the column on the right), things like A* alpha star, that you can use to find your find from one point to another, even if obstacles are in-between.
If I understand you correctly, you have the current location and you have some other location. You want to find the distance (as the crow flies) between the two points, and to find a walking path between the points.
To answer your first question, distanceFromLocation will find the distance across the earth's surface between 2 points, that is it follows the curvature of the earth, but it will give you the distance as the crow flies. So I think you're right about that.
The second question is a much harder. What you want to do is something called path-finding. Path finding, require's not only a search algorithm that will decide on the path, but you also need data about the possible paths. That is to say, if you want to find a path through the streets, the computer has to know how the streets are connected to each other. Furthermore, if you're trying to make a pathfinder that takes account for traffic and the time differences between taking two different possible paths, you will need a whole lot more data. It is for this reason that we usually leave these kinds of tasks up to big companies, with lots of resources, like Google, and Yahoo.
However, If you're still interested in doing it, check this out
http://www.youtube.com/watch?v=DoamZwkEDK0

How to calculate short & long distance via Haversine?

I am looking for a way to calculate the distance between 2 points on the globe. We've been told to use Haversine, which works fine to calculate the shortest distance between the 2 points.
Now, I'd like to calculate the "long distance" between to points. So suppose you have 2 cities, A in the west and B in the east. I want to know the distance from B to A if I would travel eastwards around the globe and then reach A coming from the west.
I've tried changing a couple of things in the haversine function, but doesn't seem to work.
Anyone know how I can simply do this using small adjustments to the haversine function?
This is what I'm using now:
lat1, lat2, lng1, lng2 are in radians
part1 = sin(lat2) * sin(lat1);
part2 = cos(lat2) * cos(lat1) * cos(lng1 - lng2);
distance = 6378.8 * acos(part1 + part2);
The way I see it is that you can draw a circle around the globe between the 2 cities. The long distance the the circumference of that circle minus the short distance. But in contrary of what was replied, the circle's length is not equal to the earth's circumference. This is only the case for 2 points on the equator.
Tnx
Jeroen
The circumference of the earth is approx 40,075KM, work out the short distance and subtract it from that.