[GRASS-user] Merge spatially connected features

Micha Silver tsvibar at gmail.com
Thu Mar 5 07:21:57 PST 2020

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


# 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...

> 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
Micha Silver
Ben Gurion Univ.
Sde Boker, Remote Sensing Lab
cell: +972-523-665918

-------------- next part --------------
A non-text attachment was scrubbed...
Name: merged_id.png
Type: image/png
Size: 61006 bytes
Desc: not available
URL: <http://lists.osgeo.org/pipermail/grass-user/attachments/20200305/9f00f975/attachment-0001.png>

More information about the grass-user mailing list