I have spent some time adding the ability to go to and from web map URLs in my program for viewing tiled maps.
The source code is available at: http://code.google.com/p/vataviamap/source/browse/trunk/VataviaMap/Shared/clsServer.vb The part that parses web map URLs is: Private Const OSMshortlinkPrefix As String = "http://osm.org/go/" Private Const OSMshortlinkEncoding As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_~" ''' <summary> ''' Given a web map URL, look for the center latitude/longitude, zoom, and bounding box ''' </summary> ''' <param name="aURL">Web map URL to examine</param> ''' <param name="aCenterLatitude">returns latitude at center of area</param> ''' <param name="aCenterLongitude">returns longitude at center of area</param> ''' <param name="aZoom">returns zoom level</param> ''' <param name="aNorth">returns north latitude of bounding box</param> ''' <param name="aWest">returns west longitude of bounding box</param> ''' <param name="aSouth">returns south latitude of bounding box</param> ''' <param name="aEast">returns east longitude of bounding box</param> ''' <returns> ''' True if link was parsed and reasonable values for the center latitude and longitude were found ''' </returns> Function ParseWebmapURL(ByVal aURL As String, _ ByRef aCenterLatitude As Double, ByRef aCenterLongitude As Double, _ ByRef aZoom As Integer, _ ByRef aNorth As Double, ByRef aWest As Double, _ ByRef aSouth As Double, ByRef aEast As Double) As Boolean Try Dim lBounds As Boolean = False Dim lURL As String = aURL.ToLower Dim lArgs() As String If lURL.StartsWith(OSMshortlinkPrefix) Then Return ParseOSMshortlink(aURL.Substring(OSMshortlinkPrefix.Length), aCenterLatitude, aCenterLongitude, aZoom) ElseIf lURL.StartsWith("http://maps.stamen.com/m2i/") Then lArgs = lURL.Split("/") If lArgs.Length > 3 AndAlso IsNumeric(lArgs(lArgs.Length - 3)) _ AndAlso IsNumeric(lArgs(lArgs.Length - 2)) _ AndAlso IsNumeric(lArgs(lArgs.Length - 1)) Then aZoom = Double.Parse(lArgs(lArgs.Length - 3)) aCenterLatitude = Double.Parse(lArgs(lArgs.Length - 2)) aCenterLongitude = Double.Parse(lArgs(lArgs.Length - 1)) End If ElseIf lURL.StartsWith("geo:") Then lArgs = lURL.Substring(4).Split(",") If lArgs.Length > 1 AndAlso IsNumeric(lArgs(0)) AndAlso IsNumeric(lArgs(1)) Then aCenterLatitude = Double.Parse(lArgs(0)) aCenterLongitude = Double.Parse(lArgs(1)) End If Else lArgs = lURL.Split("&"c, "?"c) For Each lArg As String In lArgs Dim lArgPart() As String = lArg.Split("=") If lArgPart.Length = 2 Then Select Case lArgPart(0) Case "latitude", "lat", "mlat" aCenterLatitude = Double.Parse(lArgPart(1)) Case "longitude", "lon", "mlon", "lng", "mlng" aCenterLongitude = Double.Parse(lArgPart(1)) Case "zoom", "z" aZoom = Integer.Parse(lArgPart(1)) Case "ll", "q" Dim ll() As String = lArgPart(1).Split(",") If ll.Length = 2 AndAlso IsNumeric(ll(0)) Then 'GoogleMaps DoubleTryParse(ll(0), aCenterLatitude) DoubleTryParse(ll(1), aCenterLongitude) End If Case "spn" 'TODO: parse Google's height,width into zoom Case "cp" 'Bing Dim ll() As String = lArgPart(1).Split("~") If ll.Length = 2 AndAlso IsNumeric(ll(0)) AndAlso IsNumeric(ll(1)) Then aCenterLatitude = Double.Parse(ll(0)) aCenterLongitude = Double.Parse(ll(1)) End If Case "lvl" : aZoom = lArgPart(1) Case "starttop" : aNorth = Double.Parse(lArgPart(1)) : lBounds = True Case "startbottom" : aSouth = Double.Parse(lArgPart(1)) Case "startleft" : aWest = Integer.Parse(lArgPart(1)) Case "startright" : aEast = Integer.Parse(lArgPart(1)) Case "bbox" Dim bbox() As String = lArgPart(1).Split(",") If bbox.Length = 4 Then lBounds = DoubleTryParse(bbox(0), aWest) _ AndAlso DoubleTryParse(bbox(1), aSouth) _ AndAlso DoubleTryParse(bbox(2), aEast) _ AndAlso DoubleTryParse(bbox(3), aNorth) End If End Select End If Next End If If lBounds Then aCenterLatitude = (aNorth + aSouth) / 2 aCenterLongitude = (aWest + aEast) / 2 'TODO: compute zoom from (aNorth - aSouth) and/or (aWest - aEast) End If If aZoom > ZoomMax Then aZoom = ZoomMax If aZoom < ZoomMin Then aZoom = ZoomMin Return aCenterLatitude <> 0 AndAlso aCenterLongitude <> 0 Catch Return False End Try End Function ''' <summary> ''' Parse an OpenStreetMap shortlink code into Latitude, Longitude and Zoom ''' </summary> ''' <param name="aCode">OpenStreetMap shortlink code</param> ''' <param name="aCenterLatitude">returns latitude at center of area</param> ''' <param name="aCenterLongitude">returns longitude at center of area</param> ''' <param name="aZoom">returns zoom level</param> ''' <returns>True if link was parsed and reasonable values for the ByRef arguments were found</returns> ''' <remarks>Based on http://git.openstreetmap.org/?p=rails.git;a=blob_plain;f=lib/short_link.rb;hb=HEAD ''' see also https://help.openstreetmap.org/questions/9566/shortlink-class-in-c</remarks> Private Function ParseOSMshortlink(ByVal aCode As String, _ ByRef aCenterLatitude As Double, _ ByRef aCenterLongitude As Double, _ ByRef aZoom As Integer) As Boolean 'http://osm.org/go/0MbEUuTq = http://www.openstreetmap.org/?lat=52.50547&lon=13.36932&zoom=16 Dim x As Long = 0 Dim y As Long = 0 Dim z As Long = 0 Dim z_offset As Long = 0 Try ' replace @ in old shortlinks with ~ aCode = aCode.Replace("@", "~") For Each ch As Char In aCode.ToCharArray Dim t As Integer = OSMshortlinkEncoding.IndexOf(ch) If t < 0 Then z_offset -= 1 Else For index As Integer = 1 To 3 x <<= 1 If t And 32 Then x += 1 t <<= 1 y <<= 1 If t And 32 Then y += 1 t <<= 1 Next z += 3 End If Next ' pack the coordinates out to their original 32 bits. x <<= (32 - z) y <<= (32 - z) ' project the parameters back to their coordinate ranges. aCenterLongitude = (x * 360.0 / 2 ^ 32) - 180.0 aCenterLatitude = (y * 180.0 / 2 ^ 32) - 90.0 aZoom = z - 8 - (z_offset Mod 3) Return aCenterLatitude > -90 AndAlso aCenterLatitude < 90 AndAlso _ aCenterLongitude >= -180 AndAlso aCenterLongitude <= 180 Catch Return False End Try End Function _______________________________________________ Talk-us mailing list Talk-us@openstreetmap.org http://lists.openstreetmap.org/listinfo/talk-us