So...no also with GRASS-user as recipient...

On 05.03.20 16:21, Micha Silver wrote:

On 3/5/20 10:47 AM, Johannes Radinger wrote:

Hi Micha, hi all,

sorry for my late response...however, just today I managed to try your approach of building polylines to connect "touching stream lines"...but...

On 24.02.20 16:48, Micha Silver wrote:

On 24/02/2020 10:45, Johannes Radinger wrote:
Hi all,
I have a large river network dataset (lines). Now I'd to assign unique categories to each group of connected lines that have an attribute in common.

For example, my rivers are categorized based on some kind of stream order. I want to group all rivers that belong to stream order 2 and are spatially connected; each group should get a unique category value. I thought that I could first extract all rivers with a particular attribute (e.g. stream order = 2) which will provide me some scattered pattern of lines. Then I need a spatial join tool to make subgroups of lines that are connected. How can I achieve the latter? Any idea?




Here's a procedure that might work for you. Somewhat clunky, but I think it gets what you want.

It's based on the v.build.polylines module to connect all touching stream reaches. First extract each order from the stream vector into a new vector. Then build polylines. Patch them all together. Now you have a polyline vector with a single cat value for each set of original stream reaches that had the same order and that were touching.

Unfortunately, the v.build.polylines tool does not work as it only does not connect multiple (intersecting) lines like in a river network. As an example I tried to build polylines from the stream network of the NC dataset. Yous suggested approach should result that each sub-network (i.e. river network that is not connected to another one) should get its own ID/cat...however, v.build.polylines results in a connected stream network that consists of multiple cats:

Maybe I misunderstood your question. The steps I tried use a stream_order column to group stream segments, then apply a new attribute "merged_id" to those stream orders that touch. i.e. that connect to the same confluence point.


Here's what I get using the nc_basic_spm mapset:


r.watershed elev=elevation accum=nc_facc drain=nc_fdir bas=nc_bas stream=nc_str thresh=1000 r.stream.order stream_rast=nc_str direct=nc_fdir elev=elevation accum=nc_facc stream_vect=nc_streams
ORDERS=`v.db.select -c nc_streams group=strahler column=strahler`
echo $ORDERS

# Create a new stream vector for each stream order

for o in $ORDERS; do

    v.extract input=nc_streams output=streams_${o} where="strahler=${o}"

    # Give each polyline it's own cat value

    v.build.polylines input=streams_${o} output=streams_${o}_polyline type=line cat=first

done


# patch the stream orders back together

POLYLINES=`g.list vect pattern="streams*polyline" separator=comma`

v.patch input=$POLYLINES output=streams_polylines

v.db.addcolumn map=streams column="merged_id INTEGER"


# And use v.distance to update that merged_id column from cat values in polylines vector
v.distance from=streams to=streams_polylines upload=cat column=merged_id
v.db.addcolumn map=nc_streams column="merged_id INTEGER"
v.distance from=nc_streams to=streams_polylines upload=cat column=merged_id

Now, all stream reaches that have the same order and are "touching" have the same merged_id. See the attached image.


If that's not your purpose, then just ignore...

Micha thank you for your help and of course, you're fully correct! Merging lines that belong to the same stream order works in this case well...but this is because of the definition of the Strahler ordering system, where there is only one "touching node" (i.e. river junction) of two rivers of the same stream order (i.e. when two 2nd order streams meet, the become a 3rd order stream). Thus your solution works because of this specifics and might not work if streams are grouped based on a different (ordering) system.

I was already thinking of the next step (beyond simple Strahler): As mentioned in my initial post I am dealing with "some kind" of stream order. It is similar to grouped stream orders (e.g. stream order 1-2 = "headwater streams"). I tried to somehow reproduce my situation based on your example of the NC dataset. What I basically did was to reassign a new stream order "99" to all former 1st and 2nd order streams. Then I did exactly what you did in your example, and of course I don't unique merged_ids for the subnetworks of touching lines (see attached Figs) that all belong the the same "order" 99 (the original strahler order 3 works of course, see Fig.)...So is there a more general way (as said something like v.dissolve but for lines/networks?):

#####################
g.region raster=elevation

r.watershed --o elev=elevation accum=nc_facc drain=nc_fdir bas=nc_bas stream=nc_str thresh=1000 r.stream.order stream_rast=nc_str direct=nc_fdir elev=elevation accum=nc_facc stream_vect=nc_streams

#ORDERS=`v.db.select -c nc_streams group=strahler column=strahler`
#echo $ORDERS

# Regroup orders 1-2 (to 99)
v.db.addcolumn map=nc_streams@test2 columns="strahler_groups INTEGER"
v.db.update map=nc_streams column=strahler_groups query_column=strahler
v.db.update map=nc_streams column=strahler_groups value=99 where="strahler=1 OR strahler=2"

NEWORDERS=`v.db.select -c nc_streams group=strahler_groups column=strahler_groups`
echo $NEWORDERS

# Create a new stream vector for each stream order
for o in $NEWORDERS; do
    v.extract input=nc_streams output=streams_${o} where="strahler_groups=${o}"
    # Give each polyline it's own cat value
    v.build.polylines input=streams_${o} output=streams_${o}_polyline type=line cat=first
done

d.vect -c map=streams_99_polyline@test2
#################

Thank you very much!

Cheers,

Johannes


v.clean --overwrite input=streams@PERMANENT output=streams_break tool=break v.build.polylines --overwrite input=streams_break@test output=streams_poly cats=first type=line
d.vect -c map=streams_poly

So what would be needed here is some kind of tool that connects all touching lines and assigns a common category value, similar to the v.dissolve tool for polygon features. I can imagine that such a task might be not that uncommon also in another context? Any suggestions how to achieve this in GRASS?

A workaround that came into my mind was to create buffers around lines in order to make areas out of lines. Subsequently these touching areas can be merged using v.dissolve and the information about the common category can be queried using v.distance. Nevertheless, a rather cumbersome way to just assign a common category value to all lines that are touching...

Any further ideas?

cheers,

Johannes


Cheers,
Johannes

_______________________________________________
grass-user mailing list
grass-user@lists.osgeo.org <mailto:grass-user@lists.osgeo.org>
https://lists.osgeo.org/mailman/listinfo/grass-user

_______________________________________________
grass-user mailing list
grass-user@lists.osgeo.org
https://lists.osgeo.org/mailman/listinfo/grass-user

Reply via email to