[英]Calculating distance between two points
我知道之前曾有人問過這個問題,但是對於什么是正確的,什么是錯誤的,我的看法不一,
我正在嘗試使用“開始”和“停止”兩個按鈕來計算應用中兩點之間的距離。
我認為這很簡單,按下開始時獲取位置的緯度和經度,然后按下停止時再次獲取它們的緯度,計算兩者和乘積。 但是,它不會計划。
單擊停止按鈕以獲取反饋時,我已經在“停止”按鈕上設置了一個對話框,目前,我僅返回(大概)一個緯度或經度。
我的代碼如下:
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();
}
到目前為止,這是我更新的按鈕,我有一個原則,我想我只是在嘗試正確的存儲和傳遞變量的方法:
@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);
}
和我的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
具有distanceTo
。 用戶按下開始時,注冊從Gps獲取的位置。 當用戶按下停止鍵時,獲取當前位置並執行以下操作:
currentLocation.distanceTo(firstLocation) ;
distanceTo
返回一個浮點數,它表示此位置與給定位置之間的近似距離(以米為單位)
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;
}
}
您對startRun()不執行任何操作,您希望發生什么?
我建議您使用onLocationChanged()
使LatLng
/ Location
保持最新。 在startRun()
您可以
startLocation = currentLocation
在stopRun你
stopLocation = currentLocation
那真的就是所有這些。 現在,您將緯度和經度設置到最后一個已知的位置,我懷疑這是您要執行的操作,並且從未設置過stopLat和stopLon afai可以看到的位置。
嘗試這個:
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);
}
只需在distance()
方法中傳遞Lat long。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.