[OSM-dev] [OSM-newbies] Mercator problems

Karl Newman siliconfiend at gmail.com
Mon Dec 3 15:32:16 GMT 2007


On Dec 2, 2007 11:49 AM, Andy Robinson <blackadderajr at googlemail.com> wrote:
> On 02/12/2007, Bettersoftware <barry at bettersoftware.co.uk> wrote:
> >
> > I'm implementing a "slippy" map using VB.Net in a Windows application and
> > everything works quite well at zooms 10 to 17.  On the "Slippy" map I
> > indicate the lat/lon of the cursor position and the lat/lon of the map
> > centre. However, at zooms < 10 the accuracy of the Latitude degrades
> > considerably. The Longitude accuracy also degrades but to a lesser extent.
> >
> > After two weeks of debugging I'm stumped as my maths knowledge is not up to
> > the task in hand.
> >
> > The error I think is on in these two pieces of code :- ( You Javascript
> > people should be able to follow this easily)
> >
> >
> > Private Function getMercatorLatitude(ByVal lat As Double, ByVal Zoom As
> > Integer) As Single
> >
> >
> >
> > If (lat > 89.5) Then
> >
> > lat = 89.5
> >
> > End If
> >
> > If (lat < -89.5) Then
> >
> > lat = -89.5
> >
> > End If
> >
> > Dim phi As Double = Math.PI * lat / 180
> >
> > Dim res As Double = 0.5 * Math.Log((1 + Math.Sin(phi)) / (1 -
> > Math.Sin(phi)))
> >
> > Dim maxTileY As integer = Math.Pow(2, Zoom)
> >
> > Dim Tile As Single = ((1 - res / Math.PI) / 2) * maxTileY
> >
> > Return Tile
> > End Function
> >
> >
> >
> > Private Function getOSMTileDetails(ByVal x As Integer, ByVal y As Integer,
> > ByVal zoom As Integer) As Object
> >
> > '
> >
> > ' Returns a Rectangle2D with x = lon, y = lat, width=lonSpan, height=latSpan
> >
> > ' for an x,y,zoom as used by OSM/Google.
> >
> > '
> >
> > Dim lon As Double = -180 ' x
> >
> > Dim lonWidth As Double = 360 ' width 360
> >
> > Dim lat As Double = -1
> >
> > Dim latHeight As Double = 2
> >
> > Dim tilesAtThisZoom As Integer = Math.Pow(2, zoom)
> >
> > lonWidth = 360.0 / tilesAtThisZoom
> >
> > lon = -180 + (x * lonWidth)
> >
> > latHeight = 2.0 / tilesAtThisZoom
> >
> > lat = ((tilesAtThisZoom / 2 - y - 1) * latHeight)
> >
> > '
> >
> > ' Convert lat and latHeight to degrees in a transverse mercator projection
> >
> > ' note that in fact the coordinates go from about -85 to +85 not -90 to 90!
> >
> > '
> >
> > latHeight += lat
> >
> > latHeight = 2 * Math.Atan(Math.Exp(Math.PI * latHeight)) - (Math.PI / 2)
> >
> > latHeight *= (180 / Math.PI)
> >
> > '
> >
> > lat = (2 * Math.Atan(Math.Exp(Math.PI * lat))) - (Math.PI / 2)
> >
> > lat *= (180 / Math.PI)
> >
> > '
> >
> > latHeight -= lat
> >
> > If lonWidth < 0 Then
> >
> > lon = lon + lonWidth
> >
> > lonWidth = -lonWidth
> >
> > End If
> >
> > If latHeight < 0 Then
> >
> > lat = lat + latHeight
> >
> > latHeight = -latHeight
> >
> > End If
> >
> > Dim tileDetails As TileDetails
> >
> > tileDetails.X = lon
> >
> > tileDetails.Y = lat
> >
> > tileDetails.Height = latHeight
> >
> > tileDetails.Width = lonWidth
> >
> > Return tileDetails
> >
> > End Function
> > I apologise if this is not the correct place for a query such as this.
> >
> > Any assistance with this will be much appreciated
> >
> > Best regards
> >
> > Barry
> > _______________________________________________
> > newbies mailing list
> > newbies at openstreetmap.org
> > http://lists.openstreetmap.org/cgi-bin/mailman/listinfo/newbies
> >
> >

I'm not a VB.NET expert but at a quick glance I do see one thing that
raises a flag. Try changing all your constants to floating-point
(i.e., 180 becomes 180.0). At least do it to all of the constants
involved in a multiplication or division. It's possible you're running
into an integer truncation situation, which seems to fit your
symptoms.

Karl




More information about the dev mailing list