[GRASS-user] Merge spatially connected features

Johannes Radinger johannesradinger at gmail.com
Tue Mar 10 09:19:42 PDT 2020


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 at 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 at test2
#################

Thank you very much!

Cheers,

Johannes

>
>> v.clean --overwrite input=streams at PERMANENT output=streams_break 
>> tool=break
>> v.build.polylines --overwrite input=streams_break at 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 at lists.osgeo.org <mailto:grass-user at lists.osgeo.org>
>>>> https://lists.osgeo.org/mailman/listinfo/grass-user
>>>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: merged_id_ORDER99.png
Type: image/png
Size: 53321 bytes
Desc: not available
URL: <http://lists.osgeo.org/pipermail/grass-user/attachments/20200310/a04a2d5f/attachment-0002.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: merged_id_ORDER3.png
Type: image/png
Size: 19789 bytes
Desc: not available
URL: <http://lists.osgeo.org/pipermail/grass-user/attachments/20200310/a04a2d5f/attachment-0003.png>


More information about the grass-user mailing list