Getting locations near User's Location - android

I have an Array of longitude and latitude of landmarks.
How do i calculate the distance between the landmark and the user's location to get the landmarks which are for example in a 10km radius from the user's location

private static double distanceInKm(double lat1, double lon1, double lat2, double lon2) {
int R = 6371; // km
double x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
double y = (lat2 - lat1);
return (Math.sqrt(x * x + y * y) * R) / 1000;
}
Or
Location location1 = new Location("");
location1.setLatitude(latitude1);
location1.setLongitude(longitude1);
Location location2 = new Location("");
location2.setLatitude(latitude2);
location2.setLongitude(longitude2);
float distanceInKm = (location1.distanceTo(location2))/1000;

If you have the current location LatLong point then you can calculate the distance between to LatLongs using below code.
public float distance (float lat_a, float lng_a, float lat_b, float lng_b)
{
double earthRadius = 3958.75;
double latDiff = Math.toRadians(lat_b-lat_a);
double lngDiff = Math.toRadians(lng_b-lng_a);
double a = Math.sin(latDiff /2) * Math.sin(latDiff /2) +
Math.cos(Math.toRadians(lat_a)) * Math.cos(Math.toRadians(lat_b)) *
Math.sin(lngDiff /2) * Math.sin(lngDiff /2);
double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
double distance = earthRadius * c;
int meterConversion = 1609;
return new Float(distance * meterConversion).floatValue();
}

Related

How to calculate distance between two locations using their lat and long value and find the locations between those two point

fun getNewLatLongs(Double latitude, Double longitude,Float distance) Pair<Double, Double> {
double earth = 6378.137; // radius of earth in kms
double pi = Math.PI;
double m = 1 / (2 * pi / 360 * earth) / 1000; //1 meter in degree
double newLatitude = ("%.4f".format(latitude + distance * m)).toDouble();
val newLongitude =
("%.4f".format(longitude + distance * m / kotlin.math.cos(latitude * (pi / 180)))).toDouble();
return Pair(newLatitude, newLongitude);
}
You can easily get distance between two latitude and longitude using the below method
private 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;
return (dist);
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
You can get a middle point between two locations using the below method
private fun getCenterPointOfGivenLocation(startLatLng:LatLng , destinationLatLng:LatLng) :LatLng{
return LatLngBounds.builder().include(startLatLng).include(destinationLatLng).build().center
}
Try this
fun getDistanceBetween(
destinationLatitude: Double,
destinationLongitude: Double,
latitude: Double,
longitude: Double
): Int {
val locationA = Location("point A")
locationA.latitude = destinationLatitude
locationA.longitude = destinationLongitude
val locationB = Location("point B")
locationB.latitude = latitude
locationB.longitude = longitude
val distance = locationA.distanceTo(locationB)
return distance.toInt()
}

Android NaN on distance

So i am writing some code to calculate the miles driven based off the gps latitude and longitude store in an ArrayList, but for some reason randomly I get the NaN and I can't figure out why. Could someone please let me know what is wrong with my code or if there is a better way I should be doing it?
protected float calculateMiles()
{
float totalDistance = 0;
for(int i = 1; i < points.size(); i++) {
double lat = points.get(i).latitude;
double lng = points.get(i).longitude;
double lat2 = points.get(i-1).latitude;
double lng2 = points.get(i-1).longitude;
totalDistance += distance(lat, lng, lat2, lng2);
}
return totalDistance;
}
private 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;
return (dist);
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
I am also using the same points to draw a polyline and it works out just fine.
I suggest you use the Location.distanceBetween() method.
float[] result = new float[1];
Location.distanceBetween(lat, lng, lat2, lng2, result);
totalDistance += result[0];
The possibility you will get NaN is due to Longtitude or Latitude is null or empty. Please capture the log for all the gps latitude and longitude store in ArrayList.

Calculate nearest location Google Map Android Studio

