Det jag visar i detta inlägg startade med en Tweet om symboler som ritas ut över kanten för kartan i en layout.
Detta kan göras på flera sätt och det enklaste för specifika situationer är att helt enkelt lägga till en extra punktsymbol i layouten som har samma stil som lagret, men det är lätt att något flyttas och så blir kartan felaktig. Det vore bättre om allt kunde göras dynamiskt.
Jag tänker lösa detta med tre olika kartteman. Jag benämner dessa som ”BackgroundMap”, ”MainMap” och ”OverlayMap”.
För att ytterligare förenkla så skapar jag tre grupplager med samma namn och de symboler från kartan som jag vill sträcka ut över kartgränserna i bakgrunden kopierar jag till ”BackgroundMap” och de som skall skrivas ut över gränserna kopieras till ”OverlayMap”. I mitt fall så lägger jag även till ett filter på de kopierade lagren så att endast vattenytor finns i bakgrunden och badplatser i overlay.
Därefter skapas ett tema för varje grupp, även dessa med samma namn för tydlighetens skull. Om man gör uppdateringar i vilka lager som är aktiva i olika kartor så behöver man också uppdatera teman för detta, men det här bör inte vara några större problem.
I en layout så skall tre kartor läggas till…
Döp dessa kartor till samma namn som tidigare (bilden uppe till höger) och placera dem i önskad utritningsordning. Varje karta ställs in att följa sitt respektive tema i inställningarna för varje karta. Se till att storleken på ”MainMap” är den önskade och att övriga kartor sträcks ut så långt som du vill att de skall ”spilla över”. När detta är klart så markera alla kartor och justera dem centrerat vertikalt och horisontellt. För att underlätta så kan sedan framför allt ”OverlayMap” låsas så att det går att panorera huvudkartan.
Vill du ha koordinater och rutnät i kartan så gör du dessa inställningar i ”MainMap” objektet.
För att kartorna skall ha samma skala och passa in i utsträckning så behövs det lite uttryck för några inställningar. Det är inställningar för ”BackgroundMap” och ”OverlayMap” som skall justeras och de kan behöva anpassas något beroende på vad som skall fyllas i.
För skalan i kartorna som skall ”spilla över” så behöver skalan som används i ”MainMap” användas. Detta görs med ett uttryck som hämtar skalan med map_get().
Uttrycket hämtar variabeln map_scale från layoutobjektet som har namnet ”MainMap”. Detta uttryck går att använda för båda ”överflödeskartorna”.
För att alla kartor skall passas in mot varandra så behöver utsträckningen justeras. Då det inte går att sätta center värden med uttryck så måste lite matte användas för att kunna använda utsträckningen.
En förutsättning är att alla kartor är justerade centrerat med varandra i såväl x- som y-led (enligt tidigare).
I överflödeskartorna så används uttryck för Extents och X min samt Y min. Om dessa kan anges korrekt så behöver inte max värdena anges eftersom vi redan har synkroniserat skalan.
På samma sätt som för skalan så hämtas map_extent från MainMap till att börja med. Då kartorna inte är lika stora så behöver denna koordinat kompenseras med halva storleksskillnaden. Den egna bredden (eller höjden) kan hämtas med en variabel direkt (@map_extent_width i bilden ovan) medan bredden (eller höjden) för MainMap hämtas med map_get.
Förenklat blir formeln för X min = x_min(MainMap) – ( map_width – MainMap_width) / 2. För Y min så får uttrycket modifieras något så att det är Y och height som används i stället. Däremot så går det att använda samma uttryck för båda överflödeskartorna.
Resultatet blir att det som finns i BackgroundMap ritas ut under koordinatsiffror och kartram för MainMap, och att lager i OverlayMap ritas ut över dessa.
Det kan finnas situationer när man bara vill att Overlay symboler som finns i MainMap skall tillåtas ritas ut delvis över kartramen. Med andra ord skall symboler som har sin position utanför denna inte redovisas. Då behöver man först göra ett urval som är kopplat till MainMap kartans utsträckning.
Detta innebär lite utmaningar. Arbete med urval av enskilda objekt i ett lager görs inte i layouterna, det måste göras i QGIS vanliga karta. Men för att välja ut dessa så måste utsträckningen av kartan i layouten användas. Det finns ingen inbyggd funktion för detta som är lätt tillgänglig i QGIS, så något måste trixas lite med.
Man skulle kunna tänka sig att använda ett virtuellt lager med ett urval, men dessa använder SQL och där finns inga variabler för att hämta en layouts kartutsträckning. Man kan också tänka sig ett filter, men dessa är också baserade på SQL och endast riktade mot attributvärden. För att läsa en utsträckning för en specifik karta i en specifik layout så krävs det Python och då är ett sätt att arbeta med uttryck i stilinställningarna.
I stilinställningarna så finns det en parameter för att aktivera eller släcka ett symbollager i varje stil. Denna kan använda uttryck för att dynamiskt anpassas för varje enskilt objekt i lagret.
Med ett within() uttryck så kan varje objekts geometri testas om den finns inom en polygons utsträckning. Om man har något annat än punktsymboler så kan man vilja använda ett annat uttryck.
Kruxet ligger i att hämta utsträckningen för MainMap i den aktuella layouten. För detta krävs det en anpassad Pythonfunktion.
Här skapas ett nytt uttryck (funktionsfliken i uttrycksbyggaren) som tar två ingångsvariabler. Den första är layout_name som skall sättas till den aktuella layoutens namn, och den andra är map_name som är det ”item ID” som används för den karta som man är ute efter.
Funktionen som skapas kallas map_extent() och anropas på det sätt som visas i den tidigare bilden.
Det skapas ett project objekt av den aktuella QGIS instansen och från denna hämtas layouthanteraren till ett manager objekt. Då ett projekt kan ha flera layouter så hämtas en lista med alla layouter och denna jämförs med angivet layoutnamn för att hitta den layout man är ute efter.
Den önskade kartan kan sedan hämtas med itemById som pekar på angivet map_name. Resultatet sparas i objektet map_item. För att få ett geografiskt objekt som kan användas i uttrycken så skapas ett QgsGeometry objekt från det aktuella extent som detta kartobjekt har. Polygonen returneras sedan som map_extent.
Resultatet i layouten blir att endast objekt som faktiskt finns i kartan ritas ut i layouten. Men även de som har symbolen delvis utanför ritas ut.
Det går att modifiera funktionen så att den exempelvis tar en tredje variabel som lägger till en ”buffert” så att även punkter som är lite utanför kommer med, men att inga symboler skrivs ut ”klippta”. Men detta går också enkelt att uppnå genom att modifiera uttrycket med en buffer() funktion runt den skapade map_extent() funktionen.
Om du vill så kan du ladda ner mitt något modifierade uttryck som *.py fil och spara den i din ”python”/”expressions” katalog i din QGIS profil. Efter omstart av QGIS återfinns uttrycket under ”Layouts”. (layout_extent.py)