Ruošiant duomenis smulkesniems masteliams, prireikia generalizavimo algoritmų. Linijoms paprastai naudojami Douglas–Peucker bei Visvalingam–Whyatt algoritmai. Deja tai matematiniai/geometriniai algoritmai, neatsižvelgiantys į kartografinius reikalavimus.
Wang–Müller algoritmas būtent ir siekia (natūralių objektų) linijas generalizuoti atsižvelgiant į kartografinius reikalavimus, tokius kaip charakteringų savybių išsaugojimas ar net paryškinimas.
Originalus Wang–Müller mokslinis straipsnis algoritmą aprašo labai aptakiai, kadangi nėra atviro kodo šio algoritmo realizacijos, ne tik neįmanoma šio algoritmo panaudoti plačiai, bet ir kyla daug klausimų, kaip veikia ar turėtų veikti kai kurios šio algoritmo vietos.
Vilniaus Universiteto studentas Motiejus Jakštys atliko puikų darbą – ne tik realizavo pagrindinę Wang–Müller algoritmo dalį atviromis technologijomis, bet ir daug detaliau aprašė algoritmą savo moksliniame darbe, kurį visi galite rasti čia:
Darbe rasite algoritmo aprašymą, rekomendacijas algoritmo parametrų reikšmėms skirtingiems masteliams, daugybę iliustracijų ir pasiūlymų, ką toliau reikėtų daryti, norint užbaigti šio algoritmo atvirą įgyvendinimą, kad jį galėtų naudoti visi norintys.
Artimiausiu metu Motiejaus sukurtas algoritmas keliaus į Atvirojo žemėlapio repozitoriją, kur bus tęsiamas šio algoritmo vystymas.
Prieš kelis mėnesius twitteryje vienas iš QGIS programuotojų (Nyall Dawson) rado iliustraciją apie kartografiškai tvarkingą punktyrų braižymą. Per kelias valandas buvo identifikuota, kad tai žymioji Šveicarijos kartografų knyga apie generalizaciją (publikuojama SwissTopo). Šveicarai greitai suorganizavo Nyall’ui šią knygą ir prašom – jau turime pirmus vaisius QGIS’e!
Kai keliai žemėlapyje braižomi punktyrais, gali iškilti šiokių tokių nesklandumų. Tarkim jei kelio pradžioje pataikoma braižyti punktyro tarpą (t.y. nebraižyti nieko), žemėlapio skaitytojui gali kilti klausimas, ar čia punktyro braižymo specifika, ar šie keliai realybėje nėra sujungti?
Šiai problemai spręsti galime panaudoti pirmą iš dviejų naujų parinkčių – „Priderinti punktyro šabloną prie linijos ilgio“:
Ir tada QGIS „pritemps“ šabloną taip, kad linija baigtųsi braižoma punktyro dalimi:
Tušti punktyro segmentai gali kelti problemų ir ties aštriais kampais, kur gali kilti neaiškumų, kokia yra reali situacija ant žemės:
Panaudojus antrąją QGIS parinktį „Pataisyti punktyro šabloną aštriuose kampuose“, bus panaikinta ir ši dviprasmybė:
Taigi QGIS ir toliau tobulina kartografinį rezultatą.
Tik nepamirškite, kad tam, jog veiktų ši funkcija, kelius reikia padalinti ties susikirtimais.
Tikriausiai visi esate matę senovinius vandens simbolizavimo būdus – kai braižomos intervalais nuo kranto atitolusios linijos, primenančios bangas:
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:
Š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:
Viskas. Tokį stilių galite įsirašyti į dažnai naudojamų stilių sąrašą ir per sekundę parinkti kituose savo projektuose.
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:
Š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?
Kaip nusprendžiama, kad reikia antros etiketės ir kur ją reikėtų braižyti?
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?
Smulkiuose masteliuose nesinori pastatų visai išimti iš žemėlapio, bet jei pastatus tiesiog braižysime tokius, kaip yra, gausime atsitiktinį „smėlį“:
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).
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:
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:
Šiuo principu tipifikuotus pastatus rasite atvirame Lietuvos topografiniame žemėlapyje: https://topo.openmap.lt
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.
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ų.
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.
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.
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.
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”
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”