Spatial morphers form spatial add-ons to the set of
`morphers`

provided by `tidygraph`

. These
functions are not meant to be called directly. They should either be passed
into `morph`

to create a temporary alternative
representation of the input network. Such an alternative representation is a
list of one or more network objects. Single elements of that list can be
extracted directly as a new network by passing the morpher to
`convert`

instead, to make the changes lasting rather
than temporary. Alternatively, if the morphed state contains multiple
elements, all of them can be extracted together inside a
`tbl_df`

by passing the morpher to
`crystallise`

.

```
to_spatial_contracted(
x,
...,
simplify = FALSE,
summarise_attributes = "ignore",
store_original_data = FALSE
)
to_spatial_directed(x)
to_spatial_explicit(x, ...)
to_spatial_neighborhood(x, node, threshold, weights = NULL, from = TRUE, ...)
to_spatial_shortest_paths(x, ...)
to_spatial_simple(
x,
remove_multiple = TRUE,
remove_loops = TRUE,
summarise_attributes = "first",
store_original_data = FALSE
)
to_spatial_smooth(
x,
protect = NULL,
summarise_attributes = "ignore",
require_equal = FALSE,
store_original_data = FALSE
)
to_spatial_subdivision(x)
to_spatial_subset(x, ..., subset_by = NULL)
to_spatial_transformed(x, ...)
```

- x
An object of class

`sfnetwork`

.- ...
Arguments to be passed on to other functions. See the description of each morpher for details.

- simplify
Should the network be simplified after contraction? This means that multiple edges and loop edges will be removed. Multiple edges are introduced by contraction when there are several connections between the same groups of nodes. Loop edges are introduced by contraction when there are connections within a group. Note however that setting this to

`TRUE`

also removes multiple edges and loop edges that already existed before contraction. Defaults to`FALSE`

.- summarise_attributes
Whenever multiple features (i.e. nodes and/or edges) are merged into a single feature during morphing, how should their attributes be combined? Several options are possible, see

`igraph-attribute-combination`

for details.- store_original_data
Whenever multiple features (i.e. nodes and/or edges) are merged into a single feature during morphing, should the data of the original features be stored as an attribute of the new feature, in a column named

`.orig_data`

. This is in line with the design principles of`tidygraph`

. Defaults to`FALSE`

.- node
The geospatial point for which the neighborhood will be calculated. Can be an integer, referring to the index of the node for which the neighborhood will be calculated. Can also be an object of class

`sf`

or`sfc`

, containing a single feature. In that case, this point will be snapped to its nearest node before calculating the neighborhood. When multiple indices or features are given, only the first one is taken.- threshold
The threshold distance to be used. Only nodes within the threshold distance from the reference node will be included in the neighborhood. Should be a numeric value in the same units as the weight values used for distance calculation.

- weights
The edge weights used to calculate distances on the network. Can be a numeric vector giving edge weights, or a column name referring to an attribute column in the edges table containing those weights. If set to

`NULL`

, the values of a column named`weight`

in the edges table will be used automatically, as long as this column is present. If not, the geographic edge lengths will be calculated internally and used as weights.- from
Should distances be calculated from the reference node towards the other nodes? Defaults to

`TRUE`

. If set to`FALSE`

, distances will be calculated from the other nodes towards the reference node instead.- remove_multiple
Should multiple edges be merged into one. Defaults to

`TRUE`

.- remove_loops
Should loop edges be removed. Defaults to

`TRUE`

.- protect
Nodes to be protected from being removed, no matter if they are a pseudo node or not. Can be given as a numeric vector containing node indices or a character vector containing node names. Can also be a set of geospatial features as object of class codesf or

`sfc`

. In that case, for each of these features its nearest node in the network will be protected. Defaults to`NULL`

, meaning that none of the nodes is protected.- require_equal
Should nodes only be removed when the attribute values of their incident edges are equal? Defaults to

`FALSE`

. If`TRUE`

, only pseudo nodes that have incident edges with equal attribute values are removed. May also be given as a vector of attribute names. In that case only those attributes are checked for equality. Equality tests are evaluated using the`==`

operator.- subset_by
Whether to create subgraphs based on nodes or edges.

