Объедините Multilinestring в одну строку, чтобы создать точки с регулярным расположением, используя sf

Я пытаюсь создать случайные точки на строке, используя SF. Однако данные являются многострочными, и для st_line_sample требуется строковая строка. Поэтому я хотел бы превратить многострочную строку только в одну строку. Если вы посмотрите на код, я должен сгенерировать только одну точку для строки, но он генерирует одну точку для каждой строки. Я не могу соединить линии, чтобы они превратились в одну строку, которую можно было бы использовать для создания на ней одной точки.

Как можно получить только одну строку строки из мультилинии, чтобы сгенерировать количество случайных точек на линии?

library(sf)
library(mapview)

chemins.simple %>% 
  st_zm(geom) %>% 
  st_cast('LINESTRING') %>% 
  st_line_sample(n = 1, 
            type = "regular") %>% 
  mapview() + mapview(chemins.simple)

Данные ниже

chemins.simple = structure(list(Name = "Sentier Parc Maisonneuve", description = NA_character_, 
    timestamp = structure(NA_real_, class = c("POSIXct", "POSIXt"
    ), tzone = ""), begin = structure(NA_real_, class = c("POSIXct", 
    "POSIXt"), tzone = ""), end = structure(NA_real_, class = c("POSIXct", 
    "POSIXt"), tzone = ""), altitudeMode = NA_character_, tessellate = NA_integer_, 
    extrude = NA_integer_, visibility = NA_integer_, drawOrder = NA_integer_, 
    icon = NA_character_, sentier = NA_character_, layer = NA_character_, 
    path = NA_character_, geom = structure(list(structure(list(
        structure(c(299582.847886435, 299567.18907952, 299533.785023203, 
        299515.754560643, 299489.877968861, 299474.41195845, 
        299482.409654204, 299490.968980874, 5047541.45303887, 
        5047515.52023998, 5047476.83372278, 5047450.17574194, 
        5047418.25329369, 5047405.40685391, 5047374.54606886, 
        5047360.74761632, 0, 0, 0, 0, 0, 0, 0, 0), dim = c(8L, 
        3L)), structure(c(299490.968980874, 299497.29763185, 
        299517.115667715, 299552.432591057, 5047360.74761632, 
        5047350.76804681, 5047334.25633307, 5047315.1869463, 
        0, 0, 0, 0), dim = 4:3), structure(c(299552.432591057, 
        299572.471975622, 299580.660505604, 299582.021973701, 
        5047315.1869463, 5047290.4503043, 5047268.99526155, 5047206.73936411, 
        0, 0, 0, 0), dim = 4:3), structure(c(299582.021973701, 
        299588.0164882, 299600.947249195, 299630.602987485, 299665.55385166, 
        299701.470512757, 299727.863346363, 299758.996957146, 
        299802.35340954, 299839.140374969, 299876.649347262, 
        299907.772848518, 299930.504446245, 5047206.73936411, 
        5047178.37871541, 5047157.46467836, 5047127.49377699, 
        5047104.97108792, 5047092.39963862, 5047085.8799339, 
        5047078.22045237, 5047075.4591553, 5047067.43201061, 
        5047049.77064173, 5047028.70621312, 5047003.83116685, 
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), dim = c(13L, 
        3L)), structure(c(299651.605306308, 299634.64341842, 
        299624.972126109, 299582.847886435, 5047607.50989447, 
        5047604.07051358, 5047596.26302026, 5047541.45303887, 
        0, 0, 0, 0), dim = 4:3), structure(c(299903.07988968, 
        299838.094689635, 299772.477232293, 299750.23396301, 
        299735.638185202, 299715.208156948, 299702.078535598, 
        299685.670961566, 299669.997900071, 299657.600720696, 
        299651.605306308, 5047528.38059123, 5047560.33007056, 
        5047598.91464364, 5047604.02168543, 5047594.94570617, 
        5047587.32852712, 5047587.33920063, 5047592.8052447, 
        5047604.45040378, 5047608.09567279, 5047607.50989447, 
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), dim = c(11L, 3L)), 
        structure(c(300348.696267149, 300327.322202229, 300298.695288719, 
        300263.694927326, 300246.383397842, 300232.079546476, 
        300194.889733763, 300177.248808883, 300154.270060961, 
        300141.323210388, 300128.611331444, 300115.132109253, 
        300099.688617737, 300072.709345899, 299903.07988968, 
        5047307.57255003, 5047318.94799577, 5047324.78492774, 
        5047343.34999599, 5047361.17527199, 5047377.0898541, 
        5047393.47561699, 5047396.94207427, 5047395.32322611, 
        5047396.42340946, 5047406.92957364, 5047427.66034101, 
        5047443.0760719, 5047456.36482701, 5047528.38059123, 
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), dim = c(15L, 
        3L)), structure(c(299903.127127851, 299903.320414223, 
        299915.378648026, 299923.777440411, 299930.504446245, 
        5046960.75487254, 5046961.28337721, 5046988.90350206, 
        5047001.25750258, 5047003.83116685, 0, 0, 0, 0, 0), dim = c(5L, 
        3L)), structure(c(299930.504446245, 299949.583123368, 
        299959.545929842, 299980.866628314, 300003.611260665, 
        300023.310726376, 300048.444105637, 300077.234279445, 
        300100.919930205, 300104.481131745, 5047003.83116685, 
        5046971.68800182, 5046943.00547969, 5046920.72166176, 
        5046911.97900684, 5046915.78123032, 5046930.48587239, 
        5046957.6847821, 5046987.79590053, 5046994.35977285, 
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0), dim = c(10L, 3L)), structure(c(300104.481131745, 
        300119.138934739, 300134.109164134, 300150.529356202, 
        300177.155842816, 300212.510325105, 300224.537076035, 
        300224.346205566, 300237.013058666, 300263.691579113, 
        300284.285763285, 300390.750589685, 300420.305984624, 
        5046994.35977285, 5047024.27306488, 5047045.34739571, 
        5047054.4237419, 5047054.76757684, 5047019.84146242, 
        5047006.38152575, 5046994.74822331, 5046983.65083931, 
        5046961.0006817, 5046941.44510252, 5046881.74703166, 
        5046896.63190805, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
        0), dim = c(13L, 3L)), structure(c(300457.455775157, 
        300447.44086401, 300426.293881923, 300391.700426951, 
        300375.480661379, 300360.17836955, 300348.696267149, 
        5047223.3217804, 5047233.97932101, 5047244.71822396, 
        5047259.60178559, 5047274.83602678, 5047297.9309186, 
        5047307.57255003, 0, 0, 0, 0, 0, 0, 0), dim = c(7L, 3L
        )), structure(c(300420.305984624, 300449.031711306, 300489.528913656, 
        300498.295918156, 300511.803110218, 300514.373762732, 
        300511.842867013, 300499.106689568, 300493.293484818, 
        300480.192280261, 300468.535068035, 300460.197952614, 
        5046896.63190805, 5046898.79319606, 5046912.94366797, 
        5046931.84221716, 5046948.5561874, 5046974.00273835, 
        5047006.63268926, 5047116.61272606, 5047149.5168537, 
        5047192.05949512, 5047212.74350708, 5047221.64446475, 
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), dim = c(12L, 3L)), 
        structure(c(300460.197952613, 300457.455775157, 5047221.64446475, 
        5047223.3217804, 0, 0), dim = 2:3)), class = c("XYZ", 
    "MULTILINESTRING", "sfg"))), n_empty = 0L, crs = structure(list(
        input = "EPSG:32188", wkt = "PROJCRS[\"NAD83 / MTM zone 8\",\n    BASEGEOGCRS[\"NAD83\",\n        DATUM[\"North American Datum 1983\",\n            ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n                LENGTHUNIT[\"metre\",1]]],\n        PRIMEM[\"Greenwich\",0,\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        ID[\"EPSG\",4269]],\n    CONVERSION[\"MTM zone 8\",\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\",-73.5,\n            ANGLEUNIT[\"degree\",0.0174532925199433],\n            ID[\"EPSG\",8802]],\n        PARAMETER[\"Scale factor at natural origin\",0.9999,\n            SCALEUNIT[\"unity\",1],\n            ID[\"EPSG\",8805]],\n        PARAMETER[\"False easting\",304800,\n            LENGTHUNIT[\"metre\",1],\n            ID[\"EPSG\",8806]],\n        PARAMETER[\"False northing\",0,\n            LENGTHUNIT[\"metre\",1],\n            ID[\"EPSG\",8807]]],\n    CS[Cartesian,2],\n        AXIS[\"easting (E(X))\",east,\n            ORDER[1],\n            LENGTHUNIT[\"metre\",1]],\n        AXIS[\"northing (N(Y))\",north,\n            ORDER[2],\n            LENGTHUNIT[\"metre\",1]],\n    USAGE[\n        SCOPE[\"Engineering survey, topographic mapping.\"],\n        AREA[\"Canada - Quebec between 75°W and 72°W.; Canada - Ontario - east of 75°W.\"],\n        BBOX[44.98,-75,62.53,-72]],\n    ID[\"EPSG\",32188]]"), class = "crs"), class = c("sfc_MULTILINESTRING", 
    "sfc"), precision = 0, bbox = structure(c(xmin = 299474.41195845, 
    ymin = 5046881.74703166, xmax = 300514.373762732, ymax = 5047608.09567279
    ), class = "bbox"), z_range = structure(c(zmin = 0, zmax = 0
    ), class = "z_range"))), row.names = 1L, sf_column = "geom", agr = structure(c(Name = NA_integer_, 
description = NA_integer_, timestamp = NA_integer_, begin = NA_integer_, 
end = NA_integer_, altitudeMode = NA_integer_, tessellate = NA_integer_, 
extrude = NA_integer_, visibility = NA_integer_, drawOrder = NA_integer_, 
icon = NA_integer_, sentier = NA_integer_, layer = NA_integer_, 
path = NA_integer_), levels = c("constant", "aggregate", "identity"
), class = "factor"), class = c("sf", "data.frame"))

