Sql 2008 Data --> render Tile and use BruTile as SharpMap Layer

Dec 14, 2010 at 9:38 AM

Ciao!

I've to do this stuff...   i've some data exported form Open Street Map and other coming from my source.....  static...  

I would like to render the entire world Tiles at some zoom levels then use this pre-rendered Tile with Bru Tile and Sharp Map.....

 

I know the Bru Tile Layer for Sharp Map because i've already used it!

 

then now my question is HOW to render the TILE !?!?  and HOW Bru Tile can read this tile from disk?   

Or i need to pass always from a "service" in some way??

 

Thanks a lot!

Alberto

Dec 14, 2010 at 10:04 AM

I've found partially an answere...

I can use FileTileProvider to load Tiles from local drive...   but i don't know yet HOW TO RENDER these Tiles.... from my vectorial data..   there is something of already done? or some example??  or again...  some other library you know?

 

Thanks

Alberto

Coordinator
Dec 14, 2010 at 5:15 PM

Hi Albert,  

There is currently no way to publish tiles in BruTile or SharpMap. I used TileCache (python) for this in the past and then there is GeoWebCache (java) and there are other options. For rendering tiles these tools use a WMS and they query the WMS according to some tile schema to generate the tiles. I is not a huge amout of work to create such a tool in .net. You can use the SharpMap WMS to render the tiles. So you need to set up a WMS on top of your own data first. If you use a WMS-C client you are already half way there. But for a proper TMS you need to write your own service. Below is the steps you need to go through to get it to work.


STEP 1
Take the WMS sample of SharpMap's WinFormSample as the start of your project

STEP 2
Replace the WMS client with a WMS-C client. You need to create a TileLayer that has a WmscTileSource. There is an example in the BruTile WPF project. You now have a working project. But the tiles will come in slow.

STEP 3
Create a new asmx project (tilecacher). This project will sit in between the WMS and your client. This project will do the caching and make things faster. 

STEP 4
Replace the WmscTileSource of the client with a TmsTileSource, and point the url to the new tilecacher project.

STEP 5
In the tilecacher project add a reference to brutile.dll. Parse the requests that come in from the client into a TileIndex

STEP 7
In the tilecacher use the WmscTileSource that you created in step two. Use the incoming TileIndex to request tiles from the WMS and return them to the client. (now you have a working application again, still slow.)

STEP 8
Start using the FileCache or the SQLiteCache to make it cache. Now it will be faster after the first request for each tile

Paul

Dec 15, 2010 at 7:51 AM

Ciao Paul...

after a lot of googleada and some code and example review...  what i saw and what i would like to use at the end...   in the rendering client is the TileLayer of SharpMap that use BruTile...     It need an ITileSource  that need in the end a ITileProvider and ITileSchema

So...   as ITileProvider i can use the FiletileProvider from BruTile that needs a FileCache object....   what i saw is that internally in the end a FileCache take a TileIndex and the associated bitmap...     so...     it should be enought if i create scripot that gived a TileSchema it render tiles images for each TileIndex i need and store thrue the FileCache into disk....    in this way    later i can use again this pre-rendered images thrue the TileLayer giving the same TileSchema.... and the same path for the FileCache!!     

.....i have to investigate yet if given a TileSchema i can obtain the entire TileIndex list fore each zoom level i want to render... ;)  but i hope yes!!! 

 

Thanks

Alberto

Coordinator
Dec 15, 2010 at 8:23 AM

So you want an all desktop client? Why do you like to use tile rendering? To make it faster?

What you are describing sounds like the SharpMapTileProvider that I used in Mapsui at some point. 

You are thinking about generating all files in a batch? An alternative to generate them on the fly and store them in a tilecache for subsequent use.

You can request all the tiles for a schema by iterating over the Schema.Resolutions and requesting Schema.GetTiles for the Schema.Extent.

Paul

Dec 15, 2010 at 9:07 AM

yes exactly!  i need to render some world view with some dynamics data at regular intervals  but  the world data i've is on high resolutions so it took too much cpu power and too much sql server time to render every time the base map from the vectorial data so i need to do this tiles rendering approach to make it faster!

And yes i would like to generate all the tiles in batch one time so on the production enviroment i'll no deploy the basemap dataset but just the directory with the tiles rendered....

nice to know that i can get all the Tiles for a specific resolution and extent....    this is enough for me!

 

So... now i can do a tool for batch rendering...   i'll give the "original sharp map layer"...   the TileSchema  and the output folder  then the tools will start to render all the requested tiles....    even if it runs for two days on a 8 core machine doesn't matter...     in the end the rendering will be very fast!  it will be just a a sort of "file server" ;)     is it?

 

