ThinkGeo.com    |     Documentation    |     Premium Support

Web Mercator Projection

We are looking to use a web mercator projection for all of our layers. A few questions on that:

  1. Are there any example projects that specifically use that projection?
  2. It appears that to fully use the projection, our custom shapefiles should have a coordinates system in meters, not decimal degrees. Is this correct?
  3. What else do we need to know about shapefiles/projections/ThinkGeo map control do we need to know?

So far, our shapefile-based layers are displaying with the web mercator projection, but our data-driven layers do not show up. This is why I’m thinking that our shapefiles need to be done in meters, not decimal degrees.

Thanks,
Dib

Hi Dib,

Web Mercator is based on meter, so the map unit should be set equal meter. You can read more detail information here: http://epsg.io/900913

If your data is based on Web Mercator, when you set mapunit equal meter, you just need to set the correct bouding box to make it shows.

If your any layer is not based on Web Mercator, you should want to reprojection that into Web Mercator by our class ManagedProj4Projection.

The code as below should be helpful:

ManagedProj4Projection proj4 = new ManagedProj4Projection();
        proj4.InternalProjectionParametersString = ManagedProj4Projection.GetEpsgParametersString("Your data projection epsg id");
        proj4.ExternalProjectionParametersString = ManagedProj4Projection.GetGoogleMapParametersString();
        proj4.Open;

        ShapeFileFeatureLayer yourLayer;
        yourLayer.FeatureSource.Projection = proj4;

The map unit and current extent make sure which part of the map should be render on screen.
We cannot know the projection information of your shape file, so you should want to get that from data provider or view the .prj file of data. If you hadn’t set the correct bounding box, you maybe won’t see the shape appear on screen.
Projections can help you convert your data or single shape into the target projection, so it can be shown in the correct bounding box.

Wish that’s helpful.

Regards,

Don

Don,

I’ve set the map unit to meters, and I can see our shapefiles one the map. There are two issues:

  1. I can’t zoom in past a certain point, like I can when using decimal degree. I’ve set minimum scale to 0. Is there another map setting that needs to change?
  2. When set to meters, the map takes up to 5 seconds to redraw after changing the extent. With decimal degrees, it is instant.

Thanks

Hi Dib,

  1.      winformsMap1.MapUnit = GeographyUnit.Meter;
    
         winformsMap1.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(1125));
         winformsMap1.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(500));
         winformsMap1.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(100));
         winformsMap1.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(50));
         winformsMap1.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(10));
         winformsMap1.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(1));
         winformsMap1.ZoomLevelSet.CustomZoomLevels.Add(new ZoomLevel(0.1));
    
         winformsMap1.MinimumScale = 0;
    

Set CustomZoomLevels can make it zoom into deeper.

  1. I think that’s maybe related with the reprojection, reprojection is an additional process so it will takes additional time, please make sure your shape file contains index file, and if possible please open cache which should be helpful.

Regards,

Don

Don,

The zoom levels worked out nicely, thanks.

I turned caching on, but the results there are not as promising. In some instances, especially when zoomed in, the redraw rate is good. When zoomed out, however, it is still unacceptable, taking several seconds to redraw the map. I still find it interesting that this isn’t an issue when the map unit is set to decimal degree, but is so noticeable when set to meters.

Thanks

Hi Dib,

In fact I hadn’t met the same problem when I tried to test it, I think maybe that’s related with your data.

Do you think it’s possible that you can upload a simplest sample which can reproduce it with your data, so we can look into it.

Regards,

Don

Don, here is the code I’m using to show the shapefiles in the test project. Where can I send/attach them to you?

