【问题标题】:How to calculate the total distance traveled?如何计算行驶的总距离?
【发布时间】:2016-04-02 16:57:21
【问题描述】:

我有一个数组列表,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);
}

【问题讨论】:

  • 你说的结果是错的,到底错了多少?可以举个例子吗
  • 当我走在 140m 长的路线上时,计算出的距离是 9950m,但不知何故绘制的路径是正确的。所以我想知道我使用上述代码的逻辑是否错误
  • ;) 太多了,我看一下,但可能需要一些时间才能恢复
  • 所以 Levon 回答但得到了我对问答的投票。 ;)

标签: android android-studio gps locationmanager


【解决方案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;
}

【讨论】:

  • 我将totalD声明为一个全局变量float totalD = 0f; ,我需要先将 tempTotalDistance 初始化为 0 吗?你能告诉我你的答案和我的代码有什么不同吗?因为我想知道背后的逻辑,所以很多
  • 我用详细的解释更新了答案。您可以在声明它们时将 0f 分配给您的浮点数。如果我的回答是正确的,请将其标记为已接受。谢谢!
  • @Levon 你能看看这个吗。我的计算有什么问题吗。stackoverflow.com/questions/40361131/…
  • @Noufal 链接失效,找不到你链接的帖子
猜你喜欢
  • 2015-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-09
  • 2013-01-27
  • 2015-07-02
相关资源
最近更新 更多