MyNixOS website logo
Description

An Interface to Rust's 'geo' Library.

An R interface to the GeoRust crates 'geo' and 'geo-types' providing access to geometry primitives and algorithms.

R-CMD-check

rsgeo

rsgeo is an interface to the Rust libraries geo-types and geo. geo-types implements pure rust geometry primitives. The geo library adds additional algorithm functionalities on top of geo-types. This package lets you harness the speed, safety, and memory efficiency of these libraries. geo-types does not support Z or M dimensions. There is no support for CRS at this moment.

# install.packages(
#   'rsgeo', 
#   repos = c('https://josiahparry.r-universe.dev', 'https://cloud.r-project.org')
# )
library(rsgeo)

rsgeo works with vectors of geometries. When we compare this to sf this is always the geometry column which is a class sfc object (simple feature column).

# get geometry from sf
data(guerry, package = "sfdep")

polys <- guerry[["geometry"]] |>
  sf::st_cast("POLYGON")

# cast to rust geo-types
rs_polys <- as_rsgeo(polys)

head(rs_polys)
#> <rs_POLYGON[6]>
#> [1] Polygon { exterior: LineString([Coord { x: 801150.0, y: 2092615.0 }, Coord...
#> [2] Polygon { exterior: LineString([Coord { x: 729326.0, y: 2521619.0 }, Coord...
#> [3] Polygon { exterior: LineString([Coord { x: 710830.0, y: 2137350.0 }, Coord...
#> [4] Polygon { exterior: LineString([Coord { x: 882701.0, y: 1920024.0 }, Coord...
#> [5] Polygon { exterior: LineString([Coord { x: 886504.0, y: 1922890.0 }, Coord...
#> [6] Polygon { exterior: LineString([Coord { x: 747008.0, y: 1925789.0 }, Coord...

Cast geometries to sf

sf::st_as_sfc(rs_polys)
#> Geometry set for 116 features 
#> Geometry type: POLYGON
#> Dimension:     XY
#> Bounding box:  xmin: 47680 ymin: 1703258 xmax: 1031401 ymax: 2677441
#> CRS:           NA
#> First 5 geometries:
#> POLYGON ((801150 2092615, 800669 2093190, 80068...
#> POLYGON ((729326 2521619, 729320 2521230, 72928...
#> POLYGON ((710830 2137350, 711746 2136617, 71243...
#> POLYGON ((882701 1920024, 882408 1920733, 88177...
#> POLYGON ((886504 1922890, 885733 1922978, 88547...

Calculate the unsigned area of polygons.

bench::mark(
  rust = unsigned_area(rs_polys),
  sf = sf::st_area(polys),
  check = FALSE
)
#> # A tibble: 2 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 rust         55.6µs  57.65µs    16411.     3.8KB     0   
#> 2 sf           1.36ms   1.44ms      649.   786.9KB     8.42

Find centroids

bench::mark(
  centroids(rs_polys),
  sf::st_centroid(polys),
  check = FALSE
)
#> # A tibble: 2 × 6
#>   expression                  min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>             <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 centroids(rs_polys)    174.95µs    213µs     3720.     3.8KB     9.53
#> 2 sf::st_centroid(polys)   2.43ms    2.6ms      359.   892.9KB     4.70

Extract points coordinates

coords(rs_polys) |> 
  head()
#>        x       y line_id polygon_id
#> 1 801150 2092615       1          1
#> 2 800669 2093190       1          1
#> 3 800688 2095430       1          1
#> 4 800780 2095795       1          1
#> 5 800589 2096112       1          1
#> 6 800333 2097190       1          1

Plot the polygons and their centroids

plot(rs_polys)
plot(centroids(rs_polys), add = TRUE)

Calculate a distance matrix. Note that there is often floating point error differences so check = FALSE in this case.

pnts <- centroids(rs_polys)
pnts_sf <- sf::st_as_sfc(pnts)

bench::mark(
  rust = distance_euclidean_matrix(pnts, pnts),
  sf = sf::st_distance(pnts_sf, pnts_sf),
  check = FALSE
)
#> # A tibble: 2 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 rust       323.53µs 573.06µs     1540.     108KB     4.08
#> 2 sf           3.48ms   3.69ms      256.     351KB     0

Simplify geometries.

x <- rs_polys
x_simple <- simplify_geoms(x, 5000)

plot(x_simple)
bench::mark(
  rust = simplify_geoms(rs_polys, 500),
  sf = sf::st_simplify(polys, FALSE, 500),
  check = FALSE
)
#> # A tibble: 2 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 rust         6.29ms   6.76ms      141.    1.91KB     0   
#> 2 sf           8.52ms   9.02ms      108.    1.24MB     2.08

Union geometries with union_geoms(). Some things sf is better at! One of which is performing unary unions of complex geometries.

plot(union_geoms(rs_polys))

bench::mark(
  union_geoms(rs_polys),
  sf::st_union(polys),
  check = FALSE
)
#> # A tibble: 2 × 6
#>   expression                 min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>            <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 union_geoms(rs_polys)    205ms    209ms      4.78        0B        0
#> 2 sf::st_union(polys)      120ms    134ms      7.49     921KB        0

We can cast between geometries as well.

lns <- cast_geoms(rs_polys, "linestring")