Обновлено:

С этими данными (перерисованными в QGIS) все работает нормально. Однако я не знаю, почему это нельзя сделать легко (перейти от данных выше к данным ниже...)

chemins.simple %>% 
          filter(Name %in% "sentier_velo") %>% 
  st_transform(crs = 32188) %>% 
  st_zm(geom) %>%
  st_sample(size = 25, type = "regular") %>% 
  mapview() + 
  mapview(chemins.simple)

chemins.simple = structure(list(Name = "sentier_velo", description = NA_character_, 
    timestamp = structure(NA_real_, tzone = "", class = c("POSIXct", 
    "POSIXt")), begin = structure(NA_real_, tzone = "", class = c("POSIXct", 
    "POSIXt")), end = structure(NA_real_, tzone = "", class = c("POSIXct", 
    "POSIXt")), altitudeMode = NA_character_, tessellate = NA_integer_, 
    extrude = NA_integer_, visibility = NA_integer_, drawOrder = NA_integer_, 
    icon = NA_character_, sentier = NA_character_, layer = NA_character_, 
    path = NA_character_, geom = structure(list(structure(list(
        structure(c(299903.127127852, 299915.378648026, 299923.777440411, 
        299930.504446245, 299949.583123368, 299959.545929842, 
        299980.866628314, 300003.611260665, 300023.310726376, 
        300048.444105637, 300077.234279445, 300100.919930205, 
        300119.138934739, 300134.109164134, 300150.529356202, 
        300177.155842816, 300224.537076035, 300224.346205566, 
        300284.285763285, 300390.750589685, 300420.305984624, 
        300449.031711306, 300489.528913656, 300498.295918157, 
        300511.803110218, 300514.373762732, 300511.842867013, 
        300499.106689568, 300493.293484818, 300480.192280261, 
        300468.535068035, 300460.197952613, 300457.455775157, 
        300447.44086401, 300426.293881923, 300391.700426951, 
        300375.480661379, 300360.17836955, 300348.696267149, 
        300327.322202229, 300298.695288719, 300263.694927326, 
        300246.383397842, 300232.079546476, 300194.889733763, 
        300177.248808883, 300154.270060961, 300141.323210388, 
        300128.611331444, 300115.132109253, 300099.688617737, 
        300072.709345899, 299903.07988968, 299838.094689635, 
        299772.477232293, 299750.23396301, 299735.638185202, 
        299715.208156948, 299702.078535598, 299685.670961566, 
        299669.997900071, 299657.600720696, 299651.605306308, 
        299634.64341842, 299624.972126109, 299582.847886435, 
        299567.18907952, 299533.785023203, 299515.754560643, 
        299489.877968861, 299474.41195845, 299482.409654204, 
        299490.968980874, 299497.29763185, 299517.115667715, 
        299552.432591057, 299572.471975622, 299580.660505604, 
        299582.021973701, 299588.0164882, 299600.947249195, 299630.602987485, 
        299665.55385166, 299701.470512757, 299758.996957146, 
        299802.35340954, 299839.140374969, 299876.649347262, 
        299907.772848518, 299930.504446245, 5046960.75487254, 
        5046988.90350206, 5047001.25750258, 5047003.83116685, 
        5046971.68800182, 5046943.00547969, 5046920.72166176, 
        5046911.97900684, 5046915.78123032, 5046930.48587239, 
        5046957.6847821, 5046987.79590053, 5047024.27306488, 
        5047045.34739571, 5047054.4237419, 5047054.76757684, 
        5047006.38152575, 5046994.74822331, 5046941.44510252, 
        5046881.74703166, 5046896.63190805, 5046898.79319606, 
        5046912.94366797, 5046931.84221716, 5046948.5561874, 
        5046974.00273835, 5047006.63268926, 5047116.61272606, 
        5047149.5168537, 5047192.05949512, 5047212.74350708, 
        5047221.64446475, 5047223.3217804, 5047233.97932101, 
        5047244.71822396, 5047259.60178558, 5047274.83602677, 
        5047297.9309186, 5047307.57255003, 5047318.94799577, 
        5047324.78492774, 5047343.34999599, 5047361.17527199, 
        5047377.0898541, 5047393.47561699, 5047396.94207427, 
        5047395.3232261, 5047396.42340945, 5047406.92957363, 
        5047427.66034101, 5047443.0760719, 5047456.36482701, 
        5047528.38059123, 5047560.33007056, 5047598.91464364, 
        5047604.02168543, 5047594.94570617, 5047587.32852712, 
        5047587.33920063, 5047592.8052447, 5047604.45040378, 
        5047608.09567278, 5047607.50989447, 5047604.07051358, 
        5047596.26302026, 5047541.45303887, 5047515.52023998, 
        5047476.83372278, 5047450.17574194, 5047418.25329369, 
        5047405.40685391, 5047374.54606886, 5047360.74761632, 
        5047350.76804681, 5047334.25633307, 5047315.1869463, 
        5047290.4503043, 5047268.99526155, 5047206.73936411, 
        5047178.37871541, 5047157.46467836, 5047127.49377699, 
        5047104.97108792, 5047092.39963862, 5047078.22045236, 
        5047075.4591553, 5047067.43201061, 5047049.77064173, 
        5047028.70621312, 5047003.83116685), dim = c(90L, 2L))), class = c("XY", 
    "MULTILINESTRING", "sfg"))), class = c("sfc_MULTILINESTRING", 
    "sfc"), precision = 0, bbox = structure(c(xmin = 299474.41195845, 
    ymin = 5046881.74703166, xmax = 300514.373762732, ymax = 5047608.09567278
    ), class = "bbox"), crs = structure(list(input = "EPSG:32188", 
        wkt = "PROJCRS[\"NAD83 / MTM zone 8\",\n    BASEGEOGCRS[\"NAD83\",\n        DATUM[\"North American Datum 1983\",\n            ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n                LENGTHUNIT[\"metre\",1]]],\n        PRIMEM[\"Greenwich\",0,\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        ID[\"EPSG\",4269]],\n    CONVERSION[\"MTM zone 8\",\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\",-73.5,\n            ANGLEUNIT[\"degree\",0.0174532925199433],\n            ID[\"EPSG\",8802]],\n        PARAMETER[\"Scale factor at natural origin\",0.9999,\n            SCALEUNIT[\"unity\",1],\n            ID[\"EPSG\",8805]],\n        PARAMETER[\"False easting\",304800,\n            LENGTHUNIT[\"metre\",1],\n            ID[\"EPSG\",8806]],\n        PARAMETER[\"False northing\",0,\n            LENGTHUNIT[\"metre\",1],\n            ID[\"EPSG\",8807]]],\n    CS[Cartesian,2],\n        AXIS[\"easting (E(X))\",east,\n            ORDER[1],\n            LENGTHUNIT[\"metre\",1]],\n        AXIS[\"northing (N(Y))\",north,\n            ORDER[2],\n            LENGTHUNIT[\"metre\",1]],\n    USAGE[\n        SCOPE[\"Engineering survey, topographic mapping.\"],\n        AREA[\"Canada - Quebec between 75°W and 72°W.; Canada - Ontario - east of 75°W.\"],\n        BBOX[44.98,-75,62.53,-72]],\n    ID[\"EPSG\",32188]]"), class = "crs"), n_empty = 0L)), row.names = 1L, sf_column = "geom", agr = structure(c(Name = NA_integer_, 
description = NA_integer_, timestamp = NA_integer_, begin = NA_integer_, 
end = NA_integer_, altitudeMode = NA_integer_, tessellate = NA_integer_, 
extrude = NA_integer_, visibility = NA_integer_, drawOrder = NA_integer_, 
icon = NA_integer_, sentier = NA_integer_, layer = NA_integer_, 
path = NA_integer_), levels = c("constant", "aggregate", "identity"
), class = "factor"), class = c("sf", "data.frame"))

