---
title: "New geometry interface"
author: "Alec L. Robitaille, Quinn Webber and Eric Vander Wal"
output: 
  rmarkdown::html_vignette:
    number_sections: true
    toc: true
vignette: >
  %\VignetteIndexEntry{New geometry interface}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  eval = TRUE,
  echo = TRUE,
  comment = "#>"
)
```

## Introduction

{spatsoc} v 0.2.13 provides a new geometry interface and internal functions that
provide consistent spatial measures across all {spatsoc} functions.

The motivation for `get_geometry` is to allow users to supply a geometry column
instead of providing coordinates and optionally crs through the "coords" and
"crs" args. This interface is enabled by default on all functions that accept
coordinates / geometry, by leaving the coords null and ensuring the geometry
column has been set up using `get_geometry()`.

Details on spatial measures below under [Spatial measures]. 

---

See the other vignettes for further information:

- [Introduction to spatsoc](https://docs.ropensci.org/spatsoc/articles/intro.html)
  - temporal grouping
  - spatiotemporal grouping with `group_pts`, `group_lines`, `group_polys`
  - distance based edge-list generation with `edge_dist`
- [Frequently asked questions about spatsoc](https://docs.ropensci.org/spatsoc/articles/faq.html)
  - install
  - function details for `group_times`, `group_pts`, `group_lines`, `group_polys`,
  `edge_dist`, `edge_nn`, and `randomizations`
  - package design including modify-by-reference, data.table column allocation
  - calculating summary information
- [Using spatsoc in social network analysis](https://docs.ropensci.org/spatsoc/articles/using-in-sna.html)
  - generating gambit-of-the-group data
  - generating observed networks
  - data stream randomization, randomized networks
  - network metrics
- [Using distance based edge-lists generating functions, dyad_id, and fusion_id](https://docs.ropensci.org/spatsoc/articles/using-edge-and-dyad.html)
  - generate distance based edge-lists with `edge_dist` and `edge_nn`
  - generate dyad identifiers for edge-lists with `dyad_id`
  - identify fusion events with `fusion_id`
- [Geometry interface](https://docs.ropensci.org/spatsoc/articles/geometry-interface-and-spatial-measures.html)
  - using `get_geometry` to setup a geometry column and use the geometry interface
  - details of underlying distance, direction and centroid spatial measures
  - converting to and from related packages
- [Interspecific interactions](https://docs.ropensci.org/spatsoc/articles/interspecific-interactions.html)
  - combine two movement datasets
  - identify interspecific interactions


## Setup

Load packages

```{r}
library(spatsoc)
library(data.table)
```

Example data and variables

```{r}
# Read example data
DT <- fread(system.file('extdata', 'DT.csv', package = 'spatsoc'))

coords <- c('X', 'Y')
crs <- 32736
datetime <- 'datetime'
id <- 'ID'
```

## `get_geometry`

`get_geometry` can be used to setup a `DT` with a simple feature geometry list
column. Optionally, the input coordinates can be transformed using the argument
"output_crs". The default output geometry column name can be changed using the 
argument "geometry_colname". 

### Usage

```{r}
# Get geometry
get_geometry(DT, coords = coords, crs = crs)

