I need to calculate distance between current location and the destination. I have the latitude and longitude of current and destination locations. I found the below code from SO and internet while searching. But the calculation give 1366 km while the google maps gives 1675 km between 2 locations. Can someone help how can I calculate accurate distance. The destinations are world wide including my current city locations.
//Distance in Kilometers
fun distanceInKms ( lat1: Double, long1: Double, lat2: Double, long2: Double) : Double
{
val degToRad= Math.PI / 180.0;
val phi1 = lat1 * degToRad;
val phi2 = lat2 * degToRad;
val lam1 = long1 * degToRad;
val lam2 = long2 * degToRad;
return 6371.01 * Math.acos( Math.sin(phi1) * Math.sin(phi2) + Math.cos(phi1) * Math.cos(phi2) * Math.cos(lam2 - lam1) );
}
Can someone help me out with this please?
Use the android.location.Location class, available since API level 1 in Android. It has a static distanceBetween method doing it all for you.
See:
http://developer.android.com/reference/android/location/Location.html
float[] results = new float[1];
android.location.Location.distanceBetween(startLatitude, startLongitude, endLatitude, endLongitude, results);
//distance in meters now in results[0]
Divide by 1000 to get it in kilometers (km).
you can use it , it get like google don't forgot to add internet permission
String getDistanceOnRoad(double latitude, double longitude,
double prelatitute, double prelongitude) {
String result_in_kms = "";
String url = "http://maps.google.com/maps/api/directions/xml? origin="
+ latitude + "," + longitude + "&destination=" + prelatitute
+ "," + prelongitude + "&mode=driving&sensor=false&units=metric";
String tag[] = { "text" };
HttpResponse response = null;
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
response = httpClient.execute(httpPost, localContext);
InputStream is = response.getEntity().getContent();
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = builder.parse(is);
if (doc != null) {
NodeList nl;
ArrayList<String> args = new ArrayList<String>();
for (String s : tag) {
nl = doc.getElementsByTagName(s);
if (nl.getLength() > 0) {
Node node = nl.item(nl.getLength() - 1);
args.add(node.getTextContent());
} else {
args.add(" - ");
}
}
result_in_kms = String.format("%s", args.get(0));
}
} catch (Exception e) {
e.printStackTrace();
}
return result_in_kms;
}
this library have class to get time, distance and draw polyline between 2 places it work like google map
https://github.com/memo1231014/MUT-master
Example for the library
RouteInformations rInformation = new RouteInformations(new AsyncResponse() {
#Override
public void processFinish(RouteDetails arg0) {
// TODO Auto-generated method stub
try
{
map.addPolyline(arg0.getLineOptions()); //you can add the return line and add it to the map
//here you can get distance , duration it will return like you drive a car
MUT.fastDialog(Map.this,"Time and Distance","Distance : "+arg0.getDistance()+"\nDuration : "+arg0.getDuration());
}
catch(Exception e)
{
MUT.lToast(Map.this,"Can't draw line Try Again");
}
}
});
//you should pass the 2 lat and lang which you want to draw a aline or get distance or duration between them
RouteDetails routeDetails=new RouteDetails();
routeDetails.setLatLong1(from.getPosition());
routeDetails.setLatLong2(to.getPosition());
rInformation.execute(routeDetails);
Related
In my app user can insert multiple location and show in map. How can i achieve this? I know how to draw route between two location but i want to draw route between multiple marker as like image.
In image marker show location that is entered by user. I also want to calculate distance between marker like calculate distance between B to C and C to D.
How can I achieve this??
Use direction api which return multi-part directions using a series of waypoints.
Direction api Documentation
private static final LatLng LOWER_MANHATTAN = new LatLng(40.722543,-73.998585);
private static final LatLng BROOKLYN_BRIDGE = new LatLng(40.7057, -73.9964);
private static final LatLng WALL_STREET = new LatLng(40.7064, -74.0094);
private String getMapsApiDirectionsUrl() {
String origin = "origin=" + LOWER_MANHATTAN.latitude + "," + LOWER_MANHATTAN.longitude;
String waypoints = "waypoints=optimize:true|" + BROOKLYN_BRIDGE.latitude + "," + BROOKLYN_BRIDGE.longitude + "|";
String destination = "destination=" + WALL_STREET.latitude + "," + WALL_STREET.longitude;
String sensor = "sensor=false";
String params = origin + "&" + waypoints + "&" + destination + "&" + sensor;
String output = "json";
String url = "https://maps.googleapis.com/maps/api/directions/"
+ output + "?" + params;
return url;
}
}
When you get response from above request . you need to draw route from response
public void drawRoute(String result) {
try {
//Tranform the string into a json object
final JSONObject json = new JSONObject(result);
JSONArray routeArray = json.getJSONArray("routes");
JSONObject routes = routeArray.getJSONObject(0);
JSONObject overviewPolylines = routes.getJSONObject("overview_polyline");
String encodedString = overviewPolylines.getString("points");
List<LatLng> list = decodePoly(encodedString);
Polyline line = mMap.addPolyline(new PolylineOptions()
.addAll(list)
.width(12)
.color(Color.parseColor("#05b1fb"))//Google maps blue color
.geodesic(true)
);
} catch (JSONException e) {
}
}
You will get more detail of this from Draw-route-github
For Distance calculation you need to Distance Matrix API is a service that provides travel distance and time for a matrix of origins and destinations
Using direction api you can achieve this.
you just have to pass user inserted marker as waypoints as follow
https://maps.googleapis.com/maps/api/directions/json?
origin=sydney,au&destination=perth,au
&waypoints=via:-37.81223%2C144.96254%7Cvia:-34.92788%2C138.60008
&key=YOUR_API_KEY
you will get list of route which have the distance between to points
//retrofit
#GET("https://maps.googleapis.com/maps/api/directions/json")
Observable<DirectionResults> getDirectionWithWayPoints(#Query("origin") String origin, #Query("destination") String destination, #Query("waypoints") String wayPoints, #Query("key") String key);
// plotting logic
api.getDirectionWithWayPoints(startPoint, endPoint, stringBuilder.toString(), getString(R.string.API_KEY))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribeWith(new Observer<DirectionResults>() {
#Override
public void onSubscribe(Disposable d) {
}
#Override
public void onNext(DirectionResults directionResults) {
hideDialog();
if (null == directionResults) {
return;
}
ArrayList<LatLng> routelist = new ArrayList<>();
routelist.add(latLngStart);
if (directionResults.getRoutes().size() > 0) {
List<LatLng> decodelist;
RoutesItem routeA = directionResults.getRoutes().get(0);
if (routeA.getLegs().size() > 0) {
for (int j = 0; j < routeA.getLegs().size(); j++) {
List<StepsItem> steps = routeA.getLegs().get(j).getSteps();
StepsItem step;
Location location;
String polyline;
for (int i = 0; i < steps.size(); i++) {
step = steps.get(i);
polyline = step.getPolyline().getPoints();
decodelist = DirectionsJSONParser.decodePoly(polyline);
routelist.addAll(decodelist);
}
}
}
}
if (routelist.size() > 0) {
routelist.add(latLngEnd);
rectLine = new PolylineOptions().width(12).color(
Color.CYAN);
for (int i = 0; i < routelist.size(); i++) {
rectLine.add(routelist.get(i));
}
// Adding route on the map
if (null != mMap) {
mMap.addPolyline(rectLine);
fixZoom(rectLine, mMap);
getVehicleId();
}
}
}
#Override
public void onError(Throwable e) {
hideDialog();
e.printStackTrace();
}
#Override
public void onComplete() {
}
});
}
}
Google provides libraries out of the box for solving this kind of issues.
I would structure my application in following manner.
Use Retrofit 2 for connecting to network. (https://square.github.io/retrofit/)
Use google API's, you will need more than 1 API to achieve both of the tasks.
2.a To find out distances between two points use Google Distance Matrix API (https://developers.google.com/maps/documentation/distance-matrix/start).
2.b To add multiple markers you can refer to following answer
Google Maps JS API v3 - Simple Multiple Marker Example
For draw route you can use :
PolylineOptions options = new
PolylineOptions().width(5).color(Color.BLUE).geodesic(true);
for (int z = 0; z < list.size(); z++) {
LatLng point = list.get(z);
options.add(point);
}
line = myMap.addPolyline(options);
And calculating distance for usimg **Google Maps Direction API**
I am using the following code the fetching the distance between difference latitude and longitude.Some time it works fine but some time it return the 0.0. I can't understand the reason why it happen. I have enable both GPS and Network
My code is..
public static String getDistanceOnRoad(String latitude, String longitude,
String prelatitute, String prelongitude) {
String result_in_kms = "";
float num_in_Km=0;
String url = "http://maps.google.com/maps/api/directions/xml?origin="
+ latitude + "," + longitude + "&destination=" + prelatitute
+ "," + prelongitude + "&sensor=false&units=metric";
String tag[] = { "text" };
HttpResponse response = null;
try {
HttpClient httpClient = new DefaultHttpClient();
HttpContext localContext = new BasicHttpContext();
HttpPost httpPost = new HttpPost(url);
response = httpClient.execute(httpPost, localContext);
InputStream is = response.getEntity().getContent();
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document doc = builder.parse(is);
if (doc != null) {
NodeList nl;
ArrayList args = new ArrayList();
for (String s : tag) {
nl = doc.getElementsByTagName(s);
if (nl.getLength() > 0) {
Node node = nl.item(nl.getLength() - 1);
args.add(node.getTextContent());
} else {
args.add(" - ");
}
}
result_in_kms = String.format("%s", args.get(0));
//result come with 'm' and 'km' tag so remove this tag
String num=stripNonDigits(result_in_kms);
//if result in KM then does not devide by 1000
if(!isdisIn_M_or_KM(result_in_kms)){
num_in_Km=Float.valueOf(num)/1000;
}
else num_in_Km=Float.valueOf(num);
Log.i("", "");
}
} catch (Exception e) {
e.printStackTrace();
}
return String.valueOf(num_in_Km);
}
For Finding the distance using GPS, There is no Need of Network Connection. GPS will provide the Latitude and Longitude based on the the time interval you apply.
kindly refer the below link
Calculate distance between two latitude-longitude points? (Haversine formula)
From my application I can open gallery. Is there any way to get latitude and longitude of any selected image in gallery to my application?
You can actually use a "buildin" function:
ExifInterface exif = new ExifInterface(path);
float[] latLong = new float[2];
boolean hasLatLong = exif.getLatLong(latLong)
if (hasLatLong) {
System.out.println("Latitude: " + latLong[0]);
System.out.println("Longitude: " + latLong[1]);
}
Maybe is something new, but I think is much more convenient than the accepted answer.
You Should Go with ExifInterface class to read various EXIF metadata from Images:
Example :
ExifInterface exif = new ExifInterface(filepath);
exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
Edited :
Now Here you will get lat-long as Below format.
lat = 30/1,12/1,34/1,
long=81/1,22/1,41/1
To Convert this into Real Values this Blog Helped Me.
we need to do conversion from degree, minute, second form to GeoPoint form.
By Below Way you can Do it.
String LATITUDE = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE);
String LATITUDE_REF = exif.getAttribute(ExifInterface.TAG_GPS_LATITUDE_REF);
String LONGITUDE = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE);
String LONGITUDE_REF = exif.getAttribute(ExifInterface.TAG_GPS_LONGITUDE_REF);
// your Final lat Long Values
Float Latitude, Longitude;
if((LATITUDE !=null)
&& (LATITUDE_REF !=null)
&& (LONGITUDE != null)
&& (LONGITUDE_REF !=null))
{
if(LATITUDE_REF.equals("N")){
Latitude = convertToDegree(LATITUDE);
}
else{
Latitude = 0 - convertToDegree(LATITUDE);
}
if(LONGITUDE_REF.equals("E")){
Longitude = convertToDegree(LONGITUDE);
}
else{
Longitude = 0 - convertToDegree(LONGITUDE);
}
}
private Float convertToDegree(String stringDMS){
Float result = null;
String[] DMS = stringDMS.split(",", 3);
String[] stringD = DMS[0].split("/", 2);
Double D0 = new Double(stringD[0]);
Double D1 = new Double(stringD[1]);
Double FloatD = D0/D1;
String[] stringM = DMS[1].split("/", 2);
Double M0 = new Double(stringM[0]);
Double M1 = new Double(stringM[1]);
Double FloatM = M0/M1;
String[] stringS = DMS[2].split("/", 2);
Double S0 = new Double(stringS[0]);
Double S1 = new Double(stringS[1]);
Double FloatS = S0/S1;
result = new Float(FloatD + (FloatM/60) + (FloatS/3600));
return result;
};
#Override
public String toString() {
// TODO Auto-generated method stub
return (String.valueOf(Latitude)
+ ", "
+ String.valueOf(Longitude));
}
public int getLatitudeE6(){
return (int)(Latitude*1000000);
}
public int getLongitudeE6(){
return (int)(Longitude*1000000);
}
the exif.getLatLong(float[]) is now deprecated, you can use a better method which returns a double[] :
ExifInterface exifInterface = new ExifInterface(file);
double[] latlng = exifInterface.getLatLong();
if (latlng != null) {
Double currentLatitude = latlng[0];
Double currentLongitude = latlng[1];
Log.d("Debug", "Exif : latitude: " + currentLatitude + ", longitude: " + currentLongitude)
}
Happy coding.
I use distanceBetween() of Location class to calculate the distance between two points as follows:
private 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];
Log.i("destination coordinates", "Latitude:" + lat2 + ", Longitude: " + lng2);
Location.distanceBetween(lat1, lng1, lat2, lng2, dist);
return dist[0] * 0.000621371192f;
}
Documentation says that distanceBetween() "Computes the approximate distance in meters between two locations, and optionally the initial and final bearings of the shortest path between them." However the difference between the result returned by distanceBetween() and real GPS device or Google Navigation app is pretty big. For example my method will return 6.2 miles while google maps shows 10 miles for the same location. I double check the coordinates of the starting point p1 and ending point p2 and they seems to be correct. Is that how distanceBetween() method works or Am I doing something wrong? And by the way Is there a way to use Google Place API to retrieve a distance as a JSON response?
Distance calculated by Google Maps: 6.1 miles
And the result of
Location.distanceBetween(41.742964, -87.995971, 41.811511, -87.967923, dist) is
4.947700
Google Navigation generally reports driving or walking distance along the set of steps in the directions list, not straight-line distance, which is what distanceBetween() reports.
To get a distance from a Google Maps I have used Google Directions API
and JSON parser to retrieve the distance value:
private double getDistanceInfo(double lat1, double lng1, String destinationAddress) {
StringBuilder stringBuilder = new StringBuilder();
Double dist = 0.0;
try {
destinationAddress = destinationAddress.replaceAll(" ","%20");
String url = "http://maps.googleapis.com/maps/api/directions/json?origin=" + lat1 + "," + lng1 + "&destination=" + destinationAddress + "&mode=driving&sensor=false";
HttpPost httppost = new HttpPost(url);
HttpClient client = new DefaultHttpClient();
HttpResponse response;
stringBuilder = new StringBuilder();
response = client.execute(httppost);
HttpEntity entity = response.getEntity();
InputStream stream = entity.getContent();
int b;
while ((b = stream.read()) != -1) {
stringBuilder.append((char) b);
}
} catch (ClientProtocolException e) {
} catch (IOException e) {
}
JSONObject jsonObject = new JSONObject();
try {
jsonObject = new JSONObject(stringBuilder.toString());
JSONArray array = jsonObject.getJSONArray("routes");
JSONObject routes = array.getJSONObject(0);
JSONArray legs = routes.getJSONArray("legs");
JSONObject steps = legs.getJSONObject(0);
JSONObject distance = steps.getJSONObject("distance");
Log.i("Distance", distance.toString());
dist = Double.parseDouble(distance.getString("text").replaceAll("[^\\.0123456789]","") );
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return dist;
}
Just now I've purchased Google API Key. I've find the exact place by using google Places. The most important thing is I've to find the place programmatically which means that When I open my application it will display the place in a textview. Also i want to find the nearest places.
Can anyone please explain with a complete sample code (in java, not java script code)
You can use following code for Google places Api
Here i have search airports but you can search your own places and when you find
here getJsonResponse id your httpclient
String url = "https://maps.googleapis.com/maps/api/place/textsearch/json?query="**Place To Search**"&sensor=true&key=**Your Api Key**";
String res = getJsonRespose(url);
if (res != null && !res.equalsIgnoreCase("")) {
JSONObject jObject = new JSONObject(res);
// if (jObject.getString("status").equalsIgnoreCase("ok")) {
JSONArray jArray = jObject.getJSONArray("results");
if (jArray.length() > 0) {
for (int i = 0; i < jArray.length(); i++) {
AirportListData adata = new AirportListData();
JSONObject geo = jArray.getJSONObject(i);
JSONObject jLocation = geo.getJSONObject("geometry");
JSONObject jgetLocation = jLocation
.getJSONObject("location");
Address = geo.getString("formatted_address");
name = geo.getString("name");
adata.setAirportName(name);
lat = jgetLocation.getDouble("lat");
lng = jgetLocation.getDouble("lng");
adata.setLat(lat);
adata.setLng(lng);
double dis = getDistance(lat, lng);
adata.setAddress(Address);
adata.setDistnace(dis / 1000);
ardata.add(adata);
Log.e("address", "Distance" + (dis / 1000) + "Address"
+ Address + "name" + name + "lat" + lat + "lng"
+ lng);
}
}
}
When You got All places you can Call getDistance Method and find distance between your current place and places you got and after calculating that you got nearest place
public static double getDistance(double lat, double lng) {
try {
float[] result = new float[3];
// Log.e("lat long : ", c.getDouble(1) + " : " + c.getDouble(2) +
// " : " + latitude + " : " + longitude);
Location.distanceBetween(Constantdata.lat, Constantdata.lon, lat,
lng, result);
double distance = ((double) result[0]);
return distance;
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return 0.0;
}
Here Constantdata.lat and constant.lon is your current latitude and longitude and lat long is places latitude and logitude that you got