Было бы приемлемым обходным решением, если бы вы сохранили многострочный код, но использовали st_line_sample() с density вместо n?

margusl 23.04.2024 19:41

Выдает ошибку: Error in st_line_sample(., density = 2, type = "regular") : inherits(x, "sfc_LINESTRING") is not TRUE

M. Beausoleil 23.04.2024 20:35

Я имел в виду скорее принципиально. Подойдет ли вам использование плотности точек вместо абсолютного количества? Хотя с моей стороны выборка работает нормально, если я только заменю n на density в вашем репрексе, chemins.simple %>% st_zm(geom) %>% st_cast('LINESTRING') %>% st_line_sample(density = .02, type = "regular")

margusl 23.04.2024 20:44

Я бы предпочел абсолютную сумму. Почему я не могу сделать это одной строкой? Это облегчит задачу!

M. Beausoleil 23.04.2024 22:16

Превратить ее в одну линию, подходящую для выборки (т. е. без перекрытий и пересечений), немного сложно, поскольку вам нужно будет выяснить и исправить порядок сегментов, а также направление сегментов. В противном случае вы получите что-то вроде этого: - i.sstatic.net/dvJtT.png (строка строк — это просто последовательность точек, и порядок точек имеет значение). Было бы мало коротких путей, если бы это был просто круговой путь. Или линейный путь без развилок. Но сейчас это похоже на проблему с графом, что-то для igraph/tidygraph/sfnetworks.

