Convert a point form StatePlane to Degrees Minutes Seconds

1965
8
05-04-2011 10:55 AM
by
New Contributor II
How would I convert a point form StatePlane to Degrees Minutes Seconds using the javaScript API?
Tags (2)
8 Replies
Frequent Contributor II
Occasional Contributor
Billy,

If you find the response of the geometry service to be too slow, this can be done using JavaScript on the front-end. It depends on which State Plane zone you are converting (you will have to look up the appropriate false easting/northing, origin, ellipsoid, etc.), but below is the code I use. I have it populating two SPAN boxes at the bottom of my map, but you could change this to return the coordinates instead. It is very responsive and can real-time return coordinates on a mouse pan.

`//BEGIN CUSTOM FUNCTION FOR LAT-LONG DISPLAYfunction convertSP(uX,uY) { // Constants below from NAD 1983 State Plane Nevada West FIPS 2703(Feet). // From ArcMap layer properties. Coordinate system -> NV state plane -> modify // e_sqr is for NAD83 or GRS80 (http:en.wikipedia.org/wiki/NAD83#North_American_Datum_of_1983) var false_easting = (2624666 + (2/3)); // false easting var false_northing = (13123333 + (1/3))  // Should be 0. this is a 'fudge' factor. var a = 6378137.0  //Equatorial Radius (meters) For GRS80 var e_sqr =  0.006694300229 //Eccentricity of ellipsoid (GRS80) var lat_o = 34.75000000000   //Origin Latitude NV state plane var long_o = (118.58 + ((1/3) * 0.01))    // Central Meridan NV state plane var k_o = 0.99990000000000001  // Scale  var pointx_ft = uX    // number   ft var pointx_ft = uX - false_easting // false easting accounted for. var pointy_ft = uY  //number      ft        var pointy_ft = uY - false_northing // false northing accounted for. var e_sqr_2 = Math.pow(e_sqr, 2)    // need this to calculate M var e_sqr_3 = Math.pow(e_sqr, 3)    // need this to calculate M var radianlat_o = lat_o/(180/Math.PI)      //degrees converted to radians     57.2957 var radianLong_o = long_o/(180/Math.PI)    //degrees converted to radians  var pointx_m = pointx_ft/3.2808399  var pointy_m = pointy_ft/3.2808399 var Mpart1_o = ((1-(e_sqr/4)-((3*e_sqr_2)/64)-((5*e_sqr_3)/256))*radianlat_o) var Mpart2_o = ((((3*e_sqr)/8)+((3*e_sqr_2)/32)+((45*e_sqr_3)/1024))*Math.sin(2*radianlat_o)) var Mpart3_o = ((((15*e_sqr_2)/256) + ((45*e_sqr_3)/1024))*4*Math.sin(4*radianlat_o) ) var Mpart4_o =  ((35*e_sqr_3)/3072)*4*Math.sin(6*radianlat_o) var M_o = a*(Mpart1_o - Mpart2_o + Mpart3_o - Mpart4_o)  var e_prim_sqr = e_sqr / (1 - e_sqr)  var M = M_o + (pointy_m / k_o)  var e1 = (1-Math.sqrt((1 - e_sqr))) / (1+Math.sqrt((1 - e_sqr)))             //note: constant only for e_sqr of 0.00676866  var u = M / (   a*( 1-(e_sqr/4)- (3*(Math.pow(e_sqr,2)/64) -   (5*(Math.pow(e_sqr,3)/256) )))  )  //radians var lat1_part1 =  ((3 * (e1/2)) - (27 * (Math.pow(e1,3)/32) )) * Math.sin(2*u) var lat1_part2 =  ((21 * (Math.pow(e1,2)/16)) - (55 * (Math.pow(e1,4)/32) )) * Math.sin(4*u) var lat1_part3 =  ((151 * (Math.pow(e1,3)/96))  * Math.sin(6*u)  ) var lat1_part4 =  ((1097 * (Math.pow(e1,4)/512))  * Math.sin(8*u)  ) var lat1 = u + lat1_part1 + lat1_part2 + lat1_part3   + lat1_part4  lat1 = lat1 * (180/Math.PI) var radian_lat1 = lat1/(180/Math.PI)    //degrees converted to radians var C1 = e_prim_sqr * (0.5*(1 + Math.cos(2*radian_lat1))) var T1 = (1-Math.cos(2*radian_lat1))/(1+Math.cos(2*radian_lat1)) var N1 = a/(Math.sqrt(1-(e_sqr*0.5*(1-Math.cos(2*radian_lat1))))) var R1 = (a*(1-e_sqr))/ Math.sqrt(Math.pow((1-e_sqr * (0.5*(1 - Math.cos(2*radian_lat1))) ),3) ) var D =  pointx_m/(N1*k_o) var Lat_final_part1 = lat1 var Lat_final_part2 = (N1 * (Math.tan(radian_lat1) / R1)) var Lat_final_part3 = Math.pow(D,2)/2 - ((( 5 + (3*T1) + (10*C1) - (4* Math.pow(C1,2)) - (9 * e_prim_sqr)) * Math.pow(D,4))/24) var Lat_final_part4 =  ((61 + (90 * T1) + (298 * C1) + (45 * Math.pow(T1,2)) - (252 * e_prim_sqr) - (3 * Math.pow(C1,2)))* Math.pow(D,6))/720 var Lat_final = Lat_final_part1 - ((Lat_final_part2 *(Lat_final_part3 + Lat_final_part4))     * (180/Math.PI)) var Long_final_part1 = long_o var Long_final_part2 = D   //D var Long_final_part3 = (((1 + (2*T1) + C1))* (Math.pow(D,3))) /6 var Long_final_part4 = 5 - (2 * C1) + (28*T1) - (3 * Math.pow(C1,2)) + (8 * e_prim_sqr) + (24 * Math.pow(T1,2))     Long_final_part4a = Long_final_part4 * (Math.pow(D,5) )     Long_final_part4b = Long_final_part4a /120 var Long_final = (-Long_final_part1 + (((Long_final_part2 - (Long_final_part3 + Long_final_part4b))) /Math.cos(radian_lat1)) * 180/Math.PI) // conversion to ddmmss Degreelat = Math.floor(Lat_final) Degreelong = (Math.floor(Long_final)  + 1) //adjustment minlat = Math.floor(((Lat_final - Degreelat)*60)) minlong = Math.floor((((Long_final - Degreelong)*60))+ 1) seclat = Math.abs(((Lat_final - Degreelat - (minlat/60)) * 3600)) // - 1) seclong = Math.abs(((Long_final - Degreelong - (minlong/60)) * 3600 )) minlong = Math.abs(minlong);  if (seclat >= 1) {  seclat = (seclat -1); } else {  seclat = (seclat + 59);  minlat = (minlat -1) }  seclat = seclat.toFixed(2); seclong = seclong.toFixed(2);  var latitude = Lat_final.toString(); var longitude = Long_final.toString(); latitude = latitude.substr(0,10); longitude = longitude.substr(0,10); if (minlat<10) {  minlat = "0" + minlat; } if (seclat<10) {  seclat = "0" + seclat; } if (minlong<10) {  minlong = "0" + minlong; } if (seclong<10) {  seclong = "0" + seclong; } if (seclat == "60.00") {  seclat = "00.00";  minlat = minlat +1; } if (seclong == "60.00") {  seclong = "00.00";  minlong = minlong +1; }  northing = uY.toFixed(0); easting = uX.toFixed(0);  dojo.byId("coordDMS").innerHTML = " " + Degreelat + "&#176;" + minlat + "\'" + seclat + "\"N " + (-Degreelong) + "&#176;" + minlong + "\'" + seclong + "\"W "; dojo.byId("coordStPl").innerHTML = " Northing: " + northing + " Easting: " + easting + " ";}//END CUSTOM FUNCTION FOR LAT-LONG DISPLAY`
New Contributor III

