您的位置:首页 > 其它

Windows 8 地理位置定位 4.根据经纬度计算地面两点间的距离

2013-01-13 12:47 661 查看
关于根据经纬度计算地面两点间距离的公式及推导可以参考我的另一篇博客/article/5249890.html

本例依然只有一个页面

先上运行截图:

C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Windows.Devices.Geolocation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Core;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

namespace Win8Location
{
public sealed partial class DistanceAndSpeed : Page
{
Geolocator geo = null;
private double prevLongitude;
private double prevLatitude;
private double totalDistance;//(米)
private DateTimeOffset prevTime;
private TimeSpan totalTime = TimeSpan.Zero;

public DistanceAndSpeed()
{
this.InitializeComponent();
}

async private void btnStartTracking_Click(object sender, RoutedEventArgs e)
{
btnStartTracking.IsEnabled = false;
btnStopTracking.IsEnabled = true;
if (geo == null)
{
geo = new Geolocator();
}
if (geo != null)
{
geo.StatusChanged += geo_StatusChanged;
try
{
Geoposition position = await geo.GetGeopositionAsync();
string msg = position.Coordinate.Timestamp + ">开始定位并跟踪\n";
msg += "当前经度:" + position.Coordinate.Longitude + "\n";
msg += "当前纬度:" + position.Coordinate.Latitude + "\n\n";
txtMsg.Text += msg;
prevLongitude = position.Coordinate.Longitude;
prevLatitude = position.Coordinate.Latitude;
prevTime = position.Coordinate.Timestamp;
}
catch (Exception ex)
{
txtMsg.Text += DateTime.Now + ">出错了:" + ex.Message + "\n\n";
}
geo.PositionChanged += geo_PositionChanged;
}
}

async void geo_PositionChanged(Geolocator sender, PositionChangedEventArgs args)
{
Geoposition pos = args.Position;
double currLong = pos.Coordinate.Longitude;
double currLat = pos.Coordinate.Latitude;
DateTimeOffset currTime = pos.Coordinate.Timestamp;

double updateDistance = GetDistance(prevLongitude, prevLatitude, currLong, currLat);
totalDistance += updateDistance;
TimeSpan updateTime = currTime - prevTime;
totalTime += updateTime;

StringBuilder msg = new StringBuilder();
msg.Append(currTime + "\n");
msg.Append("当前经度:" + args.Position.Coordinate.Longitude + "\n");
msg.Append("当前纬度:" + args.Position.Coordinate.Latitude + "\n");
msg.Append("距上一个位置的距离(米):" + updateDistance.ToString("0") + "\n");
msg.Append("距上一个位置经历的时间:" + updateTime.ToString(@"hh\:mm\:ss") + "\n");
msg.Append("距上一个位置间的平均速度(米/秒):" + GetSpeed(updateDistance, updateTime).ToString("0") + "\n");
msg.Append("已经历的总路程(米):" + totalDistance.ToString("0") + "\n");
msg.Append("已经历的总时间:" + totalTime.ToString(@"hh\:mm\:ss") + "\n");
msg.Append("已经历的总平均速度(米/秒):" + GetSpeed(totalDistance, totalTime).ToString("0") + "\n\n");

await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
txtMsg.Text += msg;
});

prevLongitude = currLong;
prevLatitude = currLat;
prevTime = currTime;
}

async void geo_StatusChanged(Geolocator sender, StatusChangedEventArgs args)
{
string msg = DateTime.Now + ">定位器状态:" + args.Status + "\n\n";
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
txtMsg.Text += msg;
});
}

private void btnStopTracking_Click(object sender, RoutedEventArgs e)
{
btnStartTracking.IsEnabled = true;
btnStopTracking.IsEnabled = false;
if (geo != null)
{
txtMsg.Text += DateTime.Now + ">停止位置跟踪\n\n";
geo.StatusChanged -= geo_StatusChanged;
geo.PositionChanged -= geo_PositionChanged;
}
}

/// <summary>
/// 根据经纬度计算地面两点间的距离
/// </summary>
/// <param name="prevLong">前一个点的经度</param>
/// <param name="prevLat">前一个点的纬度</param>
/// <param name="currLong">当前点的经度</param>
/// <param name="currLat">当前点的纬度</param>
/// <returns>两点间的距离(米)</returns>
private double GetDistance(double prevLong, double prevLat, double currLong, double currLat)
{
const double degreesToRadians = (Math.PI / 180.0);
const double earthRadius = 6371; // 地球半径平均值为6371千米

var prevRadLong = prevLong * degreesToRadians;
var prevRadLat = prevLat * degreesToRadians;
var currRadLong = currLong * degreesToRadians;
var currRadLat = currLat * degreesToRadians;

double cosX = Math.Cos(prevRadLat) * Math.Cos(currRadLat) * Math.Cos(prevRadLong - currRadLong) + Math.Sin(prevRadLat) * Math.Sin(currRadLat);
double X = Math.Acos(cosX);//两点与球心连线的夹角
double d = earthRadius * X * 1000;//单位转换为米
return d;
}

private double GetSpeed(double distance, TimeSpan timeSpan)
{
double speed = distance / timeSpan.TotalSeconds;
return speed;
}

private void btnClear_Click(object sender, RoutedEventArgs e)
{
txtMsg.Text = string.Empty;
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: