Find geopoints in a radius near me - android

I have a DB with Geopoints.
I need to do a query to get all geopoints in the radius of X meters of me.
How can i do this?
I think the best way is get the minimal lat/long possible point, and the max lat/long point and get all of them for which: geopoint > minPoint AND geopoint < MaxPoint
Other ideas?

You can use this class to get de distance between to points:
How to use:
double distInKm = GeoMath.getDistance(12.345, -8.788, 12.33, -8.77);
Or, if point1 and point2 are GeoPoint:
double distInKm = GeoMath.getDistance(point1, point2);
You can also calculate a Geopoint that is a distance of you and along a bearing.
This computes a point that is 5 km northward from point1:
GeoPoint northPointAt5 = GeoMath.getGeoPointAlongBearing(point1, 0, 5);
You can calculate the other points at 90 degrees, 180 degrees and 270 degrees to calculate minPoint AND MaxPoint.
GeoMath class:
public class GeoMath {
public static final int EARTH_MEAN_RADIUS = 6371; // earth's mean radius in Km
public static double getDistance(double startLatitude, double startLongitude,
double endLatitude, double endLongitude){
return distHaversine(startLatitude,startLongitude,endLatitude,endLongitude);
}
public static double getDistance(GeoPoint point1, GeoPoint point2){
return distHaversine(point1.getLatitudeE6()/1E6, point1.getLongitudeE6()/1E6,
point2.getLatitudeE6()/1E6, point2.getLongitudeE6()/1E6);
}
private static double getSpanInRadians(double max, double min){
return Math.toRadians(max - min);
}
//Distance in Km between point1 (lat1,lon1) and point2 (lat2,lon2) Haversine formula
private static double distHaversine(double lat1, double lon1, double lat2, double lon2) {
double dLat = getSpanInRadians(lat2,lat1);
double dLon = getSpanInRadians(lon2,lon1);
lat1 = Math.toRadians(lat1);
lat2 = Math.toRadians(lat2);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.cos(lat1) * Math.cos(lat2) * Math.sin(dLon/2) * Math.sin(dLon/2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = EARTH_MEAN_RADIUS * c;
return Math.round(dist * 1000)/1000; //3 decimal places
}
// Get GeoPoint at distance along a bearing
// bearing in degrees
// distance in Km
public static GeoPoint getGeoPointAlongBearing(GeoPoint location, double bearing, double distance){
double PI = Math.PI;
double NM = 1.852; //1 nm = 1.852 Km -> nm = Km/NM
GeoPoint geoPointAlongBearing;
double locationLatRad = Math.toRadians(location.getLatitudeE6()/1E6);
double locationLongRad = Math.toRadians(location.getLongitudeE6()/1E6)*(-1.0d);
double distanceRad = distance/NM * PI/(180*60);
double bearingRad = Math.toRadians(bearing);
double latAlongBearingRad = Math.asin(Math.sin(locationLatRad) *
Math.cos(distanceRad) +
Math.cos(locationLatRad) *
Math.sin(distanceRad) *
Math.cos(bearingRad));
double lonAlongBearingRad = mod(locationLongRad -
Math.asin(Math.sin(bearingRad) *
Math.sin(distanceRad) /
Math.cos(latAlongBearingRad)) + PI, 2 * PI) - PI;
double latAlongBearing = rad2lat(latAlongBearingRad);
double lonAlongBearing = rad2lng(lonAlongBearingRad) * (-1);
geoPointAlongBearing = new GeoPoint((int)(latAlongBearing*1E6),(int)(lonAlongBearing*1E6));
return geoPointAlongBearing;
}
private static double mod(double y, double x) {
return y - x * Math.floor(y/x);
}
}

With your query I think that you will find all points inside a square centered at your location and with a side length X.
After that, yuo can get all the points that are inside a circle centered at your location with radius X.
What about this pseudo code:
//create your location
Location yourLocation=new Location("myLoc");
double latitude = geoPointYourLocation.getLatitudeE6() / 1E6;
double longitude = geoPointYourLocation.getLongitudeE6() / 1E6;
yourLocation.setLatitude(latitude);
yourLocation.setLongitude(longitude);
//Browse geopoints from DB, convert to GeoPoint and check if it is at a distance less than X
for (geoPointTemp in in query geopoint of your DDBB inside square) {
//create the location of the geopoint
Location locTemp=new Location("locTemp");
double latitude = geoPointTemp.getLatitudeE6() / 1E6;
double longitude = geoPointTemp.getLongitudeE6() / 1E6;
locTemp.setLatitude(latitude);
locTemp.setLongitude(longitude);
//calculate the distance between you and de temporary location
double distance=yourLocation.distanceTo(locTemp);
if(distance<X){
//do something
}

With Mysql, you can use built-in spacial functions such as GLength, linestring ....

Related

How to detect Nearst available lattitude and Longitude in Android App

I have data of associates with their Longitudes and Latitudes. I want to detect the nearest associate to the User Location. user location i will detect with the Android SDK.
My Question how to match the params in such a way that APP can show the best nearest associates. thanks in Advance.
Considering your list of associates is non-null array of lats longs.
LatLng GetNearest(LatLng myPos, LatLng[] Associates)
{
double nearestDistance = distance(myPos.lat, myPos.lng, Associates[0].lat,Associates[0].lng);
LatLng Nearest = Associates[0];
for(int i = 1; i < Associates.length(); i ++)
{
double _d = distance(myPos.lat, myPos.lng, Associates[i].lat, Associates[i].lng);
if(_d < nearestDistance)
{
nearestDistance = _d;
Nearest = Associates[i];
}
}
return Nearest;
}
/** calculates the distance between two locations in MILES */
private double distance(double lat1, double lng1, double lat2, double lng2) {
double earthRadius = 3958.75; // in miles, change to 6371 for kilometer output
double dLat = Math.toRadians(lat2-lat1);
double dLng = Math.toRadians(lng2-lng1);
double sindLat = Math.sin(dLat / 2);
double sindLng = Math.sin(dLng / 2);
double a = Math.pow(sindLat, 2) + Math.pow(sindLng, 2)
* Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2));
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double dist = earthRadius * c;
return dist; // output distance, in MILES
}
I assume you have a POJO of Associates, in which you have Longitudes and Latitudes for each of your associate, So let's say you have an Array of associates then to find the nearest to user location, use this short and simple logic :
for (Associates associate : associates) {
Double associateLatitude = associate.getLatitude();
Double associateLongitude = associate.getLongitude();
android.location.Location locationOne = new android.location.Location("");
locationOne.setLatitude(userLatitude);
locationOne.setLongitude(userLongitude);
android.location.Location locationTwo = new android.location.Location("");
locationTwo.setLongitude(associateLongitude);
locationTwo.setLatitude(associateLatitude);
float distance = locationOne.distanceTo(locationTwo);
if (disTemp == 0.0f) {
disTemp = distance;
nearestAssociate = associate;
} else if (disTemp > distance) {
disTemp = distance;
nearestAssociate = associate;
}
}

