![]() |
C# code to convert DD to UTM .. here it is !!
To whom it may concern,
I had some trouble converting DD to UTM ( WGS84 ). I looked in every dark corner on the net, but I was unable to find the code to do it programmatically without the use of ( sometimes ) expensive third party controls. So .. I decided to hack something together myself , and all in managed code :D. I decide to post it, since I know there are many people looking for it and they don't have to go throught the same struggle as me to get is done. remember .. this is just code to convert Lat/Long DD ( eg. 44.123456 ) to UTM Northing/Easting ( eg. 7342333, 218734, 31T). I'm still working on the code to do it the other way around and code to include other Datums. You can use this code directly in your application. You'll need to do a little bit of work if you want to update MathEngine.cs with this code. Cheers, private void ConvertLatLongToUTM(object Sender, EventArgs e) { //Read the inputs string sLong = textboxLongitude.Text; string sLat = textboxLatitude.Text; double dLong = ParseIn(sLong); double dLat = ParseIn(sLat); textboxLongitude.Text = dLong.ToString("0.000000°"); textboxLatitude.Text = dLat.ToString("0.000000°"); double dX; double dY; string Zone; //Convert LatLongtoUTM(dLat, dLong, out dY, out dX, out Zone); //Populate UTM units ( Northing, Easting and Zone ) txtboxEasting.Text = dX.ToString("###,###,### meters"); txtboxNorthing.Text = dY.ToString("###,###,### meters"); txtZone.Text = Zone; //Populate North/South char cZoneLetter = UTMZone[UTMZone.Length - 1]; bool bNorth = (cZoneLetter >= 'N'); //Populate da Zone string sZoneNo = UTMZone.Substring(0, UTMZone.Length - 1); } private double ParseIn(string sIn) { sIn = sIn.Trim(); StringBuilder sb = new StringBuilder(sIn); for (int n = 0; n < sIn.Length; n++) { if (!Char.IsDigit(sIn[n]) && sIn[n] != '-' && sIn[n] != '.') { sb[n] = 'X'; } } sb.Replace("X", ""); if (sb.Length == 0) { return 0.0; } return Double.Parse(sb.ToString()); } void LatLongtoUTM( double Lat, double Long, out double UTMNorthing, out double UTMEasting, out string Zone ) { double a = 6378137; //WGS84 double eccSquared = 0.00669438; //WGS84 double k0 = 0.9996; double LongOrigin; double eccPrimeSquared; double N, T, C, A, M; //Make sure the longitude is between -180.00 .. 179.9 double LongTemp = (Long+180)-((int)((Long+180)/360))*360-180; // -180.00 .. 179.9; double LatRad = Lat*deg2rad; double LongRad = LongTemp*deg2rad; double LongOriginRad; int ZoneNumber; ZoneNumber = ((int)((LongTemp + 180)/6)) + 1; if( Lat >= 56.0 && Lat < 64.0 && LongTemp >= 3.0 && LongTemp < 12.0 ) ZoneNumber = 32; // Special zones for Svalbard if( Lat >= 72.0 && Lat < 84.0 ) { if( LongTemp >= 0.0 && LongTemp < 9.0 ) ZoneNumber = 31; else if( LongTemp >= 9.0 && LongTemp < 21.0 ) ZoneNumber = 33; else if( LongTemp >= 21.0 && LongTemp < 33.0 ) ZoneNumber = 35; else if( LongTemp >= 33.0 && LongTemp < 42.0 ) ZoneNumber = 37; } LongOrigin = (ZoneNumber - 1)*6 - 180 + 3; //+3 puts origin in middle of zone LongOriginRad = LongOrigin * deg2rad; //compute the UTM Zone from the latitude and longitude Zone = ZoneNumber.ToString() + UTMLetterDesignator(Lat); eccPrimeSquared = (eccSquared)/(1-eccSquared); N = a/Math.Sqrt(1-eccSquared*Math.Sin(LatRad)*Math.Sin(Lat Rad)); T = Math.Tan(LatRad)*Math.Tan(LatRad); C = eccPrimeSquared*Math.Cos(LatRad)*Math.Co s(LatRad); A = Math.Cos(LatRad)*(LongRad-LongOriginRad); M = a*((1 - eccSquared/4 - 3*eccSquared*eccSquared/64 - 5*eccSquared*eccSquared*eccSquared/256)*LatRad - (3*eccSquared/8 + 3*eccSquared*eccSquared/32 + 45*eccSquared*eccSquared*eccSquared/1024)*Math.Sin(2*LatRad) + (15*eccSquared*eccSquared/256 + 45*eccSquared*eccSquared*eccSquared/1024)*Math.Sin(4*LatRad) - (35*eccSquared*eccSquared*eccSquared/3072)*Math.Sin(6*LatRad)); UTMEasting = (double)(k0*N*(A+(1-T+C)*A*A*A/6 + (5-18*T+T*T+72*C-58*eccPrimeSquared)*A*A*A*A*A/120) + 500000.0); UTMNorthing = (double)(k0*(M+N*Math.Tan(LatRad)*(A*A/2+(5-T+9*C+4*C*C)*A*A*A*A/24 + (61-58*T+T*T+600*C-330*eccPrimeSquared)*A*A*A*A*A*A/720))); if(Lat < 0) UTMNorthing += 10000000.0; //10000000 meter offset for southern hemisphere } private char UTMLetterDesignator(double Lat) { char LetterDesignator; if ((84 >= Lat) && (Lat >= 72)) LetterDesignator = 'X'; else if ((72 > Lat) && (Lat >= 64)) LetterDesignator = 'W'; else if ((64 > Lat) && (Lat >= 56)) LetterDesignator = 'V'; else if ((56 > Lat) && (Lat >= 48)) LetterDesignator = 'U'; else if ((48 > Lat) && (Lat >= 40)) LetterDesignator = 'T'; else if ((40 > Lat) && (Lat >= 32)) LetterDesignator = 'S'; else if ((32 > Lat) && (Lat >= 24)) LetterDesignator = 'R'; else if ((24 > Lat) && (Lat >= 16)) LetterDesignator = 'Q'; else if ((16 > Lat) && (Lat >= 8)) LetterDesignator = 'P'; else if ((8 > Lat) && (Lat >= 0)) LetterDesignator = 'N'; else if ((0 > Lat) && (Lat >= -8)) LetterDesignator = 'M'; else if ((-8 > Lat) && (Lat >= -16)) LetterDesignator = 'L'; else if ((-16 > Lat) && (Lat >= -24)) LetterDesignator = 'K'; else if ((-24 > Lat) && (Lat >= -32)) LetterDesignator = 'J'; else if ((-32 > Lat) && (Lat >= -40)) LetterDesignator = 'H'; else if ((-40 > Lat) && (Lat >= -48)) LetterDesignator = 'G'; else if ((-48 > Lat) && (Lat >= -56)) LetterDesignator = 'F'; else if ((-56 > Lat) && (Lat >= -64)) LetterDesignator = 'E'; else if ((-64 > Lat) && (Lat >= -72)) LetterDesignator = 'D'; else if ((-72 > Lat) && (Lat >= -80)) LetterDesignator = 'C'; else LetterDesignator = 'Z'; //Latitude is outside the UTM limits return LetterDesignator; } class Ellipsoid { //Attributes public string ellipsoidName; public double EquatorialRadius; public double eccentricitySquared; public Ellipsoid(string name, double radius, double ecc) { ellipsoidName = name; EquatorialRadius = radius; eccentricitySquared = ecc; } }; |
Nice.. I posted the URL to the forum to let the other devs take a peak.
|
Reprojection
General purpose reprojection is rather tricky. We use proj.4 as a standard reprojection library. It is part of the WorldWind SVN I was planning to make a similar method in PluginSDK.
http://proj.maptools.org/ |
I couldn't agree more. I need this particular conversion for a DLL that I'm writing. I don't want to blow the DLL out of proportion so I 'hardcoded' the conversion. I couldn't see any harm in posting it.
What are you suggesting ? .. for the sake of standarisation quit posting customised code. I could go with that .. not a problem :) |
Thanks for posting this, arguably it's better solved by other means but it's always great to find other's solutions via this or that code.
BTW, there are C# examples of running GDAL/OGR/PROJ.4 in the /csharp directory of FWTools. Not relevant given your immediate need, but they might be of interest. |
Also keep in mind with OGR that the C# bindings are based off of the OGR C libs, so the detailed C++ documentation and examples on the fwtools site aren't of much use.
|
Nice
Nice. Using proj.4 would be nice too if reduced to a set of simple calls in pluginSDK for common stuff... That way we would abstract out what library or implementation were using.
Nigel PS Here's a set of conversions written in PERL http://search.cpan.org/src/GRAHAMC/G...TM-0.06/UTM.pm |
Thank you all for posting back at me. I value the input. It may look like I'm re-inventing the wheel and to be honest .. that's exactly what I'm doing. I finished the code to convert UTM to Lat/long and it's working well.
I know that What_nick is making a similar projection conversion in pluginSDK, so I might as well wait to prevent me from doing double work. Currently I'm working on implementing this in MathEngine.cs. I'm thinking about posting that instead of continiously dumping code in here. Two birds with one stone. Perhaps I'm going to rattle a few dev cages and run this particular topic by them, if they're not reading it already. Although it's an open forum and that bits of code are always more than welcome , I'm still fairly new on WW and therefore unaware of any code of conduct and/or the hierachie in here. Cheers |
Quote:
You can post patches here or in the irc channel. If you are going to be making a lot of changes then check with Bull_[UK] on irc to see about getting commit access. |
Yah, post it. Should be interesting to fiddle with.
Nigel Quote:
|
| All times are GMT +1. The time now is 03:07 AM. |
Powered by vBulletin® Version 3.7.1
Copyright ©2000 - 2013, Jelsoft Enterprises Ltd.