Suppose we have two beacons placed in both sides of the road. We know their latitude and longitude where they are positioned (we treat them as a location). We also know the distance in meters between these two beacons (measered using Haversine Formula). Our device is moving between(inside range of these beacons) these two points.Is there out any function that will help us calculate our current position based on the distance between two beacons or based on the distance from device to a single beacon?
How can i find the location of the device based on these data i have, or is there any thing that will be useful to achieve what i want?
SHORTLY: I want to know where the user is located between two BEACONS without using GPS System but the data i have from the beacon (in this case: Exact Beacons locations, exact distance from user to the beacon and the exact distance between two beacons)
As an illustration:
(Filled Black dots are BEACONS with an imaginary Range, Red dots are some user unknown positions and Green Lines are the Known Distances ; we also know the latitude and longitude of Black Dots) Based on these data i want to find the position of user (Single Red Dot)
note: I checked out this question however i didnt understand why the location is returned as an int and why time t is included there.
Here the Methods to set the locations and get the distance from where you are standing between these two point.
private Location BeaconLocation1() {
Location location = new Location("POINT_LOCATION1");
location.setLatitude(45.0);
location.setLongitude(45.0);
return location;
}
private Location BeaconLocation2() {
Location location = new Location("POINT_LOCATION2");
location.setLatitude(45.5);
location.setLongitude(45.5);
return location;
}
public class MyLocationListener implements LocationListener {
public void onLocationChanged(Location location) {
Location pointLocation1 = BeaconLocation1();
Location pointLocation2 = BeaconLocation2();
float distance1 = location.distanceTo(pointLocation1);
float distance2 = location.distanceTo(pointLocation2);
Toast.makeText(MapsActivity.this,
"Distance from Point1: "+distance1+" Meters", Toast.LENGTH_LONG).show();
Toast.makeText(MapsActivity.this,
"Distance from Point2: "+distance2+" Meters", Toast.LENGTH_LONG).show();
}
public void onStatusChanged(String s, int i, Bundle b) {
}
public void onProviderDisabled(String s) {
}
public void onProviderEnabled(String s) {
}
}
EDIT :
see this post
convert meters to latitude longitude from any point
To focus on your question, no there is no one-shot formula to do everything but there are some to make the process easier. You will have to look around in a whole bunch of math libraries to find them though.
This is the theory behind it.
Okay so we require the latitude and longitude of point 3. I'm going to explain the theory behind it as the code is just too much for me to do right now.
For this we will make use of the bearing from one point to another. You can use this link to get that formula: Bearing formula
I am assuming we know the distance between the device and each of the separate beacons otherwise this is impossible unless you want to use a sort of radar approach to identify this. I can't really help with that. If we do know this we can construct imaginary circles around the two beacons using the distance from them to the device as their radii.
E.g. From device to beacon one is 500 meters. From device to beacon 2 is 200M. Draw an imaginary circle around beacon one with a raduis of 500M and a imaginary circle around beacon two with a radius of 200M.
obviously we can't construct these circles programatically it would be too tedious. So we will use the equation of a circle: (x -h)^2 + (y - k)^2 =r^2.
Quick high school revision reveals that
h and k are the x and y coordinates of the center of the circle, an offset from the Cartesian plain. we will center our imaginary Cartesian plain at point one. Now we will workout the bearing to point two an use the distance from point to to construct a line from 0,0 on our Cartesian plane(Point 1) to point 2. Using tan of our bearing we get the gradient of the line. Now we will use cos and sine of our bearing and using the distance of our hypotenuse to obtain the y and x position of beacon 2 relative to beacon 1 on our Cartesian plane. Now we will sub these values back into our circle equations:
your first equation will always be:
(x -0)^2 + (y - 0)^2 =r^2. Where r is the radius in this example 500M.
second equation is
(x -h)^2 + (y - k)^2 =r^2.Where r is the radius in this example 200M. Except now h will be your calculated x value above and y will be the calculated y value above.
Now for the tricky party. We need to find where these circle intersect. From our buddies at math stack exchange i got the formula.Points of intersection
Now your circles might have zero 1 or two point of intersection based on the devices position. If you get two results you will have to run the entire thing again while the device is moving to see whether we are moving closer or further away from the centers of the circles. From that we can conclude which side is the correct point and the we can dram a straight line to beacon 1 on our Cartesian plain, obtain the gradient of the line, convert it into a bearing from beacon 1 and then reverse engineer the haversine and bearing formula to get the co-ordinates.
It's not pretty or easy but you'll get there eventually.
This is most likely not the only solution so feel free to go searching for other ones.
Best of luck.
Related
I can use GPS to get my current location, I'd like to retrieve all the POIs which within my circle region.
The center point of circle is my current location, radius of circle region is x.
POI item is stored in database with its location and other information.
Which solution is the best way to retrieve all the POIs which within my circle.
Any suggestion?
Thanks,
Considering that you've retrieved all of your location points, retrieved your location using LocationManager and wish to check which of those lie inside of your circle area, this may be one way to achieve your goal:
int RADIUS;
ArrayList<Point> points;
Location myLocation;
for(Point point : points){
Location pointLocation = Location("");
pointLocation.setLatitude(point.x); // assume x values are latitudes
pointLocation.setLongitude(point.y); // assume y values are longitudes
if(myLocation.distanceTo(Location pointLocation) < RADIUS){
// This point lies inside
}
}
Another, less Android-ish way would be to check if your data points satisfy the equation:
(myLocation.getLatitude() - pointLocation.getLatitude()) ^ 2 + (myLocation.getLongitude()) - pointLocation.getLongitude()) ^ 2 <= RADIUS ^ 2
Since this equation presupposes that the Earth surface is flat, the result would contain error, magnitude of which would grow with the RADIUS value.
i have punch of GPS coordinates (latitude longitude) i want to create groups each one will contain coordinates that in the same radius , iam using this code to get distance between 2 points:-
float radius = (float) 1000.0;
float distance = loc.distanceTo(loc2);
if (distance < radius)
Toast.makeText(getApplicationContext(), "inside", Toast.LENGTH_LONG).show();
}
but with this code i need to compare each coordinate with the rest to check which one is closest ,which seem insufficient , is there any other way?
thanks in advance
The other way is to use a geo spatial index, like quad tree.
In that case you would first calculate which quad cells are within the radius, and then you only consider the points inside that cells.
But this is some programming, search and understanding effort, so use such an index when a brute force search over all points is to slow.
I have a database full of map Locations (Latitude, Longitude), is there a way I could do a SQL query to return me all points around a certain location?
Right now I basically grab everything in the database and loop through each one and check the distance using
Location.distanceBetween(startPoint.latitude, startPoint.longitude,endPoint.latitude,endPoint.longitude, results);
and keeping items that are within the set distance but there could be a lot of points to loop through.
So is there anyway to do this in an SQL statement?
You can use a WHERE clause expression to filter on angular distance r from an origin (x0, y0). Since SQLite doesn't have a square root function, you'll have to use the squared distance:
SELECT ... FROM ...
WHERE (Latitude-x0)*(Latitude-x0) + (Longitude-y0)*(Longitude-y0) < r*r;
The only place this won't work well is near the poles or the prime meridian. It's also a planar approximation to the sphere, so it will only work for values of r that are quite small. Finally, it scales latitude and longitude equally, so the selected region looks more and more elliptical the farther away the origin is from the equator.
You will have to convert linear distance (e.g., "within 30 meters") to latitude/longitude differences. This is a rather complex subject because the Earth is not a perfect sphere. However, for rough calculations you can use the approximation that 1 nautical mile = 1852 meters = 1 arc minute of longitude at the equator. Since lines of longitude get closer together as the latitude moves away from the equator, you will need to use some trig to figure out what value of r to use at a given latitude. For more info on this problem see this thread or this one, or search the web for "convert meters to latitude longitude".
I have a database full of map Locations (Latitude, Longitude), is there a way I could do a SQL query to return me all points around a certain location?
You can easily check a square region.
Using very simplified latitude / longitude coordinates say you're at [25.86, 57.03] and you wanted everything in the "neighborhood" (+/- .05) you can use a query like this:
SELECT * FROM Coords WHERE (latitude BETWEEN 25.81 AND 25.91) AND (longitude BETWEEN 56.98 AND 57.08);
You can also use the SQLite R*Tree extension.
An R-Tree is a special index that is designed for doing range queries. R-Trees are most commonly used in geospatial systems where each entry is a rectangle with minimum and maximum X and Y coordinates.
The source code to the SQLite R*Tree module is included as part of the SQLite3 amalgamation but is disabled by default. To enable the R*Tree module, simply compile with the SQLITE_ENABLE_RTREE C-preprocessor macro defined.
I have a data set of different locations, and want to show the nearest locations (within 5 km).
How can I determine the minimum/maximum of latitude and longitude?
f.e.: I need to fill my car up, and am looking for all gas stations in my neighborhood so I can go to the nearest. How do I do this on an Android phone?
I'd like to avoid iterating through all of the locations as well, because I've got about 2500 locations and rising. Any suggestions on that?
Thank you guys in advance for the advice on this!
Update:
Thank you for the feedback you guys gave me, I solved my issue by iterating through all locations on the server and using the Google Distance Matrix API to calculate the distances: http://code.google.com/intl/nl/apis/maps/documentation/distancematrix/
Simplifying, latitude is the angle over/under the equator, longitude is angle right/left of greenwich meridian.
So to calculate (on average) how much for example 1ยบ latitude is, you convert it to radians (multiply by PI/180), and then multiply by Earth's mean radius (6,371.0 km).
For your question, the process is the inverse one: take 5 km and convert it to degrees:
Divide it by Earth's radius
Multiply by 180/PI
This way you will get delta degrees, that is, how much degrees are 5 kms (on average, if you want exactitude, you will need the exact Earth radius differentials over those 5 kms) with which you can build a circle around the given location (just like a compass would).
All the calcuations give and methods are approximations but well within tolerances for what you require.
The earth circumference is approx 40076000 metres.
the distance traveled per degree of latitude is allways the same and is simply a proportion of the earth circ.
the distance travel per degree in longitude however changes depending upon your latitude ( this rings on the glode get smaller nearer the poles ).
so for a given distance m, the corresponing Latitude and Longitude values are
earthcirc = 40076000;
// at Lat and Lon for distance m (in meters)
LatDelta = (m * 360) / earthcirc;
LonDelta = (m * 360) / abs(eathcirc*cos(lat));
This gives you your square lat long deltas for a simple search of your data. but on fingin a candidate your should then do a full distance calc as the corner of the square is quite a bit more than 5 KM away.
distance between 2 lat/longs
distLat = (lat1-lat2) * earthcirc) / 360;
distLong = (long1-long2) * earthcirc * cos((lat1+lat2)/2) / 360;
dist = sqrt( sqr(distLat) + sqr(distLong) );
I know most compilers/languages use radians for cos/sin functions but its easire to explain in degrees.
as for searching your data the simplest way is to order in be either lat or long then you can do a binary search to find the possible location to check instead of a full scan. There are better ways to order the data ( quad trees ) but for 2500 ish entries i wouldnt bother
There are two issues here, 1) how to calculate the distance between two pairs of lat/lon and 2) how to find the point with shortest distance to a given point.
There are formulas on the net, some more accurate than others, for example http://www.movable-type.co.uk/scripts/latlong.html
This is a (geo) spatial indexing problem (http://en.wikipedia.org/wiki/Spatial_index#Spatial_Index ). You can use for example a quad tree with lat/lng as X/Y (I assume your points are not too close to the polars, which complicate things but still doable). The quad tree let you find in Log(N) time the neighborhood of your car without having to iterate over all points.
Not exact code but hopefully it will help.
I have an interesting question. I have a latitude value of 51.445376 and a longitude value of -0.190624 (as an example, say this was recieved by an androids location listener). This particular location (and it's values) is a point of interest and it is stored in my database. I am using a location listener on my android, and I will send the users current location to the server to detect if the user has come within a one kilometre radius of that particular point of interest. Does anyone know what algorithm to use to check if the users current longitude and latitude is within that one kilometre radius of the point of interests longitude and latitude? Or something I can see?
Perhaps someone could help me out, as my math is not the greatest in the world.
For geographic coordinates, use this function (public domain):
public static double distanceInKM(
double latStart,double lonStart,
double latEnd,double lonEnd
){
latStart=Math.toRadians(latStart);
latEnd=Math.toRadians(latEnd);
return 6370.997*Math.acos(
Math.cos(Math.toRadians(lonEnd - lonStart))*Math.cos(latStart)*
Math.cos(latEnd)+Math.sin(latStart)*Math.sin(latEnd));
}
Calculating the shortest geographic path is called the "inverse geodesic problem", and this is discussed in C.F.F. Karney's article "Algorithms for geodesics, 2012. The method above shows a distance function based on the spherical law of cosines, which is a less accurate way to compute this path, especially because it assumes Earth is a perfect sphere.
This post from 2008 might be helpful.
It links to a MovableType description of how to use the Haversine formula to calculate the distance between two points on a sphere. It's important to note that it's not 100% accurate since the Earth is not a perfect sphere (it's equatorial radius is some 20km different from its polar radius) but should be sufficient for your needs.
The MovableType link also describes how to use an equi-rectangular projection (translation of lat/long to rectangular coordinates) and the pythagorean theorem to determine a rougher (but faster) approximation of the distance (good for small distances of ~1-2km.)
A simple solution: Simply find the distance, by first finding dx and dy.
Say I have point 1 (p1) and point 2 (p2)
dx = p2.x - p1.x;
dy = p2.y - p1.y;
Now find the distance d as follows
d = sqrt(dx^2 + dy^2)
In a programming language like java, you can use the following lines:
double d = Math.sqrt(dx*dx + dy*dy);
Hope this helps as your starting point!
Note: x & y must be calculated accordingly for your lat&lon info. I was going to write a short code snippet but I saw someone else has a nice solution (I upvoted his response).