I know how to find the distance between two location on android studio google map but how to calculate which distance is the nearest one compering with 3 or 4 found location?
public void onDirectionFinderSuccess(List<Route> routes) {
progressDialog.dismiss();
polylinePaths = new ArrayList<>();
originMarkers = new ArrayList<>();
destinationMarkers = new ArrayList<>();
for (Route route : routes) {
mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(route.startLocation, 16));
((TextView) findViewById(R.id.tvDuration)).setText(route.duration.text);
((TextView) findViewById(R.id.tvDistance)).setText(route.distance.text);
originMarkers.add(mMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.start_blue))
.title(route.startAddress)
.position(route.startLocation)));
destinationMarkers.add(mMap.addMarker(new MarkerOptions()
.icon(BitmapDescriptorFactory.fromResource(R.drawable.end_green))
.title(route.endAddress)
.position(route.endLocation)));
PolylineOptions polylineOptions = new PolylineOptions().
geodesic(true).
color(Color.BLUE).
width(10);
for (int i = 0; i < route.points.size(); i++)
polylineOptions.add(route.points.get(i));
polylinePaths.add(mMap.addPolyline(polylineOptions));
}
}
If you want to calculate the distance,you can calculate like this way
private double caldistance(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;
return (dist);
}
private double deg2rad(double deg) {
return (deg * Math.PI / 180.0);
}
private double rad2deg(double rad) {
return (rad * 180.0 / Math.PI);
}
Calculate the distance for all found locations and having smallest distance will be the nearest location.
public double distance(double lat1, double lat2, double lon1,
double lon2, double el1, double el2) {
final int R = 6371; // Radius of the earth
Double latDistance = Math.toRadians(lat2 - lat1);
Double lonDistance = Math.toRadians(lon2 - lon1);
Double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
+ Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(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 * 1000; // convert to meters
double height = el1 - el2;
distance = Math.pow(distance, 2) + Math.pow(height, 2);
return Math.sqrt(distance);
}
If you want to get all the nearest locations
Create two Locations like this:
Location source = new Location("");
Location destination = new Location("");
source.setLatitude(src_lat);
source.setLongitude(src_lng);
destination.setLatitude(dest_lat);
destination.setLongitude(dest_lng);
if(source.distanceTo(destination)<3000){ // 3000 meters = 3 km
// do something ...
}

intelligent calculating distance between two geo locations in android

Look at this example:
public void start(){
//...
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, TEN_SECONDS, TEN_METERS, this);
}
#Override
public void onLocationChanged(Location location) {
if(location.distanceTo(_lastLocation) > TEN_KM_IN_METERS){
actionA(location);
_lastLocation = location;
} else {
actionB(location);
}
}
The implementation of Location#distanceTo(l) is pretty complicated and CPU-intensive. So i don't want to call this operation on every location update.
Question: is it any proper way to avoid unnecessary Location#distanceTo(l) calls
What i tried so far. According Wiki - Decimal degrees i do it that way:
private boolean closeTogether(Location a, Location b) {
double changeLat = Math.abs(a.getLatitude() - b.getLatitude());
final float myNaiveMax = 0.005;
if (changeLat > myNaiveMax) {
return false;
}
double changeLon = Math.abs(a.getLongitude() - b.getLongitude());
if (changeLon > myNaiveMax) {
return false;
}
return true;
}
#Override
public void onLocationChanged(Location location) {
if(!closeTogether(location, _lastLocation) && location.distanceTo(_lastLocation) > TEN_KM_IN_METERS){
actionA(location);
_lastLocation = location;
} else {
actionB(location);
}
}
I've found that the Haversine formula is very good for this. Works well for my delivery tracking application. Here's how I calculate the distance between two points. Should get you started :)
/**
* getDistanceBetweenTwoPoints
* #param p1 - First point
* #param p2 - Second point
* #return distance between the two specified points (as the crow flys)
*/
public static double getDistanceBetweenTwoPoints(PointF p1, PointF p2) {
double R = 6371000; // Earth radius
double dLat = Math.toRadians(p2.x - p1.x);
double dLon = Math.toRadians(p2.y - p1.y);
double lat1 = Math.toRadians(p1.x);
double lat2 = Math.toRadians(p2.x);
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.atan2(Math.sqrt(a), Math.sqrt(1 - a));
double d = R * c;
return d;
}
Edit And another
public static PointF calculateDerivedPosition(PointF point,
double range, double bearing)
{
double EarthRadius = 6371000; // m
double latA = Math.toRadians(point.x);
double lonA = Math.toRadians(point.y);
double angularDistance = range / EarthRadius;
double trueCourse = Math.toRadians(bearing);
double lat = Math.asin(Math.sin(latA) * Math.cos(angularDistance) +
Math.cos(latA) * Math.sin(angularDistance) * Math.cos(trueCourse));
double dlon = Math.atan2(Math.sin(trueCourse) * Math.sin(angularDistance) * Math.cos(latA),
Math.cos(angularDistance) - Math.sin(latA) * Math.sin(lat));
double lon = ((lonA + dlon + Math.PI) % (Math.PI * 2)) - Math.PI;
lat = Math.toDegrees(lat);
lon = Math.toDegrees(lon);
PointF newPoint = new PointF((float) lat, (float) lon);
return newPoint;
}

