我的最终目标:
写一个 TSQL函数将NAD83状态平面转换(特别是ESRI投影102738 http://spatialreference.org/ref/esri/102738/)到WGS84 Lat / Lng 所以我可以近乎实际时间,在Google地图上绘制原始坐标。
我不想使用外部库,例如Proj4或GDAL,因为我想避免外部的,非sql依赖,我担心将来的管理员在我们的数据库时不会重新安装服务器升级。
我找到了将NAD83 UTM转换为WGS84 Lat / Long的javascript代码(http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html)(见下文)。我已成功将其移植/转换为SQL。
我不知道如何找到数学来编写一个可以将NAD83状态平面坐标转换为NAD 83 UTM的函数(这样我就可以使用我现有的函数将UTM转换为Lat / Lng)
TSQL我从JS移植到将NAD83 UTM转换为WGS84:
/*Adapted from: http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html*/
-----------------------------------------
--USER INPUTS
DECLARE @Operation VARCHAR(50) = 'FromUTMToGeo'
DECLARE @Input_X_or_Lat FLOAT = 686847.2227879118
DECLARE @Input_Y_or_Lng FLOAT = 3653063.504053675
DECLARE @Input_Geog_Zone INT = 14
DECLARE @Input_Geog_Hemi VARCHAR(1) = 'N'
------------------------------------------
--CONSTANTS
DECLARE @gbl_pi FLOAT = 3.14159265358979
DECLARE @gbl_sm_a FLOAT = 6378137.0;
DECLARE @gbl_sm_b FLOAT = 6356752.314;
DECLARE @gbl_sm_EccSquared FLOAT = 6.69437999013e-03;
DECLARE @gbl_UTMScaleFactor FLOAT = 0.9996;
--RadToDeg(rad): (rad / pi * 180.0)
--DegToRad(deg): (deg / 180.0 * pi)
------------------------------------------
IF @Operation = 'FromUTMToGeo'
BEGIN
----------------------------------
DECLARE @x float = 0
DECLARE @y float = 0
DECLARE @southhemi bit = 0
IF @Input_Geog_Hemi = 'S' SET @southhemi = 1
----------------------------------
--X and Y
SET @x = (@Input_X_or_Lat - 500000.0)
SET @x = @x / @gbl_UTMScaleFactor
IF @southhemi = 1 BEGIN SET @y = (@Input_Y_or_Lng - 10000000.0) END
SET @y = @Input_Y_or_Lng / @gbl_UTMScaleFactor
----------------------------------
--cmeridian
-- DegToRad (-183.0 + (zone * 6.0));
DECLARE @cmeridian FLOAT = (-183.0 + (@Input_Geog_Zone * 6.0)) / 180 * @gbl_pi
DECLARE @lambda0 FLOAT = @cmeridian
----------------------------------
--Calculate Latitude and Longtitude
DECLARE @phif FLOAT
DECLARE @Nf FLOAT
DECLARE @Nfpow FLOAT
DECLARE @nuf2 FLOAT
DECLARE @ep2 FLOAT
DECLARE @tf FLOAT
DECLARE @tf2 FLOAT
DECLARE @tf4 FLOAT
DECLARE @cf FLOAT
DECLARE @x1frac FLOAT
DECLARE @x2frac FLOAT
DECLARE @x3frac FLOAT
DECLARE @x4frac FLOAT
DECLARE @x5frac FLOAT
DECLARE @x6frac FLOAT
DECLARE @x7frac FLOAT
DECLARE @x8frac FLOAT
DECLARE @x2poly FLOAT
DECLARE @x3poly FLOAT
DECLARE @x4poly FLOAT
DECLARE @x5poly FLOAT
DECLARE @x6poly FLOAT
DECLARE @x7poly FLOAT
DECLARE @x8poly FLOAT
DECLARE @Lat_AsRad FLOAT
DECLARE @Lng_AsRad FLOAT
DECLARE @Latitude FLOAT
DECLARE @Longitude FLOAT
-------------------------------------------------------------
/* Get the value of phif, the footpoint latitude. */
DECLARE @y_ FLOAT
DECLARE @alpha_ FLOAT
DECLARE @beta_ FLOAT
DECLARE @gamma_ FLOAT
DECLARE @delta_ FLOAT
DECLARE @epsilon_ FLOAT
DECLARE @n FLOAT
DECLARE @FootpointLatitude FLOAT
/* Precalculate n (Eq. 10.18) */
SET @n = (@gbl_sm_a - @gbl_sm_b) / (@gbl_sm_a + @gbl_sm_b);
/* Precalculate alpha_ (Eq. 10.22) */
/* (Same as alpha in Eq. 10.17) */
SET @alpha_ = ((@gbl_sm_a + @gbl_sm_b) / 2.0) * (1 + (POWER(@n, 2.0) / 4) + (POWER(@n, 4.0) / 64));
/* Precalculate y_ (Eq. 10.23) */
SET @y_ = @y / @alpha_;
/* Precalculate beta_ (Eq. 10.22) */
SET @beta_ = (3.0 * @n / 2.0) + (-27.0 * POWER(@n, 3.0) / 32.0) + (269.0 * POWER(@n, 5.0) / 512.0);
/* Precalculate gamma_ (Eq. 10.22) */
SET @gamma_ = (21.0 * POWER(@n, 2.0) / 16.0) + (-55.0 * POWER(@n, 4.0) / 32.0);
/* Precalculate delta_ (Eq. 10.22) */
SET @delta_ = (151.0 * POWER(@n, 3.0) / 96.0) + (-417.0 * POWER(@n, 5.0) / 128.0);
/* Precalculate epsilon_ (Eq. 10.22) */
SET @epsilon_ = (1097.0 * POWER(@n, 4.0) / 512.0);
/* Now calculate the sum of the series (Eq. 10.21) */
SET @FootpointLatitude = @y_ + (@beta_ * SIN(2.0 * @y_))
+ (@gamma_ * SIN(4.0 * @y_))
+ (@delta_ * SIN(6.0 * @y_))
+ (@epsilon_ * SIN(8.0 * @y_));
SET @phif = @FootpointLatitude
-------------------------------------------------------------
/* Precalculate ep2 */
SET @ep2 = (POWER(@gbl_sm_a, 2.0) -POWER(@gbl_sm_b, 2.0)) / POWER(@gbl_sm_b, 2.0);
/* Precalculate cos (phif) */
SET @cf = COS(@phif);
/* Precalculate nuf2 */
SET @nuf2 = @ep2 * POWER(@cf, 2.0);
/* Precalculate Nf and initialize Nfpow */
SET @Nf = POWER(@gbl_sm_a, 2.0) / (@gbl_sm_b * SQRT(1 + @nuf2));
SET @Nfpow = @Nf;
/* Precalculate tf */
SET @tf = TAN(@phif);
SET @tf2 = @tf * @tf;
SET @tf4 = @tf2 * @tf2;
/* Precalculate fractional coefficients for x**n in the equations
below to simplify the expressions for latitude and longitude. */
SET @x1frac = 1.0 / (@Nfpow * @cf);
SET @Nfpow *= @Nf; /* now equals Nf**2) */
SET @x2frac = @tf / (2.0 * @Nfpow);
SET @Nfpow *= @Nf; /* now equals Nf**3) */
SET @x3frac = 1.0 / (6.0 * @Nfpow * @cf);
SET @Nfpow *= @Nf; /* now equals Nf**4) */
SET @x4frac = @tf / (24.0 * @Nfpow);
SET @Nfpow *= @Nf; /* now equals Nf**5) */
SET @x5frac = 1.0 / (120.0 * @Nfpow * @cf);
SET @Nfpow *= @Nf; /* now equals Nf**6) */
SET @x6frac = @tf / (720.0 * @Nfpow);
SET @Nfpow *= @Nf; /* now equals Nf**7) */
SET @x7frac = 1.0 / (5040.0 * @Nfpow * @cf);
SET @Nfpow *= @Nf; /* now equals Nf**8) */
SET @x8frac = @tf / (40320.0 * @Nfpow);
/* Precalculate polynomial coefficients for x**n.
-- x**1 does not have a polynomial coefficient. */
SET @x2poly = -1.0 - @nuf2;
SET @x3poly = -1.0 - 2 * @tf2 - @nuf2;
SET @x4poly = 5.0 + 3.0 * @tf2 + 6.0 * @nuf2 - 6.0 * @tf2 * @nuf2 - 3.0 * (@nuf2 *@nuf2) - 9.0 * @tf2 * (@nuf2 * @nuf2);
SET @x5poly = 5.0 + 28.0 * @tf2 + 24.0 * @tf4 + 6.0 * @nuf2 + 8.0 * @tf2 * @nuf2;
SET @x6poly = -61.0 - 90.0 * @tf2 - 45.0 * @tf4 - 107.0 * @nuf2 + 162.0 * @tf2 * @nuf2;
SET @x7poly = -61.0 - 662.0 * @tf2 - 1320.0 * @tf4 - 720.0 * (@tf4 * @tf2);
SET @x8poly = 1385.0 + 3633.0 * @tf2 + 4095.0 * @tf4 + 1575 * (@tf4 * @tf2);
/* Calculate latitude */
SET @Lat_AsRad = @phif + @x2frac * @x2poly * (@x * @x)
+ @x4frac * @x4poly * POWER(@x, 4.0)
+ @x6frac * @x6poly * POWER(@x, 6.0)
+ @x8frac * @x8poly * POWER(@x, 8.0);
--Radians to Degrees
SET @Latitude = (@Lat_AsRad / @gbl_pi * 180.0)
/* Calculate longitude */
SET @Lng_AsRad = @lambda0 + @x1frac * @x
+ @x3frac * @x3poly * POWER(@x, 3.0)
+ @x5frac * @x5poly * POWER(@x, 5.0)
+ @x7frac * @x7poly * POWER(@x, 7.0);
--Radians to Degrees
SET @Longitude = (@Lng_AsRad / @gbl_pi * 180.0)
------------------------------------------------------------------
SELECT @Latitude As Lat, @Longitude As Lng
END
感谢您的帮助!
答案 0 :(得分:2)
我做了类似的事情但是必须对公式进行修正以创建我所在区域的最接近的近似值。我知道有更好的方法来处理纠正,但它足够接近我的预期目的。
此功能基于NOAA程序SPCS83(Vergsion 2.1) http://www.ngs.noaa.gov/PC_PROD/SPCS83/ 参考:http://www.softwright.com/faq/engineering/Coordinate%20Systems.html
这是Lat函数:
DECLARE @X numeric(15,8)
DECLARE @Y numeric(15,8)
DECLARE @t numeric(15,8)
DECLARE @lon numeric(15,8)
DECLARE @x1 numeric(15,8)
DECLARE @lat0 numeric(15,8)
DECLARE @part1 numeric(15,8)
DECLARE @lat1 numeric(15,8)
DECLARE @lat numeric(15,8)
set @X =((@xCoord * .3048) - 500000)
set @Y =(@yCoord * .3048)
set @t = power(((Sqrt(power(@x,2) + Power((6184598.958 - @y),2))) / 11760085.63),1.376682)
set @lon = ((ATAN(@X / (6184598.958 - @Y))) / 0.726384231) + -2.103121749
set @x1 = @X + 500000
set @lat0 = 1.570796326 - (2 * Atan(power( ((Sqrt(power(@x,2) + power((6184598.958 - @y),2))) / 11760085.63) ,1.376682)))
set @part1 = (1 - (0.08227185422 * Sin(@lat0))) / (1 + (0.08227185422 * Sin(@lat0)))
set @lat1 = .570796326 - (2 * Atan(power(((Sqrt(Power(@x,2) + power((6184598.958 - @y),2))) / 11760085.63),1.376682) * power(@part1, 0.041136)))
While Abs(@lat1 - @lat0) > 0.000000003
Begin
Set @lat0 = @lat1
Set @part1 = (1 - (0.08227185422 * Sin(@lat0))) / (1 + (0.08227185422 * Sin(@lat0)))
Set @lat1 = 1.570796326 - (2 * Atan( @t * ( power(@part1 ,(0.08227185422 / 2) ) ) ))
END
set @lat = @lat1 / 0.01745329252
set @lon = @lon / 0.01745329252
set @lat=(((@lat * 100000) / 100000) + .00331)
--set @lon = @lon * 100000
-- exec StatePlane2Geodetic 1084101.380000, 114080.430000
--print cast(@lat as varchar(20)) + ', ' + cast(@lon as varchar(20))
return @lat
这是Lon功能:
BEGIN
DECLARE @X numeric(15,8)
DECLARE @Y numeric(15,8)
DECLARE @t numeric(15,8)
DECLARE @lon numeric(15,8)
DECLARE @x1 numeric(15,8)
DECLARE @lat0 numeric(15,8)
DECLARE @part1 numeric(15,8)
DECLARE @lat1 numeric(15,8)
DECLARE @lat numeric(15,8)
set @X =((@xCoord * .3048) - 500000)
set @Y =(@yCoord * .3048)
set @t = power(((Sqrt(power(@x,2) + Power((6184598.958 - @y),2))) / 11760085.63),1.376682)
set @lon = ((ATAN(@X / (6184598.958 - @Y))) / 0.726384231) + -2.103121749
set @x1 = @X + 500000
set @lat0 = 1.570796326 - (2 * Atan(power( ((Sqrt(power(@x,2) + power((6184598.958 - @y),2))) / 11760085.63) ,1.376682)))
set @part1 = (1 - (0.08227185422 * Sin(@lat0))) / (1 + (0.08227185422 * Sin(@lat0)))
set @lat1 = .570796326 - (2 * Atan(power(((Sqrt(Power(@x,2) + power((6184598.958 - @y),2))) / 11760085.63),1.376682) * power(@part1, 0.041136)))
While Abs(@lat1 - @lat0) > 0.000000003
Begin
Set @lat0 = @lat1
Set @part1 = (1 - (0.08227185422 * Sin(@lat0))) / (1 + (0.08227185422 * Sin(@lat0)))
Set @lat1 = 1.570796326 - (2 * Atan( @t * ( power(@part1 ,(0.08227185422 / 2) ) ) ))
END
set @lat = @lat1 / 0.01745329252
set @lon = @lon / 0.01745329252
set @lat=(((@lat * 100000) / 100000) + .00331)
--set @lon = @lon * 100000
--print cast(@lat as varchar(20)) + ', ' + cast(@lon as varchar(20))
return @lon