/
tm_pos.R
162 lines (153 loc) · 7.9 KB
/
tm_pos.R
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#' Set the position of map components
#'
#' Set the position of map components, such as legends, title, compass, scale bar, etc.
#' `tm_pos()` is the function to position these components:
#' `tm_pos_out()` places the components outside the map area and `tm_pos_in()` inside the map area.
#' Each `position` argument of a map layer or component should be specified with
#' one of these functions. The functions `tm_pos_auto_out()` and `tm_pos_auto_in()`
#' are used to set the components automatically, and are recommended to use globally,
#' via [tmap_options()]. See Details how the positioning works.
#'
#' @param cell.h,cell.v The plotting area is overlaid with a 3x3 grid, of which
#' the middle grid cell is the map area. Components can be drawn into any cell.
#' `cell.h` specifies the horizontal position (column) can take values
#' `"left"`, `"center"`, and `"right"`. `cell.v` specifies the vertical position
#' (row) and can take values `"top"`, `"center"`, and `"bottom"`.
#' See details for a graphical explanation.
#' @param pos.h,pos.v The position of the component within the cell.
#' The main options for `pos.h` are `"left"`, `"center"`, and `"right"`.
#' For `cell.v` these are `"top"`, `"center"`, and `"bottom"`.
#' These options can also be provided in upper case; in that case there is no offset
#' (see the tmap option `component.offset`). Also numbers between 0 and 1 can be provided,
#' which determine the position of the component inside the cell (with (0,0) being left bottom).
#' The arguments `just.h` and `just.v` determine the justification point.
#' @param align.h,align.v The alignment of the component in case multiple components are stacked.
#' When they are stacked horizontally, `align.v` determines how components
#' that are smaller in height than the available height (determined by the outer.margins
#' if specified and otherwise by the highest component) are justified:
#' `"top"`, `"center"`, or `"bottom"`. Similarly, `align.h` determines how components
#' are justified horizontally when they are stacked vertically: `"left"`, `"center"`, or `"right"`.
#' @param just.h,just.v The justification of the components.
#' Only used in case `pos.h` and `pos.v` are numbers.
#' @details
#'
#' | | | | | |
#' |---------------:|:---------------|:------------------|:------------------|:------|
#' | | +------------------- | +-------------------------------- | +------------------- | +
#' | | \| | \| |\| |\| |
#' | `"top"` | \| | \| |\| |\| |
#' | | \| | \| |\| |\| |
#' | | +------------------- | +-------------------------------- | +------------------- | +
#' | | \| | \| |\| |\| |
#' | | \| | \| |\| |\| |
#' | `cell.v`  "center"| \| | \|   Map(s) |\| |\| |
#' | | \| | \| |\| |\| |
#' | | \| | \| |\| |\| |
#' | | +------------------- | +-------------------------------- | +------------------- | +
#' | | \| | \| |\| |\| |
#' | `"bottom"` | \| | \| |\| |\| |
#' | | \| | \| |\| |\| |
#' | | +------------------- | +-------------------------------- | +------------------- | +
#' | |   `"left"` |   `"center"` |    `"right"` | |
#' | | |   `cell.h` | | |
#'
#' `tm_pos_in()` sets the position of the component(s) inside the maps area,
#' which is equivalent to the center-center cell (in case there are facets,
#' these are all drawn in this center-center cell).
#'
#' `tm_pos_out()` sets the position of the component(s) outside the map.
#'
#' The amount of space that the top and bottom rows, and left and right columns
#' occupy is determined by the [tm_layout()] arguments `meta.margins` and `meta.auto.margins`.
#' The former sets the relative space of the bottom, left, top, and right side.
#' In case these are set to `NA`, the space is set automatically based on 1)
#' the maximum relative space specified by `meta.auto.margins` and 2)
#' the presence and size of components in each cell.
#' For instance, if there is one landscape oriented legend in the center-bottom cell,
#' then the relative space of the bottom row is set to the height of that legend
#' (given that it is smaller than the corresponding value of `meta.auto.margins`),
#' while the other four sides are set to 0.
#'
#' `tm_pos_auto_out()` is more complex: the `cell.h` and `cell.v` arguments should be set
#' to one of the four corners. It does not mean that the components are drawn in a corner.
#' The corner represents the sides of the map that the components are drawn.
#' By default, legends are drawn either at the bottom or on the right-side of
#' the map by default (see `tmap_options("legend.position")`).
#' Only when there are row- and column-wise legends and a general legend (using [tm_facets_grid()]),
#' the general legend is drawn in the corner, but in practice this case will be rare.
#'
#' The arguments `pos.h` and `pos.v` determine where the components are drawn within the cell.
#' Again, with `"left"`, `"center"`, and `"right"` for `pos.h`
#' and `"top"`, `"center"`, and `"bottom"` for `pos.v`.
#' The values can also be specified in upper-case, which influences the offset
#' with the cell borders, which is determined by tmap option `component.offset`.
#' By default, there is a small offset when components are drawn inside and no
#' offset when they are drawn outside or with upper-case.
#'
#' `tm_pos_auto_in()` automatically determines `pos.h` and `pos.v` given the
#' available space inside the map. This is similar to the default positioning in tmap3.
#'
#' In case multiple components are draw in the same cell and the same position
#' inside that cell, they are stacked (determined which the `stack` argument in
#' the legend or component function). The `align.h` and `align.v` arguments
#' determine how these components will be justified with each other.
#'
#' Note that legends and components may be different for a facet row or column.
#' This is the case when [tm_facets_grid()] or [tm_facets_stack()] are applied
#' and when scales are set to free (with the `.free` argument of the map layer functions).
#' In case a legends or components are draw row- or column wise, and the position
#' of the legends (or components) is right next to the maps, these legends
#' (or components) will be aligned with the maps.
#'
#' @export
#' @name tm_pos
#' @rdname tm_pos
tm_pos = function(cell.h, cell.v, pos.h, pos.v, align.h, align.v, just.h, just.v) {
args = lapply(as.list(match.call()[-1]), eval, envir = parent.frame())
args$type = "na"
structure(args, class = "tm_pos")
}
#' @export
#' @name tm_pos_in
#' @rdname tm_pos
tm_pos_in = function(pos.h, pos.v, align.h, align.v, just.h, just.v) {
args = lapply(as.list(match.call()[-1]), eval, envir = parent.frame())
args$type = "in"
structure(args, class = "tm_pos")
}
#' #' @export
#' tm_pos_cell = function(pos.h, pos.v, just.h, just.v) {
#' args = lapply(as.list(match.call()[-1]), eval, envir = parent.frame())
#' args$type = "cell"
#' structure(args, class = "tm_pos")
#' }
#' @export
#' @name tm_pos_out
#' @rdname tm_pos
tm_pos_out = function(cell.h, cell.v, pos.h, pos.v, align.h, align.v, just.h, just.v) {
args = lapply(as.list(match.call()[-1]), eval, envir = parent.frame())
args$type = "out"
structure(args, class = "tm_pos")
}
#' @export
#' @name tm_pos_auto_out
#' @rdname tm_pos
tm_pos_auto_out = function(cell.h, cell.v, pos.h, pos.v, align.h, align.v, just.h, just.v) {
args = lapply(as.list(match.call()[-1]), eval, envir = parent.frame())
args$type = "autoout"
structure(args, class = "tm_pos")
}
#' @export
#' @name tm_pos_auto_in
#' @rdname tm_pos
tm_pos_auto_in = function(align.h, align.v, just.h, just.v) {
args = lapply(as.list(match.call()[-1]), eval, envir = parent.frame())
args$type = "autoin"
structure(args, class = "tm_pos")
}
str2pos = function(x) {
tm_pos_in(x[1], x[2])
}
num2pos = function(x) {
tm_pos_in(x[1], x[2])
}