margusl 23.04.2024 22:47

ХОРОШО! Это изображение — именно то, что я получал, когда менял геометрию и пытался получить одну линию. Я думал, что будет проще, но оказалось, что это более сложная проблема.

M. Beausoleil 23.04.2024 22:54
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
6
158
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Следующий подход, вероятно, нелегко обобщить для других форм, но он работает с этим конкретным репрексом.

Координаты проекции сначала округляются (до метра), чтобы конечные точки линий оказались в одинаковых узлах в графовой сети, затем строки преобразуются в объект sfnetworks (igraph / tidygraph + пространственный). Отсюда мы можем получить правильную последовательность сегментов по эйлерову пути (пройти через каждое ребро ровно один раз), преобразовать ребра обратно в объект sf и подмножество сегментов линий с индексами ребер из пути.

Еще есть st_line_merge(), и как только координаты округляются, он неплохо справляется со своей задачей, но не может справиться с этим трехсторонним соединением и возвращает 2 строки, цикл + этот короткий участок.

library(sf)
#> Linking to GEOS 3.11.2, GDAL 3.6.2, PROJ 9.2.0; sf_use_s2() is TRUE
library(sfnetworks)
library(tidygraph, warn.conflicts = FALSE)
library(dplyr, warn.conflicts = FALSE)
library(mapview)

line_sfn <-
  chemins.simple %>% 
  st_zm(geom) %>% 
  st_geometry() %>%
  st_cast("LINESTRING") %>% 
  # round coordinates so line endpoints would end up in same graph nodes
  lapply(function(x) round(x, 0)) %>% 
  # back to sfc
  st_sfc(crs = st_crs(chemins.simple)) %>% 
  # directed graph
  as_sfnetwork(directed = TRUE)

line_sfn
#> # A sfnetwork with 13 nodes and 13 edges
#> #
#> # CRS:  EPSG:32188 
#> #
#> # A directed simple graph with 1 component with spatially explicit edges
#> #
#> # A tibble: 13 × 1
#>                  x
#>        <POINT [m]>
#> 1 (299583 5047541)
#> 2 (299491 5047361)
#> 3 (299552 5047315)
#> 4 (299582 5047207)
#> 5 (299931 5047004)
#> 6 (299652 5047608)
#> # ℹ 7 more rows
#> #
#> # A tibble: 13 × 3
#>    from    to                                                                  x
#>   <int> <int>                                                   <LINESTRING [m]>
#> 1     1     2 (299583 5047541, 299567 5047516, 299534 5047477, 299516 5047450, …
#> 2     2     3   (299491 5047361, 299497 5047351, 299517 5047334, 299552 5047315)
#> 3     3     4   (299552 5047315, 299572 5047290, 299581 5047269, 299582 5047207)
#> # ℹ 10 more rows

