Why I am using Openstreetmap as Map provider
Every developer will come up with the problem that he must export some Maps into any PDF or export file. In most common scenarios the central part will go through google maps azure maps or another map provider to get a static tile to export.
But there is one common problem, missing details. So let's start first with the requirement
The Requirement
We have several geopoints that mark an area on a map. Our requirement is to export some particular regions as Images so that they can be included into a generated pdf. The importance is that most streets must be readable because they will be used by salesmen to get from house to house. This map will inform them, which regions they are allowed to operate in.
The Problem
We tried several map providers, some of them have very fancy features but not all of them export static images from a map. The only one that I figured out was firstly azure maps. It will export the images and draw also a polygon on the map with the given geopoints that we have in the database.
But unfortunately, when we apply the correct zoom level we get only a glimpse of the street names. For a salesman that is not very helpful and gets later in some struggle.
Let me give you a small sample of this exported map
The map provider solution
First of all, before we can go into further investigation, we consulted the azure maps API with some small hopes that we can get more details out of this, but with no luck. After that we search for another provider, google maps are out, and bing maps is another choice but unfortunately, they export only static maps but do not allow drawing polygons on them at the same time.
After a little research, we come up with OpenStreetMap.
Open Streetmap to the rescue
So this is open source, in their wiki are several pieces of documentation about how to use the data in several ways. That was the first problem.
How do we solve our problem?
So first of all I divided the problem into smaller chunks. So in our problem, we need the map (Tile) and draw the polygon on it.
Fist solution get the map
First of all, I try to get the map, a search in the wiki about it, there are exists several tile servers.
I decided to use the default one from arcgis. The tiles can easily be called via get (also in the browser).
For example, the pattern from arcgis is this
https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/$z/$x/$y
Where $z is set to the zoom level, $x is the index of the horizontal row and $y is the index of the vertical row. The index will start with 0.
https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/1/0/0
This will result in this image:
Because we are on the minimized zoom level at the point 0 from the left and 0 from the top.
So with the right zoom level and the right position located, you will be able to merge the maps together into one image and then you got the right map image to display.
Brief instruction about zoom levels
Let me explain a little bit about zoom levels because it can be a little bit confusing... and yes that's for all map providers the same. Let's image the zoom level 0 that's the global world map. That results in this tile
On each next zoom level, there will each tile will be divided into four more tiles. So when we look at our first example it will represent the left upper tile from the world map. But it's zoomed. You can calculate the tiles like this: 2zoom x 2zoom
For example a zoom level of 4 will represent 24 x 24 = 16*16 = 265 Tiles in total. So when you want the last tile in the lower brighter corner you will access them via
https://server.arcgisonline.com/arcgis/rest/services/World_Imagery/MapServer/tile/4/15/15
Because it will index the last tile from this.
Get the right Images
In many languages, there are existing converters that transform the geo coordinates into these X and Y Coordinates. For example, let's use this JS data
This will transform the lat and long values with the given zoom level to the X and Y coordinates of the map.
There are some edge cases, but let's assume we hit the right point of our tile. After this you will be able to select the next tiles to the top, bottom left, and right to get more space around.
Then merge them together and you have a ready-to-go map.
Draw the Polygon
So the next part is, to draw the polygon onto the map. Fortunately for this exists several spatial libraries that can do it for you most of the based on the Cairo graphics engine. This engine takes the series of points that represents the polygon and projects them onto the right position on the merged tile.
So finally I got some results like these:
For sure this has more details on it than the other map provider.
Conclusion
Sure there is much information so I found a nice library that I forked on GitHub, this can be found here. Yes, that topic is complex from the first point of view, but when we investigate some details on this, it is very simple to understand this. Then you must add some math to it and you will be the master of maps ;).
Yes everybody thinks now: "Why Openstreetmaps? It's not validated and contains several mistakes". Yes for sure, but it's free for use, also for commercial use. Also, you have the possibility to get more details about this, and it is community driven. So errors would be fixed faster than commercial maps. Because they use some service provider that drives around and notes every change on its map or goes to the government to get their new street structures or s.th. else.
So give it a try.