I know this is and old post but thank you for sharing this code. I found it useful.

I converted your code/formulas above into T-sql functions, one for lat and one for long. Here is the latitude one in case anyone is interested for Florida State Plane East 0901 EPSG 2236:

SET ANSI_NULLS ON

GO

SET QUOTED_IDENTIFIER ON

GO

Alter FUNCTION [dbo].[Langd_Convert_Feet_to_DecimalDegrees_Latitude]

(

-- Add the parameters for the function here

@y Numeric(38,8), -- latitude

@x Numeric(38,8)  -- longitude

)

RETURNS Numeric(38,8)

AS

BEGIN

-- Constants below from NAD 1983 State Plane Florida East FIPS 0901(Feet).

/* From Esri WKT https://epsg.io/2236

["GRS_1980",6378137,298.257222101]],

PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]],PROJECTION["Transverse_Mercator"],

PARAMETER["latitude_of_origin",24.33333333333333],PARAMETER["central_meridian",-81],

PARAMETER["scale_factor",0.999941177],PARAMETER["false_easting",656166.667],PARAMETER["false_northing",0],

UNIT["Foot_US",0.30480060960121924]]

*/

Declare @false_easting Numeric(38,8) = 656166.667 -- original formula was (656166.6666666665 + (2/3)); -- false easting

