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;
}
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.
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'm implementing the animations for the group of cars(Markers) to rotate at the same time in google map v2.
so that i need to code my animation part inside handler.post() method.
By doing this the animation part(handler.post() method) is running for only one marker.
i have coded handler.post() method inside the for loop. It runs only for the first time which means only one marker is rotating. after that it is not working. My code is as follows.
private void animateCarsInMarkers(final MarkerOptions mark, final long bearing, final LatLng startPosition, final int position){
final Handler handler = new Handler();
final long start = SystemClock.uptimeMillis();
final long duration = 3000;
final Interpolator interpolator = new LinearInterpolator();
final Marker marker = mGoogleMap.addMarker(mark);
final float rotationValue = Float.parseFloat(String.valueOf(bearing));
try {
if(tempCarsArray != null && !tempCarsArray.isEmpty()){
sLongitude = tempCarsArray.get(position).getDouble(LONGITUDE);
sLatitude = tempCarsArray.get(position).getDouble(LATITUDE);
sBearing = tempCarsArray.get(position).getLong("Bearing");
final double dLongitude = startPosition.longitude;
final double dLatitude = startPosition.latitude;
handler.post(new Runnable() {
#Override
public void run() {
long elapsed = SystemClock.uptimeMillis() - start;
float time = interpolator.getInterpolation((float) elapsed / duration);
double lng = time * dLongitude + (1 - time) * sLongitude;
double lat = time * dLatitude + (1 - time) * sLatitude;
float rotationValue = time * dbearing + (1-time) * sBearing;
marker.setRotation((-rotationValue > 180) ? (rotationValue / 2) : rotationValue);
marker.setPosition(new LatLng(lat, lng));
if (time < 1.0) {
handler.postDelayed(this, 16);
}
}
});
tempCarsArray.clear();
} else {
marker.setPosition(startPosition);
marker.setRotation(-rotationValue > 180 ? rotationValue / 2 : rotationValue);
}
}catch (JSONException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
This is the method which i called inside for loop. But it runs only for the first time in loop. Later it is not working. So only one marker is animated among the group of markers. My for loop is as follows :
for(int i=0; i<size; i++){
animateCarsInMarkers(mark, bearing, latLng, i);
}
This loop runs only when the value of i=0 and it wont runs again.
Thanks in advance.
If your 'for loop' ran only once, it means that your "for loop condition part", i<size for this instance, has already satisfied the condition. What I would suggest is for you to actually log "size" and check its value.
If you're looking for the size of an array, use tempCarsArray.length like:
for(int i=0; i < tempCarsArray.length; i++){
animateCarsInMarkers(mark, bearing, latLng, i);
}
To check if size is causing the problem, try this.
If you know the actual number of markers you're expecting to rotate, try to substitute with an integer for now, like:
//if you're expecting 5 markers
for(int i=0; i < 5 ; i++){
animateCarsInMarkers(mark, bearing, latLng, i);
}
If all markers did rotate, it means your size variable has only a value of 1.
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 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.. :/