Either a `morphed_sfnetwork`

, which is a list of one or more
`sfnetwork`

objects, or a `morphed_tbl_graph`

, which is a
list of one or more `tbl_graph`

objects. See the
description of each morpher for details.

It also possible to create your own morphers. See the documentation
of `morph`

for the requirements for custom morphers.

`to_spatial_contracted()`

: Combine groups of nodes into a single node per group.`...`

is forwarded to`group_by`

to create the groups. The centroid of the group of nodes will be used as geometry of the contracted node. If edge are spatially explicit, edge geometries are updated accordingly such that the valid spatial network structure is preserved. Returns a`morphed_sfnetwork`

containing a single element of class`sfnetwork`

.`to_spatial_directed()`

: Make a network directed in the direction given by the linestring geometries of the edges. Differs from`to_directed`

, which makes a network directed based on the node indices given in the`from`

and`to`

columns. In undirected networks these indices may not correspond with the endpoints of the linestring geometries. Returns a`morphed_sfnetwork`

containing a single element of class`sfnetwork`

. This morpher requires edges to be spatially explicit. If not, use`to_directed`

.`to_spatial_explicit()`

: Create linestring geometries between source and target nodes of edges. If the edges data can be directly converted to an object of class`sf`

using`st_as_sf`

, extra arguments can be provided as`...`

and will be forwarded to`st_as_sf`

internally. Otherwise, straight lines will be drawn between the source and target node of each edge. Returns a`morphed_sfnetwork`

containing a single element of class`sfnetwork`

.`to_spatial_neighborhood()`

: Limit a network to the spatial neighborhood of a specific node.`...`

is forwarded to`node_distance_from`

(if`from`

is`TRUE`

) or`node_distance_to`

(if`from`

is`FALSE`

). Returns a`morphed_sfnetwork`

containing a single element of class`sfnetwork`

.`to_spatial_shortest_paths()`

: Limit a network to those nodes and edges that are part of the shortest path between two nodes.`...`

is evaluated in the same manner as`st_network_paths`

with`type = 'shortest'`

. Returns a`morphed_sfnetwork`

that may contain multiple elements of class`sfnetwork`

, depending on the number of requested paths. When unmorphing only the first instance of both the node and edge data will be used, as the the same node and/or edge can be present in multiple paths.`to_spatial_simple()`

: Remove loop edges and/or merges multiple edges into a single edge. Multiple edges are edges that have the same source and target nodes (in directed networks) or edges that are incident to the same nodes (in undirected networks). When merging them into a single edge, the geometry of the first edge is preserved. The order of the edges can be influenced by calling`arrange`

before simplifying. Returns a`morphed_sfnetwork`

containing a single element of class`sfnetwork`

.`to_spatial_smooth()`

: Construct a smoothed version of the network by iteratively removing pseudo nodes, while preserving the connectivity of the network. In the case of directed networks, pseudo nodes are those nodes that have only one incoming and one outgoing edge. In undirected networks, pseudo nodes are those nodes that have two incident edges. Equality of attribute values among the two edges can be defined as an additional requirement by setting the`require_equal`

parameter. Connectivity of the network is preserved by concatenating the incident edges of each removed pseudo node. Returns a`morphed_sfnetwork`

containing a single element of class`sfnetwork`

.`to_spatial_subdivision()`

: Construct a subdivision of the network by subdividing edges at each interior point that is equal to any other interior or boundary point in the edges table. Interior points in this sense are those points that are included in their linestring geometry feature but are not endpoints of it, while boundary points are the endpoints of the linestrings. The network is reconstructed after subdivision such that edges are connected at the points of subdivision. Returns a`morphed_sfnetwork`

containing a single element of class`sfnetwork`

. This morpher requires edges to be spatially explicit and nodes to be spatially unique (i.e. not more than one node at the same spatial location).`to_spatial_subset()`

: Subset the network by applying a spatial filter, i.e. a filter on the geometry column based on a spatial predicate.`...`

is evaluated in the same manner as`st_filter`

. Returns a`morphed_sfnetwork`

containing a single element of class`sfnetwork`

. For filters on an attribute column, use`to_subgraph`

