-
Notifications
You must be signed in to change notification settings - Fork 0
/
README.Rmd
171 lines (116 loc) · 4.95 KB
/
README.Rmd
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
163
164
165
166
167
168
169
170
171
---
output: github_document
---
<!-- README.md is generated from README.Rmd. Please edit that file -->
```{r, include = FALSE}
knitr::opts_chunk$set(
collapse = TRUE,
comment = "#>",
fig.path = "man/figures/README-",
out.width = "100%"
)
```
# realarea
<!-- badges: start -->
<!-- badges: end -->
The goal of realarea is to provide helpers to determine the actual area covered and the calculated area vs the "real" geographic area represented in a projected raster.
## Installation
You can install the development version of realarea like so:
``` r
remotes::install_github("hypertidy/realarea")
```
## Example
We have a shapefile and we want to assess suitability of a given map projection.
```{r example}
library(realarea)
luxshp <- system.file("ex/lux.shp", package="terra", mustWork = TRUE)
lux <- terra::vect(luxshp)
```
With `crs_grid()` we can create a suitable raster grid from that vector data set.
By default we just get a nice grid from it in the native crs.
```{r crs_grid}
crs_grid(lux)
```
But specify an actual map projection and we can get some more benefit, and with 'res' we can get exactly what we want: a raster from which we can calculate real-world area (with `terra::expanse()`) and compare that with the nominal cell size which is `prod(res(<x>))`.
```{r crs}
crs <- "EPSG:23032"
crs_grid(lux, crs = crs)
luxutm1000 <- crs_grid(lux, crs = crs, res = 1000)
luxaea1000 <- crs_grid(lux, crs = "+proj=aea +lon_0=6 +lat_0=50 +lat_1=50.1 +lat_2=49.4", res = 1000)
```
What is the total area of the input polygon?
What do we get from the two projections?
```{r area}
library(terra)
polyarea <- sum(expanse(lux))
sqrt(polyarea)
utmarea <- sum(values(mask(cellSize(luxutm1000), luxutm1000)), na.rm = TRUE)
sqrt(utmarea)
## this one is closest to the polygon area
aeaarea <- sum(values(mask(cellSize(luxaea1000), luxaea1000)), na.rm = TRUE)
sqrt(aeaarea)
plot(cellSize(luxutm1000)/prod(res(luxutm1000)))
plot(cellSize(luxaea1000)/prod(res(luxaea1000)))
```
So, unsurprsingly the local Albers Equal Area Conic projection is a better choice than UTM, but
do we really care about that level of discrepancy? Probably not, but you can't have a single rule
that always works, it depends where, how long how wide, on the projection, what you need to measure,
and what you are actually doing. :)
When folks look for a crs, they often restrict themselves only to codes (e.g. EPSG) that are pre-defined, that can work ok for nations and particular well-mapped regions, but there's no hard rule, you can define your own projection for particular purposes.
What about other fun projections?
```{r vicgrid}
library(terra)
library(sf)
p <- vect(silicate::inlandwaters[5:6, ])
utm <- crs_grid(p, "EPSG:32755")
plot(cellSize(utm)/prod(res(utm)))
plot(project(p, "EPSG:32755"), add = TRUE)
vicgrid <- crs_grid(p, "EPSG:7899")
plot(cellSize(vicgrid)/prod(res(vicgrid)))
plot(project(p, "EPSG:7899"), add = TRUE)
```
What if we had a region like the Albers national projection used by GA?
```{r wateven,eval=FALSE, include=FALSE}
share <- strsplit(system("whereis proj", intern = TRUE), " ")[[1]][4]
con <- RSQLite::dbConnect(RSQLite::SQLite(), file.path(share, "proj.db"))
library(dbplyr)
library(dplyr)
DBI::dbListTables(con)
library(stringr)
albex <- tbl(con, "extent") |> filter(code == 3577) |> transmute(xmin = west_lon, xmax = east_lon, ymin = south_lat, ymax = north_lat) |> collect() |> unlist()
albex
```
So, what does that look like?
```{r vaster}
albex <- c(112.85,153.69,-43.7,-9.86)
bdy <- reproj::reproj_xy(vaster::vaster_boundary(c(32, 32), albex),
"EPSG:3577", source = "EPSG:4326")
plot(bdy, asp = 1)
```
```{r albersgrid}
library(terra)
p <- terra::vect(matrix(albex[c(1, 1, 2, 2, 1,
3, 4, 4, 3, 3)], ncol = 2), type = "polygons", crs = "EPSG:4326")
p <- terra::densify(p, 1, flat = TRUE) ## beware densify, we don't want great circles ...
grd <- crs_grid(p, "EPSG:3577")
terra::plot(grd); plot(project(p, "EPSG:3577"), add = TRUE)
plot(cellSize(grd)/prod(res(grd)))
oz <- vect(sds::CGAZ(), query = sds::CGAZ_sql("Australia"))
plot(project(oz, "EPSG:3577"), add = TRUE)
```
Let's expand that out to Australia's broader remit, this takes a bit of special handling and is teaching me something I needed to figure out ... WIP
```{r ozex}
ozex <- c(55, 164, -90, -6)
p <- terra::vect(matrix(ozex[c(1, 1, 2, 2, 1,
3, 4, 4, 3, 3)], ncol = 2), type = "polygons", crs = "EPSG:4326")
p <- terra::densify(p, 1000)
grd <- crs_grid(p, "EPSG:3577")
grd <- crop(grd, c(xmin(grd), xmax(grd), -7.5e6, ymax(grd)))
agrd <- cellSize(grd)
agrd[!agrd > 1e5] <- NA
plot(agrd/prod(res(agrd)))
m <- reproj::reproj_xy(do.call(cbind, maps::map(plot = F)[1:2]), "EPSG:3577", source = "EPSG:4326")
lines(m)
```
## Code of Conduct
Please note that the realarea project is released with a [Contributor Code of Conduct](https://contributor-covenant.org/version/2/1/CODE_OF_CONDUCT.html). By contributing to this project, you agree to abide by its terms.