android - how can I get the bearing degree between two locations?

As title said, I have current location, and want to know the bearing in degree from my current location to other location. I have read this post, is the value return by location.getBearing() my answer?
Let say it simply: from the picture, I expect the value of 45 degree.
I was having trouble doing this and managed to figure it out converting the C? approach to working out the bearing degree.
I worked this out using 4 coordinate points
Start Latitude
Start Longitude
End Latitude
End Longitude
Here's the code:
protected double bearing(double startLat, double startLng, double endLat, double endLng){
double latitude1 = Math.toRadians(startLat);
double latitude2 = Math.toRadians(endLat);
double longDiff= Math.toRadians(endLng - startLng);
double y= Math.sin(longDiff)*Math.cos(latitude2);
double x=Math.cos(latitude1)*Math.sin(latitude2)-Math.sin(latitude1)*Math.cos(latitude2)*Math.cos(longDiff);
return (Math.toDegrees(Math.atan2(y, x))+360)%360;
}
Just change the variable names were needed.
Output bearing to a TextView
Hope it helped!
Location have method bearingTo:
float bearingTo(Location dest)
Location from = new Location(LocationManager.GPS_PROVIDER);
Location to = new Location(LocationManager.GPS_PROVIDER);
from.setLatitude(0);
from.setLongitude(0);
to.setLongitude(10);
to.setLatitude(10);
float bearingTo = from.bearingTo(to);
Here is the code for calculating bearing angle between two points(startPoint, endPoint):
public float CalculateBearingAngle(double startLatitude,double startLongitude, double endLatitude, double endLongitude){
double Phi1 = Math.toRadians(startLatitude);
double Phi2 = Math.toRadians(endLatitude);
double DeltaLambda = Math.toRadians(endLongitude - startLongitude);
double Theta = atan2((sin(DeltaLambda)*cos(Phi2)) , (cos(Phi1)*sin(Phi2) - sin(Phi1)*cos(Phi2)*cos(DeltaLambda)));
return (float)Math.toDegrees(Theta);
}
Call for function:
float angle = CalculateBearingAngle(startLatitude, startLongitude, endLatitude, endLongitude);
I found best method for calculating "Bearing between two point " from this answer and convert it to java from python. And this method work like charm for me!
here is the code:
public static double getBearing(double startLat, double startLng, double endLat, double endLng) {
double latitude1 = Math.toRadians(startLat);
double longitude1 = Math.toRadians(-startLng);
double latitude2 = Math.toRadians(endLat);
double longitude2 = Math.toRadians(-endLng);
double dLong = longitude2 - longitude1;
double dPhi = Math.log(Math.tan(latitude2 / 2.0 + Math.PI / 4.0) / Math.tan(latitude1 / 2.0 + Math.PI / 4.0));
if (abs(dLong) > Math.PI)
if (dLong > 0.0)
dLong = -(2.0 * Math.PI - dLong);
else
dLong = (2.0 * Math.PI + dLong);
return (Math.toDegrees(Math.atan2(dLong, dPhi)) + 360.0) % 360.0;
}

