<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-9064593862349906054</id><updated>2012-01-28T20:17:22.157Z</updated><category term='vb.net active directory largeinteger pullingteeth'/><category term='maps'/><category term='work'/><category term='.net development'/><title type='text'>Kev Winchcombe's Inane Scribbles</title><subtitle type='html'>A collection of some problems I've not found answers to with a one-hit google.
&lt;br&gt;There's possibly, or even probably, or more likely definately, 
&lt;br&gt;better ways to achieve the same results.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://kwinchcombe.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9064593862349906054/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://kwinchcombe.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Kev Winchcombe</name><uri>http://www.blogger.com/profile/07812274593001670627</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>2</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-9064593862349906054.post-1917091390338002312</id><published>2008-03-04T16:22:00.000Z</published><updated>2008-03-04T17:33:02.462Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='vb.net active directory largeinteger pullingteeth'/><title type='text'>VB.Net And The Revenge Of The Locked Out User Account</title><content type='html'>&lt;h2&gt;HighParts, LowParts, Low Points and (eventually) High Points.&lt;/h2&gt;So this morning I got in early to work and realised that a couple of application user accounts were locked out.&lt;br /&gt;"I know" I thought I'll write a console app to flag these up to our Helpdesk and what's more I'll do it all before the rest of my team get in, in thirty minutes time.&lt;br /&gt;Sounds too good to be true, yeah, of course it was...what an idiot!  I probably could have achieved this if only I was a C# programmer, but alas not, it's VB.Net for me.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Here's What I Wanted&lt;/h2&gt;A console app to check the locked out status of each each within a certain Active Directory structure OU (named Application Accounts, snazzy eh?). An added bonus would be if I could tell when the account was locked out.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Here's What Happened&lt;/h2&gt;As hoped the app took only a few minutes to write, except of course the 'added bonus' which has taken me the rest of the day.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;So Why The Delay?&lt;/h2&gt;To check whether an account is locked you retrieve the lockoutTime property for a directory entry. This 'large integer' value represents the nanoseconds between 1st January 1601 and the time the account was locked out.&lt;br /&gt;Large integers need to split into a HighPart and a LowPart using Reflection.&lt;br /&gt;(Are you still with me? God knows this confused the hell out of me.)&lt;br /&gt;All the examples I found were in C# and most included bitshifting '&lt;&lt;' which didn't seem to work for me.&lt;br /&gt;(At this point my memory thought of '32 bits of a bus' in &lt;a target="_blank" href="http://www.youtube.com/watch?v=dPmiC_Zt88I"&gt;John Cleese's Compaq Advert&lt;/a&gt;.)&lt;br /&gt;So I settled for copying the best bits (that is, the bits I understood) from many posts/articles and I cobbled them together giving the final result.&lt;br /&gt;NOTE: I'd love to thank particular blogs, articles, people, but truth be told I've read so many articles today I wouldn't know which ones I took which bit from.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;What Was The End Result?&lt;/h2&gt;An application that detects locked out users and emails someone else. Great, nothing more for me to do.&lt;br /&gt;&lt;br /&gt;&lt;h2&gt;Here's The Code&lt;/h2&gt;&lt;br /&gt;&lt;div style="margin-top:-30px; overflow:auto; border: 1px solid #f0f0f0;"&gt;&lt;pre&gt;&lt;small&gt;&lt;br /&gt;Imports System.DirectoryServices&lt;br /&gt;Imports System.IO&lt;br /&gt;Imports System.Net.Mail&lt;br /&gt;&lt;br /&gt;Module Module1&lt;br /&gt;&lt;br /&gt;    Sub Main()&lt;br /&gt;        Dim results As SearchResultCollection&lt;br /&gt;        Dim srch As New DirectorySearcher()&lt;br /&gt;        srch.Filter = "objectClass=User"&lt;br /&gt;        srch.SearchRoot = New DirectoryEntry("LDAP://OU=Application Accounts,DC=XXXXX,DC=XXXXX,DC=XXXXX")&lt;br /&gt;        results = srch.FindAll&lt;br /&gt;        For Each result As SearchResult In results&lt;br /&gt;            TestLockedOut(result)&lt;br /&gt;        Next&lt;br /&gt;        srch.Dispose()&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;&lt;br /&gt;    ''' Test the account to see if locked out, if so send an email &lt;br /&gt;    ''' &amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="user"&amp;gt;Active directory search result&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;    Private Sub TestLockedOut(ByVal user As SearchResult)&lt;br /&gt;        Dim strUser As String, intValue As Integer&lt;br /&gt;        strUser = user.GetDirectoryEntry.Properties("sAMAccountName").Value.ToString&lt;br /&gt;        intValue = CType(user.GetDirectoryEntry.Properties("userAccountControl").Value, Integer)&lt;br /&gt;        Console.Write(strUser)&lt;br /&gt;        Dim objLockout As Object = user.GetDirectoryEntry.Properties("lockoutTime").Value&lt;br /&gt;        If Not (objLockout Is Nothing) Then&lt;br /&gt;            Dim intLargeInteger As Int64 = GetLargeIntegerValue(objLockout)&lt;br /&gt;            If intLargeInteger &amp;gt; 0 Then&lt;br /&gt;                Console.Write("  locked out " &amp; DateTime.FromFileTime(intLargeInteger))&lt;br /&gt;                SendEmail(strUser, DateTime.FromFileTime(intLargeInteger))&lt;br /&gt;            End If&lt;br /&gt;            Console.WriteLine(" ")&lt;br /&gt;        End If&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;&lt;br /&gt;    ''' Retrieve the value from the object and convert to an amount of nanoseconds since 1st Jan 1601&lt;br /&gt;    ''' &amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="largeInteger"&amp;gt;The retrieved value from 'lockoutTime'&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;    ''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;    Private Function GetLargeIntegerValue(ByVal largeInteger As Object) As Int64&lt;br /&gt;        Dim type As System.Type = largeInteger.GetType()&lt;br /&gt;        Dim reflectionBinder As Reflection.Binder = System.Type.DefaultBinder&lt;br /&gt;        Dim args() As Object&lt;br /&gt;        Dim highPart As Integer = CType(type.InvokeMember("HighPart", Reflection.BindingFlags.GetProperty, reflectionBinder, largeInteger, args), Integer)&lt;br /&gt;        Dim lowPart As Integer = type.InvokeMember("LowPart", Reflection.BindingFlags.GetProperty, reflectionBinder, largeInteger, args) ', Integer)&lt;br /&gt;        Dim result As Long&lt;br /&gt;        result = CType(highPart * (2 ^ 32), Long) + (lowPart And &amp;H7FFFFFFF)&lt;br /&gt;        If lowPart And &amp;H80000000 Then result += (2 ^ 31)&lt;br /&gt;        Return result&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    Private Sub SendEmail(ByVal AccountName As String, ByVal LockedDateTime As DateTime)&lt;br /&gt;        ' lots of help on the system.net.mail namespace is available here : http://www.systemnetmail.com/&lt;br /&gt; ' do you own thing to send a mail&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;End Module&lt;br /&gt;&lt;/small&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9064593862349906054-1917091390338002312?l=kwinchcombe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kwinchcombe.blogspot.com/feeds/1917091390338002312/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9064593862349906054&amp;postID=1917091390338002312' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9064593862349906054/posts/default/1917091390338002312'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9064593862349906054/posts/default/1917091390338002312'/><link rel='alternate' type='text/html' href='http://kwinchcombe.blogspot.com/2008/03/vbnet-and-revenge-of-locked-out-user.html' title='VB.Net And The Revenge Of The Locked Out User Account'/><author><name>Kev Winchcombe</name><uri>http://www.blogger.com/profile/07812274593001670627</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-9064593862349906054.post-2273149030462207281</id><published>2007-10-04T00:07:00.001+01:00</published><updated>2008-03-20T15:18:03.196Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='maps'/><category scheme='http://www.blogger.com/atom/ns#' term='work'/><category scheme='http://www.blogger.com/atom/ns#' term='.net development'/><title type='text'>An Englishman In Google Maps - Plotting Easting/Northing on Google Maps</title><content type='html'>&lt;h2&gt;Plotting Easting/Northing on Google Maps or Virtual Earth&lt;/h2&gt;&lt;br /&gt;&lt;p&gt;I work for a public sector organisation in the UK and wanted to be able to display various bits of information using Google Maps. (Nothing personal Mr Gates but the first map-related RSS article I read was about how to &lt;a href="http://gathadams.com/2007/08/21/add-google-maps-to-your-net-site-in-10-minutes/" target="_blank"&gt;add Google Maps to your site in 10 minutes&lt;/a&gt; - not Virtual Earth.)&lt;br /&gt;Great I thought: we've got the OS Easting/Northing for every local property so putting that on the maps will be easy.&lt;br /&gt;&lt;br /&gt;As if.&lt;br /&gt;&lt;br /&gt;Anyone who's tried this before will know that it's actually quite tedious and is marginally preferable to drilling your own teeth with a Black &amp;amp; Decker. Personally I wished that I learned more javascript earlier in my career and have advised my kids that they should pay attention at school when sines and cosines are mentioned.&lt;br /&gt;&lt;br /&gt;To get a point on Google Maps it seemed I would have to convert the &lt;a target="_blank" href="http://www.ordnancesurvey.co.uk/oswebsite/gps/information/coordinatesystemsinfo/guidecontents/"&gt;OS Grid Ref&lt;/a&gt; to a Latitude/Longitude and plot that on the map. Almost correct except that this would plot an OS Lat/Lon against a &lt;a target="_blank" href="http://en.wikipedia.org/wiki/WGS84"&gt;WGS84&lt;/a&gt; map, so the OS Lat/Long needs to be converted to a WGS84 Lat/Lon first.&lt;br /&gt;&lt;br /&gt;Luckily the &lt;a target="_blank" href="http://www.movable-type.co.uk/scripts/latlong-gridref.html"&gt;conversions were already available&lt;/a&gt; (thanks to &lt;a target="_blank"  href="http://www.movable-type.co.uk/" target="_blank"&gt;Chris Veness&lt;/a&gt;) on the web but I couldn't locate a VB based version. So I decided to write my own VB.Net stuff to do the conversions so I could do these calculations server-side rather than in Javascript. To do this I converted Chris Veness' scripts which I barely understood. Once I'd written the converter I used it to bulk convert all property easting/northings and save the WGS84 Lat/Long in the databases, meaning that I'd never have to convert them again.&lt;br /&gt;&lt;br /&gt;Caveat: I've tested this for various properties within my organisation's local area and it works for me. If it works for you too, great, if not then let me know where the errors are.&lt;br /&gt;&lt;br /&gt;I created a .Net class project named GISFunctions.&lt;br /&gt;&lt;/p&gt;&lt;br /&gt;&lt;h3&gt;How To Test The Class Project&lt;/h3&gt;&lt;br /&gt;&lt;div style="margin-top:-30px; overflow:auto; border: 1px solid #f0f0f0;"&gt;&lt;pre&gt;&lt;small&gt;    Dim strEasting as String = "462533"&lt;br /&gt;    Dim strNorthing as String = "104496"&lt;br /&gt;    Dim objEastingNorthing As New GISFunctions.EastingNorthing(strEasting &amp;amp; strNorthing)&lt;br /&gt;    ' create OS Lat/Long&lt;br /&gt;    Dim latlngOS As GISFunctions.LatitudeLongitude&lt;br /&gt;    latlngOS = GISFunctions.Conversions.OSGridToLatLong(dr("Xref").ToString &amp;amp; dr("Yref").ToString)&lt;br /&gt;    ' create WGS84 Lat/Long&lt;br /&gt;    Dim latlngWGS84 As GISFunctions.LatitudeLongitude&lt;br /&gt;    latlngWGS84 = GISFunctions.Conversions.OSGB36toWGS84(latlngOS)&lt;/small&gt;&lt;/pre&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;The Code For The Class Project&lt;/h3&gt;&lt;br /&gt;&lt;div style="margin-top:-30px; overflow:auto; border: 1px solid #f0f0f0;"&gt;&lt;pre&gt;&lt;small&gt;Public Class EastingNorthing&lt;br /&gt;    Private _easting As String&lt;br /&gt;    Private _northing As String&lt;br /&gt;    Private _gridSquare As String&lt;br /&gt;    Private _gridReference As String&lt;br /&gt;    Private _gridReferenceDigitsOnly As String&lt;br /&gt;    Public Sub New(ByVal reference As String)&lt;br /&gt;        _gridReference = reference&lt;br /&gt;        ConvertGridReference(reference)&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property Easting() As String&lt;br /&gt;        Get&lt;br /&gt;            Return _easting&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property Northing() As String&lt;br /&gt;        Get&lt;br /&gt;            Return _northing&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property GridSquare() As String&lt;br /&gt;        Get&lt;br /&gt;            Return _gridSquare&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property EastingNorthing() As String&lt;br /&gt;        Get&lt;br /&gt;            Return _easting &amp;amp; _northing&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property GridReference() As String&lt;br /&gt;        Get&lt;br /&gt;            Return _gridReference&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property GridReferenceDigitsOnly() As String&lt;br /&gt;        Get&lt;br /&gt;            Return _gridReferenceDigitsOnly&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Private Sub ConvertGridReference(ByVal reference As String)&lt;br /&gt;        If IsNumeric(reference.Substring(0, 2)) = False Then&lt;br /&gt;            _gridSquare = reference.Substring(0, 2)&lt;br /&gt;            _easting = reference.Substring(2, (reference.Length - 2) / 2)&lt;br /&gt;            _northing = reference.Substring(2 + ((reference.Length - 2) / 2))&lt;br /&gt;            Dim tmpString As String = Conversions.ConvertOSGridLetterToNumber(_gridSquare)&lt;br /&gt;            _easting = tmpString.Substring(0, 1) + _easting&lt;br /&gt;            _northing = tmpString.Substring(1, 1) + _northing&lt;br /&gt;        Else&lt;br /&gt;            _easting = reference.Substring(0, reference.Length / 2)&lt;br /&gt;            _northing = reference.Substring(reference.Length / 2)&lt;br /&gt;            _gridSquare = Conversions.ConvertOSGridNumberToLetter(_easting, _northing)&lt;br /&gt;        End If&lt;br /&gt;        _gridReferenceDigitsOnly = _easting.ToString &amp;amp; _northing.ToString&lt;br /&gt;        _gridReference = _gridSquare &amp;amp; _easting.Substring(1) &amp;amp; _northing.Substring(1)&lt;br /&gt;    End Sub&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;''' &amp;lt;summary&amp;gt;&lt;br /&gt;''' A class which contains latitude, longitude and height&lt;br /&gt;''' &amp;lt;/summary&amp;gt;&lt;br /&gt;''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;Public Class LatitudeLongitude&lt;br /&gt;    Private _latitude As Double&lt;br /&gt;    Private _longitude As Double&lt;br /&gt;    Private _height As Double&lt;br /&gt;    Public Sub New(ByVal latitude As Double, ByVal longitude As Double, ByVal height As Double)&lt;br /&gt;        _latitude = latitude&lt;br /&gt;        _longitude = longitude&lt;br /&gt;        _height = height&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Public Property latitude() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _latitude&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Double)&lt;br /&gt;            _latitude = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public Property longitude() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _longitude&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Double)&lt;br /&gt;            _longitude = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public Property height() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _height&lt;br /&gt;        End Get&lt;br /&gt;        Set(ByVal value As Double)&lt;br /&gt;            _height = value&lt;br /&gt;        End Set&lt;br /&gt;    End Property&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;''' &amp;lt;summary&amp;gt;&lt;br /&gt;''' EllipseParameter contains ellipse definition parameters used for conversion&lt;br /&gt;''' &amp;lt;/summary&amp;gt;&lt;br /&gt;''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;Public Class EllipseParameter&lt;br /&gt;    Private _semiMajorAxisA As Double&lt;br /&gt;    Private _semiMinorAxisB As Double&lt;br /&gt;    Private _f As Double&lt;br /&gt;    Public Sub New(ByVal EllipseType As String)&lt;br /&gt;        Select Case LCase(EllipseType)&lt;br /&gt;            Case "wgs84"&lt;br /&gt;                _semiMajorAxisA = 6378137&lt;br /&gt;                _semiMinorAxisB = 6356752.3142&lt;br /&gt;                _f = 1 / 298.257223563&lt;br /&gt;            Case "airy1830"&lt;br /&gt;                _semiMajorAxisA = 6377563.396&lt;br /&gt;                _semiMinorAxisB = 6356256.91&lt;br /&gt;                _f = 1 / 299.3249646&lt;br /&gt;            Case Else&lt;br /&gt;                Throw New Exception("EllipseType should be either WGS84 or Airy1830")&lt;br /&gt;        End Select&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property SemiMajorAxisA() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _semiMajorAxisA&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property SemiMinorAxisB() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _semiMinorAxisB&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property f() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _f&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;''' &amp;lt;summary&amp;gt;&lt;br /&gt;''' ConversionParameter is a class of parameters used when converting from OSGB36 to WGS84 and vice versa&lt;br /&gt;''' &amp;lt;/summary&amp;gt;&lt;br /&gt;''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;Public Class ConversionParameter&lt;br /&gt;    Private _tx As Double&lt;br /&gt;    Private _ty As Double&lt;br /&gt;    Private _tz As Double&lt;br /&gt;    Private _rx As Double&lt;br /&gt;    Private _ry As Double&lt;br /&gt;    Private _rz As Double&lt;br /&gt;    Private _s As Double&lt;br /&gt;    Private _conversionType As String&lt;br /&gt;&lt;br /&gt;    Public Sub New(ByVal ConversionType As String)&lt;br /&gt;        _conversionType = ConversionType&lt;br /&gt;        Select Case LCase(ConversionType)&lt;br /&gt;            Case "osgb36towgs84"&lt;br /&gt;                _tx = 446.448&lt;br /&gt;                _ty = -125.157&lt;br /&gt;                _tz = 542.06&lt;br /&gt;                _rx = 0.1502&lt;br /&gt;                _ry = 0.247&lt;br /&gt;                _rz = 0.8421&lt;br /&gt;                _s = -20.4894&lt;br /&gt;            Case "wgs84toosgb36"&lt;br /&gt;                _tx = -446.448&lt;br /&gt;                _ty = 125.157&lt;br /&gt;                _tz = -542.06&lt;br /&gt;                _rx = -0.1502&lt;br /&gt;                _ry = -0.247&lt;br /&gt;                _rz = -0.8421&lt;br /&gt;                _s = 20.4894&lt;br /&gt;            Case Else&lt;br /&gt;                Throw New Exception("ConversionType should be either WGS84toOSGB36 or OSGB36toWGS84")&lt;br /&gt;        End Select&lt;br /&gt;    End Sub&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property ConversionType() As String&lt;br /&gt;        Get&lt;br /&gt;            Return _conversionType&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property tx() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _tx&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property ty() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _ty&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property tz() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _tz&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property rx() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _rx&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property ry() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _ry&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property rz() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _rz&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;&lt;br /&gt;    Public ReadOnly Property s() As Double&lt;br /&gt;        Get&lt;br /&gt;            Return _s&lt;br /&gt;        End Get&lt;br /&gt;    End Property&lt;br /&gt;End Class&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Public Class Conversions&lt;br /&gt;    Public Shared Function OSGB36toWGS84(ByVal p1) As LatitudeLongitude&lt;br /&gt;        Dim latlngNew = ConvertCoordinates(p1, New EllipseParameter("Airy1830"), New ConversionParameter("OSGB36toWGS84"), _&lt;br /&gt;            New EllipseParameter("WGS84"))&lt;br /&gt;        Return latlngNew&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    Public Shared Function WGS84toOSGB36(ByVal p1) As LatitudeLongitude&lt;br /&gt;        Dim latlngNew = ConvertCoordinates(p1, New EllipseParameter("WGS84"), New ConversionParameter("WGS84toOSGB36"), _&lt;br /&gt;            New EllipseParameter("Airy1830"))&lt;br /&gt;        Return latlngNew&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    Private Shared Function ConvertCoordinates(ByVal OriginalLatLong As LatitudeLongitude, ByVal EllipseParamSource As EllipseParameter, _&lt;br /&gt;        ByVal ConversionParam As ConversionParameter, ByVal ElliseParamTarget As EllipseParameter)&lt;br /&gt;        ' convert polar to cartesian coordinates (using source ellipse)&lt;br /&gt;        Dim dblOriginalLatitudeInRadians As Double = ConvertDegreesToRadians(OriginalLatLong.latitude)&lt;br /&gt;        Dim dblOriginalLongitudeInRadians As Double = ConvertDegreesToRadians(OriginalLatLong.longitude)&lt;br /&gt;        Dim dblTempSemiMajorAxis As Double = EllipseParamSource.SemiMajorAxisA&lt;br /&gt;        Dim dblTempSemiMinorAxis As Double = EllipseParamSource.SemiMinorAxisB&lt;br /&gt;        Dim f As Double = EllipseParamSource.f&lt;br /&gt;        Dim dblsinPhi = Math.Sin(dblOriginalLatitudeInRadians)&lt;br /&gt;        Dim dblcosPhi = Math.Cos(dblOriginalLatitudeInRadians)&lt;br /&gt;        Dim dblsinLambda = Math.Sin(dblOriginalLongitudeInRadians)&lt;br /&gt;        Dim dblcosLambda = Math.Cos(dblOriginalLongitudeInRadians)&lt;br /&gt;        Dim H As Integer = 1 'p1.height&lt;br /&gt;        Dim eSq = (dblTempSemiMajorAxis * dblTempSemiMajorAxis - dblTempSemiMinorAxis * dblTempSemiMinorAxis) / (dblTempSemiMajorAxis * dblTempSemiMajorAxis)&lt;br /&gt;        Dim nu = dblTempSemiMajorAxis / Math.Sqrt(1 - eSq * dblsinPhi * dblsinPhi)&lt;br /&gt;        Dim x1 = (nu + H) * dblcosPhi * dblcosLambda&lt;br /&gt;        Dim y1 = (nu + H) * dblcosPhi * dblsinLambda&lt;br /&gt;        Dim z1 = ((1 - eSq) * nu + H) * dblsinPhi&lt;br /&gt;        ' apply helmert transform using appropriate params&lt;br /&gt;        Dim rx As Double = ConversionParam.rx / 3600 * Math.PI / 180  ' normalise seconds to radians&lt;br /&gt;        Dim ry As Double = ConversionParam.ry / 3600 * Math.PI / 180&lt;br /&gt;        Dim rz As Double = ConversionParam.rz / 3600 * Math.PI / 180&lt;br /&gt;        Dim s1 As Double = ConversionParam.s / 1000000.0 + 1              ' normalise ppm to (s+1)&lt;br /&gt;        ' apply transform&lt;br /&gt;        Dim x2 As Double = ConversionParam.tx + x1 * s1 - y1 * rz + z1 * ry&lt;br /&gt;        Dim y2 As Double = ConversionParam.ty + x1 * rz + y1 * s1 - z1 * rx&lt;br /&gt;        Dim z2 As Double = ConversionParam.tz - x1 * ry + y1 * rx + z1 * s1&lt;br /&gt;        ' convert cartesian to polar coordinates (using target ellipse)&lt;br /&gt;        dblTempSemiMajorAxis = ElliseParamTarget.SemiMajorAxisA&lt;br /&gt;        dblTempSemiMinorAxis = ElliseParamTarget.SemiMinorAxisB&lt;br /&gt;        Dim precision = 4 / dblTempSemiMajorAxis  ' results accurate to around 4 metres&lt;br /&gt;        eSq = (dblTempSemiMajorAxis * dblTempSemiMajorAxis - dblTempSemiMinorAxis * dblTempSemiMinorAxis) / _&lt;br /&gt;            (dblTempSemiMajorAxis * dblTempSemiMajorAxis)&lt;br /&gt;        Dim p = Math.Sqrt(x2 * x2 + y2 * y2)&lt;br /&gt;        Dim phi = Math.Atan2(z2, p * (1 - eSq)), phiP = 2 * Math.PI&lt;br /&gt;        Do While (Math.Abs(phi - phiP) &amp;gt; precision)&lt;br /&gt;            nu = dblTempSemiMajorAxis / Math.Sqrt(1 - eSq * Math.Sin(phi) * Math.Sin(phi))&lt;br /&gt;            phiP = phi&lt;br /&gt;            phi = Math.Atan2(z2 + eSq * nu * Math.Sin(phi), p)&lt;br /&gt;        Loop&lt;br /&gt;        Dim lambda = Math.Atan2(y2, x2)&lt;br /&gt;        H = p / Math.Cos(phi) - nu&lt;br /&gt;        Dim LatLng As New LatitudeLongitude(ConvertRadiansToDegrees(phi), ConvertRadiansToDegrees(lambda), H)&lt;br /&gt;        Return LatLng&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;&lt;br /&gt;    ''' convert geodesic co-ordinates to OS grid reference&lt;br /&gt;    ''' &amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="OriginalLatLong"&amp;gt;&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;    ''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;    Public Shared Function LatLongToOSGrid(ByVal OriginalLatLong As LatitudeLongitude)&lt;br /&gt;        Dim lat = ConvertDegreesToRadians(OriginalLatLong.latitude)&lt;br /&gt;        Dim lon = ConvertDegreesToRadians(OriginalLatLong.longitude)&lt;br /&gt;        Dim dblSemiMajorAxisA As Double = 6377563.396&lt;br /&gt;        Dim dblSemiMinorAxisB As Double = 6356256.91          ' Airy 1830 major &amp;amp; minor semi-axes&lt;br /&gt;        Dim dboScaleFactorF0 As Double = 0.9996012717                         ' NatGrid scale factor on central meridian&lt;br /&gt;        Dim dblTrueOriginLat0 As Double = ConvertDegreesToRadians(49)&lt;br /&gt;        Dim dblTrueOriginLon0 As Double = ConvertDegreesToRadians(-2)  ' NatGrid true origin&lt;br /&gt;        Dim dblMapCoordTrueOriginN0 As Double = -100000&lt;br /&gt;        Dim dblMapCoordTrueOriginE0 As Double = 400000        ' northing &amp;amp; easting of true origin, metres&lt;br /&gt;        Dim dblEccentricitySquared As Double = 1 - (dblSemiMinorAxisB * dblSemiMinorAxisB) / (dblSemiMajorAxisA * dblSemiMajorAxisA)  ' eccentricity squared&lt;br /&gt;        Dim n As Double = (dblSemiMajorAxisA - dblSemiMinorAxisB) / (dblSemiMajorAxisA + dblSemiMinorAxisB), n2 = n * n, n3 = n * n * n&lt;br /&gt;        Dim cosLat As Double = Math.Cos(lat), sinLat = Math.Sin(lat)&lt;br /&gt;        Dim nu As Double = dblSemiMajorAxisA * dboScaleFactorF0 / Math.Sqrt(1 - dblEccentricitySquared * sinLat * sinLat)              ' transverse radius of curvature&lt;br /&gt;        Dim rho As Double = dblSemiMajorAxisA * dboScaleFactorF0 * (1 - dblEccentricitySquared) / Math.Pow(1 - dblEccentricitySquared * sinLat * sinLat, 1.5)  ' meridional radius of curvature&lt;br /&gt;        Dim eta2 As Double = nu / rho - 1&lt;br /&gt;        Dim Ma As Double = (1 + n + (5 / 4) * n2 + (5 / 4) * n3) * (lat - dblTrueOriginLat0)&lt;br /&gt;        Dim Mb As Double = (3 * n + 3 * n * n + (21 / 8) * n3) * Math.Sin(lat - dblTrueOriginLat0) * Math.Cos(lat + dblTrueOriginLat0)&lt;br /&gt;        Dim Mc As Double = ((15 / 8) * n2 + (15 / 8) * n3) * Math.Sin(2 * (lat - dblTrueOriginLat0)) * Math.Cos(2 * (lat + dblTrueOriginLat0))&lt;br /&gt;        Dim Md As Double = (35 / 24) * n3 * Math.Sin(3 * (lat - dblTrueOriginLat0)) * Math.Cos(3 * (lat + dblTrueOriginLat0))&lt;br /&gt;        Dim M As Double = dblSemiMinorAxisB * dboScaleFactorF0 * (Ma - Mb + Mc - Md)              ' meridional arc&lt;br /&gt;        Dim cos3lat As Double = cosLat * cosLat * cosLat&lt;br /&gt;        Dim cos5lat As Double = cos3lat * cosLat * cosLat&lt;br /&gt;        Dim tan2lat As Double = Math.Tan(lat) * Math.Tan(lat)&lt;br /&gt;        Dim tan4lat As Double = tan2lat * tan2lat&lt;br /&gt;        Dim I As Double = M + dblMapCoordTrueOriginN0&lt;br /&gt;        Dim II As Double = (nu / 2) * sinLat * cosLat&lt;br /&gt;        Dim III As Double = (nu / 24) * sinLat * cos3lat * (5 - tan2lat + 9 * eta2)&lt;br /&gt;        Dim IIIA As Double = (nu / 720) * sinLat * cos5lat * (61 - 58 * tan2lat + tan4lat)&lt;br /&gt;        Dim IV As Double = nu * cosLat&lt;br /&gt;        Dim V As Double = (nu / 6) * cos3lat * (nu / rho - tan2lat)&lt;br /&gt;        Dim VI As Double = (nu / 120) * cos5lat * (5 - 18 * tan2lat + tan4lat + 14 * eta2 - 58 * tan2lat * eta2)&lt;br /&gt;        Dim dLon As Double = lon - dblTrueOriginLon0&lt;br /&gt;        Dim dLon2 As Double = dLon * dLon&lt;br /&gt;        Dim dLon3 As Double = dLon2 * dLon&lt;br /&gt;        Dim dLon4 As Double = dLon3 * dLon&lt;br /&gt;        Dim dLon5 As Double = dLon4 * dLon&lt;br /&gt;        Dim dLon6 As Double = dLon5 * dLon&lt;br /&gt;        Dim dblNorthing = I + II * dLon2 + III * dLon4 + IIIA * dLon6&lt;br /&gt;        Dim dblEasting = dblMapCoordTrueOriginE0 + IV * dLon + V * dLon3 + VI * dLon5&lt;br /&gt;        Return ConvertOSGridNumberToLetter(dblEasting, dblNorthing) ', 8)&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;&lt;br /&gt;    ''' Convert OS Grid Reference to a Latitude/Longitude&lt;br /&gt;    ''' &amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="GridReference"&amp;gt;An OS Grid Reference in the form TG1234512345 or 612345312345&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;A LatitudeLongitude class containing the OS Lat/Long&amp;lt;/returns&amp;gt;&lt;br /&gt;    ''' &amp;lt;remarks&amp;gt;For a lat/long that can be used in GoogleMaps or VirtualEarth the returned class needs to be converted using ConvertOSGB36toWGS84&amp;lt;/remarks&amp;gt;&lt;br /&gt;    Public Shared Function OSGridToLatLong(ByVal GridReference As String) As LatitudeLongitude&lt;br /&gt;        ' convert grid reference to Easting/Northing&lt;br /&gt;        Dim gr As New EastingNorthing(GridReference)&lt;br /&gt;        ' convert Easting/Northing to Latitude/Longitude&lt;br /&gt;        Return OSGridToLatLong(gr.Easting, gr.Northing)&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;&lt;br /&gt;    ''' Convert OS Grid Easting and Northing to Latitude/Longitude&lt;br /&gt;    ''' &amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="Easting"&amp;gt;An OS Grid Reference Easting in the form nnn or nnnnnn etc.&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="Northing"&amp;gt;An OS Grid Reference Northing in the form nnn or nnnnnn etc.&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;A LatitudeLongitude class containing the OS Lat/Long&amp;lt;/returns&amp;gt;&lt;br /&gt;    ''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;    Public Shared Function OSGridToLatLong(ByVal Easting As Double, ByVal Northing As Double) As LatitudeLongitude&lt;br /&gt;        Dim dblEasting As Double = CType((Easting.ToString &amp;amp; "000000").Substring(0, 6), Double)&lt;br /&gt;        Dim dblNorthing As Double = CType((Northing.ToString &amp;amp; "000000").Substring(0, 6), Double)&lt;br /&gt;        Dim dblSemiMajorAxisA As Double = 6377563.396               ' Airy 1830 major semi-axis&lt;br /&gt;        Dim dblSemiMinorAxisB As Double = 6356256.91                ' Airy 1830 minor semi-axis&lt;br /&gt;        Dim dboScaleFactorF0 As Double = 0.9996012717               ' NatGrid scale factor on central meridian&lt;br /&gt;        Dim dblTrueOriginLat0 As Double = 49 * Math.PI / 180        ' NatGrid true origin latitude&lt;br /&gt;        Dim dblTrueOriginLon0 As Double = -2 * Math.PI / 180        ' NatGrid true origin longitude&lt;br /&gt;        Dim dblMapCoordTrueOriginN0 As Double = -100000             ' northing of true origin, metres&lt;br /&gt;        Dim dblMapCoordTrueOriginE0 As Double = 400000              ' easting of true origin, metres&lt;br /&gt;        Dim dblEccentricitySquared As Double = 1 - (dblSemiMinorAxisB * dblSemiMinorAxisB) / (dblSemiMajorAxisA * dblSemiMajorAxisA) ' eccentricity squared&lt;br /&gt;        Dim n As Double = (dblSemiMajorAxisA - dblSemiMinorAxisB) / (dblSemiMajorAxisA + dblSemiMinorAxisB)&lt;br /&gt;        Dim n2 As Double = n * n&lt;br /&gt;        Dim n3 As Double = n * n * n&lt;br /&gt;        Dim lat As Double = dblTrueOriginLat0&lt;br /&gt;        Dim M As Double = 0&lt;br /&gt;        Do&lt;br /&gt;            lat = (dblNorthing - dblMapCoordTrueOriginN0 - M) / (dblSemiMajorAxisA * dboScaleFactorF0) + lat&lt;br /&gt;            Dim Ma As Double = (1 + n + (5 / 4) * n2 + (5 / 4) * n3) * (lat - dblTrueOriginLat0)&lt;br /&gt;            Dim Mb As Double = (3 * n + 3 * n * n + (21 / 8) * n3) * Math.Sin(lat - dblTrueOriginLat0) * Math.Cos(lat + dblTrueOriginLat0)&lt;br /&gt;            Dim Mc As Double = ((15 / 8) * n2 + (15 / 8) * n3) * Math.Sin(2 * (lat - dblTrueOriginLat0)) * Math.Cos(2 * (lat + dblTrueOriginLat0))&lt;br /&gt;            Dim Md As Double = (35 / 24) * n3 * Math.Sin(3 * (lat - dblTrueOriginLat0)) * Math.Cos(3 * (lat + dblTrueOriginLat0))&lt;br /&gt;            M = dblSemiMinorAxisB * dboScaleFactorF0 * (Ma - Mb + Mc - Md)                ' meridional arc&lt;br /&gt;        Loop While (dblNorthing - dblMapCoordTrueOriginN0 - M &amp;gt;= 0.00001)  ' ie until &amp;lt; 0.01mm&lt;br /&gt;        Dim sinLat As Double = Math.Sin(lat)&lt;br /&gt;        Dim nu As Double = dblSemiMajorAxisA * dboScaleFactorF0 / Math.Sqrt(1 - dblEccentricitySquared * sinLat * sinLat)                     ' transverse radius of curvature&lt;br /&gt;        Dim rho As Double = dblSemiMajorAxisA * dboScaleFactorF0 * (1 - dblEccentricitySquared) / Math.Pow(1 - dblEccentricitySquared * sinLat * sinLat, 1.5)     ' meridional radius of curvature&lt;br /&gt;        Dim eta2 As Double = nu / rho - 1&lt;br /&gt;        Dim tanLat As Double = Math.Tan(lat)&lt;br /&gt;        Dim tan2lat As Double = tanLat * tanLat&lt;br /&gt;        Dim tan4lat As Double = tan2lat * tan2lat&lt;br /&gt;        Dim tan6lat As Double = tan4lat * tan2lat&lt;br /&gt;        Dim secLat As Double = 1 / Math.Cos(lat)&lt;br /&gt;        Dim VII As Double = tanLat / (2 * rho * nu)&lt;br /&gt;        Dim VIII As Double = tanLat / (24 * rho * (nu ^ 3)) * (5 + 3 * (tanLat ^ 2) + eta2 - 9 * (tanLat ^ 2) * eta2)&lt;br /&gt;        Dim IX As Double = tanLat / (720 * rho * (nu ^ 5)) * (61 + 90 * (tanLat ^ 2) + 45 * (tanLat ^ 4))&lt;br /&gt;        Dim X As Double = secLat / nu&lt;br /&gt;        Dim XI As Double = secLat / (6 * (nu ^ 3)) * (nu / rho + 2 * (tanLat ^ 2))&lt;br /&gt;        Dim XII As Double = secLat / (120 * (nu ^ 5)) * (5 + 28 * (tanLat ^ 2) + 24 * (tanLat ^ 4))&lt;br /&gt;        Dim XIIA As Double = secLat / (5040 * (nu ^ 7)) * (61 + 662 * (tanLat ^ 2) + 1320 * (tanLat ^ 4) + 720 * (tanLat ^ 6))&lt;br /&gt;        Dim dE As Double = (dblEasting - dblMapCoordTrueOriginE0)&lt;br /&gt;        lat = lat - VII * (dE ^ 2) + VIII * (dE ^ 4) - IX * (dE ^ 6)&lt;br /&gt;        Dim lon As Double = dblTrueOriginLon0 + X * dE - XI * (dE ^ 3) + XII * (dE ^ 5) - XIIA * (dE ^ 7)&lt;br /&gt;        Return New LatitudeLongitude(ConvertRadiansToDegrees(lat), ConvertRadiansToDegrees(lon), 0)&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;Convert standard grid reference ('SU6253304496') to fully numeric ref ([462533,104496])&amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="GridReference"&amp;gt;Ordnance Survey grid reference in the form SUen, e.g. SU123123 or TG1234512345&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;The converted grid offset digits, e.g. SU123123 returns 41 (4 squares along, 1 grid up)&amp;lt;/returns&amp;gt;&lt;br /&gt;    Public Shared Function ConvertOSGridLetterToNumber(ByVal GridReference As String) As String&lt;br /&gt;        ' get numeric values of letter references, mapping A-&amp;gt;0, B-&amp;gt;1, C-&amp;gt;2, etc:&lt;br /&gt;        Dim intFirstChar As Integer = Asc(GridReference.ToUpper.Chars(0)) - 65&lt;br /&gt;        Dim intSecondChar As Integer = Asc(GridReference.ToUpper.Chars(1)) - 65&lt;br /&gt;        ' shuffle down letters after 'I' since 'I' is not used in grid:&lt;br /&gt;        If (intFirstChar &amp;gt; 7) Then intFirstChar -= 1&lt;br /&gt;        If (intSecondChar &amp;gt; 7) Then intSecondChar -= 1&lt;br /&gt;        ' convert grid letters into 100km-square indexes from false origin (grid square SV):&lt;br /&gt;        Dim intEasting As Integer = ((intFirstChar - 2) Mod 5) * 5 + (intSecondChar Mod 5)&lt;br /&gt;        Dim intNorthing As Integer = (19 - Math.Floor(intFirstChar / 5) * 5) - Math.Floor(intSecondChar / 5)&lt;br /&gt;        Return intEasting.ToString &amp;amp; intNorthing.ToString&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;Convert fully numeric ref ([462533104496]) to standard grid reference ('SU6253304496')&amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="Easting"&amp;gt;Ordnance Survey Easting in the form n,  e.g. 123 or 12345&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="Northing"&amp;gt;Ordnance Survey Northing in the form n, e.g. 123 or 12345&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;The grid square equivalent of the input parameters, e.g. 412345 and 1e.g. SU123123 returns 41 (4 squares along, 1 grid up)&amp;lt;/returns&amp;gt;&lt;br /&gt;    Public Shared Function ConvertOSGridNumberToLetter(ByVal Easting As Integer, ByVal Northing As Integer) As String&lt;br /&gt;        ' get the 100km-grid indices&lt;br /&gt;        Dim e100k As Integer = Math.Floor(Easting / 100000)&lt;br /&gt;        Dim n100k As Integer = Math.Floor(Northing / 100000)&lt;br /&gt;        If (e100k &amp;lt; 0 OrElse e100k &amp;gt; 6 OrElse n100k &amp;lt; 0 OrElse n100k &amp;gt; 12) Then Return ""&lt;br /&gt;        ' translate those into numeric equivalents of the grid letters&lt;br /&gt;        Dim intFirstChar = (19 - n100k) - (19 - n100k) Mod 5 + Math.Floor((e100k + 10) / 5)&lt;br /&gt;        Dim intSecondChar = (19 - n100k) * 5 Mod 25 + e100k Mod 5&lt;br /&gt;        ' compensate for skipped 'I' and build grid letter-pairs&lt;br /&gt;        If (intFirstChar &amp;gt; 7) Then intFirstChar += 1&lt;br /&gt;        If (intSecondChar &amp;gt; 7) Then intSecondChar += 1&lt;br /&gt;        Return Chr(intFirstChar + 65) + Chr(intSecondChar + 65) ' String.fromCharCode(l1+'A'.charCodeAt(0), l2+'A'.charCodeAt(0))&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;&lt;br /&gt;    ''' convert degrees to radians&lt;br /&gt;    ''' &amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="Degrees"&amp;gt;Value to be converted&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;    ''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;    Public Shared Function ConvertDegreesToRadians(ByVal Degrees As Double) As Double&lt;br /&gt;        Return Degrees * Math.PI / 180&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;&lt;br /&gt;    ''' convert radians to degrees (signed)&lt;br /&gt;    ''' &amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="Radians"&amp;gt;Value to be converted&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;    ''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;    Public Shared Function ConvertRadiansToDegrees(ByVal Radians As Double) As Double&lt;br /&gt;        Return Radians * 180 / Math.PI&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;&lt;br /&gt;    ''' Return co-ordinate in degrees, minutes and seconds from a decimal value&lt;br /&gt;    ''' &amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="NumericDegrees"&amp;gt;Numeric degrees&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;    ''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;    Public Shared Function ConvertNumericDegreesToDegreesMinutesSeconds(ByVal NumericDegrees As Double) As String&lt;br /&gt;        Dim dblTemp As Double = Math.Abs(NumericDegrees)&lt;br /&gt;        dblTemp += 1 / 720000000  ' add .005 millisecond for rounding&lt;br /&gt;        Dim deg As Double = Math.Floor(dblTemp)&lt;br /&gt;        Dim min As Double = Math.Floor((dblTemp - deg) * 60)&lt;br /&gt;        Dim sec As Double = Math.Floor((dblTemp - deg - min / 60) * 3600)&lt;br /&gt;        Return deg.ToString("000") + Chr("176") + min.ToString("00") + "'" + sec.ToString("0") + """"&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;&lt;br /&gt;    ''' convert numeric degrees to deg/min/sec longitude&lt;br /&gt;    ''' &amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="NumericDegrees"&amp;gt;Numeric degrees&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;    ''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;    Public Shared Function ConvertNumericDegreesToLatitude(ByVal NumericDegrees As Double) As String&lt;br /&gt;        Dim strTemp As String = ""&lt;br /&gt;        strTemp = ConvertNumericDegreesToDegreesMinutesSeconds(NumericDegrees).Substring(1)&lt;br /&gt;        If NumericDegrees &amp;lt; 0 Then strTemp &amp;amp;= "S" Else strTemp &amp;amp;= "N"&lt;br /&gt;        Return strTemp&lt;br /&gt;    End Function&lt;br /&gt;&lt;br /&gt;    ''' &amp;lt;summary&amp;gt;&lt;br /&gt;    ''' convert numeric degrees to deg/min/sec longitude&lt;br /&gt;    ''' &amp;lt;/summary&amp;gt;&lt;br /&gt;    ''' &amp;lt;param name="NumericDegrees"&amp;gt;Numeric degrees&amp;lt;/param&amp;gt;&lt;br /&gt;    ''' &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;&lt;br /&gt;    ''' &amp;lt;remarks&amp;gt;&amp;lt;/remarks&amp;gt;&lt;br /&gt;    Public Shared Function ConvertNumericDegreesToLongitude(ByVal NumericDegrees As Double) As Double&lt;br /&gt;        Dim strTemp As String = ""&lt;br /&gt;        strTemp = ConvertNumericDegreesToDegreesMinutesSeconds(NumericDegrees)&lt;br /&gt;        If NumericDegrees &amp;lt; 0 Then strTemp &amp;amp;= "W" Else strTemp &amp;amp;= "E"&lt;br /&gt;        Return strTemp&lt;br /&gt;    End Function&lt;br /&gt;End Class&lt;br /&gt;&lt;/small&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/9064593862349906054-2273149030462207281?l=kwinchcombe.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://kwinchcombe.blogspot.com/feeds/2273149030462207281/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=9064593862349906054&amp;postID=2273149030462207281' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/9064593862349906054/posts/default/2273149030462207281'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/9064593862349906054/posts/default/2273149030462207281'/><link rel='alternate' type='text/html' href='http://kwinchcombe.blogspot.com/2007/09/englishman-in-google-maps.html' title='An Englishman In Google Maps - Plotting Easting/Northing on Google Maps'/><author><name>Kev Winchcombe</name><uri>http://www.blogger.com/profile/07812274593001670627</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry></feed>
