[英]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.