如何计算行走的总距离?

时间:2016-04-02 16:57:22

标签: android android-studio gps locationmanager

我有一个数组列表,ArrayList(),用于保存lat和lng。然后在有新点时绘制一条线。我想在这个数组中得到元素,以便计算总距离。但不知何故,我使用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);
}

1 个答案:

答案 0 :(得分:1)

我不确定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;
}