---
title: "Working with WMS rasters"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Working with WMS rasters}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(collapse = TRUE, comment = "#>", eval = FALSE)
```

```{r setup}
library(Argentum)
library(terra)
library(sf)
```

## Why WMS at all

If WFS gives you real geometries, why ever ask for a picture?

Three reasons, and they come up constantly with Argentine data.

**Some layers only exist as WMS.** Satellite imagery, orthophotos, scanned
historical charts and relief shading have no vector equivalent. The publisher
has a raster; WMS is how they share it.

**Some WFS layers are too heavy to be worth it.** A national parcel layer is
millions of polygons. If you only need it as a visual backdrop, downloading
the geometry is wasteful — ask the server to draw it instead.

**The publisher's own cartography carries information.** A cadastral server
renders parcels with the symbology its own staff use. Reproducing that from
raw geometry is work you do not need to do.

## The one required argument

WMS has no concept of "the whole layer". Every request renders a fixed
rectangle, so `bbox` is mandatory:

```{r}
ign <- "https://wms.ign.gob.ar/geoserver/ows"

r <- argentum_read_wms(
  ign,
  layer = "ign:provincia",
  bbox  = c(-59, -35, -57, -34),
  width = 1000
)

r
```

A note on the IGN basemap: the official `capabaseargenmap` layer now
answers `GetMap` requests from generic clients with HTTP 403 ("Bloqueado:
uso de WMS en mapa base") - IGN reserves it for its own applications. The
examples therefore use thematic layers, which remain open.

Only `width` is given above; `height` is derived from the aspect ratio of the
bounding box, so the map is not stretched. Give both if you want a specific
canvas, or give only `height` if that is what your layout constrains.

The `bbox` column of `argentum_layers()` gives you a starting extent when you
do not know the layer's footprint:

```{r}
layers <- argentum_layers(ign, service = "wms")
layers[layers$name == "ign:provincia", "bbox"]
```

## Combining raster and vector

This is the payoff. The raster comes back with its CRS set, so it composes
directly with anything you read over WFS:

```{r}
aoi <- c(-59, -35, -57, -34)

basemap  <- argentum_read_wms(ign, "ign:provincia", bbox = aoi, width = 1200)
boundaries <- argentum_read_wfs(ign, "ign:provincia", bbox = aoi, crs = 4326)

terra::plotRGB(basemap)
plot(sf::st_geometry(boundaries), add = TRUE, border = "white", lwd = 2)
```

Because `argentum_read_wms()` returns a plain `SpatRaster`, everything in
`terra` works on it: `crop()`, `mask()`, `project()`, `writeRaster()`.

## Stacking layers in one request

Passing several layer names draws them in a single server-side composite,
first at the bottom. One request instead of several, and the server handles
the blending:

```{r}
argentum_read_wms(
  ign,
  layer = c("ign:provincia", "ign:limite_politico"),
  bbox  = aoi
)
```

## Legends

A rendered map without its legend is often unreadable. `GetLegendGraphic`
returns the symbology the server used:

```{r}
legend <- argentum_wms_legend(ign, "ign:provincia")
terra::plotRGB(legend)
```

The legend is an image, not a map, so it carries no CRS.

## Choosing a format

`"image/png"` is the default and keeps transparency, which you need when
overlaying. `"image/jpeg"` is meaningfully smaller for photographic imagery
but cannot be transparent. `"image/tiff"` is worth requesting when you intend
to analyse rather than display the pixels — though most servers still render
to 8-bit RGB, so it is not a substitute for the underlying data.

```{r}
argentum_read_wms(ign, "some_orthophoto", bbox = aoi, format = "image/jpeg",
                  transparent = FALSE)
```

## A note on axis order

WMS 1.3.0 changed how coordinates are ordered: for CRSs whose authority
definition is latitude-first, the `BBOX` parameter must be given
latitude-first too. WMS 1.1.1 was always longitude-first.

This trips people up badly, because getting it wrong does not produce an
error — it produces a map of the wrong place, or of the ocean.

`Argentum` handles the flip based on the version the server actually
negotiated. It includes the Argentine Gauss-Krüger zones (EPSG:22171 through
22175), which are defined northing-first and are therefore affected, a case
most generic clients get wrong.

You should never need to think about it. If you do hit a swapped map, force
the older protocol and compare:

```{r}
argentum_capabilities(ign, "wms", version = "1.1.1")
```
