Vandens kranto efektai QGIS’e

Tikriausiai visi esate matę senovinius vandens simbolizavimo būdus – kai braižomos intervalais nuo kranto atitolusios linijos, primenančios bangas:

Vanduo senoviniuose žemėlapiuose

Daniel Huffman suorganizavo virtualius pristatymus, kaip daryti žemėlapius. Tarp krūvos įdomių video buvo ir Sarah Bell (ESRI) pristatymas, kaip braižyti tokius „bangų“ efektus Adobe Iliustratoriuje. Žiūrėjau žiūrėjau, ir, nors labai gražu, viskas labai jau sudėtingai atrodo. Jau nekalbant apie tai, kad apdorojimas vyksta jau po to, kai žemėlapio vektorinė informacija sukurta iš geografinių duomenų. Tai reiškia, kad jei norėsime sukurti kitos vietos žemėlapį su tokiais pačiais vandens efektais, tai viską reikės daryti iš naujo.

Norėjau pabandyti, ar galima tokius pačius vandens kranto efektus gauti QGIS’e nenaudojant sudėtingų algoritmų, nekuriant papildomų sluoksnių ir pan. Ir, po trumpos diskusijos su kitais QGIS žinovais, buvo rastas gan elegantiškas sprendimas. QGIS turi puikią galimybę vaizduoti ne tik pirminę (tikrą) objekto geometriją, bet ir modifikuotą geometriją. T.y. imama geometrija iš šaltinio, tada ji apdorojama (Python’o išraiška) ir tada gauta geometrija naudojama simbolizavimui (ar etikečių braižymui). Taip pat simbolį galima kurti iš kelių sluoksnių, reiškią tą pačią pradinę geometriją galime keisti kelis kartus gaudami kelias skirtingas braižomas geometrijas.

Taigi QGIS’e imame ežerų sluoksnį, paliekame „standartinį“ vandens poligono simbolizavimą, o virš jo sukuriame papildomą „Geometrijos generatoriaus sluoksnį“, kuriame nurodome buffer veiksmą su neigiamu atstumu:

Geometrijos generatoriaus nustatymai QGIS’e

Šios modifikuotos geometrijos simbolizavime nurodome, kad užpildymas būtų permatomas, o linijos spalvą parenkame tarkim tokią, kokia yra vandens kontūro spalva (na arba pagal skonį).

Tokių sluoksnių sukuriame (ir sudedame vieną ant kito) tiek, kiek norime. Ir prašom, per kelias minutes gauname štai taip atrodančius vandens poligonus:

Vandens kranto linijos QGIS’e

Viskas. Tokį stilių galite įsirašyti į dažnai naudojamų stilių sąrašą ir per sekundę parinkti kituose savo projektuose.

Papildomos vandens telkinių etiketės

Anksčiau buvo rašyta apie vieną iš būdų, kaip skaičiuoti/braižyti pagal geometriją išlankstytas vandens telkinių etiketes. Tai sąlyginai paprastas būdas, tinkantis absoliučiai daugumai Lietuvos vandens telkinių. Atėjo laikas po truputį galvoti apie sudėtingesnius variantus. Šį kartą nepateiksiu sprendimo, nes nežinau, kaip daryti būtų teisinga. Šis įrašas bus klausimai Jums visiems, labai lauksiu Jūsų nuomonių komentaruose.

Pakalbėkime apie situacijas, kai vienam objektui – vienam vandens telkiniui – braižome daugiau nei vieną etiketę.

Jau pirmame etape buvo šiek tiek aptarta situacija, kai esant labai dideliam vandens telkiniui (arba stambiam masteliui) braižome daugiau nei vieną telkinio etiketę, kad „slenkant“ žemėlapį ekrane mes dažniau pamatytume vandens telkinio etiketę, tai apie šitą nešnekėkim. Taip pat kol kas negalvokime apie ežerus, kurie yra ilgų siaurų formų, kur etiketės netelpa pačiame vandens telkinyje ir galėtų/turėtų būti braižomos išorėje (tarkim Sartų ežero etiketės smulkesniuose masteliuose).

Šį kartą kalba apie lyg ir paprastesnį variantą – vandens telkinius, kurie dėl savo formos lyg ir prašosi antros (ar trečios, ketvirtos ir .t.t.) etiketės. Pavyzdžiui ež. Didžiulis:

ež. Didžiulis
https://topo.openmap.lt/#t/12/54.34116/24.39061/0/0/

Šis ežeras turi sudėtingą geometriją, etiketė nubraižyta didžiausioje ežero dalyje, t.y. ten, kur etiketė telpa geriausiai. Bet nėra visiškai aišku, ar šiaurinė dalis (greta Duškonių) irgi yra Didžiulio ežeras, ar ten jau koks nors kitas ežeras? Pavyzdžiui rytinėje pusėje (šalia Papiškių) tikrai yra kitas ežeras – Savistas.