plot(line_sfn)

as.igraph(line_sfn) %>%  plot()


eulerian_path <- 
  line_sfn %>% 
  # edges back to regular sf
  st_as_sf(active = "edges") %>% 
  # find Eulerian path (pass through every edge exactly once),
  # use edge indices to subset edges in sf object in correct order
  slice(igraph::eulerian_path(line_sfn)$epath %>% as.vector()) %>% 
  # lines to multipoints
  st_cast("MULTIPOINT") %>% 
  # to a single multipoint feature, now correctly ordered
  summarise(do_union = FALSE) %>% 
  # points to linestring
  st_cast("LINESTRING")
eulerian_path
#> Simple feature collection with 1 feature and 0 fields
#> Geometry type: LINESTRING
#> Dimension:     XY
#> Bounding box:  xmin: 299474 ymin: 5046882 xmax: 300514 ymax: 5047608
#> Projected CRS: NAD83 / MTM zone 8
#> # A tibble: 1 × 1
#>                                                                                x
#>                                                                 <LINESTRING [m]>
#> 1 (299903 5046961, 299903 5046961, 299915 5046989, 299924 5047001, 299931 50470…

pt_samples <- st_line_sample(eulerian_path, n = 20)
mapview(eulerian_path) + mapview(pt_samples)


-e- к LINESTRING всего лишь с помощью sf

sf::st_line_merge() делает немного больше, чем я ожидал, по крайней мере, с помощью этого репрекса мы можем получить действительный результат при приведении st_line_merge()MULTILINESTRING результата к POINTs, а затем к LINESTRING:

merged_ <- 
  chemins.simple %>% 
  st_zm(geom) %>% 
  # 1 multiline
  st_geometry() %>%
  # to 13 line features
  st_cast("LINESTRING") %>% 
  lapply(function(x) round(x, 0)) %>% 
  st_sfc(crs = st_crs(chemins.simple)) %>% 
  # to 1 multiline with 13 lines
  st_union() %>% 
  # to 1 multiline with 2 lines
  st_line_merge() %>% 
  # to 96 point features
  st_cast("POINT") %>% 
  # to 1 multipoint
  st_combine() %>% 
  st_cast("LINESTRING")
merged_
#> Geometry set for 1 feature 
#> Geometry type: LINESTRING
#> Dimension:     XY
#> Bounding box:  xmin: 299474 ymin: 5046882 xmax: 300514 ymax: 5047608
#> Projected CRS: NAD83 / MTM zone 8
#> LINESTRING (299903 5046961, 299915 5046989, 299...
plot(merged_)

Created on 2024-04-25 with reprex v2.1.0

Другие вопросы по теме