I'm trying to calculate distance between LatLng points. It's easy to calculate for two coordinates. I have to calculate distance between more than two LatLngs and calculate the cumulative distance from a set of LatLngs. I calculated distance between two points as per the following code.
tvDistance=(TextView)findViewById(R.id.textView4);
Location loc1=new Location("");
loc1.setLatitude(11.2805);
loc1.setLongitude(77.5989);
Location loc2=new Location("");
loc2.setLatitude(11.2801);
loc2.setLongitude(77.5976);
DecimalFormat format=new DecimalFormat("#.##");
double distanceInMeters = loc1.distanceTo(loc2)/1000;
tvDistance.setText(format.format(distanceInMeters) + " Km's");
Now I have for example sixteen LatLng points. First is starting place and last is stopping place. I have the LatLngs in a ArrayList. tried the following code. But it caused ArrayIndexOutOfBoundException.
Do anybody know a method please share with me. Thanks.
private void calculateDistance() {
for (int i=0;i<coordList.size();i++){
LatLng l1=coordList.get(i);
double lat1=l1.latitude;
double lng1=l1.longitude;
Location location1=new Location("");
location1.setLatitude(lat1);
location1.setLongitude(lng1);
LatLng l2=coordList.get(i+1);
double lat2=l2.latitude;
double lng2=l2.longitude;
Location location2=new Location("");
location2.setLatitude(lat2);
location2.setLongitude(lng2);
DecimalFormat format=new DecimalFormat("#.##");
double distance=location1.distanceTo(location2)/1000;
Toast.makeText(MainPage.this,format.format(distance) + " Km's",Toast.LENGTH_SHORT).show();
}
}
You can use SphericalUtil.computeLength method:
http://googlemaps.github.io/android-maps-utils/javadoc/com/google/maps/android/SphericalUtil.html#computeLength-java.util.List-
Sources: https://github.com/googlemaps/android-maps-utils/blob/master/library/src/com/google/maps/android/SphericalUtil.java
The line
LatLng l2=coordList.get(i+1);
causes the exception.
jon
->Its easy to calculate the distance if you have sets of latitudes and longitudes
ArrayList<RideRoutes> ride_route_list = new ArrayList<>();
//suppose "ride_route_list" contains collections of Latitudes and longitudes
String distance_covered_str;
double total_meters = 0.0;
for(int i = 0; i < (ride_route_list.size() - 1); i++){
double previous_latitude = Double.parseDouble(ride_route_list.get(i).getRout_latitude());
double previous_longitude = Double.parseDouble(ride_route_list.get(i).getRout_longitude());
double updated_latitude = Double.parseDouble(ride_route_list.get(i+1).getRout_latitude());
double updated_longitude = Double.parseDouble(ride_route_list.get(i+1).getRout_longitude());
Location start_latlng = new Location("location_previous");
start_latlng.setLatitude(previous_latitude);
start_latlng.setLongitude(previous_longitude);
Location end_latlng = new Location("location_updated");
end_latlng.setLatitude(updated_latitude);
end_latlng.setLongitude(updated_longitude);
total_meters += start_latlng.distanceTo(end_latlng);
}
double distance_covered_km = total_meters / 1000;
distance_covered_str = String.format(Locale.getDefault(), "%.2f", distance_covered_km);
Note:
->here ride_route_list is an ArrayList which contains the list of Latitude and longitude
RideRoutes Class Structure:
public class RideRoutes {
private String rout_latitude;
private String rout_longitude;
public RideRoutes(String rout_latitude, String rout_longitude) {
this.rout_latitude = rout_latitude;
this.rout_longitude = rout_longitude;
}
public String getRout_latitude() {
return rout_latitude;
}
public void setRout_latitude(String rout_latitude) {
this.rout_latitude = rout_latitude;
}
public String getRout_longitude() {
return rout_longitude;
}
public void setRout_longitude(String rout_longitude) {
this.rout_longitude = rout_longitude;
}
}
Related
I wrote this method to determine a distance to a destination along a path and also to determine a distance to the next waypoint along that path. The problem is, sometimes I don't go within 10 meters of the waypoint so it's not getting caught as having been reached. Sure, I could increase the threshold of distance that would make the waypoint met, but I'd rather come up with another solution to determine if I've passed that waypoint and just skip it (by adding it to the waypointsReached list) to move on to the next one. Checking to see if the distance from my location to the waypoint is increasing instead of decreasing won't work because I may stray off the path before I even get to the waypoint.
Can anyone help me wrap my head around an idea of a way I can determine if I've just passed the waypoint and move on to the next one?
Here's the method I've written to get my distance to the final destination and to the next waypoint.
// method to calculate distance to destinatoin from a loaded route
private void CalculateRouteToDestination(Location location) {
new AsyncTask<Location, Void, ArrayList<Double>>(){
#Override
protected ArrayList<Double> doInBackground(Location... params) {
ArrayList<Double> distances = new ArrayList<Double>();
Location location = params[0];
//predefinedRoutePoints
int closestLocationIndex = 0;
double smallestDistance = -1;
int cnt = 0;
for(LatLng ltlg : predefinedRoutePoints) {
// create new location object for the latlng coords
Location cLocation = new Location("");
cLocation.setLatitude(ltlg.latitude);
cLocation.setLongitude(ltlg.longitude);
// get the distance from current location to all of the points in the array and set the index from the array where it is
double cDistance = location.distanceTo(cLocation);
if(smallestDistance == -1 || cDistance < smallestDistance) {
closestLocationIndex = cnt;
smallestDistance = cDistance;
}
cnt++;
}
// now with the index from the array of the cloest point, calculate the distance to the last point in the array from that index (distance to destination)
double distanceToDestination = 0;
for(int i = closestLocationIndex; i < predefinedRoutePoints.size(); i++) {
//Log.d("home","iteration:"+i);
if(i != (predefinedRoutePoints.size() -1)) {
Location l1 = new Location("");
l1.setLatitude(predefinedRoutePoints.get(i).latitude);
l1.setLongitude(predefinedRoutePoints.get(i).longitude);
Location l2 = new Location("");
l2.setLatitude(predefinedRoutePoints.get(i+1).latitude);
l2.setLongitude(predefinedRoutePoints.get(i+1).longitude);
distanceToDestination += l1.distanceTo(l2);
}
}
// now add the distance the user is to the cloest point to get the final output of distance to destinatoin
distanceToDestination += smallestDistance;
distances.add(distanceToDestination);
// check if need to measure distance to next waypoint
double distanceToNextWaypoint = 0;
if(predefinedWaypoints.size() > 0){
if(predefinedWaypoints.size() != waypointsReached.size()) {
for (int i = closestLocationIndex; i < predefinedWaypoints.get(waypointsReached.size()).WaypointIndex; i++) {
Location l1 = new Location("");
l1.setLatitude(predefinedRoutePoints.get(i).latitude);
l1.setLongitude(predefinedRoutePoints.get(i).longitude);
Location l2 = new Location("");
l2.setLatitude(predefinedRoutePoints.get(i + 1).latitude);
l2.setLongitude(predefinedRoutePoints.get(i + 1).longitude);
distanceToNextWaypoint += l1.distanceTo(l2);
}
distanceToNextWaypoint += smallestDistance;
if(distanceToNextWaypoint < 10) {
waypointsReached.add(predefinedWaypoints.get(waypointsReached.size()));
}
distances.add(distanceToNextWaypoint);
}
}
return distances;
}
#Override
protected void onPostExecute(ArrayList<Double> v) {
distanceToDestinationText.setText("Destination To Destination: "+Utilities.GetMiles(v.get(0))+"mi");
if(v.size() > 1) {
distanceToNextWaypoint.setText("Next Waypoint: "+Utilities.GetMiles(v.get(1))+"mi");
} else {
distanceToNextWaypoint.setVisibility(View.GONE);
distanceToNextWaypoint.setText("Next Waypoint: 0.0mi");
}
}
}.execute(location);
}
I am implementing animation in google map using this example. I am getting LatLng data from a server. But the problem arises when I get too many data for a single point on map. The animated marker wait on a single point so long as there are data for that point. Please see the following sample code
for (i = 0; i < jsonAssets.length(); i++) {
JSONObject nlmJsonObject = jsonAssets.getJSONObject(i);
JSONObject lastData_JsonObject = nlmJsonObject.getJSONObject("last_data");
JSONObject nlm_locJsonObject = lastData_JsonObject.getJSONObject("loc");
JSONArray coordinated = nlm_locJsonObject.getJSONArray("coordinates");
Log.d("LASTLATLONG_ANIMATION", coordinated.toString());
latt = (double) coordinated.get(0);
lng = (double) coordinated.get(1);
addMarkerToMap(new LatLng(lng, latt));
}
animator.startAnimation(true);
How can I check and omit similar points to make my map animation smoother?
Thanks
Just edited your code, to give the idea
private double latt;
private double lng;
private void showMarkers(){
// Your other codes
for (i = 0; i < jsonAssets.length(); i++) {
JSONObject nlmJsonObject = jsonAssets.getJSONObject(i);
JSONObject lastData_JsonObject = nlmJsonObject.getJSONObject("last_data");
JSONObject nlm_locJsonObject = lastData_JsonObject.getJSONObject("loc");
JSONArray coordinated = nlm_locJsonObject.getJSONArray("coordinates");
Log.d("LASTLATLONG_ANIMATION", coordinated.toString());
// Current values
double currentLat = (double) coordinated.get(0);
double currentLng = (double) coordinated.get(1);
// Compare. If not same add the marker
if(currentLat != latt && currentLng != lng){
latt = (double) coordinated.get(0);
lng = (double) coordinated.get(1);
addMarkerToMap(new LatLng(lng, latt));
}
}
animator.startAnimation(true);
}
The best option is to add a new marker only when it's location is farther than a given distance to the last marker added.
My example uses the SphericalUtil.computeDistanceBetween from the Google Maps API Utility Library to compute the distance betwen two LatLng objects:
final float MIN_DISTANCE = 10; // Minimum distance in meters to consider that two locations are the same
LatLng lastLatLng = null;
// ...
for (i = 0; i < jsonAssets.length(); i++) {
JSONObject nlmJsonObject = jsonAssets.getJSONObject(i);
JSONObject lastData_JsonObject = nlmJsonObject.getJSONObject("last_data");
JSONObject nlm_locJsonObject = lastData_JsonObject.getJSONObject("loc");
JSONArray coordinated = nlm_locJsonObject.getJSONArray("coordinates");
Log.d("LASTLATLONG_ANIMATION", coordinated.toString());
latt = (double) coordinated.get(0);
lng = (double) coordinated.get(1);
LatLng currentLatLng = new LatLng(latt, lng);
if (lastLatLng == null || SphericalUtil.computeDistanceBetween(lastLatLng, currentLatLng) > MIN_DISTANCE) {
addMarkerToMap(new LatLng(lng, latt));
lastLatLng = currentLatLng;
}
}
animator.startAnimation(true);
I have a "Place" object with a LatLng coordinate for each:
import com.google.android.gms.maps.model.LatLng;
public class Place{
public String name;
public LatLng latlng;
public Restaurant(String name, LatLng latlng) {
this.name = name;
this.latlng = latlng;
}
}
and I have an ArrayList of these Places, something like this:
ArrayList<Place> places = new ArrayList<Place>();
places.add("Place 1", LatLng(90.0,90.0));
places.add("Place 2", LatLng(93.0,93.0));
places.add("Place 3", LatLng(83.0,92.0));
places.add("Place 4", LatLng(93.0,91.0));
and I have "my" LatLng:
LatLng myLocation = new LatLng(10.0,10.0);
How can I sort these objects according to closest to me? Thanks for the help
Taking the algorithm from this answer from the question posted by #shieldstroy, that uses the Great Circle Distance, I got this example working.
Here is the Comparator:
public class SortPlaces implements Comparator<Place> {
LatLng currentLoc;
public SortPlaces(LatLng current){
currentLoc = current;
}
#Override
public int compare(final Place place1, final Place place2) {
double lat1 = place1.latlng.latitude;
double lon1 = place1.latlng.longitude;
double lat2 = place2.latlng.latitude;
double lon2 = place2.latlng.longitude;
double distanceToPlace1 = distance(currentLoc.latitude, currentLoc.longitude, lat1, lon1);
double distanceToPlace2 = distance(currentLoc.latitude, currentLoc.longitude, lat2, lon2);
return (int) (distanceToPlace1 - distanceToPlace2);
}
public double distance(double fromLat, double fromLon, double toLat, double toLon) {
double radius = 6378137; // approximate Earth radius, *in meters*
double deltaLat = toLat - fromLat;
double deltaLon = toLon - fromLon;
double angle = 2 * Math.asin( Math.sqrt(
Math.pow(Math.sin(deltaLat/2), 2) +
Math.cos(fromLat) * Math.cos(toLat) *
Math.pow(Math.sin(deltaLon/2), 2) ) );
return radius * angle;
}
}
Here is the high level code, I just put this in onCreate():
//My location, San Francisco
double lat = 37.77657;
double lng = -122.417506;
LatLng latLng = new LatLng(lat, lng);
//set up list
ArrayList<Place> places = new ArrayList<Place>();
places.add(new Place("New York", new LatLng(40.571256,73.98369)));
places.add(new Place("Colorado", new LatLng(39.260658,-105.101615)));
places.add(new Place("Los Angeles", new LatLng(33.986816,118.473819)));
for (Place p: places){
Log.i("Places before sorting", "Place: " + p.name);
}
//sort the list, give the Comparator the current location
Collections.sort(places, new SortPlaces(latLng));
for (Place p: places){
Log.i("Places after sorting", "Place: " + p.name);
}
Here is the log output:
04-17 23:04:16.074 12963-12963/com.maptest.daniel.maptest I/Places before sorting﹕ Place: New York
04-17 23:04:16.074 12963-12963/com.maptest.daniel.maptest I/Places before sorting﹕ Place: Colorado
04-17 23:04:16.074 12963-12963/com.maptest.daniel.maptest I/Places before sorting﹕ Place: Los Angeles
04-17 23:04:16.074 12963-12963/com.maptest.daniel.maptest I/Places after sorting﹕ Place: Los Angeles
04-17 23:04:16.074 12963-12963/com.maptest.daniel.maptest I/Places after sorting﹕ Place: Colorado
04-17 23:04:16.074 12963-12963/com.maptest.daniel.maptest I/Places after sorting﹕ Place: New York
For calculating the distance there are different methods available. A quite simple one is the Haversine Formula (http://rosettacode.org/wiki/Haversine_formula#Java). A more accurate calculation would be the Vincenty Formula. If the two locations are not far away, the Haversine solution is quite sufficient.
After calculating the distance, you just sort your array using a comparator, like:
Collections.sort(places, new Comparator<Place>() {
public int compare(Place p1, Place p2) {
return Double.compare(p1.getDistance(), p2.getDistance());
}
});
As you got your current location, You can sort by calculating the driving distance (which is most suitable for places like restaurants ) as follows,
Calculate the distance to each object
http://maps.googleapis.com/maps/api/directions/json?origin="+yourLat+","+yourLong+"&destination="+toLat+","+toLong+"&sensor=false&mode=DRIVING
Once you calculate each distance , apply some simple sorting algorithm for those distances.
you can use the
distanceInMeters = (loc1.distanceTo(loc2));
from google maps API and then add the results to the Key in a TreeMap
I'm trying to calculate the route between two locations with a code that you already know.
In my case the first location is MY location and the second location is the nearest LatLng
of a path.
This code below calculates the nearest LatLng:
private LatLng nearestLatLng(Location mCurrentLocation) {
LatLng latLngCurrentLocation = new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude());
double nearestLatitude = 0;
double nearestLongitude = 0;
float minDistance = 1000; //I don't know how to initialize
float currentDistance;
for(int i=0; i<mLatLngGpxList.size(); i++) {
LatLng currentTrackLatLng = mLatLngGpxList.get(i);
currentDistance = getDistance(latLngCurrentLocation, currentTrackLatLng);
if(currentDistance <= minDistance) {
minDistance = currentDistance;
nearestLatitude = currentTrackLatLng.latitude;
nearestLongitude = currentTrackLatLng.longitude;
}
}
//mGoogleMap.addMarker(new MarkerOptions().position(new LatLng(nearestLatitude, nearestLongitude)));
return new LatLng(nearestLatitude,nearestLongitude);
}
//Calcola la distanza tra due LatLng
private float getDistance(LatLng first, LatLng second) {
float [] dist = new float[1];
Location.distanceBetween(first.latitude, first.longitude, second.latitude, second.longitude, dist);
return dist[0];
}
If i draw a path in my country, i can also draw the path for reach it, but if i draw a path
away from my country, i get this:
org.json.JSONException: Index 0 out of range [0..0)
at org.json.JSONArray.get(JSONArray.java:263)
at org.json.JSONArray.getJSONObject(JSONArray.java:480)
etc.
and consequently no path to my path is drawn. Why? :(
Ps: i DON'T get "error_message" : "You have exceeded your daily request quota for this API."
Update: the error is in the code above. Advice? :/
Second Update: float minDistance = 1000; --> became float minDistance = 100000000
and now works. It remains a logical problem but i'll see.. :/
I am developing an Android application.
I am getting a list of latitudes and longitudes from the server.
I have to arrange those values based on my location. I mean the nearest latitude/longitude first and then the next one etc.
I have my latitude and longitude and the list of latitude and longitudes. How can I find the nearest one?
This might not be the best way but it works :)
public static final double PI = 3.14159265;
public static final double deg2radians = PI/180.0;
public static final double miles = 0.000621371192;
public static final double kms = 0.001;
public static double getDistance(double latitude1, double longitude1, double latitude2,double longitude2) {
double distance;
Location locationA = new Location("point A");
locationA.setLatitude(latitude1);
locationA.setLongitude(longitude1);
Location locationB = new Location("point B");
locationB.setLatitude(latitude2);
locationB.setLongitude(longitude2);
distance = locationA.distanceTo(locationB);
double radd = distance * kms;
return radd;
}
pseudo code :
location.distanceTo(locFromServer);
and for the sorting
Colection.sort(listOfLocations;new Comparator(){
compareTo(){
// location.distanceTo(locFromServer)
}
}
You can simply calculate the distances of the user's position to the downloaded locations, and select the smallest one.
Have a look here: Quicker way to calculate geographic distance between two points.