Gal tai būtų tinkamas pavyzdys, kada prireikia antros etiketės? Bet nubraižyti antrą etiketę tokiu pačiu šrifto dydžiu neišeis – netilps.

Šiokių tokių minčių kyla žiūrint į vizualizaciją automatinio proceso, kai ieškoma, kurioje vietoje ir kokio dydžio braižyti pirmąją etiketę:

Čia matote, kaip iš pradžių ežerą (Virkščių) bandoma padengti 23 dydžio šriftui reikalingais kvadratais. Kadangi vietos, kur telpa tokio dydžio kvadratai nebūtinai liesis viena su kita, tai išrenkamas didžiausias vientisas gabalas, jo kvadratai pažymimi „O“, visi kiti – „X“. Jei iš „O“ sudaryto ploto neužtenka reikiamai etiketei įbraižyti, tai bandoma su mažesniu šrifto dydžiu – 22 ir taip toliau, kol arba šriftas per mažas, arba randama tinkama vieta etiketei. Galbūt kažkas iš čia matomo proceso – telkinio skaidymas į didesnius gabalus – galėtų būti panaudoti papildomų etikečių poreikiui ir vietai nustatyti? Gal taip, gal ne.

Taigi kyla du klausimai, tikiuosi, kad atsakymai į juos padės suprasti, kuria linkme judėti būtų teisingiausia?

  1. Kaip nusprendžiama, kad reikia antros etiketės ir kur ją reikėtų braižyti?
  2. Jei braižoma antra etiketė, ar ji turi būti tokio paties šrifto, dydžio, tokių pačių tarpų tarp raidžių, kaip ir pagrindinė/pirmoji?

Lauksiu jūsų nuomonės.

Pastatų tipifikavimas

Smulkiuose masteliuose nesinori pastatų visai išimti iš žemėlapio, bet jei pastatus tiesiog braižysime tokius, kaip yra, gausime atsitiktinį „smėlį“:

Negeneralizuoti pastatai smulkiame mastelyje virsta „smėliu“

Norėdami šito išvengti, turime pastatus generalizuoti. Pradžioje pastatus reikia supaprastinti (sumažinti kraštinių skaičių paliekant pagrindines/charakteringas). Antras pastatų generalizavimo etapas – tipifikacija. Žemiau aprašysiu tipifikacijos eksperimento, naudojant atvirą PostGIS sistemą, trumpą aprašymą.

Imame paprastą apibrėžimą: tipifikuoti – imti pastatų centrą ir jame braižyti minimalaus tinkamo dydžio kvadratą, orientuojant jį į artimiausią kelią. T.y. paprastam eksperimentui ignoruosiu pastatų pasiskirstymą, išdėstymo šablonus ir pan.

Mastelyje n pastatus, kurių plotas didesnis už kritinę ribą p, supaprastiname, o visus likusius – tipifikuojame. Tipifikavimo seka: iteruojame per pastatus, pradedant nuo didžiausio. Jei pastato centroide nubraižytas minimalus kvadratas yra toliau nuo kitų jau apdorotų (supaprastintų ar tipifikuotų didesnių) pastatų, tai pastato kvadratą braižome, priešingu atveju pastatas išmetamas (nebraižomas mastelyje n).

Pastatų generalizavimas (20m)

Aukščiau pateiktoje iliustracijoje štrichuoti – originalūs pastatai, geltoni – supaprastinti (paliekant tik kraštines, ilgesnes nei 20m), violetiniai – tipifikuoti pastatai.

Kažkur ties 40m jau pasiekiame lyg ir ribą, nes kai kurie tipifikuoti pastatai tampa net labiau išraiškingi už realybėje didesnius pastatus:

Pastatų generalizavimas (40m)

Toliau lieka žaisti su parametrais:

  • supaprastinimo/tipifikavimo riba konkrečiame norimame mastelyje (ši riba, panašu, turi būti gerokai didesnė už mastelyje matomą taško dydį),
  • minimaliu atstumu tarp pastatų.

Dar viena ne iki galo aiški detalė – kokius reikia naudoti kelius tipifikuotų pastatų orientavimui. Pradinė mintis lyg ir būtų naudoti kelius, kurie rodomi atitinkamame mastelyje, ir tai dažniausiai veikia, bet yra ir išimtinių atvejų, tarkime jei kelias eina iki sodybos su keliais pastatais, jei pastatus orientuosime į šio kelio galą, gausime nelabai teisybę atspindintį išsidėstymą puslankiu.

Pirmame įrašo paveiksle pateiktas pastatų „smėlis“ virsta tokiais simboliais, kurie turėtų aiškiau rodyti, kad čia yra atskiri pastatai:

Tipifikuoti pastatai

