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
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()
}
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.
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 ...
}
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;
}
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;
}