简体   繁体   中英

Calculating distance between two points

I know this has been asked loads before, however I'm getting mixed views on whats correct and whats not,

I am trying to calculate the distance between two points in my app using two buttons, Start and stop.

I figured this would be simple, get the lat and long of the position when start is pressed, then get them again when stop is pressed, calculate the two and voila. However it isn't going to plan.

I have set up a dialog on the stop button when its clicked for feedback and currently I'm only returning (presumably) a single latitude or longitude.

My codes below::

 public class MapRun extends FragmentActivity implements LocationListener,
            LocationSource {
        private OnLocationChangedListener mListener;
        private LocationManager locationManager;

        private GoogleMap mMap;
        double lat, lng;
        static double startLat;
        double startLong;
        double stopLat;
        double stopLong;
        public static Location l;

        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.maprun);

            locationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
            // Creating a criteria object to retrieve provider
            Criteria criteria = new Criteria();

            // Getting the name of the best provider
            String provider = locationManager.getBestProvider(criteria, true);

            // Getting Current Location
            Location location = locationManager.getLastKnownLocation(provider);

            l = location;
            lat = l.getLatitude();
            lng = l.getLongitude();

            onLocationChanged(location);
            locationManager.requestLocationUpdates(provider, 20000, 0, this);

            setUpMapIfNeeded();
        }

        @Override
        public void onPause() {
            if (locationManager != null) {
                locationManager.removeUpdates(this);
            }

            super.onPause();
        }

        @Override
        public void onResume() {
            super.onResume();

            setUpMapIfNeeded();

            if (locationManager != null) {
                mMap.setMyLocationEnabled(true);
            }
        }

        /**
         * Sets up the map if it is possible to do so (i.e., the Google Play
         * services APK is correctly installed) and the map has not already been
         * instantiated.. This will ensure that we only ever call
         * {@link #setUpMap()} once when {@link #mMap} is not null.
         * <p>
         * If it isn't installed {@link SupportMapFragment} (and
         * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt
         * for the user to install/update the Google Play services APK on their
         * device.
         * <p>
         * A user can return to this Activity after following the prompt and
         * correctly installing/updating/enabling the Google Play services. Since
         * the Activity may not have been completely destroyed during this process
         * (it is likely that it would only be stopped or paused),
         * {@link #onCreate(Bundle)} may not be called again so we should call this
         * method in {@link #onResume()} to guarantee that it will be called.
         */
        private void setUpMapIfNeeded() {
            // Do a null check to confirm that we have not already instantiated the
            // map.
            if (mMap == null) {
                // Try to obtain the map from the SupportMapFragment.
                mMap = ((SupportMapFragment) getSupportFragmentManager()
                        .findFragmentById(R.id.map)).getMap();
                // Check if we were successful in obtaining the map.

                if (mMap != null) {
                    setUpMap();
                }

                // This is how you register the LocationSource
                mMap.setLocationSource(this);
            }
        }

        /**
         * This is where we can add markers or lines, add listeners or move the
         * camera. In this case, we just add a marker near Africa.
         * <p>
         * This should only be called once and when we are sure that {@link #mMap}
         * is not null.
         */
        private void setUpMap() {
            mMap.setMyLocationEnabled(true);
        }

        @Override
        public void activate(OnLocationChangedListener listener) {
            mListener = listener;
        }

        @Override
        public void deactivate() {
            mListener = null;
        }

        @Override
        public void onLocationChanged(Location location) {
            if (mListener != null) {
                mListener.onLocationChanged(location);

                // Move the camera to the user's location once it's available!

                mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(
                        location.getLatitude(), location.getLongitude()), 16.0f));
            }
        }

        @Override
        public void onProviderDisabled(String provider) {
            // TODO Auto-generated method stub
            Toast.makeText(this, "provider disabled", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onProviderEnabled(String provider) {
            // TODO Auto-generated method stub
            Toast.makeText(this, "provider enabled", Toast.LENGTH_SHORT).show();
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras) {
            // TODO Auto-generated method stub
            Toast.makeText(this, "status changed", Toast.LENGTH_SHORT).show();
        }




        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            super.onCreateOptionsMenu(menu);
            MenuInflater inflater = getMenuInflater();
            inflater.inflate(R.menu.map_menu, menu);
            return true;
        }

        @Override
        public boolean onOptionsItemSelected(MenuItem item) {
            switch (item.getItemId()) {
            case R.id.startRun:

                startRun();
            case R.id.stopRun:

                stopRun();

                return true;

            default:
                return super.onOptionsItemSelected(item);
            }

        }

        public void startRun() {
            ;



        }

        public void stopRun() {
            Location startPoint = new Location("Ran From");

            startPoint.setLatitude(lat);
            startPoint.setLongitude(lng);

            Location stopPoint = new Location("Ran To");
            stopPoint.setLatitude(stopLat);
            stopPoint.setLongitude(stopLong);
            float distance = startPoint.distanceTo(stopPoint);
            String distStr = String.valueOf(distance);
            Dialog d = new Dialog(this);
            d.setTitle("distance");
            TextView tv = new TextView(this);
            tv.setText(distStr);
            d.setContentView(tv);
            d.show();

        }

Here are my updated buttons so far, I've got the principle I think I'm just struggling with the correct way to store and pass the variables:

@Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
        case R.id.startRun:
            currentLocation = lat + lng;
            startLocation = currentLocation;

        case R.id.stopRun:
            currentLocation = lat + lng;
            stopLocatio

n = currentLocation;

        float distance = startLocation.distanceTo(stopLocation);
        String distStr = String.valueOf(distance);
        Dialog d = new Dialog(this);
        d.setTitle("distance");
        TextView tv = new TextView(this);
        tv.setText(distStr);
        d.setContentView(tv);
        d.show();

        return true;

    default:
        return super.onOptionsItemSelected(item);
    }