How can I calculate a current distance to polyline points on google maps v2 in android?

I have used tutorial from the link below to display Google map route in Android app. My question is how can I calculate distance to polyline points on map? Like when I use Google maps app and it tells when a street turn is getting close. I want to implement similar feature in my app. I am able to display the route polyline on the map and it updates itself while I drive along it but I want it to warn me 500 feet in advance of a coming turn. How can I do that?
Here is the link:
http://jigarlikes.wordpress.com/2013/04/26/driving-distance-and-travel-time-duration-between-two-locations-in-google-map-android-api-v2/
I use this method for Markers. Assuming you have Latitude and Longitude of the points that make up the Polyline this should do:
public class MapUtils {
public static float distBetween(LatLng pos1, LatLng pos2) {
return distBetween(pos1.latitude, pos1.longitude, pos2.latitude,
pos2.longitude);
}
/** distance in meters **/
public static float distBetween(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 (float) (dist * meterConversion);
}
}
To determine wether the road is turning, I would look into euclidean angle between vectors (x being current location and y being a polyline point)
Simply take your current location and a LatLng from some distance ahead for this.
Calculation is based on: http://en.wikipedia.org/wiki/Euclidean_space#Angle
Location currentLocation; // obtained somewhere in your code
LatLng polylinePoint; // a point further ahead
double cLat = currentLocation.getLatitude();
double cLon = currentLocation.getLongitude();
double pLat = polylinePoint.latitude;
double pLon = polylinePoint.longitude;
double angle = Math.acos(
(cLat*pLat+cLon+pLon) / norm(cLat,cLon)*norm(pLat,cLon));
private double norm(double x, double y) {
return Math.sqrt(Math.pow(x, 2)*Math.pow(y, 2));
}
This is untested so might contain error.

Creating a method using Haversine Formula, Android V2