Some unions are faster when using rsgeo vectors like linestrings.

lns_sf <- sf::st_cast(polys, "LINESTRING")

bench::mark(
  union_geoms(lns),
  sf::st_union(lns_sf),
  check = FALSE
)
#> # A tibble: 2 × 6
#>   expression                min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>           <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 union_geoms(lns)      117.5µs    174µs    4275.         0B     0   
#> 2 sf::st_union(lns_sf)   87.8ms     94ms      10.7    2.46MB     2.68

Find the closest point to a geometry

close_pnt <- closest_point(
  rs_polys, 
  geom_point(800000, 2090000)
)

plot(rs_polys[1])
plot(close_pnt, pch = 15, add = TRUE)

Find the haversine destination of a point, bearing, and distance. Compare to the very fast geosphere destination point function.

bench::mark(
  rust = haversine_destination(geom_point(10, 10), 45, 10000),
  Cpp = geosphere::destPoint(c(10, 10), 45, 10000),
  check = FALSE
)
#> # A tibble: 2 × 6
#>   expression      min   median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr> <bch:tm> <bch:tm>     <dbl> <bch:byt>    <dbl>
#> 1 rust         5.86µs   7.34µs   120442.     3.2KB     12.0
#> 2 Cpp         17.06µs  19.11µs    34150.    11.8MB     34.2
origin <- geom_point(10, 10)

destination <- haversine_destination(origin, 45, 10000)

plot(c(origin, destination), col = c("red", "blue"))

Find intermediate point on a great circle.

middle <- haversine_intermediate(origin, destination, 1/2)

plot(origin)
plot(destination, add = TRUE, col = "red")
plot(middle, add = TRUE, col = "blue")

Find extreme coordinates with extreme_coords()

france <- union_geoms(rs_polys)

plot(france)
plot(extreme_coords(france)[[1]], add = TRUE, pch = 15)

Get bounding rectangles

rects <- bounding_rect(rs_polys)
plot(rects)

Convex hulls

convex_hull(rs_polys) |> 
  plot()

Expand into constituent geometries as a list of geometry vectors

expand_geoms(rs_polys) |> 
  head()
#> [[1]]
#> <rs_LINESTRING[1]>
#> [1] LineString([Coord { x: 801150.0, y: 2092615.0 }, Coord { x: 800669.0, y: 2...
#> 
#> [[2]]
#> <rs_LINESTRING[2]>
#> [1] LineString([Coord { x: 729326.0, y: 2521619.0 }, Coord { x: 729320.0, y: 2...
#> [2] LineString([Coord { x: 647667.0, y: 2468296.0 }, Coord { x: 647777.0, y: 2...
#> 
#> [[3]]
#> <rs_LINESTRING[1]>
#> [1] LineString([Coord { x: 710830.0, y: 2137350.0 }, Coord { x: 711746.0, y: 2...
#> 
#> [[4]]
#> <rs_LINESTRING[1]>
#> [1] LineString([Coord { x: 882701.0, y: 1920024.0 }, Coord { x: 882408.0, y: 1...
#> 
#> [[5]]
#> <rs_LINESTRING[1]>
#> [1] LineString([Coord { x: 886504.0, y: 1922890.0 }, Coord { x: 885733.0, y: 1...
#> 
#> [[6]]
#> <rs_LINESTRING[1]>
#> [1] LineString([Coord { x: 747008.0, y: 1925789.0 }, Coord { x: 746630.0, y: 1...

We can flatten the resultant geometries into a single vector using flatten_geoms()

expand_geoms(rs_polys) |> 
  flatten_geoms() |> 
  head()
#> <rs_LINESTRING[6]>
#> [1] LineString([Coord { x: 801150.0, y: 2092615.0 }, Coord { x: 800669.0, y: 2...
#> [2] LineString([Coord { x: 729326.0, y: 2521619.0 }, Coord { x: 729320.0, y: 2...
#> [3] LineString([Coord { x: 647667.0, y: 2468296.0 }, Coord { x: 647777.0, y: 2...
#> [4] LineString([Coord { x: 710830.0, y: 2137350.0 }, Coord { x: 711746.0, y: 2...
#> [5] LineString([Coord { x: 882701.0, y: 1920024.0 }, Coord { x: 882408.0, y: 1...
#> [6] LineString([Coord { x: 886504.0, y: 1922890.0 }, Coord { x: 885733.0, y: 1...

Combine geometries into a single multi- geometry

combine_geoms(lns)
#> <rs_LINESTRING[1]>
#> [1] MultiLineString([LineString([Coord { x: 801150.0, y: 2092615.0 }, Coord { ...

Spatial predicates

x <- rs_polys[1:5]
intersects_sparse(x, rs_polys)
#> [[1]]
#> [1]  1 48 50 92 94
#> 
#> [[2]]
#> [1]   2   7  63  78  80  81  98 101
#> 
#> [[3]]
#> [1]  3 20 27 53 77 84 94
#> 
#> [[4]]
#> [1]   4   5  30 107 109
#> 
#> [[5]]
#> [1]  4  5 30 48

Notes

Right now plotting is done using wk by first casting the rsgeo into an sfc object.

Metadata

Version

0.1.6

License

Unknown

Platforms (75)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-darwin
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-darwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-windows