print(DT)
```

## Spatial measures

### Distance

The underlying distance function used depends on the crs of the coordinates or
geometry provided.

- If the crs is longlat degrees (as determined by
[sf::st_is_longlat()]), the distance function is [sf::st_distance()] which
passes to [s2::s2_distance()] if [sf::sf_use_s2()] is TRUE and
[lwgeom::st_geod_distance()] if [sf::sf_use_s2()] is FALSE. The distance
returned has units set according to the crs.

- If the crs is not longlat degrees (eg. NULL, NA_crs_, or projected), the
distance function used is [stats::dist()], maintaining expected behaviour from
previous versions. The distance returned does not have units set.

Note: in both cases, if the coordinates are NA then the result will be NA.


### Direction

The underlying distance function used depends on the crs of the coordinates or
geometry provided.

- If the crs is provided and longlat degrees (as determined by
[sf::st_is_longlat()]), the distance function is [lwgeom::st_geod_azimuth()].

- If the crs is provided and not longlat degrees (eg. a projected UTM),
the coordinates or geometry are transformed to `sf::st_crs(4326)` before the
distance is measured using [lwgeom::st_geod_azimuth()].

- If the crs is NULL or `NA_crs_`, the distance function cannot be used
and an error is returned.

The crs for direction functions (eg. `direction_step`, `direction_to_centroid`)
should be either longlat or a crs that can be transformed to `sf::st_crs(4326)`.
A user can check their crs by using the function 
`sf::st_can_transform(src = crs, dst = 4326)`.

If a user provides a crs that is not longlat and cannot be transformed to 4326, 
they will receive an internal error with the following structure:

 `"In CPL_transform(x, crs, aoi, pipeline, reverse, desired_accuracy, : GDAL Error 6: Cannot find coordinate operations from..."`

### Centroid

@section Centroid function:

The underlying centroid function used depends on the crs of the coordinates or
geometry provided.

- If the crs is longlat degrees (as determined by
[sf::st_is_longlat()]) and [sf::sf_use_s2()] is TRUE, the distance function is
[sf::st_centroid()] which passes to [s2::s2_centroid()].

- If the crs is longlat degrees but [sf::sf_use_s2()] is FALSE, the centroid
calculated will be incorrect. See [sf::st_centroid()].

- If the crs is not longlat degrees (eg. NULL, NA_crs_, or projected), the
centroid function used is mean.

Note: if the input is length 1, the input is returned directly without any
processing.

The `distance_to_centroid`, `direction_to_centroid` and `leader_direction_group`
expect a centroid column named 'centroid' when the geometry interface is used.
Ensure the `centroid_group` function has been used with the geometry interface
before running these functions. 

The following warning may be returned when centroid functions are used with 
longlat coordinates / geometry and the {s2} package is not available or 
`sf::sf_use_s2()` is `FALSE`. Please set `sf::sf_use_s2(TRUE)` and try again. 


## Converting from other packages

Instead of using `get_geometry()`, coming from other packages, we can convert
the objects to data.tables for processing with {spatsoc}. Caution: {spatsoc}'s
expectation is that the "geometry" column is a `sfc_POINT` representing each
relocation.

### Converting from {sftrack}

```{r}
library(sftrack)
data("raccoon")
raccoon$timestamp <- as.POSIXct(raccoon$timestamp, "EST")
burstz <- list(id = raccoon$animal_id, month = as.POSIXlt(raccoon$timestamp)$mon)
my_track <- as_sftrack(raccoon,
  group = burstz, time = "timestamp",
  error = NA, coords = c("longitude", "latitude")
)

DT_sftrack <- as.data.table(my_track)

print(DT_sftrack)
```

### Converting from {move2}

```{r}
library(move2)
fishers <- mt_read(mt_example(file = "fishers.csv.gz"))
DT_move2 <- as.data.table(fishers)

print(DT_move2)
```

## Converting to other packages

After processing with {spatsoc}, optionally convert output to work with other
packages. Caution: {spatsoc}'s expectation is that users take their input
data.table through any required functions in {spatsoc} before converting to
other packages or using eg. {dplyr}. Intermixing packages between {spatsoc}
functions can lead to issues with {data.table} class or column allocation. See
more details under Package Design in
[FAQ](https://docs.ropensci.org/spatsoc/articles/faq.html).

### Converting to {sf}

```{r}
library(sf)
DT_sf <- st_as_sf(DT, sf_column_name = 'geometry')
print(DT_sf)
plot(DT_sf)
```


### Converting to {sftrack}

```{r}
library(sftrack)

# First convert to sf as above
DT_sf <- st_as_sf(DT, sf_column_name = 'geometry')
# Then convert to sftrack
DT_sftrack <- as_sftrack(DT_sf, group = c(id = id), time = datetime)

head(DT_sftrack)
plot(DT_sftrack)
```

### Converting to {move2}

```{r}
library(move2)

# Convert to a {move2} object using mt_as_move2
DT_move2 <- mt_as_move2(DT,
  time_column = datetime,
  track_id_column = id,
  sf_column_name = 'geometry'
)

print(DT_move2)
plot(DT_move2)
```
