如何计算总行驶距离?

How to calculate the total distance traveled?

我有一个数组列表,ArrayList(),用来保存纬度和经度。然后当有一个新点时会画一条线。我想获取此数组中的元素,以计算总距离。但是不知何故我使用 calculateDistance 方法来计算总距离,结果不正确。所以我想知道我是不是做错了什么。

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);
}

我不确定 totalD 变量是在哪里声明的,但它似乎正在为您添加到列表中的每个点累积值。假设您从 A 点步行到 B 点,距离为 10 米,因此您的初始 ArrayList 仅包含 2 个点,当您计算距离时,它被正确计算为 10 米并分配给 totalD 变量。现在你走得更远,从 B 点到 C 点,再说 5 米,你的 ArrayList 现在包含 3 个点 A、B 和 C,总距离应该是 15 米 (10 + 5)。按照编写函数的方式,您遍历点列表,然后将其全部添加到 totalD 而无需重新设置它。因此,您的 totalD 在之前的计算中已经具有 10 的值,现在通过再次遍历 ArrayList 并获得总数 15,您将这 15 添加到您在第一次计算中获得的前 10。您的 totalD 现在是 25(10 + 15,所有先前计算的结果相加),而不是简单的 15(仅最后一次计算的结果)。所以在你的 calculateDistance() 方法中而不是

totalD +=  results[0];

你应该有一个局部变量,比如 tempTotalDistance,然后将所有点之间的距离添加到其中,然后将其最终值分配给你的全局 totalD。您的新 calculateDistance() 可能看起来像这样:

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;
}