Albert

Dec 29, 2010 at 10:20 AM

ehy i tried to do something like this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BruTile;
using SharpMap.Geometries;
using ProjNet.CoordinateSystems;
using MapEngine.Projection;
using System.Globalization;

namespace MapEngine
{
    public class TileRenderingEngine
    {
        /// <summary>
        /// Build a Tile Schema basing on the information provided
        /// </summary>
        /// <param name="name"></param>
        /// <param name="boudingBox"></param>
        /// <param name="targetCoordinateSystemEpsgId"></param>
        /// <param name="zoomLevels"></param>
        /// <returns></returns>
        public static ITileSchema BuildTileSchema(string name, BoundingBox boudingBox, int targetCoordinateSystemEpsgId, int zoomLevels)
        {
            var tileSchema = new TileSchema();
            tileSchema.Name = name;
            tileSchema.Height = 256;
            tileSchema.Width = 256;
            tileSchema.Format = "png";
            tileSchema.Srs = "EPSG:" + targetCoordinateSystemEpsgId.ToString(CultureInfo.InvariantCulture);
            tileSchema.Axis = AxisDirection.InvertedY;
            
            //Calculate the extent, resolutions and other information...

            //ASSUME THAT THE BOUNDING BOX IS DEFINED IN WGS 84 COORDINATE SYSTEM!!!
            var ct = ProjectionHelper.GetCoordinateTransformationFromEPSGID(4326, targetCoordinateSystemEpsgId);

            //calculate projected bounding Box (if necessary!)
            var targetBoundingBox = boudingBox;

            if (ct != null)
            {
                targetBoundingBox = SharpMap.CoordinateSystems.Transformations.GeometryTransform.TransformBox(boudingBox, ct.MathTransform);
            }
                        
            //Set tile schema origin
            tileSchema.OriginX = targetBoundingBox.Left;
            tileSchema.OriginY = targetBoundingBox.Top;

            //Set extent
            tileSchema.Extent = new Extent(targetBoundingBox.Left, targetBoundingBox.Bottom, targetBoundingBox.Right, targetBoundingBox.Top);
            
            //Calculate Resolutions
            var currentZoomLevel = targetBoundingBox.Width;

            for (int level = 0; level < zoomLevels; level++)
            {
                currentZoomLevel = currentZoomLevel / 2;
                tileSchema.Resolutions.Add(currentZoomLevel);
            }
            
            return tileSchema;        
        }
    }
}

it create a tile schema...  but after when i try to get the tileinfos...   i didn't get anything!!!

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MapEngine;
using SharpMap.Geometries;
using BruTile;

namespace TileRendering
{
    class Program
    {
        static void Main(string[] args)
        {
            var worldBBox = new BoundingBox(-180.0,-85.05,180.0,85.05);
            var schema = TileRenderingEngine.BuildTileSchema("worldTileSchema", worldBBox, 4326, 3);
            IList<TileInfo> infos = schema.GetTilesInView(schema.Extent, 0);            
            
            var schema2 = CreateTileSchema();
            IList<TileInfo> infos2 = schema.GetTilesInView(schema2.Extent, 0);                                                
        }


        private static ITileSchema CreateTileSchema()
        {
            double[] resolutions = new double[] { 
                156543.033900000, 78271.516950000, 39135.758475000, 19567.879237500, 9783.939618750, 
                4891.969809375, 2445.984904688, 1222.992452344, 611.496226172, 305.748113086, 
                152.874056543, 76.437028271, 38.218514136, 19.109257068, 9.554628534, 4.777314267,
                2.388657133, 1.194328567, 0.597164283};

            TileSchema schema = new TileSchema();
            schema.Name = "OpenStreetMap";
            foreach (float resolution in resolutions) schema.Resolutions.Add(resolution);
            schema.OriginX = -20037508.342789;
            schema.OriginY = 20037508.342789;
            schema.Axis = AxisDirection.InvertedY;
            schema.Extent = new Extent(-20037508.342789, -20037508.342789, 20037508.342789, 20037508.342789);
            schema.Height = 256;
            schema.Width = 256;
            schema.Format = "png";
            schema.Srs = "EPSG:900913";
            return schema;
        }

    }
}

 

this is very strange!  schema  doesn't run but   the schema2 yes!    but in the end i follow almost the same things   same axis orientation....   the only difference is that my schema is not projected!  

 

any suggestion!?

 

 

 

Dec 29, 2010 at 10:43 AM

i found! was the resolution!!!  i've to divide to width of the tile!