När jag skapade kartan över Kina i ett tidigare inlägg så använde jag floder från NaturalEarthData som har ett attribut med ”scale rank” som användes för att sätta bredden på vattendragen. Detta skapade en enkel storleksskillnad på floderna som åtminstone antyder vilket som är huvudfloden i ett helt system.

Men det finns ytterligare sätt att stilsätta den här typen av linjer som ytterligare visualiserar att ett vattendrag normalt växer nedströms. Ett problem med detta är att man måste veta var en linje börjar, och var den slutar. Det första problemet är att ett enda rakt vattendrag kan bestå av flera sammanhängande linjer som var och en har en början och ett slut, men det kan man jobba runt genom att använda en geometrigenerator med line_merge($geometry).
Ett problem som inte går att komma runt på ett lika ”enkelt” sätt är vilken ände av linjen som är ”början” och vilken ände som är ”slutet”. Med andra ord, var börjar vattendraget och var slutar det. För oss är det enkelt att se att vattendrag brukar sluta där det rinner ut i ett större vattendrag, men hur skall man lösa det i en dator? Linjer måste vara dragna i en bestämd riktning, eller ”orienterade” i samma riktning som vattnet flödar. Är det inte så, så kommer linjestilar att vara riktade åt olika håll.

Det blir också problem där linjer går ihop (vilket vattendrag ofta gör), eller där det skapas ett ”delta” med en uppdelning i flera strömmar i ett utlopp.

Inte ens om man använder data som skulle kunna vara skapade ”topologiskt” korrekt på det här viset, exempelvis Lantmäteriets data över Sverige, så är riktningen perfekt på alla linjer. Det stora problemet är dock fortfarande att flera linjer går samman och delas upp längs vattendragen, och dessutom så börjar och slutar en del vattendrag i större vattensamlingar som är representerade av polygoner…

Det hjälper en del att data har storleksklasser som kan användas för att styra storleken på början och slutet av linjer med olika klass. Men där rena vattendrag går samman kan det fortfarande vara lite bekymmer.
Jag provade ett uttryck som räknar hur många andra objekt varje enskilt objekt intersects med en aggregate() funktion, vilket verkade hänga datorn omedelbart. Uttrycket ger ett resultat, men jag är inte säker på att det är optimalt, eller ens hanterbart när det skall implementeras.
Uttrycket användes för att styra Start value i stilinställningarna. Om det är ett objekt som bara gränsar till sig själv och ett objket till, så är det samma uttryck som tidigare, men om det är flera objekt än så, så används samma uttryck som för End value, vilket gör att hela objektet stilsätts med enhetlig bredd.
if( aggregate( layer:='hl_riks', aggregate:='count', expression:='KKOD', filter:=intersects(point_n(geometry(@parent),1), $geometry) )>1, 2 -- Ansluter till andra vattendrag , 1 -- Normal, ansluter inte till andra vattendrag )
I uttrycket ovan så har jag justerat det så att intersects() bara körs mot den punkt som är första brytpunkten i varje objekt. Detta går lite snabbare, men det är fortfarande otroligt långsamt. Det här kan vara ett av de fall när det faktiskt är motiverat att bearbeta data i förväg och lägga till information för att snabba upp hanteringen. Det förutsätter även att linjerna är ritade i vattenströmningsriktningen, vilket är ett annat problem som jag nog återkommer till i ett senare inlägg, men här utgår jag från att linjerna i huvudsak är korrekt ritade.

Genom att använda fältkalkylatorn (ovan) går det att skapa ett nytt fält i attributtabellen som består av värdet för hur många objekt startpunkten på varje linje gränsar till. Det är precis samma aggregate() funktion som används här som i stilinställningarna tidigare. En nackdel här är att nu körs processen på HELA datasetet och inte bara det som skall ritas ut på skärmen. Om det tog lång tid innan, så är det ingenting mot vad det kommer att göra för att beräkna ett större dataset som hydrografilinjer på nationell nivå.

Nu börjar vi nog närma oss så långt det går att komma utan att göra för mycket våld på data. När det nya attributet skapats så kan det användas med en enkel if() sats i uttrycket för Start value så att de linjer som ansluter till flera andra linjer inte får variabel längd. Det här går mycket snabbare och det märks knappt i renderingshastigheten att stilen är lite extra ”fancy”.
Nu är detta inte perfekt för en del punkter i Lantmäteriets lager är inte topologiskt korrekta, så en del startpunkter ”missar” angränsande linjer… Detta går att komma runt om man också lägger på en buffer() för startpunkten i uttrycket för att beräkna antal angränsande objekt, men detta tar så klart ytterligare lite längre tid…
Har någon ytterligare förslag på hur man kan stilsätta den här typen av objekt på ett snyggt sätt så lämna gärna en kommentar här.