Print composer in QGIS gives us the possibility of creating printable maps and atlases, which can be saved as the .pdf or .svg. The print composer provides a wide spectrum of options by adding various elements and components to our maps. Next, we can resize, align and rotate each other as we need to. As a result, we receive a powerful way to publicize our geographical information produced with QGIS, which can be included in reports, publications, etc.
Undeniably the most important element in the QGIS print composer is our map, but we also should bear in mind the most important components of this map. One of them is the coordinate grids. Coordinates are a set of values identifying each of a set of places on our map. When they are displayed as the grid, they can in some cases also act as the map scale, but predominantly their role is to easier locate the object on our map. This role is much bigger when instead of map units (derived from CRS) we decide to set up metric units combined with custom labeling. This is roughly the type of coordinates, which I would like to discuss here. It will be simple, without programming involvement.
The explanations of how to draw and set up map grids in the QGIS printing layout you can find in the links and videos attached at the very end. I will start with the existing map grids.
Looking at the map above we can spot an already existing coordinate grid, which is based on the EPSG:27700 CRS system corresponding to the British National Grid. Moreover, the labels overlay grids, which is not the best practice. The goal of this article is to turn these coordinate grids into custom with offset labeling.
1. Firstly, we should select our map from the Items panel on our right. Afterward in the “Item properties” panel below we must find the “Grids” section with the “List of grids” available. Any grid available there can be modified (Pic. 2).
2. When you click “Modify Grid” you should see other sections expanded. The most important by now is the very first one – “Appearance“, which defines both the grid intervals and their offset. Here is also the place to change the CRS of our map grids, but we don’t need to do it. We just have to define the interval unit and value (Pic. 3).
Changing the grid units from map units to metric units must be thought over with respect to the real map dimensions. They can be set i.e. by right-clicking on the map. Since you have chosen the A3 paper size, you can have max. 420mm in width and 297mm in height. When you reserve some space for other elements like a legend, etc, this space will be even smaller (Pic. 5). There is no point to set cm units with 100 intervals then. Instead of it you can select mm units and keep 100 intervals or 10 intervals for centimeters. For the comparison, I used the A2 paper size, where an interval of 100 millimeters has been applied (Pic. 4).
In the situation like above, an appropriate will be to apply 100mm intervals or 10cm intervals for receiving the same number of grid boxes.
3. Browse your “Map Grid Properties” panel down until reaching the “Draw Coordinates” section. It’s switched on, as you can see labels overlaid on the girds. We should turn them off and keep just grids (Pic. 6).
4. Create the new grid layer and preferably change the name of both (Pic. 7). Since now we will have one grid layer for the grid display and another one will be prepared for the labels only. Our job starts to make sense now and vice versa!
5. Now, we will focus on our new grid created, which will be dedicated to the labels only. However, our prerequisite should be displaying the grids as default, before we define the interval, and what is the most important here – the offset. For sake of simplification, we can change the grid color in order to distinguish it from the 1st grid set. Next, we should define the same interval features as we did for our first grid. The default interval will be the “Map Unit“, therefore these two grids will be separate from each other. By changing the interval to “Millimeter” like we did for our first grid, and setting the value 100 both for X and Y the second grid will be exactly overlapped with the first one. In order to get an interesting effect, we should use the “Offset” feature and set it up both for X and Y values. For millimeter units, changing these values to 6 or 7 should give a satisfactory effect for us. The second grid is offset properly (Pic. 8), thereby can be used for displaying the labels, which you can see already in the middle of the 2nd grid provided.
Since we are fine with the position of the 2nd grid, we should change the “Grid type” from “Solid” to “Frame and annotations only“. It will switch the grid off and keep labels only (Pic. 8, 2).
These labels remain not correct, as they show the millimeter units rather than custom values.
6. This is the time for playing with the label formula in order to make them customized for our own purpose.
By the way, we can set their position in this section by placing them inside or outside the frame, etc. For the custom setting purpose, it’s essential to change the format from “Decimal” as the default to “Custom” as presented in the image next to (Pic. 8).
Toggling the “Format” type only to “Custom” means nothing itself unless we hit the Ε symbol bounded red. This is the place, where the Expression Based Annotation window opens with all formulas available in our QGIS software.
Our initial formula could look like the below:
CASE WHEN @grid_axis = 'y' THEN substr('ABCDEFGHIJKLMNOPQRST', (@grid_number) / 100 , 1) WHEN @grid_axis = 'x' THEN (@grid_number) / 100 END
which would give the result like in the image below:
with strict attention to the interval rate and offset. Namely, both numbers determine the value of the label appearing on our map. By analyzing our formula we should take a look at the key values there:
– for Y-axis we use the substr function, which assigns the letter to our value, thereby the @grid_number = 1 corresponds to the “A” letter. In turn, the number 1 at the very end…
THEN substr('ABCDEFGHIJKLMNOPQRST', (@grid_number) / 100 , 1)
…determines the total amount of letters to be displayed. By putting number 2 there we will have “AB” instead of “A” and so on.
– for the X axis we have simply the @grid_number divided by 100 because we set the “Interval” value 100 for the X (Pic. 10). As you surely noticed, the same equation has been applied for the Y axis.
Concluding the interval value defined in the “Map Grid Properties” must collaborate with the value of the @grid_number. Imagine, that you will keep the @grid_number value as 100 with the interval as 100. The result will be at least inappropriate because we will have numbering every 100 instead of 1 (Pic. 11). This is because the grids are marked in every 100 as defined in the “Interval“.
We have to always remember about proper equations and adjust the final @grid_number value to the value of our interval defined.
With the substr function, the situation looks different. With the same non-conformity as described above, we will receive just one letter (Pic. 12) and it won’t be “A“. The letter will be offset-based and might start from “C“,”D“, or “B” depending on what offset we defined. When you take a look at the symbols within the substr function you can count up to 20. It means, that the letters won’t appear when @grid_number exceeds 20. In our case, since the interval is set to 100 and the grid appears every 100 units (millimeter), we have letters just for 20 units. Finally, we can see the string label just in one place.
Let’s jump to the offset values, which also affect our label values here. We can sort it out in two ways.
The first way will simply deduct the offset value defined. When we set the offset value as 6, then our formula for the X axis should look like this:
WHEN @grid_axis = 'x' THEN ((@grid_number) - 6) /100
where we are reducing the @grid_number by 6 and next subtracting by our Interval value.
The first way is to include everything within the round function, which will help us smartly to get rid of all the decimals.
WHEN @grid_axis = 'x' THEN round((@grid_number)/100,0)
Finally, we should be happy with our custom labeling for the X axis… (Pic. 13).
…but we should still sort the Y-axis problem out because the first symbol appears twice (Pic. 14).
This is because our @grid_number has been divided by 100 and provided something like “symbol 0” which is replaced by the “A” letter – the first defined in our string.
WHEN @grid_axis = 'y' THEN substr('ABCDEFGHIJKLMNOPQRST', (@grid_number) /100 , 1)
In this case, we have to push (increase) our @grid_number value by 1 in order to supersede this “symbol 0” with the first string letter defined.
Essential will be alteration like below, which finally will make our custom grid fine(Pic. 15).
WHEN @grid_axis = 'y' THEN substr('ABCDEFGHIJKLMNOPQRST', (@grid_number + 100) /100 , 1)
If you don’t want to start from “0” at your X-axis, you can do the same for the first part of your formula:
WHEN @grid_axis = 'x' THEN round((@grid_number + 100)/100,0)
The final formula for our custom grid should look as follows:
CASE WHEN @grid_axis = 'y' THEN substr('ABCDEFGHIJKLMNOPQRST', (@grid_number + 100) /100 , 1) WHEN @grid_axis = 'x' THEN round((@grid_number)/100,0) END
CASE WHEN @grid_axis = 'y' THEN substr('ABCDEFGHIJKLMNOPQRST', (@grid_number + 100) /100 , 1) WHEN @grid_axis = 'x' THEN round((@grid_number + 100)/100,0) END
and the final map including custom grids with offset labels will be also presented nicely(Pic. 16, 17)!
- Wikimho.com: how to add grid coordinates in QGIS 2.12.0-Lyon in the print composer canvas?
- pCloud: Setting up the grid properties in QGIS print composer#
- https://docs.nextgis.ru/docs_ngqgis/source/map_composer.html (Russian)
- https://tr.azedupress.com/737729-excess-decimal-points-showing-on-BNMNXP-article (Turkish)
- Can anybody help explain how to remove the random decimal points on my grid? QGIS 3.8.1
- Github.com: Allow data-defined control over grid spacing and offset
- Github.com: Custom format for grid coordinates
- Github.com: Grid lowest Y coordinate hidden in layout when set outside frame
- Github.com/: Layout grid offset
- Github.com: Changing grid options in print layout makes QGIS crash on subsequent project load