Šiuo principu tipifikuotus pastatus rasite atvirame Lietuvos topografiniame žemėlapyje: https://topo.openmap.lt

Vandens telkinių etiketės (I etapas)

Jau buvo nemažai galvota ir rašyta apie vandens telkinių etiketes. Iš pradžių buvo svarstytas variantas tiesiog skaičiuoti centro liniją, bet taip gali būti rasta vieta etiketei, kur tekstas fiziškai netelpa (pavyzdžiui siauroje vandens telkinio vietoje), taipogi vien centro linijos skaičiavimas nenurodo, kokio dydžio šriftą galima naudoti. Stambiame mastelyje vandens telkinių etikečių reikia daugiau, kad būtų didesnė tikimybė matomoje žemėlapio dalyje matyti ir ežero ar tvenkinio pavadinimą. Taigi reikėjo kitokio sprendimo, kurio bendras principas buvo aprašytas atskirame įraše. Šiame įraše bus aprašytas praktinis etikečių skaičiavimo įgyvendinimas. Tiksliau jo pirma dalis.

Sunkiausia dalis yra sudėlioti etiketes sudėtingos geometrijos poligonuose, t.y. telkiniuose, turinčiuose ne vienos ištisos „dešrelės“, o sudėtingesnes formas: X, Y, E ar tiesiog vizualiai kai kuriuose masteliuose turinčius kelias atskiras dalis. Ir sunkiausia yra ne sugalvoti algoritmą, o iš principo aprašyti, kaip kada kur ir kiek turi būti etikečių. Taigi pagrindiniai klausimai yra kartografiniai, o ne programavimo.

Sausio pradžioje buvo gauta daug naudingų patarimų ir pasiūlymų iš Lietuvos kartografų. Dauguma jų buvo būtent apie sudėtingesnes etiketes (sudėtingos formos vandens telkiniams), tai pirmame etape patarimų panaudota nedaug, bet jų labai prireiks II etape.

Pirmame etape sukurtas algoritmas, skaičiuojantis etiketes paprastesnės formos ežerams. Absoliuti dauguma ežerų yra būtent tokie, ir dabartinis algoritmas dažniausiai duoda visai neblogą rezultatą.

I etapo rezultatai

Etiketės gali būti braižomos arba taške (horizontaliai), arba palei liniją. Kiekviena etiketė turi ir būtent jai paskaičiuotą šrifto dydį ir tarpą tarp raidžių. Etiketės skaičiuojamos kiekvienam masteliui atskirai. Vienas mastelis vienam telkiniui gali turėti vieną ar daugiau etikečių (paprastai stambiuose masteliuose, kur vienu metu matoma tik dalis ežero ar tvenkinio).

Skaičiavimas vyksta kiekvienam telkiniui atskirai. Pradedama nuo stambiausio mastelio. Patikrinama, ar vandens telkinyje telpa pavadinimas dideliu šriftu ir gal net keliose vietose. Jei taip – tam masteliui sukuriama viena ar daugiau
tokių stambių etikečių.

Kai didelės etiketės nebetelpa, bandoma skaičiuoti pagal formą išlenktas etiketes. Pradžioje bandoma sukurti didelę etiketę (30pt dydžio), jei tokia netelpa – bandoma kurti mažesnę etiketę. Bandoma tol, kol arba randama etiketės pozicija, arba nustatoma, kad net mažiausiam parinktam šrifto dydžiui etiketė netelpa.

Pagal ežero formą nubraižyta etiketė

https://topo.openmap.lt/#t/13/55.04815/25.55899/0/0/

Jei etiketės linija yra ilga, tai ji dalinama į dalis, kad vandens telkinys turėtų daugiau nei vieną etiketę ir žemėlapyje vaizduojant skirtingas telkinio dalis padidėtų tikimybė, kad bus rodoma ir etiketė.

Priklausomai nuo to, kokio ilgio gavosi etiketei skirta linija ir koks yra vandens telkinio pavadinimas, paskaičiuojama, kokie bus tarpai tarp raidžių.

Kai etiketės linija trumpa, tarp raidžių paliekami mažesni tarpai.

https://topo.openmap.lt/#t/14/55.30602/25.5749/0/0/

Jei ežeras per mažas, kad jame tilptų pagal formą išlankstyta etiketė, bet jis pakankamai didelis konkrečiame mastelyje – braižoma taškinė (horizontali) etiketė.

Pastebėtina, kad etiketės skaičiuojamos atskirai kiekvienam vandens telkiniui, atskirai kiekvienam masteliui. Taigi viename mastelyje greta vienas kito gali būti ežerai su skirtingo šrifto dydžio ir skirtingų tarpų tarp raidžių etiketėmis.

Skirtingo šrifto dydžio, skirtingų tarpų tarp raidžių ir net skirtingo tipo etiketės (Želvykščio ežero etiketė horizontali).