.`to_spatial_transformed()`

: Transform the geospatial coordinates of the network into a different coordinate reference system.`...`

is evaluated in the same manner as`st_transform`

. Returns a`morphed_sfnetwork`

containing a single element of class`sfnetwork`

.

The vignette on spatial morphers.

```
library(sf, quietly = TRUE)
library(tidygraph, quietly = TRUE)
net = as_sfnetwork(roxel, directed = FALSE) %>%
st_transform(3035)
# Temporary changes with morph and unmorph.
net %>%
activate("edges") %>%
mutate(weight = edge_length()) %>%
morph(to_spatial_shortest_paths, from = 1, to = 10) %>%
mutate(in_paths = TRUE) %>%
unmorph()
#> # A sfnetwork with 701 nodes and 851 edges
#> #
#> # CRS: EPSG:3035
#> #
#> # An undirected multigraph with 14 components with spatially explicit edges
#> #
#> # Edge Data: 851 × 7 (active)
#> # Geometry type: LINESTRING
#> # Dimension: XY
#> # Bounding box: xmin: 4150707 ymin: 3206375 xmax: 4152367 ymax: 3208565
#> from to name type geometry weight in_pat…
#> <int> <int> <chr> <fct> <LINESTRING [m]> [m] <lgl>
#> 1 1 2 Havixbe… reside… (4151491 3207923, 4151474 3207946) 28.9 NA
#> 2 3 4 Pieners… second… (4151398 3207777, 4151390 3207727… 108. NA
#> 3 5 6 Schulte… reside… (4151408 3207539, 4151417 3207573… 54.4 NA
#> 4 7 8 NA path (4151885 3206698, 4151861 3206711… 155. NA
#> 5 9 10 Welsing… reside… (4151732 3207017, 4151721 3206809) 209. TRUE
#> 6 11 12 NA footway (4152152 3206984, 4152143 3206932… 63.0 NA
#> # … with 845 more rows
#> #
#> # Node Data: 701 × 1
#> # Geometry type: POINT
#> # Dimension: XY
#> # Bounding box: xmin: 4150707 ymin: 3206375 xmax: 4152367 ymax: 3208565
#> geometry
#> <POINT [m]>
#> 1 (4151491 3207923)
#> 2 (4151474 3207946)
#> 3 (4151398 3207777)
#> # … with 698 more rows
# Lasting changes with convert.
net %>%
activate("edges") %>%
mutate(weight = edge_length()) %>%
convert(to_spatial_shortest_paths, from = 1, to = 10)
#> # A sfnetwork with 18 nodes and 17 edges
#> #
#> # CRS: EPSG:3035
#> #
#> # An unrooted tree with spatially explicit edges
#> #
#> # Edge Data: 17 × 7 (active)
#> # Geometry type: LINESTRING
#> # Dimension: XY
#> # Bounding box: xmin: 4151491 ymin: 3206809 xmax: 4151802 ymax: 3207923
#> from to name type geometry weight .tidyg…
#> <int> <int> <chr> <fct> <LINESTRING [m]> [m] <int>
#> 1 2 3 Welsingheide resid… (4151732 3207017, 4151721… 209. 5
#> 2 2 6 Nottulner Landweg resid… (4151732 3207017, 4151755… 84.4 94
#> 3 5 8 Roxeler Strasse secon… (4151531 3207830, 4151535… 98.3 159
#> 4 8 12 Roxeler Strasse secon… (4151519 3207865, 4151524… 37.0 295
#> 5 5 7 Dorffeldstrasse resid… (4151620 3207798, 4151621… 49.3 486
#> 6 9 15 Dorffeldstrasse resid… (4151786 3207133, 4151794… 32.7 591
#> # … with 11 more rows
#> #
#> # Node Data: 18 × 2
#> # Geometry type: POINT
#> # Dimension: XY
#> # Bounding box: xmin: 4151491 ymin: 3206809 xmax: 4151802 ymax: 3207923
#> geometry .tidygraph_node_index
#> <POINT [m]> <int>
#> 1 (4151491 3207923) 1
#> 2 (4151732 3207017) 9
#> 3 (4151721 3206809) 10
#> # … with 15 more rows
```