# Edited snap points to lines for river nodes
#' @export
snapPointsToLinesbyOrder<-
function (points, lines, maxDist = NA, withAttrs = TRUE, idField = NA)
{ # browser()
if (rgeosStatus()) {
if (!requireNamespace("rgeos", quietly = TRUE))
stop("package rgeos required for snapPointsToLines")
}
else stop("rgeos not installed")
if (inherits(points, "SpatialPoints") && missing(withAttrs))
withAttrs = FALSE
if (inherits(points, "SpatialPoints") && withAttrs == TRUE)
stop("A SpatialPoints object has no attributes! Please set withAttrs as FALSE.")
if (!is.na(maxDist)) {
w = gWithinDistance(points, lines, dist = maxDist,
byid = TRUE)
validPoints = apply(w, 2, any)
validLines = apply(w, 1, any)
points = points[validPoints, ]
lines = lines[validLines, ]
}
# get a matrix of distances for the point to each of the lines (within the specified buffer area)
d = gDistance(points, lines, byid = TRUE)
# Round to make sure you will always get a 0 because 0.00000000092766569 for example is
# clearly 0 but won't come out in the which.
d <- round(d, 2)
# nearest_line_index = apply(d, 2, which.min) <<< ORIGINAL CODE
# return all the rows in d which == 0 (rather than which.min that gives the first)
# this gives you a vector of all the row positions of each river segment which has
# 0 distance to the node
all_nearest_line_indexes<-apply(d, 2, function(x) which(x==0))
# now find out of all the closest line segments for each node with the highest order
# have to wrap this in a a loop because which.max does not work if there is only 1 element
# in the vector. Thus if there is only one line where there is 0 distance all_nearest_line_indexes
# becomes nearest_line_index (although this should never happen apart from at the mouth as all other locations
# will have at least 2 matches!)
if(length(all_nearest_line_indexes) == 1) {
nearest_line_index <- all_nearest_line_indexes
} else {
nearest_line_index<-apply(all_nearest_line_indexes, 2, function(x) x[which.max(lines[x, ]$order)])
}
# Get coordinates of all bits of the lines
coordsLines = coordinates(lines)
# Get coordinates of the points
coordsPoints = coordinates(points)
# Get coordinates of nearest line coordinate (for river nodes this will be the same as the node anyway)
mNewCoords = vapply(1:length(points), function(x) nearestPointOnLine(coordsLines[[nearest_line_index[x]]][[1]],
coordsPoints[x, ]), FUN.VALUE = c(0, 0))
if (!is.na(idField))
# ID of the line of the river line of interest in the lines sldf
nearest_line_id = lines@data[, idField][nearest_line_index]
else nearest_line_id = sapply(slot(lines, "lines"), function(i) slot(i,
"ID"))[nearest_line_index]
if (withAttrs)
df = cbind(points@data, nearest_line_id)
else df = data.frame(nearest_line_id, row.names = names(nearest_line_index))
SpatialPointsDataFrame(coords = t(mNewCoords), data = df,
proj4string = CRS(proj4string(points)))
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.