Using MBTiles
With last week’s 14.1 release, ThinkGeo UI now has native support for MBTiles!
The MBTiles file format is an open specification based on the SQLite database. Files can contain raster or vector tilesets and it’s designed to allow you to package many files into a single tileset.
MBTiles have become very popular in recent years with providers like MapBox, MapTiler and OpenZoomStack making extensive use of the format. In today’s post, we’ll show examples of using .mbtiles in your app.
Tip
To see the new MbTilesLayer in action, just clone the HowDoI samples, run the solution and then click on the ‘Display a MBTiles File’ under the ‘Map Offline Data’ section of the samples.
While the sample below is using ThinkGeo Desktop for WPF, the MbTiles layers work just the same in our Mobile and Web components.
Sample Overview
This sample uses an MbTilesLayer with a vector tileset styled with a .json file. Note: your style json file needs to conform to the Mapbox or MapLibre style specifications. You can learn more about the thinkGeo MBStyle class and styling here.
If your .mbtiles file is raster-based, simply use the MbTilesRasterLayer in the same way, but there’s no need to pass in a .json file for styling since raster tiles are pre-rendered and cannot be styled by the client.
Code Walkthrough
The code below shows the minimum required to create a new MbTilesLayer passing a .mbtiles file and style.json file. In this sample, the .mbtiles file contains a vector tileset and accompanying style.json file.
// Set the MapUnit and create a LayerOverlay to add our mbtiles layer to later.
MapView.MapUnit = GeographyUnit.Meter;
var layerOverlay = new LayerOverlay();
layerOverlay.TileType = TileType.MultiTile;
MapView.Overlays.Add(layerOverlay);
// Load the .mbtiles sample file and pass in an optional style.json file to define how the layer is styled.
var openstackMbtiles = new MbTilesLayer(@".\Data\Mbtiles\maplibre.mbtiles", @".\Data\Mbtiles\style.json");
layerOverlay.Layers.Add(openstackMbtiles);
// Set the current extent of the map.
MapView.CurrentExtent = new RectangleShape(-11305077.39954415, 11301934.55158609, 6893050.193489946, -2669531.148872344);
MapView.Background = new SolidColorBrush(Color.FromRgb(216, 242, 255));
// Refresh the map after layers are loaded.
await MapView.RefreshAsync();
The sample also demonstrates how to change the LayerOverlay’s TileWidth and TileHeight properties from the default 256 to a larger 512x512 size.
private async void SwitchTileSize_OnCheckedChanged(object sender, RoutedEventArgs e)
{
// Make sure the overlay is initialized.
if (MapView.Overlays.Count > 0 && MapView.Overlays[0] is LayerOverlay layerOverlay)
{
// Get the tile size from the radio button.
var tileSize = int.Parse(((RadioButton)sender).Tag.ToString());
MapView.ZoomLevelSet = new SphericalMercatorZoomLevelSet(tileSize);
// Set the LayerOverlay's TileWidth and TileHeight to the desired value from the radio button.
layerOverlay.TileWidth = tileSize;
layerOverlay.TileHeight = tileSize;
// Update the map's ZoomLevelSet before refreshing.
if (layerOverlay.Layers[0] is MbTilesLayer mbTilesLayer)
{
mbTilesLayer.ZoomLevelSet = new SphericalMercatorZoomLevelSet(tileSize, MaxExtents.SphericalMercator);
}
await MapView.RefreshAsync();
}
}
You’ll also notice the red squares and tile identifiers in the sample. This is a debugging feature that can be enabled using the ThinkGeoDebugger class shown in the code below.
For more details on the new ThinkGeoDebugger class, check out this post.
private async void ShowTileID_OnCheckedChanged(object sender, RoutedEventArgs e)
{
//Use the ThinkGeoDebugger class if you want to display the tileIds for debugging purposes.
ThinkGeoDebugger.DisplayTileId = (sender as CheckBox).IsChecked == true;
if (MapView != null)
await MapView.RefreshAsync();
}
Finally, if your .mbtiles file has a raster tileset, you can just use the new MbTilesRasterLayer instead of the MbTilesLayer shown in the example above. We currently don’t have a sample showing a raster-based .mbtiles file, but the code below is all you need! It’s essentially the same as the MbTilesLayer sample except there’s no need to pass a style.json in the constructor since raster datasets cannot be styled on the client.
// With ThinkGeo.UI.Wpf or ThinkGeo.UI.WinForms
private async void MapView_OnLoaded(object sender, RoutedEventArgs e)
{
// Setup the MapView and Overlay
MapView.MapUnit = GeographyUnit.Meter;
var layerOverlay = new LayerOverlay();
MapView.Overlays.Add(layerOverlay);
// Create the MbTiles layer by providing the path to the raster .mbtiles file
var layer = new MbTilesRasterLayer(@"path\to\sample.mbtiles");
layerOverlay.Layers.Add(layer);
// Set starting extent to the layer's bounding box
await layer.OpenAsync();
MapView.CurrentExtent = layer.GetBoundingBox();
}
Summary
We hope today’s post has been helpful. If you have any questions or if you have a topic you would like to learn more about, please email sales@thinkgeo.com or schedule a meeting to talk in person.
About ThinkGeo
We are a GIS software company founded in 2004 and located in Frisco, TX. Our clients are in more than 40 industries including agriculture, energy, transportation, government, engineering, IT, and defense. We pride ourselves on our excellent service and transparency. ThinkGeo offers a variety of products and services to meet almost any GIS application need. We can even help you develop your next project - anywhere from a few hours of consulting to outsourcing an entire project. To learn more, email us at sales@thinkgeo.com, or call us direct at 1-214-449-0330.