TransWikia.com

Removing overlapping sf lines in R

Geographic Information Systems Asked on February 18, 2021

I have sfc LINESTRING and I would like to remove overlapping lines. Object data was created from an algorithm that joins lines with minimum distance. Using unique will not remove the initial lines.

In the example you can see that line 2 and 3 + other lines were the initial lines, then they were used to produce line 1, other lines were removed but 2 and 3 remained. and length of lines proves that!. Extracting the line with the maximum length will not work in my case because in some cases I have a non-overlaping line which I would like to keep!

> class(data)
[1] "sfc_LINESTRING" "sfc"           
> length(data)
[1] 3
> data
Geometry set for 3 features 
geometry type:  LINESTRING
dimension:      XY
bbox:           xmin: 181.4494 ymin: 4.441853 xmax: 278.9707 ymax: 14.72429
CRS:            +proj=longlat +datum=WGS84 +no_defs
LINESTRING (181.4494 4.462799, 181.4722 4.45583...
LINESTRING (181.4494 4.462799, 181.4722 4.45583...
LINESTRING (181.4494 4.462799, 181.4722 4.45583...

> st_overlaps(data,data)
although coordinates are longitude/latitude, st_overlaps assumes that they are planar
Sparse geometry binary predicate list of length 3, where the predicate was `overlaps'
 1: 2, 3
 2: 1, 3
 3: 1, 2

> st_length(data)
Units: [m]
[1] 11628206  7143693  9899478

Criteria to remove:

  • The line should be overlapping with other lines
  • The line is not the longest line.

One Answer

Here's an approach using st_covered_by, which will return TRUE if a same sized or longer LINESTRING covers the geometry, the longest line here is the second feature, so the order does not matter, because it filters out the first line. The filtering part is hacky, but as you are comparing to the same sfobject you get a wide matrix object you'll have to fiddle around with

library(sf)
library(dplyr)
library(stringr)    
df = data.frame(key = c(1,2,3), wkt = c("LINESTRING (1 6, 2 7)","LINESTRING (1 6, 2 7, 3 8, 4 9, 5 10)", "LINESTRING (4 9, 5 10)" )) %>% 
  st_as_sf( wkt = "wkt")

df$covered = df %>% st_covered_by(.) %>% lengths > 1
df %>% filter(!covered)

EDIT

As @see24 pointed out, since January 2020 there's the function st_filter, which filters geometries with predicates such as st_covered_by, st_intersects, etc; however, as st_covered_by also returns TRUE if the lines are equal (this is why we filtered with > 1 and not > 0) . Instead, we may use a pattern from the DE-91M model in st_relate, in this case:

st_filter(df, df, .predicate =  st_relate, pattern = "1FFF0FFF2" )

You may check the pattern you want beforehand with:

 st_relate(df, df)
     [,1]        [,2]        [,3]       
[1,] "1FFF0FFF2" "1FF00F102" "FF1FF0102"
[2,] "101F00FF2" "1FFF0FFF2" "101F00FF2"
[3,] "FF1FF0102" "1FF00F102" "1FFF0FFF2"

Correct answer by Elio Diaz on February 18, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP