Как исправить «Ошибка в триммере - нет оставшихся отрезков» при использовании Riverdist? - PullRequest
1 голос
/ 29 марта 2019

Я искал решения для расчета расстояния между точками отбора проб и устьем / устьем реки, следующим за линией реки. Похоже, «Ривердист» мог решить все мои проблемы, но у меня проблемы с самого начала. Я работаю на национальном уровне (Южная Африка), но сначала пытаюсь использовать отдельные водосборы, поскольку речные системы довольно большие и сложные.

Что я сделал:

  • Я сделал файл river shp максимально простым и удалил все притоки, которые не нужны
  • Используется прогнозируемый CRS
  • Пытался загрузить его с помощью "line2network"
> library(riverdist)

> limpopo <- line2network(path = "/Volumes/Shadowfax/Distribution/simple rivers/Limpopo.shp", layer="Limpopo", tolerance = 100, reproject = NULL,
+              supplyprojection = NULL)

Это сообщение об ошибке, которое я получаю: Ошибка в тримвере (триммер = проблемы, реки = реки): Ошибка - полученная речная сеть не имеет оставшихся отрезков

Мой файл shp выглядит для меня совершенно нормально.

Думаю, я что-то не так делаю при редактировании моего shp или при сохранении, но я не знаю что. Вот проблеск shp: Limpopo.shp Я должен добавить, что я в значительной степени неопытен с R или любым видом кодирования. Это мой первый выход на "Ривердист".

Надеюсь, я смогу найти помощь здесь! Спасибо!

[EDIT] Используется ответ MM. Но у меня все еще есть проблема. Сегменты реки не считаются последовательными (если это имеет смысл), и в дальнейшем у меня возникают проблемы при расчете расстояния между точками и устьем реки. Я также пытался сделать shp еще более простым в QGI перед тем, как делать это.

library(riverdist)

# Create your custom function to read the file. 
# Examine the line2network function and modify the lines that cause an issue with your specific shape file

my.custom.line2network =  function (path = ".", layer, tolerance = 100, reproject = NULL, supplyprojection = NULL) {
  sp <- suppressWarnings(rgdal::readOGR(dsn = path, layer = layer, verbose = F))
  if (class(sp) != "SpatialLinesDataFrame") 
    stop("Specified shapefile is not a linear feature.")
  if (is.na(sp@proj4string@projargs) & !is.null(supplyprojection)) 
    sp@proj4string@projargs <- supplyprojection
  if (is.na(sp@proj4string@projargs)) 
    stop("Shapefile projection information is missing.  Use supplyprojection= to specify a Proj.4 projection to use.  If the input shapefile is in WGS84 geographic (long-lat) coordinates, this will be +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0 (in double-quotes).  If so, it must also be reprojected using reproject=.")
  proj4 <- strsplit(sp@proj4string@projargs, split = " ")
  projected <- sp::is.projected(sp)
  if (is.null(reproject) & !projected) 
    stop("Distances can only be computed from a projected coordinate system. Use reproject= to specify a Proj.4 projection to use.")
  if (!is.null(reproject)) {
    sp <- sp::spTransform(sp, sp::CRS(reproject))
    proj4 <- strsplit(sp@proj4string@projargs, split = " ")
  }
  units <- "unknown"
  for (i in 1:length(proj4[[1]])) {
    if (proj4[[1]][i] != "") {
      proj4arg <- strsplit(proj4[[1]][i], split = "=")
      if (proj4arg[[1]][1] == "+units") {
        units <- proj4arg[[1]][2]
        cat("\n", "Units:", proj4arg[[1]][2], "\n")
      }
    }
  }
  if (length(sp@lines) > 1) {
    sp_line <- NA
    sp_seg <- NA
    lines <- list()
    j <- 1
    for (i in 1:length(sp@lines)) {
      for (k in 1:length(sp@lines[i][[1]]@Lines)) {
        lines[[j]] <- sp@lines[i][[1]]@Lines[[k]]@coords
        sp_line[j] <- i
        sp_seg[j] <- k
        j <- j + 1
      }
    }
  }
  if (length(sp@lines) == 1) {
    lines <- sp@lines[1][[1]]@Lines
    length <- length(lines)
    lines.new <- list()
    for (i in 1:length) {
      lines.new[[i]] <- lines[[i]]@coords
    }
    lines <- lines.new
    sp_line <- rep(1, length)
    sp_seg <- 1:length
  }
  length <- length(lines)
  rivID <- 1:length
  lineID <- data.frame(rivID, sp_line, sp_seg)
  connections <- calculateconnections(lines = lines, tolerance = tolerance)
  if (any(connections %in% 5:6)) 
    braided <- TRUE
  lengths <- rep(NA, length)
  for (i in 1:length) {
    lengths[i] <- pdisttot(lines[[i]])
  }
  names <- rep(NA, length)
  mouth.seg <- NA
  mouth.vert <- NA
  mouth <- list(mouth.seg, mouth.vert)
  names(mouth) <- c("mouth.seg", "mouth.vert")
  sequenced <- FALSE
  braided <- NA
  cumuldist <- list()
  for (i in 1:length) {
    xy <- lines[[i]]
    n <- dim(xy)[1]
    cumuldist[[i]] <- c(0, cumsum(sqrt(((xy[1:(n - 1), 1] - 
                                           xy[2:n, 1])^2) + ((xy[1:(n - 1),    2] - xy[2:n, 2])^2))))
  }
  out.names <- c("sp", "lineID", "lines", "connections", "lengths", 
                 "names", "mouth", "sequenced", "tolerance", "units", 
                 "braided", "cumuldist")
  out <- list(sp, lineID, lines, connections, lengths, names, 
              mouth, sequenced, tolerance, units, braided, cumuldist)
  names(out) <- out.names
  class(out) <- "rivernetwork"
  length1 <- length(out$lengths)
  suppressMessages(out <- removeduplicates(out))
  length2 <- length(out$lengths)
  if (length2 < length1) 
    cat("\n", "Removed", length1 - length2, "duplicate segments.", "\n")

  # THIS LINE CAUSES ISSUES COMENT IT OUT
  # THIS LINE CAUSES ISSUES COMENT IT OUT
  # suppressMessages(out <- removemicrosegs(out))

  length3 <- length(out$lengths)
  if (length3 < length2) 
    cat("\n", "Removed", length2 - length3, "segments with lengths shorter than the connectivity tolerance.", "\n")
  return(out)
}

