centerline

An R package to retrieve the centerline of polygons

https://github.com/atsyplenkov/centerline

Science Score: 26.0%

This score indicates how likely this project is to be science-related based on various indicators:

  • CITATION.cff file
  • codemeta.json file
    Found codemeta.json file
  • .zenodo.json file
    Found .zenodo.json file
  • DOI references
  • Academic publication links
  • Academic email domains
  • Institutional organization owner
  • JOSS paper metadata
  • Scientific vocabulary similarity
    Low similarity (16.4%) to scientific vocabulary
Last synced: 10 months ago · JSON representation

Repository

An R package to retrieve the centerline of polygons

Basic Info
Statistics
  • Stars: 38
  • Watchers: 2
  • Forks: 1
  • Open Issues: 4
  • Releases: 2
Created over 2 years ago · Last pushed about 1 year ago
Metadata Files
Readme Changelog License

README.Rmd

---
output: github_document
---

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

requireNamespace("ggplot2", quietly = TRUE)
requireNamespace("geomtextpath", quietly = TRUE)
requireNamespace("smoothr", quietly = TRUE)
```

# centerline 


[![Website](https://img.shields.io/website?label=centerline.anatolii.nz&url=https%3A%2F%2Fcenterline.anatolii.nz%2F)](https://centerline.anatolii.nz/)
[![Project Status: Active – The project has reached a stable, usable state and is being actively developed.](https://www.repostatus.org/badges/latest/active.svg)](https://www.repostatus.org/#active)
[![R-CMD-check](https://github.com/atsyplenkov/centerline/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/atsyplenkov/centerline/actions/workflows/R-CMD-check.yaml)
[![Check CRAN status](https://github.com/atsyplenkov/centerline/actions/workflows/CRAN-checks.yaml/badge.svg)](https://github.com/atsyplenkov/centerline/actions/workflows/CRAN-checks.yaml)
[![Codecov test coverage](https://codecov.io/gh/atsyplenkov/centerline/graph/badge.svg)](https://app.codecov.io/gh/atsyplenkov/centerline)
[![CRAN status](https://www.r-pkg.org/badges/version/centerline)](https://CRAN.R-project.org/package=centerline)
[![Monthly downloads](https://cranlogs.r-pkg.org/badges/centerline)](https://CRAN.R-project.org/package=centerline)
[![Total downloads](http://cranlogs.r-pkg.org/badges/grand-total/centerline)](https://cran.r-project.org/package=centerline)


The `centerline` R package simplifies the extraction of linear features from complex polygons, such as roads or rivers, by computing their centerlines (or median-axis) based on skeletons. It uses the super-fast [`geos`](https://paleolimbot.github.io/geos/index.html) library in the background and have bindings for your favorite spatial data library ([`sf`](https://r-spatial.github.io/sf/), [`terra`](https://rspatial.github.io/terra/) and [`geos`](https://paleolimbot.github.io/geos/index.html)).

## Installation

```{r, eval = FALSE}
# The easiest way to get centerline is to install it from CRAN:
install.packages("centerline")

# Or the development version from GitHub:
# install.packages("pak")
pak::pak("atsyplenkov/centerline")
```

## Examples for closed geometries

At the heart of this package is the `cnt_skeleton` function, which efficiently computes the skeleton of closed 2D polygonal geometries. The function uses [`geos::geos_simplify`](https://paleolimbot.github.io/geos/reference/geos_centroid.html) by default to keep the most important nodes and reduce noise from the beginning. However, it has option to densify the amount of points using [`geos::geos_densify`](https://paleolimbot.github.io/geos/reference/geos_centroid.html), which can produce more smooth results. Otherwise, you can set the parameter `keep = 1` to work with the initial geometry.

```{r skeleton_lake, warn=FALSE, message=FALSE}
library(sf)
library(centerline)

lake <-
  sf::st_read(
    system.file("extdata/example.gpkg", package = "centerline"),
    layer = "lake",
    quiet = TRUE
  )

# Original
lake_skeleton <-
  cnt_skeleton(lake, keep = 1)

# Simplified
lake_skeleton_s <-
  cnt_skeleton(lake, keep = 0.1)

# Densified
lake_skeleton_d <-
  cnt_skeleton(lake, keep = 2)

