ThinkGeo.com    |     Documentation    |     Premium Support

Tile generator vs. on the fly tile generation

Hi, 



  I’m loading a topo map as a png file in a GdiPlusRasterLayer.  I then apply tile caching using the following code:




IEnumerable<string> fileNames = Directory.EnumerateFiles(@“O:\GIS Data\Gothics&#34;, “*.png”);  // replace this with proper db call
            mapUnit = GeographyUnit.Meter;
 
            RectangleShape rect = null;
 
            foreach (string fileName in fileNames) // there’s only 1 at the moment
            {
                GdiPlusRasterLayer rasterLayer = new GdiPlusRasterLayer(fileName); //I’m using a GdiPlusRasterLayer instead of a GeoTiffRasterLayer because it renders nicer (go figure)
                rasterLayer.UpperThreshold = double.MaxValue;
                rasterLayer.LowerThreshold = 0;
 
                //get the bounding box of the area we’re loading so we can restrict the map to that area
                rasterLayer.Open();
                 
                if (rect == null)
                    rect = rasterLayer.GetBoundingBox();
                else
                    rect = rect.Union(rasterLayer.GetBoundingBox()).GetBoundingBox();
 
                rasterLayer.Close();
 
                staticOverlay.Layers.Add(rasterLayer);
            }
 
            loadedArea = rect;


MapControl.MapUnit = mapUnit; //set the units on the map according to the map’s spatial reference index
MapControl.CurrentExtent = loadedArea; // this doesn’t set the CurrentExtent to the exact loadedArea
             
MapControl.RestrictExtent = loadedArea; //restrict the map’s ability to scroll beyond the loaded map area 
MapControl.MinimumScale = MapControl.ZoomLevelSet.ZoomLevel15.Scale; 
MapControl.MaximumScale = MapControl.ZoomLevelSet.ZoomLevel12.Scale; /




//setup tile caching
FileBitmapTileCache topoTileCache = new FileBitmapTileCache();
topoTileCache.CacheDirectory = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + @”\Snowbase2\TileCache";
topoTileCache.CacheId = “BaseMapCache”;
topoTileCache.ImageFormat = TileImageFormat.Png;
             
 
staticOverlay.TileCache = topoTileCache;
staticOverlay.TransitionEffect = TransitionEffect.None;
 
//add the static overlay to the map
MapControl.Overlays.Add(“staticOverlay”, staticOverlay);

This behaves as expected and generates tiles as I zoom and pan around the map.  Next I wanted to pre-generate the tiles using the CacheGenerator app.  In the CacheGenerator’s LayerProvider, I changed the GetLayersToCache() method to:


public static Collection<Layer> GetLayersToCache()
{
    Collection<Layer> layersToCache = new Collection<Layer>();
 
    GdiPlusRasterLayer layer = new GdiPlusRasterLayer(@“O:\GIS Data\Gothics\GO_SB2_TOPO_WMS_DRAFT_500dpi.png”);
 
        layersToCache.Add(layer);
 
         return layersToCache;
 }

and then, instead of using the Top Left Point/Bottom Right Point text fields, I call


tileCacheGenerator.CachingExtent = LayerProvider.GetImageBoundingBox();

which is a method I wrote with the following implementation


public static RectangleShape GetImageBoundingBox()
        {
            RectangleShape rect = null;
            foreach (Layer layer in layersToCache)
            {
                layer.Open();
                if (rect == null)
                    rect = layer.GetBoundingBox();
                else
                    rect = rect.Union(layer.GetBoundingBox()).GetBoundingBox();
                layer.Close();
            }
 
            return rect;
        }

I also set the Map Units to Metres in the CacheGenerator, as I did with my app.

 

The final result is that the tileCacheGenerator.CachingExtent property is equal to the bounding box of the PNG file I’m loading.  However, when I try to use the tiles generated by the CacheGenerator, my application instead generates it’s own tiles which are slightly offset from the ones generated by the CacheGenerator (see image attachment).  The directory structure is also named differently so I’m guessing that they are starting at different coodinates.  Does this have to do with the fact that the mapControl’s CurrentExtent isn’t exactly equal to my PNG’s bounding box?  If so, what’s going on in the MapControl.CurrentExtent setter that changes the value I assign to it?  What do I need to do to fix this?



Thanks,



  Trevor




I should also point out that I tried setting the tileCacheGenerator.CachingExtent in the CacheGenerator app to the same rectangle as the MapControl.CurrentExtent in my app but the tiles are still offset between the 2 applications

Hi Trevor,



We cannot reproduce this issue with our data. Would you mind provide us your data that can recreate this issue? If the test data is restricted by the forum please contact at forumsupport@thinkgeo.com.



Waiting for your response.



Thanks,

Kevin

Hi Trevor,



Thanks for your data, but seems there should be a GO_SB2_TOPO_WMS_DRAFT_500dpi.pgw file, we don’t find it in the zip. Could you please have a check and provide us that? We need the *.pgw file to determine where the png file was renderred.



Apologize for any inconvenience.



Regards,

Kevin

Sorry, it’s been uploaded now

Hi Trevor,



Thanks for your details.



From the project you provided, we need to modify the method GetScalesToCache of LayerProvider.cs in Cache Generator. Because unit of your data is Meter but the default scales of ZoomLevelSet object is for DecimalDegree, so we can replace the ZoomLevelSet with GoogleMapsZoomLevelSet, then the scales will work for Meter.


//ZoomLevelSet zoomLevelSet = new ZoomLevelSet();
GoogleMapsZoomLevelSet zoomLevelSet = new GoogleMapsZoomLevelSet();

Hope this would be helpful and if the issue still persist, please feel free to let us know.



Thanks,

Kevin

That did the trick, thank you very much.

You’re always welcome, Trevor!

Any other question please feel free to let us know.



Regards,

Kevin