Declare @false_northing Numeric(38,8) = 0 -- original formula was (0 + (1/3))  -- Should be 0. this is a 'fudge' factor.

Declare @a Numeric(38,8) =  6378137.0  --Equatorial Radius (meters) For GRS80

Declare @e_sqr Numeric(38,8) =  0.006694300229 --Eccentricity of ellipsoid (GRS80)

Declare @lat_o Numeric(38,8) = 24.33333333333333  --Origin Latitude FL state plane

Declare @long_o Numeric(38,8) = 81.0 -- original formula was (81.0 + ((1/3) * 0.01)) -- Central Meridan FL state plane, no negative sign for this formula

Declare @k_o Numeric(38,8) = 0.999941177 --0.9999411764705882  -- Scale factor

Declare @pointx_ft Numeric(38,8) = @x    -- number   ft

Set @pointx_ft = @x - @false_easting -- false easting accounted for.

Declare @pointy_ft Numeric(38,8) = @y  --number      ft

Set @pointy_ft = @y - @false_northing -- false northing accounted for.

Declare @e_sqr_2 Numeric(38,8) = power(@e_sqr, 2)    -- need this to calculate M

Declare @e_sqr_3 Numeric(38,8) = power(@e_sqr, 3)    -- need this to calculate M

Declare @pointx_m Numeric(38,8) = @pointx_ft/3.2808 --@pointx_ft/3.2808399

Declare @pointy_m Numeric(38,8) = @pointy_ft/3.2808 --@pointy_ft/3.2808399

Declare @Mpart3_o Numeric(38,8) = ((((15*@e_sqr_2)/256) + ((45*@e_sqr_3)/1024))*4*sin(4*@radianlat_o) )

Declare @M_o Numeric(38,8) = @a*(@Mpart1_o - @Mpart2_o + @Mpart3_o - @Mpart4_o)

Declare @e_prim_sqr Numeric(38,8) = @e_sqr / (1 - @e_sqr)

Declare @M Numeric(38,8) = @M_o + (@pointy_m / @k_o)

Declare @e1 Numeric(38,8) = (1-sqrt((1 - @e_sqr))) / (1+sqrt((1 - @e_sqr)))             --note: constant only for @e_sqr of 0.00676866

Declare @u Numeric(38,8) = @M / (   @a*( 1-(@e_sqr/4)- (3*(power(@e_sqr,2)/64) -   (5*(power(@e_sqr,3)/256) )))  )  --radians

Declare @lat1_part1 Numeric(38,8) =  ((3 * (@e1/2)) - (27 * (power(@e1,3)/32) )) * sin(2*@u)

Declare @lat1_part2 Numeric(38,8) =  ((21 * (power(@e1,2)/16)) - (55 * (power(@e1,4)/32) )) * sin(4*@u)