And my OnLocationchanged:

@Override
    public void onLocationChanged(Location location) {
        l = location;
        lat = l.getLatitude();
        lng = l.getLongitude();
        if (mListener != null) {
            mListener.onLocationChanged(location);

            // Move the camera to the user's location once it's available!

            mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(
                    location.getLatitude(), location.getLongitude()), 16.0f));
        }
    }

Location has distanceTo . Register the Location you get from Gps, when the user press start. When the user press stop, get the current location and do:

currentLocation.distanceTo(firstLocation) ;

distanceTo returns a float that represent the approximate distance in meters between this location and the given location

public class MapRun extends FragmentActivity implements LocationListener,
        LocationSource {

   Location startLocation;
   Location endLocation;

   Location currentLocation;


    @Override
    public void onLocationChanged(Location location) {
        if (mListener != null) {
            mListener.onLocationChanged(location);

            // Move the camera to the user's location once it's available!

            mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(
                    location.getLatitude(), location.getLongitude()), 16.0f));
        }
       currentLocation = location;
    }

 public void startRun() {
        startLocation = currentLocation;
    }

    public void stopRun() {
       stopLocation = currentLocation;
    }

 public float getDistance() {
   float distance = 0f;
   if (stopLocation != null && startLocation != null)
       distance = stopLocation.distanceTo(startLocation);
   return distance;
 }

}

You do nothing on startRun(), what do you expect to happen?

I suggest you keep a LatLng / Location currentLocation up to date with onLocationChanged() . In startRun() you do

startLocation = currentLocation

in stopRun you do

stopLocation = currentLocation

Thats really all there is to this. Right now, you set your lat and lon to the last known location, which I doubt is what you wnt to do, and you never set your stopLat and stopLon afai can see.

Try this:

private double distance(double lat1, double lon1, double lat2, double lon2) {
    double theta = lon1 - lon2;
    double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2))
            + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2))
            * Math.cos(deg2rad(theta));
    dist = Math.acos(dist);
    dist = rad2deg(dist);
    dist = dist * 60 * 1.1515;
    return (dist);
}

private double deg2rad(double deg) {
    return (deg * Math.PI / 180.0);
}

private double rad2deg(double rad) {
    return (rad * 180.0 / Math.PI);
}

Just Pass Lat long in the distance() method.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM