2

I have an array list, ArrayList(), which is used to save lat and lng. And then a line will be drawn when there is a new point. I want to get the element inside this array, in order to calculate the total distance. But somehow i use the calculateDistance Method to calculate the total distance, the result is not correct. So i want to know if i had do something wrong.

private void whereAmI(){

    Location location = manager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
    updateWithNewLocation(location);

    //GPS Listener
    manager.addGpsStatusListener(gpsListener);

    //Location Listener
    int minTime = 0;//ms
    int minDist = 0;//meter
    manager.requestLocationUpdates(LocationManager.GPS_PROVIDER, minTime, minDist, locationListener);
}

GpsStatus.Listener gpsListener = new GpsStatus.Listener() {
    @Override
    public void onGpsStatusChanged(int event) {
        switch (event) {
            case GpsStatus.GPS_EVENT_STARTED:
                Log.d("x=", "GPS_EVENT_STARTED");
                Toast.makeText(MapsActivity.this, "GPS_EVENT_STARTED", Toast.LENGTH_SHORT).show();
                break;
            case GpsStatus.GPS_EVENT_STOPPED:
                Log.d("x=", "GPS_EVENT_STOPPED");
                Toast.makeText(MapsActivity.this, "GPS_EVENT_STOPPED", Toast.LENGTH_SHORT).show();
                break;
            case GpsStatus.GPS_EVENT_FIRST_FIX:
                Log.d("x=", "GPS_EVENT_FIRST_FIX");
                Toast.makeText(MapsActivity.this, "GPS_EVENT_FIRST_FIX", Toast.LENGTH_SHORT).show();
                break;
            case GpsStatus.GPS_EVENT_SATELLITE_STATUS:
                Log.d("x=", "GPS_EVENT_SATELLITE_STATUS");
                break;
        }
    }
};

LocationListener locationListener = new LocationListener(){
    @Override
    public void onLocationChanged(Location location) {
        updateWithNewLocation(location);
    }

    @Override
    public void onProviderDisabled(String provider) {
        updateWithNewLocation(null);
    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {
        switch (status) {
            case LocationProvider.OUT_OF_SERVICE:
                Log.v("x=", "Status Changed: Out of Service");
                Toast.makeText(MapsActivity.this, "Status Changed: Out of Service", Toast.LENGTH_SHORT).show();
                break;
            case LocationProvider.TEMPORARILY_UNAVAILABLE:
                Log.v("x=", "Status Changed: Temporarily Unavailable");
                Toast.makeText(MapsActivity.this, "Status Changed: Temporarily Unavailable", Toast.LENGTH_SHORT).show();
                break;
            case LocationProvider.AVAILABLE:
                Log.v("x=", "Status Changed: Available");
                Toast.makeText(MapsActivity.this, "Status Changed: Available", Toast.LENGTH_SHORT).show();
                break;
        }
    }

};

private void showMarkerMe(double lat, double lng){
    if (markerMe != null) {
        markerMe.remove();
    }

    MarkerOptions markerOpt = new MarkerOptions();
    markerOpt.position(new LatLng(lat, lng));
    markerOpt.title("I am here!");
    markerMe = mMap.addMarker(markerOpt);

    //Toast.makeText(this, "lat:" + lat + ",lng:" + lng, Toast.LENGTH_SHORT).show();
}

private void cameraFocusOnMe(double lat, double lng){
    CameraPosition camPosition = new CameraPosition.Builder()
            .target(new LatLng(lat, lng))
            .zoom(16)
            .build();

    mMap.animateCamera(CameraUpdateFactory.newCameraPosition(camPosition));
}

private void trackToMe(double lat, double lng){
    if (traceOfMe == null) {
        traceOfMe = new ArrayList<LatLng>();
    }
    traceOfMe.add(new LatLng(lat, lng));

    calculateDistance(traceOfMe);

    PolylineOptions polylineOpt = new PolylineOptions();
    for (LatLng latlng : traceOfMe) {
        polylineOpt.add(latlng);
    }

    polylineOpt.color(Color.RED);

    Polyline line = mMap.addPolyline(polylineOpt);
    line.setWidth(10);
}

private void calculateDistance(ArrayList<LatLng> points) {

    for (int i =0; i < points.size() -1; i++) {
        LatLng pointA =  points.get(i);
        LatLng pointB = points.get(i + 1);
        float[] results = new float[3];
        Location.distanceBetween (pointA.latitude, pointA.longitude, pointB.latitude, pointB.longitude, results);
        totalD +=  results[0];
    }
}

private void updateWithNewLocation(Location location) {

    String where = "";
    if (location != null) {

        double lng = location.getLongitude();

        double lat = location.getLatitude();

        float speed = location.getSpeed();

        long time = location.getTime();
        String timeString = getTimeString(time);

        speedList.add(""+ speed);

        where = "Lng: " + lng +
                "  Lat: " + lat +
                "  Speed: " + speed +
                "\nTime: " + timeString +
                "  Provider: " + "gps" +
                "  Distance: " + totalD ;


        showMarkerMe(lat, lng);
        cameraFocusOnMe(lat, lng);
        trackToMe(lat, lng);

    }else{
        where = "No location found.";
    }


    txt.setText(where);
}
Levon
  • 1,681
  • 2
  • 18
  • 40

1 Answers1

1

I'm not sure where the totalD variable is declared, but it seems like it is accumulating values with each point you add to the list. Say you walk from point A to point B with a distance of 10 meters, so your initial ArrayList contains only 2 points and when you calculate the distance it is correctly calculated as 10 meters and assigned to totalD variable. Now you walk further, from point B to point C, say another 5 meters, and your ArrayList now contains 3 points A, B, and C, with a total distance that's supposed to be 15 meters (10 + 5). The way your function was written, you go through the list of points, and add it all to totalD without ever re-setting it. So, your totalD already had a value of 10 from the previous calculation, and now by going through the ArrayList again and getting a total of 15, you add that 15 to the previous 10 that you had there from the first calculation. Your totalD is now 25 (10 + 15, the results of all previous calculations combined), instead of simply 15 (the result of only the last calculation). So in your calculateDistance() method instead of

totalD +=  results[0];

you should have a local variable, say tempTotalDistance, and then add all distances between points into it, and then assign its final value to your global totalD. Your new calculateDistance() can look something like this:

private void calculateDistance(ArrayList<LatLng> points) {

    float tempTotalDistance;

    for (int i =0; i < points.size() -1; i++) {
        LatLng pointA =  points.get(i);
        LatLng pointB = points.get(i + 1);
        float[] results = new float[3];
        Location.distanceBetween (pointA.latitude, pointA.longitude, pointB.latitude, pointB.longitude, results);
        tempTotalDistance +=  results[0];
    }

    totalD = tempTotalDistance;
}
Levon
  • 1,681
  • 2
  • 18
  • 40
  • i declare the totalD as a global variable float totalD = 0f; , do i need to initialize the tempTotalDistance as 0 first? Can you tell what is the different between your answer and my code, pls?? As i want to know the logic behind, thz a lot –  Apr 02 '16 at 17:38
  • I updated the answer with a detailed explanation. You can assign 0f to your floats when you declare them. If my answer is correct, please mark it as accepted. Thanks! – Levon Apr 02 '16 at 17:46
  • @Levon Can you look at this one.Is there anything wrong with my calaculation.http://stackoverflow.com/questions/40361131/how-to-find-the-distance-traveled-in-kilometers-by-following-gps-co-ordinates-us?noredirect=1#comment68011278_40361131 – Noufal Nov 07 '16 at 10:35
  • @Noufal The link is broken, couldn't find the post you linked to – Levon Nov 08 '16 at 13:22
  • @Levon This is the link http://stackoverflow.com/questions/40481242/the-geo-cordinates-getting-is-very-far-from-previous-one – Noufal Nov 09 '16 at 04:34