Select to view content in your preferred language

Convert a point form StatePlane to Degrees Minutes Seconds

3382
8
05-04-2011 10:55 AM
BillGrow
Deactivated User
How would I convert a point form StatePlane to Degrees Minutes Seconds using the javaScript API?
0 Kudos
8 Replies
derekswingley1
Deactivated User
0 Kudos
MatthewLawton
Deactivated User
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 DISPLAY
function 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
ScottMinter
Occasional Contributor

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).

 -- e_sqr is for NAD83 or GRS80 (http:en.wikipedia.org/wiki/NAD83#North_American_Datum_of_1983)

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

 PROJCS["NAD83_Florida_East_ftUS",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID

 ["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 @radianlat_o Numeric(38,8) = @lat_o/(180/PI())      --degrees converted to radians     57.2957

 Declare @radianLong_o Numeric(38,8) = @long_o/(180/PI())    --degrees converted to radians

 

 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 @Mpart1_o Numeric(38,8) = ((1-(@e_sqr/4)-((3*@e_sqr_2)/64)-((5*@e_sqr_3)/256))*@radianlat_o)

 Declare @Mpart2_o Numeric(38,8) = ((((3*@e_sqr)/8)+((3*@e_sqr_2)/32)+((45*@e_sqr_3)/1024))*sin(2*@radianlat_o))

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

 Declare @Mpart4_o Numeric(38,8) =  ((35*@e_sqr_3)/3072)*4*sin(6*@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 @radian_lat1 Numeric(38,8) = @lat1/(180/PI())    --degrees converted to radians

 

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

 Declare @T1 Numeric(38,8) = (1-cos(2*@radian_lat1))/(1+cos(2*@radian_lat1))

 Declare @N1 Numeric(38,8) = @a/(sqrt(1-(@e_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

derekswingley1
Deactivated User
@mflawton nice!
0 Kudos
JerrySimmons
Deactivated User
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?
0 Kudos
MatthewLawton
Deactivated User
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!
0 Kudos
JeffPace
MVP Alum
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
0 Kudos
JeffJacobson
Frequent Contributor
You can also use the proj4js library to do the projection.
0 Kudos