Defining a threshold for Distance between two GEO Locations? - android

I am getting two GEO locations in my application and I have to calculate distance between them and after distance calculation I have to compare that result with the a defined threshold which is in my case 50 meters, how would I define that threshold in float. Also, Currently I my android fone is at the same location, but I always get the calculated distance between my 2 two geolocations determined after an interval to be more than 50 meters. How is it possible? I am taking threshold of 50 meters as:
private static final float DISTANCE_CHANGE_METERS = 50.0f; //50 meters
and I am calculating distance through following formula I found on StackOverflow:
public static float distFrom(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(lat2 - lat1);
double dLng = Math.toRadians(lng2 - lng1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) * Math.sin(dLng / 2) * Math.sin(dLng / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double dist = earthRadius * c;
int meterConversion = 1609;
return new Float(dist * meterConversion).floatValue();
}
Kindly help me out in this regard. Thanks!

Currently my android phone is at the same location, but I always get the calculated distance between my 2 two geolocations determined after an interval to be more than 50 meters. How is that possible?
It actually depends on how you are passing the latitude and longitude to the distFrom function. Just to remind you that there is a simpler way to calculate the distance.
You can use just distanceTo() function in android API using Location to calculate the distance between two places like this:
Location locationA = new Location("point A");
locationA.setLatitude(latA); // co-ordinates in double
locationA.setLongitude(lngA);
Location locationB = new Location("point B");
locationB.setLatitude(latB);
locationB.setLongitude(lngB);
float distance = locationA.distanceTo(locationB);
If after using this also you are getting a distance greater than 50 meters then your co-ordinates that you are providing are not that accurate. Its perfectly fine because its tough to get accuracy with less that 50 meter precision. It would be most accurate if you are using internet along with GPS. If you see here, even if you use ACCURACY_HIGH as a criteria to choose a Location Provider, it provides accuracy of less than 100 meters. It can be accurate upto 100, 70 or even 50 meters. So even the most accurate option is not guaranteed to give extreme accuracy. If you are using GPS/Network provider for getting Location, then it your situation is very much possible. Getting location using `Network Provider1 is also not that accurate as it can catch signals of 2 network towers on different occasions, which can be well apart physically.
Hope it helps and clears the point to some extent. Its the problem to accuracy of your Location Provider.

Could you just do:
if (distFrom(lat1,lng1,lat2,lng2) > DISTANCE_CHANGE_METERS)
{
//greater than threshhold
}

Related

How to point my compass to Mecca?

I took the code of compass from this link.
http://www.androidcode.ninja/android-compass-code-example/
How to set mecca location on my compass??
What do i need to do to point my compass to Mecca?
You need to determine your location relatively to Mecca, so you will need Location permission and implement Location Updates.
You can implement that using: Receveing location updates
With this information you can determine where Mecca would be on your compass and set it accordingly. To determine the angle, use this code:
private double angleFromCoordinate(double lat1, double long1, double lat2,
double long2) {
double dLon = (long2 - long1);
double y = Math.sin(dLon) * Math.cos(lat2);
double x = Math.cos(lat1) * Math.sin(lat2) - Math.sin(lat1)
* Math.cos(lat2) * Math.cos(dLon);
double brng = Math.atan2(y, x);
brng = Math.toDegrees(brng);
brng = (brng + 360) % 360;
brng = 360 - brng; // count degrees counter-clockwise - remove to make clockwise
return brng;
}
from: Calculate angle between two Latitude/Longitude points
Well for very few words that's a long question. The answer is to extend the OnSensorChanged code from the example to calculate the heading to Mecca from the current location and adjust the heading based on the current direction the sensor is facing in. You'll need the current location co-ordinates from GPS and the fixed co-ordintates for Mecca, Calculate the direction relative to North (the way the compass is designed to point) and then adjust by the current heading.

Android - Need to add more than 100 geofences

I'm developing an application where user can set multiple locations. I get succeed to show notifications when user get Enter or Leave specific region using GeoFencing.
Now, there is situation that i need to provide monitoring for all saved locations and it can be hundreds and more. I've read at the given link "You can have multiple active geofences, with a limit of 100 per device user."
Is there any way add more then 100 geofences per device user ?
Thanks!
Have an ArrayList with all the geofences you want to monitor +100.
Listen to location updates.
When you get a location update, if the ArrayList of all your geofences is more than 100, remove all geofences been monitored and then calculate the 100 nearest geofences using the harvesine formula:
public static final double R = 6372.8; // In kilometers
public static double haversine(double lat1, double lon1, double lat2, double lon2) {
double dLat = Math.toRadians(lat2 - lat1);
double dLon = Math.toRadians(lon2 - lon1);
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
double c = 2 * Math.asin(Math.sqrt(a));
return R * c;
}
That will give you the distance between the two locations. After that you could compare that distance with the geofence region radius to know if is inside the region.
Note: This distance will be in kilometers if your radius is on meters then just multiply the haversine method result with 1000 so that it's converted to meters.
Reference
Start monitoring the result list of the 100 nearest geofences.
This will allow you to always monitor the 100 nearest geofences based on your location. Been able to monitor more than 100 since it will change the monitoring geofence regions always to the 100 nearest geofence regions.

Calculating distance travelled as the user moves

I need to calculate distance as the user moves in android. I have the starting point coordinates and can get the user's current location. How should I calculate distance.
I don't think I can call GoogleDistance Api as my application would be a real time application and calling this API would be extremely overhead or should calling GoogleDirectionsAPI would work fine.
Also I would like to test the distance travelled. How should I do it? Is there some way of sampling the data or do I really need to go out in the real world and actually travel and then test my application?
Edited: I want the distance travelled by the user and not the straight line distance between the points
I hope following will help:
In my app i started collecting lat longs after every 3fts (I set 3ft just for testing). I collected lat longs as follows:
Now I started calculating distance from point 1 to 2 and then 2 to 3 and then 3 to 4 and so on. After summing up I got total distance from 1 to 5.
I used following functions to calculate distance:
public double GetDistanceFromLatLonInKm(double lat1, double lon1, double lat2, double lon2)
{
final int R = 6371;
// Radius of the earth in km
double dLat = deg2rad(lat2 - lat1);
// deg2rad below
double dLon = deg2rad(lon2 - lon1);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = R * c;
// Distance in km
return d;
}
private double deg2rad(double deg)
{
return deg * (Math.PI / 180);
}
This method is calculating exact distance for me.
You can calculate the distance between two point using the following function
double distanceBetweenTwoPoint(double srcLat, double srcLng, double desLat, double desLng) {
double earthRadius = 3958.75;
double dLat = Math.toRadians(desLat - srcLat);
double dLng = Math.toRadians(desLng - srcLng);
double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.cos(Math.toRadians(srcLat))
* Math.cos(Math.toRadians(desLat)) * Math.sin(dLng / 2)
* Math.sin(dLng / 2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double dist = earthRadius * c;
double meterConversion = 1609;
return (int) (dist * meterConversion);
}
For the second Part: To use mock or sample data you can use "Fake GPS" app from the play store, which will generate mock location in your device.
Happy Coding
There are basically three ways to check the traveled distance -
By using GPS, check the coordinate between two points using distanceTo of Location class.
Using Accelerometer , you can check the movement of device using Accelerometer.
Using Step detector - this is recently updated by Android.
Hope this helps you to achieve your goal :)
For the first question . You have origin coordinates and the present user location coordinates so what you can do is google api v3 library provides a method that takes origin LatLng and destination LatLng and gives the distance . Add api v3 jar to your android build path.
For the second one goto google maps and give the location details it is accurate..

Using a GeoPoint location and meters X/Y, how can a Longitude/Latitude be calculated?

I have a little project I've been playing with (Android, GPS, mapping APIs), and I need to figure how to find a longitude/latitude/GeoPoint from a given longitude/latitude/GeoPoint with only knowing the meters/km longitude and latitude. e.g. I want to figure out where a point is from me, that I know is +1000 meters along the longitude and +1000 along the latitude.
It's a little different than the usual GeoPoint/distance questions you'll see, and it's not quite geo fencing radius related as the distance is X,Y meters/kms, and I don't have a bearing. (I could work out a bearing, but I don't have a suitable direct distance)
Basically, if I could reverse GeoPoint.distanceTo() it would do the job for me.
Update
Just a little more background. I'm basically applying a node triangulation idea I had, but the algorithm requires that my inputs be in a map normalized form that's not the same as longitude and latitude. I create a map/grid where 0,0 (the bottom/left) is the left/west and bottom/south most longitude/latitude values from the nodes I'm working with. All the other node X/Y on the map are determined by finding their meters from the 0,0 node's longitude/latitude using GeoPoint.distanceTo(). (note that I find their X/Y by performing distanceTo twice for each node so I have the X and Y meters from 0,0, not a direct line to the node) That distance in meters is fed into the algorithm and new X/Y map points are produced.
And so I need to figure out how to convert distance from a longitude/latitude into another, previously unknown, longitude/latitude.
double startPointLongitude = 23.459821;
double startPointLatitude = 76.998200;
double distanceLongitude = 100; // 100 meters along the longitude
double distanceLatitude = 75; // 75 meters along the latitude
Basically i took the Answer from AlexWien, corrected two things and made it into a java method
private static final double WGS84_RADIUS = 6370997.0;
private static double EarthCircumFence = 2* WGS84_RADIUS * Math.PI;
private static Position getPosition(Position sourcePosition, double mEastWest, double mNorthSouth){
double degreesPerMeterForLat = EarthCircumFence/360.0;
double shrinkFactor = Math.cos((sourcePosition.getLat()*Math.PI/180));
double degreesPerMeterForLon = degreesPerMeterForLat * shrinkFactor;
double newLat = sourcePosition.getLat() + mNorthSouth * (1/degreesPerMeterForLat);
double newLng = sourcePosition.getLng() + mEastWest * (1/degreesPerMeterForLon);
return new Position(newLat, newLng);
}
The distance between two degrees of latitude never change, it is always aprox. 111 km
(The exact value you should caculate by using the WGS84 Earth radius:
EarthCircumFence = 2* WGS84_RADIUS * Math.Pi;
metersPerDegree = (Earth Cirumfence / 360)
With this info you easily can calculate the latitude offset,
just reverse the factor and have:
degreesPerMeterForLat = EarthCircumfenceMeter / 360.0
with longitude its a bit different, the distance between two degrees of longitude shrink
the more you move away from aequator.
shrinkFactor = cos(toRadians(locationLatitude));
compensate now:
degreesPerMeterForLon = degreesPerMeterForLat / shrinkFactor;
Finally
newLatPos = latOld + numMeters * degreesPerMeterForLat;
newLonPos = lonOld + numMeters * degreesPerMeterForLon;
This works for distance offset < 10 - 50 km
Sigh, I posted this like 6 hours ago but it does not appear to have gone through.
Ok, worked it out in spite of most geographical formulas and facts occasionally going over my head. Working with geography is like working with the Gregorian calendar, it makes sense if you program for it all the time, but otherwise it's easy to get confused by an incorrect assumption.
The following except from my app will take a starting GeoPoint's long/lat
/**
* the length of one degree of latitude (and one degree of longitude at equator) in meters.
*/
private static final double DEGREE_DISTANCE_AT_EQUATOR = 111329;
/**
* calculates the x,y in meters from a given starting point's long0, lat0 to a target destination point's long1, lat1.
* #param long0 start point longitude
* #param lat0 start point latitude
* #param long1 end point longitude
* #param lat1 end point latitude
* #return
*/
public static Pair<Double, Double> xyFromLongLat(int long0, int lat0, int long1, int lat1) {
double x = (long1 / 1E6 - long0 / 1E6) * longitudeDistanceAtLatitude(lat0 / 1E6);
double y = (lat1 / 1E6 - lat0 / 1E6) * DEGREE_DISTANCE_AT_EQUATOR;
return new Pair<Double, Double>(x, y);
}
/**
* calculates longitude and latitude from a given starting point, with only the X/Y meters
* #param long0
* #param lat0
* #param x
* #param y
* #return
*/
public static Pair<Double, Double> longLatFromXY(int long0, int lat0, double x, double y) {
double lat1 = (y / DEGREE_DISTANCE_AT_EQUATOR) + (lat0 / 1E6);
double long1 = x / longitudeDistanceAtLatitude(lat0) + (long0 / 1E6);
return new Pair<Double, Double>(lat1, long1);
}

Calculate longitude from distance

Found a plenty of answers to question how to calculate distance by lat/lon and nothing for a "reverse" problem.
I have a displacment in X and Y and a GPS point (lat/lon), yet need to calc coordinates for a new point.
Using formula:
double deltaLat = dy / EARTH_RADIUS;
double deltaLon = dx / EARTH_RADIUS;
double lat = locLat + Math.signum(dy) * Math.toDegrees(deltaLat); // formula correct
double lon = locLon + Math.signum(dx) * Math.toDegrees(deltaLon);
It's accurate for calculating latitude, but for longitude I get about 10–15% error.
Does anyone have the same issue? Any possible formulas to calculate longitude by displacement?
The reason you're getting 10-15% error in longitude is because for longitude you cannot use the earth's radius to compute your displacement. Instead, you need to use the radius of the "circle" at the corresponding latitude. Therefore using your formula your longitude calculations should be more like
double deltaLon = dx / (EARTH_RADIUS * cos(locLat))
However this may give you undesired results around the poles, as cos(locLat) will get close to 0, so you may want to have some special cases for the poles (or even around them). Logically, if you think about, if you're at the pole, moving any distance along the x axis will not get your anywhere anyway.
Simplest but not the best solution is:
double deltaLat = dy / EARTH_RADIUS; // up-down
double deltaLon = dx / EARTH_RADIUS ; // left-right
double lat = locLat + Math.signum(dy) * Math.toDegrees(deltaLat); // formula correct
double lon = locLon + Math.signum(dx) * Math.toDegrees(deltaLon * 1.195);

Categories

Resources