天天看點

經緯度與距離的轉換的代碼

主要方法:

public static double CalculateSurfaceDistance(double lat1, double lng1, double lat2, double lng2)  擷取兩個坐标标點距離。

public static GEOSquare CircumscribedSquare(double latitudeInDegrees, double longitudeInDegrees, double radiusInMeters)  擷取指定點與距離的外界正方形。

/// <summary>

/// Class that provides calculations based on assuming that the earth is a perfect sphere.

/// </summary>

public class SphericalCalculations

{

/// <summary>

///

/// </summary>

public static double EarthEquatorialRadiusInMeters = 6371000;

/// <summary>

/// Get randians

/// </summary>

/// <param name="d"></param>

/// <returns></returns>

private static double Radians(double d)

{

return d * Math.PI / 180.0;

}

/// <summary>

/// Calculate the distance (in meters) between the two given lat/long points (in radians)

/// on the surface of the sphere. Uses the Haversine formula.

/// </summary>

public static double CalculateSurfaceDistance(double lat1, double lng1, double lat2, double lng2)

{

double radLat1 = Radians(lat1);

double radLat2 = Radians(lat2);

double a = radLat1 - radLat2;

double b = Radians(lng1) - Radians(lng2);

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 * EarthEquatorialRadiusInMeters;

s = Math.Round(s * 10000) / 10000;

return s;

}

/// <summary>

///

/// </summary>

/// <param name="latitudeInDegrees"></param>

/// <param name="longitudeInDegrees"></param>

/// <param name="radiusInMeters"></param>

/// <returns></returns>

public static GEOSquare CircumscribedSquare(double latitudeInDegrees, double longitudeInDegrees, double radiusInMeters)

{

double requestLatitudeInRadians =Radians( latitudeInDegrees );

double requestLongitudeInRadians = Radians(longitudeInDegrees);

//

// First we will calculate the latitude and longitude (spherical coordinates, phi and

// theta respectively) of the parallelogram that bounds the circle with the given radius

// on the surface of the sphere.

//

double phiSurfaceDistance = radiusInMeters / EarthEquatorialRadiusInMeters;

double phiMin = requestLatitudeInRadians - phiSurfaceDistance;

double phiMax = requestLatitudeInRadians + phiSurfaceDistance;

double thetaSurfaceDistanceAtPhiMin = radiusInMeters /

(SphericalCalculations.EarthEquatorialRadiusInMeters * Math.Cos(phiMin));

double thetaSurfaceDistanceAtPhiMax = radiusInMeters /

(SphericalCalculations.EarthEquatorialRadiusInMeters * Math.Cos(phiMax));

//

// Since it it a lot easier to search for points within a rectangle in a database, we

// will describe a rectangle that bounds the parallelogram.

//

double upperLeftPhi = phiMin;

double upperLeftTheta = requestLongitudeInRadians - thetaSurfaceDistanceAtPhiMin;

// Determine the larger of the two bases

double rectangleWidth = thetaSurfaceDistanceAtPhiMax >

thetaSurfaceDistanceAtPhiMin ?

thetaSurfaceDistanceAtPhiMax * 2 :

thetaSurfaceDistanceAtPhiMin * 2;

// Determine the height

double rectangleHeight = phiMax - phiMin;

GEOSquare resultSquare = new GEOSquare

{

LatitudeFrom = upperLeftPhi * 180.0 / Math.PI,

LatitudeTo = (upperLeftPhi + rectangleHeight) * 180.0 / Math.PI,

LongitudeFrom = upperLeftTheta * 180.0 / Math.PI,

LongitudeTo = (upperLeftTheta + rectangleWidth) * 180.0 / Math.PI

};

return resultSquare;

}

public class GEOSquare

{

public double LatitudeFrom { get; set; }

public double LatitudeTo { get; set; }

public double LongitudeFrom { get; set; }

public double LongitudeTo { get; set; }

}

}

測試代碼:

 [TestMethod]

public void TestCircumscribedSquare()

{

//

// TODO: Add test logic here

//

double latitudeInDegrees = 37.3456D;

double longitudeInDegrees=119.1234D;

long searchRadiusInMeters=3080;

SphericalCalculations.GEOSquare square = SphericalCalculations.CircumscribedSquare(latitudeInDegrees, longitudeInDegrees, searchRadiusInMeters);

Console.WriteLine("CircumscribedSquare: LatitudeFrom-To:{0}-{1};LongitudeFromTo:{2}-{3}", square.LatitudeFrom, square.LatitudeTo, square.LongitudeFrom, square.LongitudeTo);

Console.WriteLine("Difference in Latitude:{0}; Difference in Longitude:{1}", square.LatitudeTo - square.LatitudeFrom, square.LongitudeTo - square.LongitudeFrom);

Console.WriteLine("-------------------------");

Console.WriteLine(searchRadiusInMeters * Math.Sqrt(2));

Console.WriteLine(SphericalCalculations.CalculateSurfaceDistance(latitudeInDegrees, longitudeInDegrees, square.LatitudeFrom, square.LongitudeFrom));

Console.WriteLine(SphericalCalculations.CalculateSurfaceDistance(latitudeInDegrees, longitudeInDegrees, square.LatitudeFrom, square.LongitudeTo));

Console.WriteLine(SphericalCalculations.CalculateSurfaceDistance(latitudeInDegrees, longitudeInDegrees, square.LatitudeTo, square.LongitudeFrom));

Console.WriteLine(SphericalCalculations.CalculateSurfaceDistance(latitudeInDegrees, longitudeInDegrees, square.LatitudeTo, square.LongitudeTo));

}

[TestMethod]

public void TestGetdistinace()

{

double latitudeInDegrees = 37.3456D;

double longitudeInDegrees = 119.1234D;

Console.WriteLine(SphericalCalculations.CalculateSurfaceDistance(latitudeInDegrees, longitudeInDegrees, latitudeInDegrees, longitudeInDegrees + 0.001));

Console.WriteLine(SphericalCalculations.CalculateSurfaceDistance(51.517477, -0.096044, 51.517610, -0.097589));

}

[TestMethod]

public void TestGetBeiJingToShangHaiDistinace()

{

// Coordinates of BeiJing is (39°54'20",116°23'29")

double latitudeOfBeiJing = 39 + 54 / 60.0000 + 20 / 3600.0000;

double longitudeOfBeiJing = 116 + 23 / 60.0000 + 29 / 3600.0000;

// Coordinates of Shanghai is (31°13'49.5",121°28'13.21")

double latitudeOfShangHai = 31 + 13 / 60.0000 + 49.5 / 360.0000;

double longitudeOfShangHai = 121 + 28 / 60.0000 + 13.21 / 3600.00;

Console.WriteLine("Distance from Beijing to Shanghai is:");

Console.WriteLine("{0:0.00}KM",SphericalCalculations.CalculateSurfaceDistance(latitudeOfBeiJing, longitudeOfBeiJing, latitudeOfShangHai, longitudeOfShangHai)/1000);

//-11.355 25.44

Console.WriteLine("{0:0.00}M", SphericalCalculations.CalculateSurfaceDistance(11.4, 25.44, 11.3, 25.44));

}