How to show direction on map based on calculated angle in degrees

I have calculated angle between two Latitude and Longitude coordinates as below code.It returns angle as 3 in radians, and 193 in degrees. I want to show arrow marker on map based on this angle.How to display object direction moved,based on this angle?
public static double getAngle(double lat1, double lon1, double lat2, double lon2)
{
//Formulas
//θ = atan2( sin(Δlong).cos(lat2),cos(lat1).sin(lat2) − sin(lat1).cos(lat2).cos(Δlong) )
// Δlong = long2 - long1
Log.i("angle", "Inside getAngle");
double latitude1 = Math.toRadians(lat1);
double longitude1 = Math.toRadians(lon1);
double latitude2 = Math.toRadians(lat2);
double longitude2 = Math.toRadians(lon2);
double dlong = Math.toRadians(longitude2-longitude1);
double y = Math.sin(dlong) * Math.cos(latitude2);
double x = Math.cos(latitude1)*Math.sin(latitude2) - Math.sin(latitude1)*Math.cos(latitude2)*Math.cos(dlong);
double angle= Math.atan2(y, x);
if (angle < 0)
angle = Math.abs(angle);
else
angle = 2*Math.PI - angle;
Log.i("angle", String.valueOf(angle)+" in radians");
angle=Math.toDegrees(angle);
Log.i("angle", String.valueOf(angle)+" in degrees");
return angle;
}
I got angle and rotate arrow image on same angle on Map.This makes like direction of Route.
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
/* inside for loop of all Latitude Longitude values */
float angle=(float)finalBearing(previousLocationLatitude, previousLocationLongitude, currentLocationLatitude, currentLocationLongitude);
Bitmap sprite = BitmapFactory.decodeResource(this.getResources(),R.drawable.dir_green_image);
Matrix mat = new Matrix();
mat.preRotate(angle);///in degree
Bitmap mBitmap = Bitmap.createBitmap(sprite, 0, 0, sprite.getWidth(), sprite.getHeight(), mat, true);
mMap.addMarker(new MarkerOptions().position(new LatLng(currentLocationLatitude, currentLocationLongitude)).icon(BitmapDescriptorFactory.fromBitmap(mBitmap)).anchor((float)0.5, (float)0.5));
/* inside for loop of all Latitude Longitude values */
static public double initialBearing (double lat1, double long1, double lat2, double long2)
{
return (_bearing(lat1, long1, lat2, long2) + 360.0) % 360;
}
static public double finalBearing(double lat1, double long1, double lat2, double long2)
{
return (_bearing(lat2, long2, lat1, long1) + 180.0) % 360;
}
static private double _bearing(double lat1, double long1, double lat2, double long2)
{
double degToRad = Math.PI / 180.0;
double phi1 = lat1 * degToRad;
double phi2 = lat2 * degToRad;
double lam1 = long1 * degToRad;
double lam2 = long2 * degToRad;
return Math.atan2(Math.sin(lam2-lam1)*Math.cos(phi2),
Math.cos(phi1)*Math.sin(phi2) - Math.sin(phi1)*Math.cos(phi2)*Math.cos(lam2-lam1)
) * 180/Math.PI;
}

Categories

Resources