```

cnt_skeleton() code 👇 ```{r skeletons_plot} library(ggplot2) skeletons <- rbind(lake_skeleton, lake_skeleton_s, lake_skeleton_d) skeletons$type <- factor( c("Original", "Simplified", "Densified"), levels = c("Original", "Simplified", "Densified") ) skeletons_plot <- ggplot() + geom_sf( data = lake, fill = "#c8e8f1", color = NA ) + geom_sf( data = skeletons, lwd = 0.2, alpha = 0.5, color = "#263238" ) + coord_sf(expand = FALSE, clip = "off") + labs(caption = "cnt_skeleton() example") + facet_wrap(~type) + theme_void() + theme( plot.caption = element_text(family = "mono", size = 6), plot.background = element_rect(fill = "white", color = NA), strip.text = element_text(face = "bold", hjust = 0.25, size = 12), plot.margin = margin(0.2, -0.5, 0.2, -0.5, unit = "lines"), panel.spacing.x = unit(-2, "lines") ) ```
```{r save_skeletons, include=FALSE} ggsave( "man/figures/README-skeletons_plot.png", skeletons_plot, dpi = 500, width = 10, height = 6, units = "cm" ) ``` ```{r, echo=FALSE, out.width = "80%", fig.align = "center"} knitr::include_graphics("man/figures/README-skeletons_plot.png") ```
However, the above-generated lines are not exactly a centerline of a polygon. One way to find the centerline of a closed polygon is to define both `start` and `end` points with the `cnt_path()` function. For example, in the case of landslides, it could be the landslide initiation point and landslide terminus. ```{r} # Load Polygon Of Interest (POI) polygon <- sf::st_read( system.file( "extdata/example.gpkg", package = "centerline" ), layer = "polygon", quiet = TRUE ) # Load points data points <- sf::st_read( system.file( "extdata/example.gpkg", package = "centerline" ), layer = "polygon_points", quiet = TRUE ) |> head(n = 2) points$id <- seq_len(nrow(points)) # Find POI's skeleton pol_skeleton <- cnt_skeleton(polygon, keep = 1.5) # Connect points # For original skeleton pol_path <- cnt_path( skeleton = pol_skeleton, start_point = subset(points, points$type == "start"), end_point = subset(points, points$type == "end") ) ```
cnt_path() code 👇 ```{r path_plot} path_plot <- ggplot() + geom_sf( data = polygon, fill = "#d2d2d2", color = NA ) + geom_sf( data = pol_path, lwd = 1, color = "black" ) + geom_sf( data = points, aes( shape = type, fill = type ), color = "white", lwd = rel(1), size = rel(3) ) + scale_fill_manual( name = "", values = c( "start" = "dodgerblue", "end" = "firebrick" ) ) + scale_shape_manual( name = "", values = c( "start" = 21, "end" = 22 ) ) + coord_sf(expand = FALSE, clip = "off") + labs(caption = "cnt_path() example") + theme_void() + theme( legend.position = "inside", legend.position.inside = c(0.85, 0.2), legend.key.spacing.y = unit(-0.5, "lines"), plot.caption = element_text(family = "mono", size = 6), plot.background = element_rect(fill = "white", color = NA), strip.text = element_text(face = "bold", hjust = 0.25, size = 12), plot.margin = margin(0.2, -0.5, 0.2, -0.5, unit = "lines"), panel.spacing.x = unit(-2, "lines") ) ```
```{r save_path_plot, include=FALSE} ggsave( "man/figures/README-path_plot.png", path_plot, dpi = 500, width = 7, height = 6, units = "cm" ) ``` ```{r, echo=FALSE, out.width = "50%", fig.align = "center"} knitr::include_graphics("man/figures/README-path_plot.png") ```
And what if we don't know the starting and ending locations? What if we just want to place our label accurately in the middle of our polygon? In this case, one may find the `cnt_path_guess` function useful. It returns the line connecting the most distant points, i.e., the polygon's length. Such an approach is used in limnology for measuring [lake lengths](https://www.lakescientist.com/lake-shape/), for example. ```{r} lake_centerline <- cnt_path_guess(lake, keep = 1) ``` You can plot polygon centerline with the `geom_cnt_*` functions family:
cnt_path_guess() code 👇 ```{r centerline_plot} library(ggplot2) lakes <- rbind(lake, lake) lakes$lc <- c("black", NA_character_) centerline_plot <- ggplot() + geom_sf( data = lakes, fill = "#c8e8f1", color = NA ) + geom_cnt_text( data = lakes, aes( label = name, linecolor = lc ), keep = 1 ) + facet_wrap(~lc) + labs( caption = "cnt_path_guess() and geom_cnt_text() examples" ) + theme_void() + theme( legend.position = "inside", legend.position.inside = c(0.85, 0.2), legend.key.spacing.y = unit(-0.5, "lines"), plot.caption = element_text(family = "mono", size = 6), plot.background = element_rect(fill = "white", color = NA), strip.text = element_blank(), plot.margin = margin(0.2, -0.5, 0.2, -0.5, unit = "lines"), panel.spacing.x = unit(-2, "lines") ) ```
```{r save_centerline_plot, include=FALSE} ggsave( "man/figures/README-centerline_plot.png", centerline_plot, dpi = 500, width = 8, height = 6, units = "cm" ) ``` ```{r, echo=FALSE, out.width = "80%", fig.align = "center"} knitr::include_graphics("man/figures/README-centerline_plot.png") ``` ## Roadmap ``` centerline 📦 ├── Closed geometries (e.g., lakes, landslides) │ ├── When we do know starting and ending points (e.g., landslides) ✅ │ │ ├── centerline::cnt_skeleton ✅ │ │ └── centerline::cnt_path ✅ │ └── When we do NOT have points (e.g., lakes) ✅ │ ├── centerline::cnt_skeleton ✅ │ └── centerline::cnt_path_guess ✅ ├── Linear objects (e.g., roads or rivers) 🔲 └── Collapse parallel lines to centerline 🔲 ``` ## Alternatives - **R** - [midlines](https://github.com/RichardPatterson/midlines) - A more hydrology-oriented library that provides a multi-step approach to generate a smooth centerline of complex curved polygons (like rivers). - [cmgo](https://github.com/AntoniusGolly/cmgo) - The main aim of the package is to propose a workflow to extract channel bank metrics, and as a part of that workflow, centerline extraction was implemented. - [raybevel](https://github.com/tylermorganwall/raybevel) - Provides a way to generate **straight** skeletons of polygons. This approach is implemented in the `cnt_skeleton(method = "straight")` function of the current package. - 🐍 Python: - [centerline](https://github.com/fitodic/centerline/tree/master) library - 🦀 Rust: - [centerline_rs](https://codeberg.org/eadf/centerline_rs) library - **JS** Javascript: - [Centerline labeling blogpost](https://observablehq.com/@veltman/centerline-labeling)

Owner

  • Name: Anatolii Tsyplenkov
  • Login: atsyplenkov
  • Kind: user
  • Location: New Zealand
  • Company: @manaakiwhenua

Scientist-Geomorphologist and Research Software Engineer, fond of all things geospatial

GitHub Events

Total
  • Create event: 6
  • Commit comment event: 14
  • Release event: 1
  • Issues event: 1
  • Watch event: 9
  • Delete event: 5
  • Issue comment event: 3
  • Push event: 24
  • Pull request event: 2
  • Fork event: 1
Last Year
  • Create event: 6
  • Commit comment event: 14
  • Release event: 1
  • Issues event: 1
  • Watch event: 9
  • Delete event: 5
  • Issue comment event: 3
  • Push event: 24
  • Pull request event: 2
  • Fork event: 1

Issues and Pull Requests

Last synced: 10 months ago

All Time
  • Total issues: 12
  • Total pull requests: 7
  • Average time to close issues: 24 days
  • Average time to close pull requests: about 16 hours
  • Total issue authors: 2
  • Total pull request authors: 2
  • Average comments per issue: 0.25
  • Average comments per pull request: 1.29
  • Merged pull requests: 7
  • Bot issues: 0
  • Bot pull requests: 0
Past Year
  • Issues: 11
  • Pull requests: 7
  • Average time to close issues: 9 days
  • Average time to close pull requests: about 16 hours
  • Issue authors: 1
  • Pull request authors: 2
  • Average comments per issue: 0.0
  • Average comments per pull request: 1.29
  • Merged pull requests: 7
  • Bot issues: 0
  • Bot pull requests: 0
Top Authors
Issue Authors
  • atsyplenkov (11)
  • DOSull (1)
Pull Request Authors
  • atsyplenkov (11)
  • JosiahParry (2)
Top Labels
Issue Labels
enhancement (2) documentation (1) bug (1)
Pull Request Labels

Packages

  • Total packages: 1
  • Total downloads:
    • cran 278 last-month
  • Total dependent packages: 0
  • Total dependent repositories: 0
  • Total versions: 2
  • Total maintainers: 1
cran.r-project.org: centerline

Extract Centerline from Closed Polygons

  • Versions: 2
  • Dependent Packages: 0
  • Dependent Repositories: 0
  • Downloads: 278 Last month
Rankings
Dependent packages count: 28.1%
Dependent repos count: 34.6%
Average: 49.8%
Downloads: 86.6%
Maintainers (1)
Last synced: 11 months ago

Dependencies

.github/workflows/R-CMD-check.yaml actions
  • actions/checkout v4 composite
  • r-lib/actions/check-r-package v2 composite
  • r-lib/actions/setup-pandoc v2 composite
  • r-lib/actions/setup-r v2 composite
  • r-lib/actions/setup-r-dependencies v2 composite
DESCRIPTION cran
  • spelling * suggests
  • testthat >= 3.0.0 suggests