Declare @lat1_part3 Numeric(38,8) =  ((151 * (power(@e1,3)/96))  * sin(6*@u)  )

Declare @lat1_part4 Numeric(38,8) =  ((1097 * (power(@e1,4)/512))  * sin(8*@u)  )

Declare @lat1 Numeric(38,8) = @u + @lat1_part1 + @lat1_part2 + @lat1_part3   + @lat1_part4

Set @lat1 = @lat1 * (180/PI())

Declare @C1 Numeric(38,8) = @e_prim_sqr * (0.5*(1 + cos(2*@radian_lat1)))

Declare @R1 Numeric(38,8) = (@a*(1-@e_sqr))/ sqrt(power((1-@e_sqr * (0.5*(1 - cos(2*@radian_lat1))) ),3) )

Declare @D Numeric(38,8) =  @pointx_m/(@N1*@k_o)

Declare @Lat_final_part1 Numeric(38,8) = @lat1

Declare @Lat_final_part2 Numeric(38,8) = (@N1 * (tan(@radian_lat1) / @R1))

Declare @Lat_final_part3 Numeric(38,8) = power(@D,2)/2 - ((( 5 + (3*@T1) + (10*@C1) - (4* power(@C1,2)) - (9 * @e_prim_sqr)) * power(@D,4))/24)

Declare @Lat_final_part4 Numeric(38,8) =  ((61 + (90 * @T1) + (298 * @C1) + (45 * power(@T1,2)) - (252 * @e_prim_sqr) - (3 * power(@C1,2)))* power(@D,6))/720

Declare @Lat_final Numeric(38,8) = @Lat_final_part1 - ((@Lat_final_part2 *(@Lat_final_part3 + @Lat_final_part4))     * (180/PI()))

Declare @Long_final_part1 Numeric(38,8) = @long_o

Declare @Long_final_part2 Numeric(38,8) = @D   --D

Declare @Long_final_part3 Numeric(38,8) = (((1 + (2*@T1) + @C1))* (power(@D,3))) /6

Declare @Long_final_part4 Numeric(38,8) = 5 - (2 * @C1) + (28*@T1) - (3 * power(@C1,2)) + (8 * @e_prim_sqr) + (24 * power(@T1,2))

Declare @Long_final_part4a Numeric(38,8) = @Long_final_part4 * (power(@D,5) )

Declare @Long_final_part4b Numeric(38,8) = @Long_final_part4a /120

Declare @Long_final Numeric(38,8) = (-@Long_final_part1 + (((@Long_final_part2 - (@Long_final_part3 + @Long_final_part4b))) /cos(@radian_lat1)) * 180/PI())

RETURN @Lat_final

END

Frequent Contributor II
@mflawton nice!
New Contributor
Matthew,

I'm trying to get this code to work with NC state plane, I've made the following changes:

var false_easting = (2000000.002616666 + (2 / 3)); // false easting
var false_northing = (0 + (1 / 3)) // Should be 0. this is a 'fudge' factor.
var lat_o = 33.75 //Origin Latitude NV state plane
var long_o = (-79 + ((1 / 3) * 0.01)) // Central Meridan NC state plane

But am not getting the results I need, are there any other modifications I need to make?
Occasional Contributor
Check your Central Meridian. I think it should be "79", not "-79". Notice in my Nevada West calculation I have "118.58" even though it should technically be "-118.58". Good luck!
by
MVP Regular Contributor
I have done the save conversion in JavaScript as well.  Be very careful in determining if your State Plane is Lambert or Transverse Mercator, it is two different calculations

Here is some code for going to and from SP to LL, and to UTM and USNG as well.  Wicked fast, we use it for moveover live coordinate display. (I only convert LL to SP in transverse mercator, since that is what florida west is)
(had to attach, is 21000 lines)

Link in action to show speed
http://www.mymanatee.org/gisapps/mapviewer/index.jsp?type=default&widgetOn=Coordinates
Regular Contributor
You can also use the proj4js library to do the projection.