How can i connect two linestrings?
It is possible to lay a very slim buffer around the lines and then connect them like so:
one_line <- lines %>%
st_buffer(0.05) %>%
st_intersection() %>%
st_union() %>%
st_cast('LINESTRING')
There are 2 problems with this:
a) below is a very small subset of my data containing one such disconnected line segment - if i use the above method on the small part it forms a complete polygon which, when converted to a linestring just makes a very narrow loop
b) if i use the whole data set it kind of works but creates lines at the approximate distance of the buffer around my original line. See picture below:
Blue & red are the edge lines while black would be the original.
I thought to simply average them out but when i convert the 2 lines to coordinates (st_coordinates()
), the resulting tables have different lengths and are not in order.
I looked around but did not really find any useful answers.
Here is a dput of the geometry data:
lines <- structure(list(structure(list(structure(c(2880, 2880.92, 2881.72,
2882.47, 2883.17, 2883.84, 2884.5, 2894.05, 2894.69, 2895.29393034826,
340255.362641509, 340257.22, 340259.03, 340260.85, 340262.69,
340264.55, 340266.4, 340293.7, 340295.61, 340297.500995024), .Dim = c(10L,
2L)), structure(c(2907.22402724177, 2914.21353757771, 340330.886392736,
340350.2), .Dim = c(2L, 2L))), class = c("XY", "MULTILINESTRING",
"sfg")), structure(c(2895.3, 2896.82, 2897.26, 2897.72, 2907.2,
340297.52, 340302.26, 340303.58, 340304.89, 340330.82), .Dim = c(5L,
2L), class = c("XY", "LINESTRING", "sfg"))), n_empty = 0L, crs = structure(list(
input = "EPSG:31256", wkt = "PROJCRS[\"MGI / Austria GK East\",\n BASEGEOGCRS[\"MGI\",\n DATUM[\"Militar-Geographische Institut\",\n ELLIPSOID[\"Bessel 1841\",6377397.155,299.1528128,\n LENGTHUNIT[\"metre\",1]]],\n PRIMEM[\"Greenwich\",0,\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n ID[\"EPSG\",4312]],\n CONVERSION[\"Austria Gauss-Kruger East\",\n METHOD[\"Transverse Mercator\",\n ID[\"EPSG\",9807]],\n PARAMETER[\"Latitude of natural origin\",0,\n ANGLEUNIT[\"degree\",0.0174532925199433],\n ID[\"EPSG\",8801]],\n PARAMETER[\"Longitude of natural origin\",16.3333333333333,\n ANGLEUNIT[\"degree\",0.0174532925199433],\n ID[\"EPSG\",8802]],\n PARAMETER[\"Scale factor at natural origin\",1,\n SCALEUNIT[\"unity\",1],\n ID[\"EPSG\",8805]],\n PARAMETER[\"False easting\",0,\n LENGTHUNIT[\"metre\",1],\n ID[\"EPSG\",8806]],\n PARAMETER[\"False northing\",-5000000,\n LENGTHUNIT[\"metre\",1],\n ID[\"EPSG\",8807]]],\n CS[Cartesian,2],\n AXIS[\"northing (X)\",north,\n ORDER[1],\n LENGTHUNIT[\"metre\",1]],\n AXIS[\"easting (Y)\",east,\n ORDER[2],\n LENGTHUNIT[\"metre\",1]],\n USAGE[\n SCOPE[\"Engineering survey, topographic mapping.\"],\n AREA[\"Austria east of 14°50'E of Greenwich (32°30'E of Ferro).\"],\n BBOX[46.56,14.83,49.02,17.17]],\n ID[\"EPSG\",31256]]"), class = "crs"), idx = structure(c(1,
2, 1, 1), .Dim = c(2L, 2L)), class = c("sfc_GEOMETRY", "sfc"), precision = 0, bbox = structure(c(xmin = 2880,
ymin = 340255.362641509, xmax = 2914.21353757771, ymax = 340350.2
), class = "bbox"), classes = c("MULTILINESTRING", "LINESTRING"
))
This is an incomplete answer because it still requires some manual input but it can be generalized by implementing a few rules. The idea is to find the places where the line is broken and then go to the start/endpoints of the closest line. Then make a line segment bridging the break and combining all the line segments.
library(lwgeom)
library(tidyverse)
library(sf)
line1 <- lines %>%
st_sf() %>%
st_combine() %>%
st_sf() %>%
st_line_merge() %>%
st_cast("LINESTRING")
### this is still some manual work which needs to be improved
newline1 <- c(st_startpoint(line1[3,]), st_endpoint(line1[2,])) %>%
st_combine() %>%
st_cast("MULTIPOINT") %>%
st_union() %>%
st_cast("LINESTRING") %>%
st_sf()
newline2 <- c(st_startpoint(line1[2,]), st_endpoint(line1[1,])) %>%
st_combine() %>%
st_cast("MULTIPOINT") %>%
st_union() %>%
st_cast("LINESTRING") %>%
st_sf()
line1[nrow(line1)+1,]<-newline1
line1[nrow(line1)+1,]<-newline2
###
line1_uni <- line1 %>%
st_sf() %>%
st_combine() %>%
st_sf() %>%
st_line_merge() %>%
st_cast("LINESTRING") %>%
st_sf()
line1_uni
Simple feature collection with 1 feature and 0 fields
Geometry type: LINESTRING
Dimension: XY
Bounding box: xmin: 2880 ymin: 340255.4 xmax: 2914.214 ymax: 340350.2
Projected CRS: MGI / Austria GK East
geometry
1 LINESTRING (2880 340255.4, ...