1. 程式人生 > >GPS以中心點為圓心,指定距離為半徑獲取隨機座標點

GPS以中心點為圓心,指定距離為半徑獲取隨機座標點

    最近遇到需要獲取隨機座標的需求,就研究了一下,現在整理成C#和JAVA程式碼,方便有需要的人蔘考。主要功能是實現以指定的座標點為圓心,指定的距離為半徑,在圓內獲取一個隨機座標點。

主要功能:

    1、獲取隨機座標點;

    2、計算兩點間距離。

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;
	}
}