limpopo <- my.custom.line2network(path = "/Volumes/Shadowfax/Distribution/simple rivers/Limpopo.shp", 
                                  layer = "Limpopo", 
                                  tolerance = 100, 
                                  reproject = NULL,
                                  supplyprojection = NULL)
#displaying
plot(limpopo)

#Convert XY to river location
library(readxl)
limpopo_eel <- read_excel("/Volumes/Shadowfax/Distribution/Eel_data/limpopo_eel.xlsx")
View(limpopo_eel)

Limpopo_eel_riv <- xy2segvert(x=limpopo_eel$X, y=limpopo_eel$Y, rivers=limpopo)
hist(Limpopo_eel_riv$snapdist, main="snapping distance (m)")


#displaying point data in river location 
zoomtoseg(seg=c(4,3), rivers=limpopo)
points(limpopo_eel$X, limpopo_eel$Y, pch=16, col="red")
riverpoints(seg=Limpopo_eel_riv$seg, vert=Limpopo_eel_riv$vert, rivers=limpopo, pch=15, 
            col="blue")

#Computing a a matrix between all observations
dmat <- riverdistancemat(Limpopo_eel_riv$seg,Limpopo_eel_riv$vert,limpopo)

# starting location: segment 5, vertex 93
# ending location: segment 4, vertex 2420
detectroute(start=4, end=4, rivers=limpopo)
riverdistance(startseg=4, startvert=93, endseg=4, endvert=2420, rivers=limpopo, map=TRUE)
nter code here

И получаю это Erro riverdist при расчете расстояния

Ответы [ 2 ]

0 голосов
/ 07 мая 2019

Проблема решена.Что-то не так случилось, когда я спас мою речную шлюпку с помощью прогнозируемого CRS.При правильной проекции проблема больше не появляется.

0 голосов
/ 31 марта 2019

Я не знаком с пакетом riverdist или функцией line2network(), однако можно немного изменить line2network(), чтобы заставить его работать в этой ситуации. В функции есть строка, которая вызывает проблему.

# Create your custom function to read the file. 
# Examine the line2network function and modify the lines that cause an issue with your specific shape file

my.custom.line2network =  function (path = ".", layer, tolerance = 100, reproject = NULL, supplyprojection = NULL) {
sp <- suppressWarnings(rgdal::readOGR(dsn = path, layer = layer, verbose = F))
  if (class(sp) != "SpatialLinesDataFrame") 
    stop("Specified shapefile is not a linear feature.")
  if (is.na(sp@proj4string@projargs) & !is.null(supplyprojection)) 
    sp@proj4string@projargs <- supplyprojection
  if (is.na(sp@proj4string@projargs)) 
    stop("Shapefile projection information is missing.  Use supplyprojection= to specify a Proj.4 projection to use.  If the input shapefile is in WGS84 geographic (long-lat) coordinates, this will be +proj=longlat +datum=WGS84 +no_defs +ellps=WGS84 +towgs84=0,0,0 (in double-quotes).  If so, it must also be reprojected using reproject=.")
  proj4 <- strsplit(sp@proj4string@projargs, split = " ")
  projected <- sp::is.projected(sp)
  if (is.null(reproject) & !projected) 
    stop("Distances can only be computed from a projected coordinate system. Use reproject= to specify a Proj.4 projection to use.")
  if (!is.null(reproject)) {
    sp <- sp::spTransform(sp, sp::CRS(reproject))
    proj4 <- strsplit(sp@proj4string@projargs, split = " ")
  }
  units <- "unknown"
  for (i in 1:length(proj4[[1]])) {
    if (proj4[[1]][i] != "") {
      proj4arg <- strsplit(proj4[[1]][i], split = "=")
      if (proj4arg[[1]][1] == "+units") {
        units <- proj4arg[[1]][2]
        cat("\n", "Units:", proj4arg[[1]][2], "\n")
      }
    }
  }
  if (length(sp@lines) > 1) {
    sp_line <- NA
    sp_seg <- NA
    lines <- list()
    j <- 1
    for (i in 1:length(sp@lines)) {
      for (k in 1:length(sp@lines[i][[1]]@Lines)) {
        lines[[j]] <- sp@lines[i][[1]]@Lines[[k]]@coords
        sp_line[j] <- i
        sp_seg[j] <- k
        j <- j + 1
      }
    }
  }
  if (length(sp@lines) == 1) {
    lines <- sp@lines[1][[1]]@Lines
    length <- length(lines)
    lines.new <- list()
    for (i in 1:length) {
      lines.new[[i]] <- lines[[i]]@coords
    }
    lines <- lines.new
    sp_line <- rep(1, length)
    sp_seg <- 1:length
  }
  length <- length(lines)
  rivID <- 1:length
  lineID <- data.frame(rivID, sp_line, sp_seg)
  connections <- calculateconnections(lines = lines, tolerance = tolerance)
  if (any(connections %in% 5:6)) 
    braided <- TRUE
  lengths <- rep(NA, length)
  for (i in 1:length) {
    lengths[i] <- pdisttot(lines[[i]])
  }
  names <- rep(NA, length)
  mouth.seg <- NA
  mouth.vert <- NA
  mouth <- list(mouth.seg, mouth.vert)
  names(mouth) <- c("mouth.seg", "mouth.vert")
  sequenced <- FALSE
  braided <- NA
  cumuldist <- list()
  for (i in 1:length) {
    xy <- lines[[i]]
    n <- dim(xy)[1]
    cumuldist[[i]] <- c(0, cumsum(sqrt(((xy[1:(n - 1), 1] - 
                                           xy[2:n, 1])^2) + ((xy[1:(n - 1),    2] - xy[2:n, 2])^2))))
  }
  out.names <- c("sp", "lineID", "lines", "connections", "lengths", 
             "names", "mouth", "sequenced", "tolerance", "units", 
             "braided", "cumuldist")
  out <- list(sp, lineID, lines, connections, lengths, names, 
          mouth, sequenced, tolerance, units, braided, cumuldist)
  names(out) <- out.names
  class(out) <- "rivernetwork"
  length1 <- length(out$lengths)
  suppressMessages(out <- removeduplicates(out))
  length2 <- length(out$lengths)
  if (length2 < length1) 
    cat("\n", "Removed", length1 - length2, "duplicate segments.", "\n")

  # THIS LINE CAUSES ISSUES COMENT IT OUT
  # THIS LINE CAUSES ISSUES COMENT IT OUT
  # suppressMessages(out <- removemicrosegs(out))

  length3 <- length(out$lengths)
  if (length3 < length2) 
    cat("\n", "Removed", length2 - length3, "segments with lengths shorter than the connectivity tolerance.", "\n")
  return(out)
}

Теперь вы можете читать файл формы, используя новую функцию, которую вы только что создали

limpopo <- my.custom.line2network(path = "/Volumes/Shadowfax/Distribution/simple rivers/Limpopo.shp", 
                               layer = "Limpopo", 
                               tolerance = 100, 
                               reproject = NULL,
                               supplyprojection = NULL)

Вы должны получить следующий участок:

Limpopo river plot

...