最近遇到需要获取随机坐标的需求,就研究了一下,现在整理成C#和JAVA代码,方便有需要的人参考。主要功能是实现以指定的坐标点为圆心,指定的距离为半径,在圆内获取一个随机坐标点。
主要功能:
1、获取随机坐标点;
2、计算两点间距离。
算法参考了如下网站:http://www.geomidpoint.com/random/calculation.html,整理后的代码详见以下章节:
C#代码如下:
/// <summary>
/// GPS坐标
/// </summary>
public class GPSLocation
{
/// <summary>
/// 纬度
/// </summary>
public double Latitude { get; set; }
/// <summary>
/// 经度
/// </summary>
public double Longitude { get; set; }
}
/// <summary>
/// GPS工具类
/// </summary>
public class LocationUtils
{
const double EARTH_RADIUS = 6372.796924; // km
const double PI = 3.1415926535898;
/// <summary>
/// 根据中心坐标获取指定距离的随机坐标点
/// </summary>
/// <param name="center">中心坐标</param>
/// <param name="distance">离中心坐标距离(单位:米)</param>
/// <returns></returns>
public static GPSLocation GetRandomLocation(GPSLocation center, double distance = 50)
{
if (distance <= 0) distance = 50;
double lat, lon, brg;
distance = distance / 1000;
GPSLocation location = new GPSLocation();
double maxdist = distance;
maxdist = maxdist / EARTH_RADIUS;
double startlat = rad(center.Latitude);
double startlon = rad(center.Longitude);
var cosdif = Math.Cos(maxdist) - 1;
var sinstartlat = Math.Sin(startlat);
var cosstartlat = Math.Cos(startlat);
double dist = 0;
var rad360 = 2 * PI;
dist = Math.Acos((new Random().NextDouble() * cosdif + 1));
brg = rad360 * new Random().NextDouble();
lat = Math.Asin(sinstartlat * Math.Cos(dist) + cosstartlat * Math.Sin(dist) * Math.Cos(brg));
lon = deg(normalizeLongitude(startlon * 1 + Math.Atan2(Math.Sin(brg) * Math.Sin(dist) * cosstartlat, Math.Cos(dist) - sinstartlat * Math.Sin(lat))));
lat = deg(lat);
location.Latitude = padZeroRight(lat);
location.Longitude = padZeroRight(lon);
return location;
}
/// <summary>
/// 获取两点间的距离(单位:米)
/// </summary>
/// <param name="start">起始坐标</param>
/// <param name="end">结束坐标</param>
/// <returns></returns>
public static double GetDistance(GPSLocation start, GPSLocation end)
{
double radLat1 = rad(start.Latitude);
double radLat2 = rad(end.Latitude);
double a = radLat1 - radLat2;
double b = rad(start.Longitude) - rad(end.Longitude);
double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) + Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2)));
s = s * EARTH_RADIUS;
s = (int)(s * 10000000) / 10000;
return s;
}
/// <summary>
/// 弧度
/// </summary>
/// <param name="d"></param>
/// <returns></returns>
static double rad(double d)
{
return d * PI / 180.0;
}
/// <summary>
/// 角度
/// </summary>
/// <param name="rd"></param>
/// <returns></returns>
static double deg(double rd)
{
return (rd * 180 / Math.PI);
}
static double normalizeLongitude(double lon)
{
var n = PI;
if (lon > n)
{
lon = lon - 2 * n;
}
else if (lon < -n)
{
lon = lon + 2 * n;
}
return lon;
}
static double padZeroRight(double s)
{
double sigDigits = 8;
s = Math.Round(s * Math.Pow(10, sigDigits)) / Math.Pow(10, sigDigits);
return s;
}
}
JAVA代码如下:
public class GPSLocation {
private double latitude;
private double longitude;
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
}
public class LocationUtils {
static final double EARTH_RADIUS = 6372.796924;
static final double PI = 3.1415926535898;
/**
* 根据中心坐标获取指定距离的随机坐标点
*
* @param center
* 中心坐标
* @param distance
* 离中心坐标距离(单位:米)
* @return 随机坐标
*/
public static GPSLocation GetRandomLocation(GPSLocation center, double distance) {
if (distance <= 0) distance = 50;
double lat, lon, brg;
double dist = 0;
double rad360 = 2 * PI;
distance = distance / 1000;
GPSLocation location = new GPSLocation();
double maxdist = distance;
maxdist = maxdist / EARTH_RADIUS;
double startlat = rad(center.getLatitude());
double startlon = rad(center.getLongitude());
double cosdif = Math.cos(maxdist) - 1;
double sinstartlat = Math.sin(startlat);
double cosstartlat = Math.cos(startlat);
dist = Math.acos((new Random().nextDouble() * cosdif + 1));
brg = rad360 * new Random().nextDouble();
lat = Math.asin(sinstartlat * Math.cos(dist) + cosstartlat * Math.sin(dist) * Math.cos(brg));
lon = deg(normalizeLongitude(startlon * 1 + Math.atan2(Math.sin(brg) * Math.sin(dist) * cosstartlat, Math.cos(dist) - sinstartlat * Math.sin(lat))));
lat = deg(lat);
location.setLatitude(padZeroRight(lat));
location.setLongitude(padZeroRight(lon));
return location;
}
/**
* 获取两点间的距离(单位:米)
*
* @param start
* 起始坐标
* @param end
* 结束坐标
* @return 距离
*/
public static double GetDistance(GPSLocation start, GPSLocation end) {
double radLat1 = rad(start.getLatitude());
double radLat2 = rad(end.getLatitude());
double a = radLat1 - radLat2;
double b = rad(start.getLongitude()) - rad(end.getLongitude());
double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2)));
s = s * EARTH_RADIUS;
s = (int) (s * 10000000) / 10000;
return s;
}
/**
* 弧度
*
* @param d
* @return
*/
static double rad(double d) {
return d * PI / 180.0;
}
/**
* 角度
*
* @param rd
* @return
*/
static double deg(double rd) {
return (rd * 180 / Math.PI);
}
static double normalizeLongitude(double lon) {
double n = PI;
if (lon > n) {
lon = lon - 2 * n;
} else if (lon < -n) {
lon = lon + 2 * n;
}
return lon;
}
static double padZeroRight(double s) {
double sigDigits = 8;
s = Math.round(s * Math.pow(10, sigDigits)) / Math.pow(10, sigDigits);
return s;
}
}