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.. :/
Related
When I click on polyline I want time (custom object) to be displayed at that particular lat long position.
Code to achieve polyline
PolylineOptions lineOptions = new PolylineOptions().width(7).color(Color.BLACK).geodesic(true);
for (int i = 0; i < points.size(); i++) {
LatLng latLng1 = new LatLng(Double.parseDouble(points.get(i).getmLatitude()), Double.parseDouble(points.get(i).getmLongitude()));
lineOptions.add(latLng1);
}
if (mPolyline != null) {
mPolyline.remove();
}
mPolyline = mMap.addPolyline(lineOptions);
mPolyline.setClickable(true);
for (int i = 0; i < points.size(); i++) {
//setting tags to be used on ployline click
mPolyline.setTag(points.get(i).getTime());
}
List<PatternItem> pattern = Arrays.asList(
new Gap(15), new Dash(15), new Gap(15));
mPolyline.setPattern(pattern);
mPolyline.setJointType(JointType.ROUND);
Now when I click on polyline I get only one tag which is same for all. I want unique tags(custom objects) for every polyline position which relate to lat long
mMap.setOnPolylineClickListener(new GoogleMap.OnPolylineClickListener() {
#Override
public void onPolylineClick(Polyline polyline) {
Toast.makeText(mContext, (String) polyline.getTag(), Toast.LENGTH_SHORT).show();
}
});
Thanks for contributing :)
EDIT
mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {
#Override
public void onMapClick(LatLng latLng) {
boolean isOnRoute = PolyUtil.isLocationOnPath(latLng, lineOptions.getPoints(), false, 25);
if (isOnRoute) {
for (LocationVo mCoordinates : points) {
double distanceInMeters = SphericalUtil.computeDistanceBetween(latLng, mCoordinates.getmLatLong());
boolean isWithin50m = distanceInMeters < 50;
if (isWithin50m) {
Toast.makeText(mContext, mCoordinates.getTime(), Toast.LENGTH_SHORT).show();
break;
}
}
}
}
});
Not all my polylines match with the conditions and show no toast on click
With a tolerance of 25 meters you are defining a corridor along each path segment 25 meters on either side. So as implemented, all this tells you is the click point is somewhere in the corridor centered on the path - or effectively they've clicked on the polyline with some room for error.
The problem you are having is in your assumption that you'll always be within 50 meters of a point - this is incorrect and also not what you want as best as I can tell. By definition, once isOnRoute is true, you always want to find a point since by definition they've clicked on the polyline; this is done (inefficiently) by simply calculating all distances from click-point to all polyline points and determining the shortest distance (a simple loop
with a min logic); then use this point for your toast.
Now if you really wanted to limit what are considered "successful" clicks, where a successful click is both "on the polyline" and "near a point" then your distance check would be added using some acceptable value - this would be in effect defining a "box" around each point with dimensions 50 meters (25 x 2)-by-whatever your distance check is. Note this is not the same as just checking a radius circle around each point unless the radius of the desired circle is equivalent to the polyline tolerance.
(One other trivial point - your mixing measurement systems when using false for geodesic and then computing spherical distance - but should not be an issue with your implementation.) (If helpful I'll add a picture later.)
Summary of modification: "check if user clicks along the polyline" AND "determine closest point along line" AND "display some toast for that point".
So make this modification after isOnRoute is true:
LocationVo closestPoint = null;
double minDist = -1;
for (LocationVo mCoordinates : points) {
double distanceInMeters = SphericalUtil.computeDistanceBetween(latLng, mCoordinates.getmLatLong());
if (minDist < 0 || distanceInMeters < minDist) {
minDist = distanceInMeters;
closestPoint = mCoordinates;
}
}
if (closestPoint != null) {
Toast.makeText(mContext, closestPoint.getTime(), Toast.LENGTH_SHORT).show();
}
To implement the "box" discussed above around each point modify the one condition:
if ((distanceInMeters < MAX_DISTANCE_FROM_POINT) && (minDist < 0 || distanceInMeters < minDist)) {
Note this means in some cases you will not get a toast even if they clicked along the polyline.
How to sum of arrays of floating point numbers..as the results from distance that the array float come from results Location.distanceBetween(latStart, longStart, latB, longB, results); method in Google maps api ,,i'm trying with this, but at some point it decrease, it should always incrementing. what am i missing?
EDIT:
public float total(ArrayList<LatLng> listPoints){
if(listPoints.size()==2){
listPoints.clear();
}
listPoints.add(latLng);
float[] results = new float[2];
float sum = 0.0f;
for (int z = 0; z < listPoints.size(); z++) {
if(listPoints.size() == 1){
latStart = listPoints.get(z).latitude;
longStart = listPoints.get(z).longitude;
Toast.makeText(this, "listPoint 1", Toast.LENGTH_SHORT).show();
}else if(listPoints.size() == 2){
latB = listPoints.get(z).latitude;
longB = listPoints.get(z).longitude;
Toast.makeText(this, "listPoint 2", Toast.LENGTH_SHORT).show();
}
Location.distanceBetween(latStart, longStart, latB, longB, results);
sum+=results[0];
}
tvJarakTotal.setText(sum + "");
return sum;
}
EDIT:
the distance came from onLocationChanged() method as the user location is moving,
EDIT:
I Finally find the solution myself, by creating some trick using sharedPreference. but the accepted answer is correct to the question.
It is not entirely clear what you think you were doing in your code above. First of all, the Location#distanceBetween API takes in a pair of latitude longitude values, i.e. two geographic points, and then returns the distance between them in results[0] (q.v. the documentation).
Next, it isn't clear what the starting and ending points are intended to be. I answered below under the assumption that the listPoints are one set of points (either starting or ending), and the vales latB and longB are a fixed set of starting/ending points. Without this assumption, an answer really can't be given here.
public float total(ArrayList<LatLng> listPoints) {
float[] results;
float sum = 0.0f;
for (int z=0; z < listPoints.size(); z++) {
double latStart = listPoints.get(z).latitude;
double longStart = listPoints.get(z).longitude;
Location.distanceBetween(latStart, longStart, latB, longB, results);
sum += results[0];
tvJarak.setText(sum + "");
}
return sum;
}
Please take a look your code carefully.
float[] results = new float[listPoints.size()];
results variable is declared as a local variable but it's not initialized with any values yet.
In this case it has random value.
That's why sum gives random minus value.
float[] results = new float[listPoints.size()];
In this case your result array stored size of the listPoints array. After that you are trying to iterate result array by using listPointers array size.
Assume your :- float [] results = new [2];
Now you try to add up same value again and again inside you for a loop. Please make sure your scenario is correct or not.
You should store api date someware inside your code. like this:
lat = listPoints.get(z).latitude;
long = listPoints.get(z).longitude;
if you want you can do it like this,
public float total(ArrayList<LatLng> listPoints) {
float[] results;
float sum = 0.0f;
float lat = 0.0f, long = 0.0f;
for (int z=0; z < listPoints.size(); z++) {
lat = listPoints.get(z).latitude;
long = listPoints.get(z).longitude;
Location.distanceBetween(lat, long, latB, longB, results);
sum+=results[z];
tvJarak.setText(sum + "");
}
return sum;
}
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 calculating distance between two location using latitude and longitude... i am getting the distance easily and converting it into miles... but first difference value come in wrong format and other value coming right.
First distance is coming like this = 2.0E-4
While other like this = 48.8881
i have used the following code
Location l1 = new Location("One");
l1.setLatitude(cur_latitude);
l1.setLongitude(cur_longitude);
for (int i = 0; i < lctn.size(); i++) {
Location l2 = new Location("LocationB");
l2.setLatitude(lctn.get(i).getLocation_lat());
l2.setLongitude(lctn.get(i).getLocation_lng());
float distance = l1.distanceTo(l2);
distance =Float.parseFloat(new DecimalFormat("##.####").format( distance / 1000.0f));
Double mile = Double.parseDouble(new DecimalFormat("##.####").format(distance * 0.6214));
Log.e("km_", "" + distance);
Log.e("miles_", "" + mile);
Also please check whether i am using right formula for calculating miles....Thanks in Advance
Distance is in points that why it happening, You need to use accuracy variable and assign some value to this variable,
in my case i use
int accuracy = 20;
Then compare this accuracy with Location accuracy
if(l2.getAccuracy() <= accuracy ) {
Log.e("km_", "" + distance);
Log.e("miles_", "" + mile);
}
I suggest you to use fused location api for accurate distance.
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;
}
}