https://topo.openmap.lt/#t/14/55.3109/25.55123/0/0/

Net ir tokie pirmo etapo rezultatai nėra baigti, nes skaičiavime dalyvauja apie dešimt koeficientų, nuo kurių priklauso tiek teksto parametrai, tiek linijos geometrija, atstumas iki kranto ir kokio dydžio vidiniai objektai (salos, iškyšuliai) yra ignoruojami. Dauguma šių parametrų yra susiję tarpusavyje, todėl pareguliavus vieną tenka reguliuoti ir kitus. Šio teksto rašymo metu topo.openmap.lt žemėlapyje matomas gal 30 iteracijos rezultatas, bet net ir dabar naršant po žemėlapį randamos probleminės vietos, kurios sprendžiamos ir toliau keičiant koeficientų reikšmes.

Etiketės skirtos žemėlapiui, kuris gali būti pasukamas, todėl skaičiuojant etikečių linijas nebuvo teikiamas pirmumas gauti horizontalią etiketę.

Taipogi gali pasirodyti, kad sudėtingesnes etiketes galima būtų tiesiog nubraižyti rankomis ir vėliau naudoti, juk vandens telkinių geometrija keičiasi ypatingai retai. Bet tai jau būtų per daug paprasta, todėl viską stengiamasi padaryti išskirtinai tik algoritmo pagalba. Papildoma nauda – kai skaičiuoja algoritmas, visada aišku, kodėl konkreti etiketė buvo paskaičiuota taip, o ne kitaip, t.y. visada galima aiškiai pasakyti, kokiais kriterijais buvo vadovaujamasi.

Vienintelė vieta, kur buvo pritaikyti specifiniai veiksmai, tai Kuršių marios, kurių geometrija buvo apkarpyta pagal Lietuvos sienas, kad etiketė būtų Lietuvos viduje.

Kurių marių geometrija buvo apkarpyta, kad etiketės pozicija būtų paskaičiuota Lietuvoje.

https://topo.openmap.lt/#t/10/55.41769/21.19452/0/0/

Tai tiek apie pirmą etapą. Detalesnis techninis etikečių skaičiavimo algoritmo aprašymas (pastoviai kintantis) yra atviro žemėlapio githubo wikyje. Ten pat rasite ir etikečių skaičiavimo kodą. Viskas parašyta naudojant atviras technologijas – PostgreSQL+PostGIS – kad kiek galima daugiau projektų galėtų pasinaudoti rezultatais. Etikečių braižymo informacija greitai turėtų atsirasti ir Lietuvos OpenStreetMap shape duomenų svetainėje, kad norintys galėtų panaudoti tokias etiketes kurdami savo žemėlapius su QGIS ar kita GIS programine įranga.

Vandens telkinių etiketės

Prieš daugiau nei pusmetį buvo rašyta apie vieną iš variantų, kaip skaičiuoti vandens telkinių etikečių pozicijas. Tąkart aprašytas metodas gan paprastas, bet yra dvi problemos, kurių centro linijos sprendimas nesprendžia: etikečių šrifto dydis ir tarpai tarp raidžių. Centro linija gali puikiai praeiti pro siauriausią ežero vietą ir parinkti ją etiketei, kai kur nors toliau nuo centro yra platesnė ežero dalis, tinkama etiketei su didesniu šriftu.

Gerą mintį davė pagal OpenStreetMap duomenis kuriamo OpenTopoMap kūrėjai. Jie ežerų etiketėms sugalvojo naudoti „stačiakampių metodą“. Jie irgi pradėjo nuo centro linijų skaičiavimų, bet visgi pasirinko kvadratų metodą. Tai puikus variantas ir, nors OpenTopoMap jį panaudojo tik etiketės pozicijos paieškai, jį galima pritaikyti ir šrifto dydžio bei tarpo tarp raidžių nustatymui. Toliau skaityti „Vandens telkinių etiketės“

Pastatų generalizavimas

Yra daug pastatų generalizavimo operacijų, daug operacijų parametrų parinkimo variantų, daug operacijų atlikimo sekų variantų. Kol kas nepastebėjau, kad kas nors būtų radęs vieną teisingą variantą, tinkantį visoms situacijoms: skirtingiems masteliams ir skirtingo tankio ir/ar geometrijos pastatams (pvz. tankiai užstatytiems senamiesčiams, retai užstatytiems sodams ir dar rečiau užstatytoms laukų sodyboms).

Aprašysiu bandymus parinkti tinkamus parametrus generalizuojant pastatus 12 masteliui (kur 1 taško plotis yra ~40m). Tikiuosi, kad radus parametrų reikšmes (o tikriausiai ir patvarkius pačią generalizavimo seką), bus galima atitinkamai išdėlioti generalizaciją ir stambesniems masteliams. Toliau skaityti „Pastatų generalizavimas“