I'm not really good with mathematics but I need to calculate the distance of two different locations of the markers. Something like this:
public double CalculationByDistance(double initialLat, double initialLong, double finalLat, double finalLong){
return distance;
}
Or is there any alternative ways that I can calculate the distance of two markers, also I tried to google for answers.. but couldn't find any.
Reference:
http://en.wikipedia.org/wiki/Haversine_formula
Comments are appreciated :) Thanks!!
Try this, much simpler than Haversine!
Location me = new Location("");
Location dest = new Location("");
me.setLatitude(myLat);
me.setLongitude(myLong);
dest.setLatitude(destLat);
dest.setLongitude(destLong);
float dist = me.distanceTo(dest);
If you want to stick with Haversine, something like this:
public double CalculationByDistance(double initialLat, double initialLong,
double finalLat, double finalLong){
int R = 6371; // km (Earth radius)
double dLat = toRadians(finalLat-initialLat);
double dLon = toRadians(finalLong-initialLong);
initialLat = toRadians(initialLat);
finalLat = toRadians(finalLat);
double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
Math.sin(dLon/2) * Math.sin(dLon/2) * Math.cos(initialLat) * Math.cos(finalLat);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
return R * c;
}
public double toRadians(double deg) {
return deg * (Math.PI/180);
}
Also, you need to create a method toRadians() that convert values from degrees to radians, which is quite easy.
Hope it helps!
From your wikipedia link, applying the formula directly you can do the following:
public double CalculationByDistance(double initialLat, double initialLong, double finalLat, double finalLong){
/*PRE: All the input values are in radians!*/
double latDiff = finalLat - initialLat;
double longDiff = finalLong - initialLong;
double earthRadius = 6371; //In Km if you want the distance in km
double distance = 2*earthRadius*Math.asin(Math.sqrt(Math.pow(Math.sin(latDiff/2.0),2)+Math.cos(initialLat)*Math.cos(finalLat)*Math.pow(Math.sin(longDiff/2),2)));
return distance;
}
Use the below method for calculating the distance of two different locations.
public double getKilometers(double lat1, double long1, double lat2, double long2) {
double PI_RAD = Math.PI / 180.0;
double phi1 = lat1 * PI_RAD;
double phi2 = lat2 * PI_RAD;
double lam1 = long1 * PI_RAD;
double lam2 = long2 * PI_RAD;
return 6371.01 * acos(sin(phi1) * sin(phi2) + cos(phi1) * cos(phi2) * cos(lam2 - lam1));
}
try this
/**
* This is the implementation Haversine Distance Algorithm between two places
* #author ananth
* R = earth’s radius (mean radius = 6,371km)
Δlat = lat2− lat1
Δlong = long2− long1
a = sin²(Δlat/2) + cos(lat1).cos(lat2).sin²(Δlong/2)
c = 2.atan2(√a, √(1−a))
d = R.c
*
*/
public class HaversineDistance {
/**
* #param args
* arg 1- latitude 1
* arg 2 — latitude 2
* arg 3 — longitude 1
* arg 4 — longitude 2
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
final int R = 6371; // Radious of the earth
Double lat1 = Double.parseDouble(args[0]);
Double lon1 = Double.parseDouble(args[1]);
Double lat2 = Double.parseDouble(args[2]);
Double lon2 = Double.parseDouble(args[3]);
Double latDistance = toRad(lat2-lat1);
Double lonDistance = toRad(lon2-lon1);
Double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2) +
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
Double distance = R * c;
System.out.println(“The distance between two lat and long is::” + distance);
}
private static Double toRad(Double value) {
return value * Math.PI / 180;
}
}

how to find the distance between two geopoints?

double distance;
Location locationA = new Location("point A");
locationA.setLatitude(latA);
locationA.setLongitude(lngA);
Location locationB = new Location("point B");
locationB.setLatitude(latB);
LocationB.setLongitude(lngB);
distance = locationA.distanceTo(locationB);
the above code is not working and i am getting 0.0 Km as distance?
Also in the constructor of the location class, what does the string provider mean.
In the above code i am using PointA and PointB as the providers.
why is the above code not working?
thank you in advance.
LOGCAT
05-09 17:48:56.144: INFO/current loc(1573): lat 0.0 lng 0.0
05-09 17:48:56.155: INFO/checklocation loc(1573): lat 54.4288665 lng 10.169366
Just a quick snippet since I didn't see a complete and simple solution with GeoPoints above:
public float getDistanceInMiles(GeoPoint p1, GeoPoint p2) {
double lat1 = ((double)p1.getLatitudeE6()) / 1e6;
double lng1 = ((double)p1.getLongitudeE6()) / 1e6;
double lat2 = ((double)p2.getLatitudeE6()) / 1e6;
double lng2 = ((double)p2.getLongitudeE6()) / 1e6;
float [] dist = new float[1];
Location.distanceBetween(lat1, lng1, lat2, lng2, dist);
return dist[0] * 0.000621371192f;
}
If you want meters, just return dist[0] directly.
Try Location.distanceBetween(..)
Update:
If you are getting lat/lon from GeoPoint then they are in microdegrees. You must multiply by 1e6.
As stated above, the Location Class is the way to go. Here is the code I have used :
Location locationA = new Location("point A");
locationA.setLatitude(pointA.getLatitudeE6() / 1E6);
locationA.setLongitude(pointA.getLongitudeE6() / 1E6);
Location locationB = new Location("point B");
locationB.setLatitude(pointB.getLatitudeE6() / 1E6);
locationB.setLongitude(pointB.getLongitudeE6() / 1E6);
double distance = locationA.distanceTo(locationB);
In this example, both pointA and pointB are instances of the GeoPoint class.
This is not an answer, but note the signature for the Location constructor is Location(String provider).
i.e. the String you pass to the constructor should be one of LocationManager.GPS_PROVIDER, LocationManager.NETWORK_PROVIDER or LocationManager.PASSIVE_PROVIDER, not "point A" and "point B".
An alternative way to accomplish the above,
public class Distance {
public static double distance(double lat1, double lon1, double lat2, double lon2) {
double theta = lon1 - lon2;
double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2))
+ Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
* Math.cos(deg2rad(theta));
dist = Math.acos(dist);
dist = rad2deg(dist);
dist = dist * 60 * 1.1515;
//if (unit == "K") {
// dist = dist * 1.609344;
// else if (unit == "N") {
//dist = dist * 0.8684;
//}
return (dist);
}
public static final double PI = 3.14159265;
public static final double deg2radians = PI/180.0;
public static double getDistance(double latitude1, double longitude1, double latitude2,double longitude2) {
double lat1 = latitude1 * deg2radians;
double lat2 = latitude2 * deg2radians;
double lon1 = longitude1 * deg2radians;
double lon2 = longitude2 * deg2radians;
// Williams gives two formulae;
// this is the more accurate for close distances.
// In practice, the two differed only in the 8th or 9th place, for
// separations as small as 1 degree.
double radd = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin((lat1 - lat2) / 2),
2.0)
+ Math.cos(lat1)
* Math.cos(lat2)
* Math.pow(Math.sin((lon1 - lon2) / 2), 2.0)));
return radd;
}
/* ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */
/* :: This function converts decimal degrees to radians : */
/* ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */
private static double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
/* ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */
/* :: This function converts radians to decimal degrees : */
/* ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: */
private static double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
}
double CalculateDistance( double nLat1, double nLon1, double nLat2, double nLon2 )
{
double nRadius = 6371; // Earth's radius in Kilometers
// Get the difference between our two points
// then convert the difference into radians
double nDLat = ToRad(nLat2 - nLat1);
double nDLon = ToRad(nLon2 - nLon1);
// Here is the new line
nLat1 = ToRad(nLat1);
nLat2 = ToRad(nLat2);
double nA = pow ( sin(nDLat/2), 2 ) + cos(nLat1) * cos(nLat2) * pow ( sin(nDLon/2), 2 );
double nC = 2 * atan2( sqrt(nA), sqrt( 1 - nA ));
double nD = nRadius * nC;
return nD; // Return our calculated distance
}
http://www.jaimerios.com/?p=39

Categories

Resources