Me.map.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(800)) '1125
Me.map.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(500))
Me.map.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(100))
Me.map.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(50))
Me.map.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(10))
Me.map.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(1))
Me.map.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(0.1))
Me.map.CurrentScale = 800

    Dim layerOver As New LayerOverlay

        proj4 = New ManagedProj4Projection
        proj4.InternalProjectionParametersString = ("+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs")
        proj4.ExternalProjectionParametersString = ManagedProj4Projection.GetEpsgParametersString(4326)
        Me.map.BackgroundOverlay.BackgroundBrush = New GeoSolidBrush(BACKGROUND_COLOR_OUT)

        Dim countries As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(_folder & "countrieswoUS_merged.shp")
        countries.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(LAND_COLOR)
        countries.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
        countries.FeatureSource.Projection = proj4
        countries.Open()
        countries.WrappingMode = WrappingMode.WrapDateline
        countries.WrappingExtent = countries.GetBoundingBox
        Me._fullMapBoundingBox = countries.GetBoundingBox
        countries.Close()

        Dim statesLayer As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(_folder & "states.shp")

        For Each aZoom As ZoomLevel In Me.map.ZoomLevelSet.CustomZoomLevels
            statesLayer.ZoomLevelSet.CustomZoomLevels.Add(aZoom)
            statesLayer.ZoomLevelSet.CustomZoomLevels(statesLayer.ZoomLevelSet.CustomZoomLevels.Count - 1).DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(LAND_COLOR)
        Next

        statesLayer.FeatureSource.Projection = proj4
        statesLayer.WrappingMode = WrappingMode.WrapDateline
        statesLayer.WrappingExtent = Me._fullMapBoundingBox

        Dim countiesLayer As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(_folder & "conus_land.shp") 'conus_land counties_inland
        countiesLayer.ZoomLevelSet.ZoomLevel09.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(LAND_COLOR)
        countiesLayer.ZoomLevelSet.ZoomLevel09.DefaultAreaStyle.OutlinePen.Color = GeoColors.Transparent
        countiesLayer.ZoomLevelSet.ZoomLevel09.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
        countiesLayer.Name = "counties_land"
        countiesLayer.FeatureSource.Projection = proj4
        countiesLayer.WrappingMode = WrappingMode.WrapDateline
        countiesLayer.WrappingExtent = Me._fullMapBoundingBox

        layerOver.Name = DEFAULT_MAP_BASE
        layerOver.Layers.Add(countries)
        layerOver.Layers.Add(countiesLayer)
        layerOver.Layers.Add(statesLayer)
        layerOver.TileCache = New FileBitmapTileCache("C:\tmp", layerOver.Name)

        Me.map.Overlays.Add(DEFAULT_MAP_BASE, layerOver)
        Me._bordersOverlay = New LayerOverlay
        Me.map.Overlays.Add(OVERLAY_BORDERS, Me._bordersOverlay)
        Me.map.CurrentScale = 800
        Me.map.Refresh()

Hi Dib,

It looks you have 3 shape files here: countrieswoUS_merged states and conus_land. What’s the size of them?

If they are not so big, you can directly attach them in this topic, if not you can upload them to our FTP, you should can get a FTP account from your sales.

And please make sure all your shape file had build its index file.

Regards,

Don

countrieswoUS_merged.zip (1.1 MB)states.zip (147.4 KB)

Here are two of the three shapefiles. Am I seeing the issues with just these two in place.

Hi Dib,

Thanks your data, I tested that with your code.

But I hadn’t reproduced your issue.

It looks the zoom in and zoom out is very quickly even I delete the cache images.

Please view that here http://screencast.com/t/HkzeoPpC3xn

And here is my test code:

