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:
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 sf
object 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
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP