Skip to content

Find nearest downstream value of a river network

4 messages · Edzer Pebesma, Barry Rowlingson, Jon Olav Skoien

#
Hi Jon (thanks for reminding off-list!), I haven't looked into finding
the line with an ID, but in general finding the nearest SpatialLines
index (which of course might be ambiguous) might be done by:

library(rgeos)
d = gDistance(nres, nres, byid=TRUE)
diag(d)=1e9
apply(d,2,function(x)which(x==min(x))[1])

Does that get you any further? Or are there more clever solutions?
--
Edzer
On 04/13/2011 09:59 AM, Jon Olav Skoien wrote:

  
    
#
On Thu, May 19, 2011 at 4:17 PM, Edzer Pebesma
<edzer.pebesma at uni-muenster.de> wrote:

            
If the FROMJCT and TOJCT numbers define nodes of a graph, and the
presence of a row with FROMJCT=a and TOJCT=b defines an edge from a to
b of the graph, then you could use something like R's igraph package
to build a graph object. Once you've done that it should be easy to
use the graph algorithms in that package to wander down the river
system at your leisure...

 It might get complicated if you are modelling on the Orinoco where it
bifurcates, or a river delta :)

 Will have a play now at the end of the working day while waiting for
the Indian Premier League Cricket to start up again...

Barry
4 days later
#
Hi Edzer,

Thanks for the suggestion! It is a much simpler way of doing it, but 
unfortunately gDistance seems rather slow for larger data sets. For a 
data set with 1200 segments (the full data set has around 8000), it took 
around 4 minutes on my computer, which is considerably more than the 
method I already had. But gDistance might be what I need for something 
else...

Cheers,
Jon
On 19-May-11 17:17, Edzer Pebesma wrote:
#
On 19-May-11 18:06, Barry Rowlingson wrote:
It was my first look at the igraph package, and I dont think I found the 
optimal set of functions. So far I ended up with the following, although 
I am sure there are better solutions:

rndf = data.frame(FROMJCT = nres$FROMJCT, TOJCT = nres$TOJCT,
                OBJECTIT = nres$OBJECTID, pred = nres$pred)
igr = graph.data.frame(rndf)
igrs = topological.sort(igr, mode = "out")
rndf$to = match(as.character(rndf$TOJCT), V(igr)$name[igrs+1])

while (TRUE) {
   lcon = which(rndf$to == min(rndf$to[is.na(rndf$pred)]))
   if (length(lcon)==0) break()
   while(is.na(rndf$pred[lcon[1]])) lcon = c(neighbors(igr,lcon[1]-1)+1, 
lcon)
   rndf$pred[lcon] = rndf$pred[lcon[1]]
}

The best with this solution is that it is extremely fast compared to my 
first suggestion, about 20-30 times faster for 1200 segments. And it 
also seems to scale better with larger data sets. So I think I will 
either try to simplify this further, or just make a function of the 
lines above.
Complicated or more interesting, depending on how you see it and how 
much time you have ;-)
For the second reason I am happy that the river system I am interested 
in behaves rather "normal"...

Thanks!
Jon