Private Sub WpfMap_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
    Map1.MapUnit = GeographyUnit.DecimalDegree

    Me.Map1.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(800)) '1125
    Me.Map1.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(500))
    Me.Map1.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(100))
    Me.Map1.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(50))
    Me.Map1.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(10))
    Me.Map1.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(1))
    Me.Map1.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(0.1))


    Dim _folder = New String("D:\8268\")
    Dim LAND_COLOR = GeoColor.StandardColors.Red
    Dim layerOver As New LayerOverlay

    Dim proj4 = New ManagedProj4Projection
    proj4.InternalProjectionParametersString = ("+proj=merc +lon_0=0 +k=1 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs")
    proj4.ExternalProjectionParametersString = ManagedProj4Projection.GetEpsgParametersString(4326)
    proj4.Open()

    Dim countries As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(_folder & "countrieswoUS_merged.shp")
    countries.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.Country1
    countries.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
    countries.FeatureSource.Projection = proj4
    countries.Open()
    countries.WrappingMode = WrappingMode.WrapDateline
    countries.WrappingExtent = countries.GetBoundingBox



    Dim statesLayer As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(_folder & "states.shp")

    For Each aZoom As ZoomLevel In Me.Map1.ZoomLevelSet.CustomZoomLevels
        statesLayer.ZoomLevelSet.CustomZoomLevels.Add(aZoom)
        statesLayer.ZoomLevelSet.CustomZoomLevels(statesLayer.ZoomLevelSet.CustomZoomLevels.Count - 1).DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(LAND_COLOR)
    Next

    statesLayer.FeatureSource.Projection = proj4
    statesLayer.WrappingMode = WrappingMode.WrapDateline
    statesLayer.WrappingExtent = New RectangleShape(-180, 90, 180, -90)

    Dim countiesLayer As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(_folder & "conus_land.shp") 'conus_land counties_inland
    countiesLayer.ZoomLevelSet.ZoomLevel09.DefaultAreaStyle = AreaStyles.CreateSimpleAreaStyle(LAND_COLOR)
    countiesLayer.ZoomLevelSet.ZoomLevel09.DefaultAreaStyle.OutlinePen.Color = GeoColors.Transparent
    countiesLayer.ZoomLevelSet.ZoomLevel09.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
    countiesLayer.Name = "counties_land"
    countiesLayer.FeatureSource.Projection = proj4
    countiesLayer.WrappingMode = WrappingMode.WrapDateline
    countiesLayer.WrappingExtent = New RectangleShape(-180, 90, 180, -90)

    layerOver.Name = "abc"
    layerOver.Layers.Add(countries)
    layerOver.Layers.Add(countiesLayer)
    layerOver.Layers.Add(statesLayer)
    layerOver.TileCache = New FileBitmapTileCache("C:\tmp", layerOver.Name)

    Map1.CurrentScale = 800
    Map1.MinimumScale = 0

    Map1.CurrentExtent = countries.GetBoundingBox

    Me.Map1.Overlays.Add(layerOver)
    Me.Map1.Refresh()
End Sub

Please update your dll to our latest version, and if you still met the same problem, please build a simple sample which can reproduce your issue, so we can work for it.

Regards,

Don

Don,

With map unit set to decimal degree, I don’t have any problems either. When I set it to Meter, which I believe I need to do to use a Web Mercator projection properly, that’s when the redraw is slow.

Don,

I’ve added code to change the scale of the 20 default zoom levels for each layer. This seems to have eliminated the slow redraw issue.

Hi Dib,

I am glad to hear that works.

Why I set the mapunit to decimal degree is because your code set the 4326 as ExternalProjectionParametersString, that means you convert your shape file to 4326.

If you want to set as meter, please modify the ExternalProjectionParametersString.

Regards,

Don

Don,

I’ve switched from 4326 to 3857, which looks to be the correct external projection. I’ve got routines to show country/state/county borders. They works correctly when using 4326, but do not work when using 3857. Two questions:

  1. Is 3857 the correct EPSG value for meters/web mercator projectons?
  2. Is there something in the shapefiles that would need to be changed when using 3857?

Thanks

Hi Dib,

  1. 3857 is the projection for web mercator, you can use it like this: ManagedProj4Projection.GetGoogleMapParametersString()

  2. I am not sure what’s projection your shape file is under, if it’s under web mercator, you don’t need reprojection it, if that’s other projection even in meter, you should have to reprojection that also. And the statesLayer.WrappingExtent need be reprojection to 3857.

Regards,

Don

How do I set a projection on a .WrappingExtent?

I’m still not seeing any borders drawing with using GetGoogleMapParametersString, and setting the projection of that ShapeFileFeatureLayer.

I am noticing that when I set proj4.ExternalProjectionParametersString = ManagedProj4Projection.GetGoogleMapParametersString() , that the land does not redraw when zooming in close. When it is set to 4326, it redraws on all zoom levels.

Revision:

Turned off caching to see what was really going on. When I set

proj4.ExternalProjectionParametersString = ManagedProj4Projection.GetGoogleMapParametersString

and then set the project of each ShapeFileFeatureLayer to proj4, nothing shows up at all. When I set

proj4.ExternalProjectionParametersString = ManagedProj4Projection.GetEpsgParametersString(4326)

and set the projection, everything shows up as expected. I’m guessing this has to do with the shapefiles? I thought setting the projection for a layer override the projection for the shapefile.

Dib,

Attached is the sample code which I’ve revised, please try it out and see if the performance looks good to you.
Some notes:

  1.   If you want to use tile cache, please make sure your map’s zoomlevel scales are divided by 2 from the upper zoom level.
    
  2.   Your shape files are already in Mercator format so you don’t need to reproject them again, you can see the projection info by open the .prj in notepad.
    
  3.   For the WrappingExtent, we recommend you to use a full world extent(e.g. -180,90,180,-90) instead of the boundingbox of a shape file.
    
  4.   As the map is under Meter mode, so the WrappingExtent should be reprojected to that projection, see how I did that in the sample code.
    
  5.   Don’t forget to set the tileCache’s matrix unit if it’s not DecimalDegree.
    
    
     Private Sub WpfMap_Loaded(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
     Map1.MapUnit = GeographyUnit.Meter
    
     Dim scale = Map1.ZoomLevelSet.ZoomLevel01.Scale
     Map1.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(scale))
     For index = 0 To 25
         Map1.ZoomLevelSet.CustomZoomLevels.Add(New ZoomLevel(scale / (2 << index)))
     Next
     Me.Map1.BackgroundOverlay.BackgroundBrush = New GeoSolidBrush(GeoColor.StandardColors.LightBlue)
    
     Dim decimalProj4 = New ManagedProj4Projection
     decimalProj4.InternalProjectionParametersString = ManagedProj4Projection.GetEpsgParametersString(4326)
     decimalProj4.ExternalProjectionParametersString = ManagedProj4Projection.GetGoogleMapParametersString()
     decimalProj4.Open()
    
     Dim _fullMapBoundingBox = decimalProj4.ConvertToExternalProjection(New RectangleShape(-180, 90, 180, -90))
    
     Dim _folder = "D:\8268\"
     Dim countries As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(_folder & "countrieswoUS_merged.shp")
     countries.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.Country1
     countries.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level10
     'countries.FeatureSource.Projection = proj4
     countries.Open()
     countries.WrappingMode = WrappingMode.WrapDateline
     countries.WrappingExtent = _fullMapBoundingBox
     countries.Close()
    
     Dim statesLayer As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(_folder & "states.shp")
    
     For Each aZoom As ZoomLevel In Me.Map1.ZoomLevelSet.CustomZoomLevels
         statesLayer.ZoomLevelSet.CustomZoomLevels.Add(aZoom)
         statesLayer.ZoomLevelSet.CustomZoomLevels(statesLayer.ZoomLevelSet.CustomZoomLevels.Count - 1).DefaultAreaStyle = AreaStyles.Country2
     Next
    
     'statesLayer.FeatureSource.Projection = proj4
     statesLayer.WrappingMode = WrappingMode.WrapDateline
     statesLayer.WrappingExtent = _fullMapBoundingBox
    
     Dim countiesLayer As ShapeFileFeatureLayer = New ShapeFileFeatureLayer(_folder & "conus_land.shp") 'conus_land counties_inland
     countiesLayer.ZoomLevelSet.ZoomLevel09.DefaultAreaStyle = AreaStyles.Country2
     countiesLayer.ZoomLevelSet.ZoomLevel09.DefaultAreaStyle.OutlinePen.Color = GeoColors.Transparent
     countiesLayer.ZoomLevelSet.ZoomLevel09.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20
     countiesLayer.Name = "counties_land"
     'countiesLayer.FeatureSource.Projection = proj4
     countiesLayer.WrappingMode = WrappingMode.WrapDateline
     countiesLayer.WrappingExtent = _fullMapBoundingBox
    
     Dim layerOver As New LayerOverlay
     layerOver.Name = "test"
     layerOver.Layers.Add(countries)
     layerOver.Layers.Add(countiesLayer)
     layerOver.Layers.Add(statesLayer)
     layerOver.TileCache = New FileBitmapTileCache("C:\tmp", layerOver.Name)
     layerOver.TileCache.TileMatrix.BoundingBoxUnit = GeographyUnit.Meter
    
     Me.Map1.Overlays.Add("test", layerOver)
     'Me._bordersOverlay = New LayerOverlay
     'Me.Map1.Overlays.Add(OVERLAY_BORDERS, Me._bordersOverlay)
     Me.Map1.CurrentExtent = _fullMapBoundingBox
     Me.Map1.MinimumScale = 0
     Me.Map1.Refresh()
    
    End Sub

Thanks,

Don,

Everything is looking very good with that last code sample, thanks!

Hi Dib,

I am glad to hear that works.

Regards,

Don