r.klingeresri-de-esridist

Custom Tiles in ArcGIS JavaScript API

Blog Post created by r.klingeresri-de-esridist Employee on Aug 3, 2018

I like to explore the city via public transport and as I am a big map fan, I fell in love with the map of our Berlin based public transport service provider BVG. The map is a great product and has so many levels of information. It has a well know style established in Berlin so I wanted to use it in my own web mapping application.

As I scanned the website of the BVG I noticed the leaflet map on their page:

So I asked the question: "Where does the tiles came from". A short look in the network developer pane in firefox revealed the address https://fahrinfo.bvg.de/tiles/base/15/17605/22019.png  (example)

The Tiles can be easily added inside a ArcGIS Javascript API based webmap:

var tiledLayer = new WebTileLayer({
     urlTemplate: "https://fahrinfo.bvg.de/tiles/base/{level}/{col}/{row}.png",
     title: "BVG Basemap",
     copyright:            
          "Map Data by <a href='https://Bvg.de'>BVG</a>, " +
          "Imagery by <a href='https://Bvg.de/'>BVG</a>"
});

But as soon you embed this, you will notice: There are only 404s send back from the BVG server. So I examined the URL-schema and found out, that the Y id is somewhat different compared to mapbox or OSM Y ids for the same tile:

y-tile: BVGy-tile: MapboxzoomLevel
220201074715
220151075215
220131075415
11007537614
440252151016
440262150916

So the tile indices are somehow shifted compared to the normal schema... So let us reverse engineer the conversion. First approach: plot the IDs on a chart and try some regression:

But as you can see: the line looks straight but the equation is just ****. Let's zoom in a bit:

This is of course a bit different: the regression line flipped and we do have no residuals. The summand looks very common as it is near a power of 2. to be exact: 2^15-1

So there is a direct equation to transform the original tile row into a BVG tile row:

var rownew = -1*row+Math.pow(2,level)-1;

So now we need to import this logic into the method ArcGIS uses to get the tiles. And BAMM: here are the tiles:

var tiledLayer = new WebTileLayer({
     urlTemplate: "https://fahrinfo.bvg.de/tiles/base/{level}/{col}/{row}.png",
     title: "BVG Basemap",
     getTileUrl: function (level, row, col) {
          var rownew = -1*row+Math.pow(2,level)-1;
          return this.urlTemplate.replace("{level}", level).replace("{col}", col).replace("{row}", rownew);
     },
     copyright:            
          "Map Data by <a href='https://Bvg.de'>BVG</a>, " +
          "Imagery by <a href='https://Bvg.de/'>BVG</a>"
});

Explore the webmap on CodePen, or download it below.

And last but not least: You can even rotate it:

In the end: If you know the math, you can change the world ;-)

Outcomes