Kelių koncentracija

Prieš mėnesį buvo rašyta apie kelių klasifikacijos reikšmę kartografijoje ir apie automatinius tikrinimus. Buvo identifikuotos trys problemos:

  • Pasimetę (neprijungti) keliai
  • Per aukšta klasifikacija
  • Per žema klasifikacija

Tada buvo pateiktas pirmos problemos (pasimetusių kelių) sprendimas. Dabar kilo mintis, kaip spręsti antrąją problemą (per aukšta klasifikacija). Gan paprastas (nors ir neidealus) pasirodė toks sprendimas:

  • Daliname Lietuvą į tokio paties dydžio segmentus
  • Kiekviename segmente skaičiuojame kelių ilgius
  • Tikriname didžiausius ilgius turinčius segmentus

Gaunasi visai neblogas rezultatas, kuo raudonesnis segmentas, tuo didesnė jo kelių koncentracija:

Lietuvos kelių koncentracija

Ir priartinta viena iš koncentracijų:

Priartinta kelių koncentracija

Kaip matome, aptinkamos kelių koncentracijos. Sutvarkius didžiausias koncentracijas iškyla neteisingai aptiktos problemos (angl. false positive), t.y. didžiųjų miestų keliai. Bandžiau žaisti su skirtingais segmentų dydžiais, skirtingų klasifikacijų kelių svoriais, skaičiuojant koncentraciją segmente, bet, matyt, teisingesnis sprendimas būtų panaudoti Statistikos departamento turimas gyventojų koncentracijas ir pagal tai koreguoti kelių ilgį. T.y. kuo didesnė gyventojų koncentracija, tuo didesnė gali būti ir kelių koncentracija. Na bet šitą paliksime ateičiai. Kol kas naudinga tiek, kiek identifikuoja paprastas algoritmas 🙂

Kai kurios koncentracijos gali būti neaptinkamos, jei segmentai dengia tik jų dalį. Šitą problemą galima būtų spręsti kuriant persidengiančius segmentus.

Paskutinę problemą – per žemą klasifikaciją – gal būtų galima spręsti darant maršrutizavimo testus, bet yra daug variantų, kur tiesiog kelių grafo analizė negali duoti teisingo sprendimo. Tarkim būna, kad yra kokia nors įmonės/gyvenvietės teritorija ir greta jos tolimesniu keliu eina apvažiavimas, kuris ir turi turėti aukštesnę klasifikaciją, nes būtent apvažiavimu turėtų važiuoti transportas. Panašu, kad tokių dalykų neįmanoma spręsti be ortofotografijos ir vietos žinių…

Share

Lietuvos dviračių žemėlapis

Prieš kokius penkis metus buvo sukurtas atviras Lietuvos dviračių žemėlapis. Per tą laiką technologijos stipriai pasikeitė, tai atėjo laikas šį žemėlapį perdaryti. Taigi pristatome atnaujintą žemėlapį:

Lietuvos dviračių žemėlapis

Žemėlapis turi du lygiaverčius adresus:

Žemėlapio pagrindui sukurta į akis per daug nekrentanti šviesi tema, kur spalvas „gavo“ tik vanduo ir miškas – lengvesniam orientavimuisi. Ryškios spalvos skirtos tik esminiams žemėlapio duomenims – dviračių infrastruktūrai. Ką reiškia kiekviena spalva ar ženkliukas rasite sutartiniuose ženkluose (apačioje dešinėje):

Sutartiniai ženklai

Po sutartiniais ženklais rasite nuorodą į techninį aprašymą, kaip reikia žymėti objektus atvirajame žemėlapyje.

Žemėlapio pildymas

Šiandien Lietuvoje yra ne vienas dviračių žemėlapis. Visų jų pagrindinė problema – atnaujinimas. Jie padaromi kažkokiu metu x ir pamirštami – duomenys neatnaujinami, todėl juos ilgainiui pamiršta ir naudotojai.

Todėl šitas atviras žemėlapis turi šansų neturėti pamiršimo problemos, nes pildyti gali bet kas. Taigi pildykite žemėlapį, jei turite klausimų – klauskite sąrašyne talk-lt. Jei nenorite redaguoti žemėlapio – registruokite pastabas (OSM Notes). Svarbiausia – ne techninė žemėlapio realizacija, o žemėlapio duomenų rinkimas ir atnaujinimas!

Share

Kelių hierarchija

Tai gan techninis straipsnis apie kelių hierarchiją ir jos panaudojimą kartografijoje.

Kelių hierarchija

Straipsnio tikslas yra pasiaiškinti skirtumą tarp highway=unclassified ir highway=residential kelių, kaip reikia žymėti ir kokią tai daro įtaką. Pagrindinį dėmesį šį kartą skiriu kartografijai (žemėlapių braižymui), bet realiai tai gali turėti įtakos ir maršrutizavimui.

Kai mes braižome smulkaus mastelio žemėlapį (tarkime kai matoma visa Lietuva), mes norime braižyti tik pačius svarbiausius kelius. Jei nubraižytumėme visus visus kelius, įskaitant ir privažiavimus, tai gautume didžiulę makalynę (aš jau net nekalbu apie greitaveiką). Kai stambiname mastelį (pritraukiame artyn), tik tada norime, kad atsirastų vis daugiau ir daugiau kelių (pirmiau turi pasirodyti svarbesni keliai). Taigi smulkiausiame mastelyje norime automagistralių, arčiau norime ir krašto kelių, dar arčiau ir gyvenamųjų gatvių, o visai priartinę norime net ir šaligatvių. Tokia kelių hierarchijos prasmė braižant žemėlapį.

Šiuo metu visi žemėlapiai naudoja kelių hierarchiją… išskyrus „šuolį“ prieš atsirandant smulkesniems keliams už krašto kelius. T.y. kai jau atsiranda, atsiranda iš karto ir highway=unclassified, ir highway=residential keliai. Vienu masteliu aukščiau turime vaizdą, kur yra dideli plotai be kelių. Štai pvz. žinomiausias/matomiausias OpenStreetMap stilius „Carto“:

Atkreipkite dėmesį į tuštumą (kelių atžvilgiu) tarp 102 ir 103 kelių. Matosi tik Plytinės ir Kairėnų gatvės, nes jos pažymėtos highway=secondary.

Mapbox Streets stiliuje dar blogiau: ten, net dar labiau „priartinus“, vis tiek matosi tik labai svarbūs keliai, didžiuliai plotai neturi kelių susisiekimo:

Kodėl taip yra? Todėl, kad nors wiki ir yra aprašytas skirtumas tarp residential ir unclassified kelių – jis yra prastai suprantamas, todėl šie du kelių tipai yra dažnai painiojami. Taigi žemėlapių gamintojai šiuos du tipus laiko lygiaverčiais (dar galima būtų ir trečią tipą pridėti – pakankamai vėlai atsiradusį living_street).

Kadangi residential keliai gyvenamosiose vietovėse nutiesti gan tankiai, štai pavyzdys, kaip panašiame mastelyje atrodo nubraižyti ir unclassified, ir residential keliai:

Kelių yra tikrai per daug, jie susimala į vieną masę. Todėl tokie keliai ir nerodomi žemėlapiuose, kol pakankamai „nepriartinama“. Todėl ir turime tokį „šuolį“.

O kas būtų, jei mes sutvarkytume residential ir unclassified duomenis taip, kaip aprašyta wiki? Pagal wiki žymėjimas turėtų būti toks:

  • unclassified – jungiamasis kelias (jungiantis kelias gyvenvietes ar vieną gyvenvietę prie pagrindinio kelių tinklo). Tai yra kelias, viena klase žemesnis už highway=tertiary. Nereikia baimintis pavadinimo „unclassified“ (wiki sako, kad pavadinimas istoriškai atėjo iš Didžiosios Britanijos), tai nėra nežinomas, neaiškus, nereikšmingas kelias, greičiau priešingai. Taip pat tai nėra kelias, kurio klasifikacijos žymėtojas tiesiog nežino (tam skirtas highway=road).
  • residential – nejungiamasis kelias, tiesiog leidžiantis privažiuoti prie reikiamos vietos. Vieta nebūtinai turi būti gyvenamoji, tai gali būti ir privažiavimas prie komercinės ar pramoninės zonos.

Taip sutvarkę duomenis galėtume užpildyti šią skylę – prieš rodydami residential kelius, galėtume rodyti vien unclassified kelius, kurių funkcija (pagal wiki) yra žymėti jungiamuosius kelius, kurie neturi valstybinės klasifikacijos (t.y. neturi kelio numerio, rodomo kelio ženkluose).

Tada žemėlapis (tokiame pačiame mastelyje kaip aukščiau rodytas OSM Carto) atrodo jau taip:

Atsiranda pakankamai jungiamųjų kelių ir tuo pačiu metu žemėlapis neužteršiamas didžiuliu kiekiu gyvenamųjų kelių (jie atsiranda vienu lygiu toliau).

Duomenų tvarkymas

Tai, ką aprašiau aukščiau, nėra kažkoks kartografinis stebuklas. Problema ne kartografijoje, o duomenyse. Kol duomenys netvarkingi, gauname betvarkę. Štai pavyzdys, kaip atrodo nesutvarkyta vieta:

Matome tokias problemines vietas:

  • „pasimetę“ keliai – neprijungti prie bendro kelių tinklo (virš Laistų ir Jakų)
  • neesminės atšakos – ne jungiamieji, o prie konkrečių sodybų vedantys trumpi keliai (aplink Kiškėnus)
  • smulkūs keliai – smulkūs keliai, kurie nėra jungiamieji (prieplauka į Vakarus nuo Laistų)

Tokiame smulkiame mastelyje nepatogu ieškoti klaidų. Kviečiame į pagalbą PostGIS ir QGIS. Sujungiame visus kelius su klasifikacija unclassified ir aukštesnius į vieną tinklą, raudonai pažymėti tie, kurie prie tinklo neprijungti, pilkai – žemesnės klasifikacijos keliai (residential ir living_street):

Kaip matome, puikiai išsiskiria „pasimetę“ keliai. Jų aptikimas visiškai automatinis, kas yra puiku, nes būtent automatinis tikrinimas ir yra vienintelis būdas užtikrintai spręsti kelių klasifikavimo problemą.

Bet matome ir dviejų kitų tipų problemų: yra smulkūs nejungiamieji keliai, pažymėti žaliai – reiškia jie pažymėti unclassified, o ne residential. Taip pat matome trūkstamas jungtis – Moliakalnio g. turėtų būti pakeista į unclassified, nes iš viršaus ateina kelias, jungiantis šią gyvenvietę su kita stambesne gyvenviete.

Vat antra ir trečia klaidos ir yra labiausiai probleminės, nes ne tik kad nesugalvoju, kaip parašyti automatinį algoritmą tokių klaidų aptikimui, bet net ir negaliu sugalvoti, pagal kokius objektyvius kriterijus tai turėtų būti sprendžiama…

Share

Lietuvos upių baseinai

Atvirąjį žemėlapį galima naudoti ne tik lankytinų vietų ar kelio iki jų paieškai. Atvirojo žemėlapio duomenis galima naudoti ir darant įvairius skaičiavimus. Pabandykime paskaičiuoti Lietuvos upių baseinus.

Skaičiavimui imsime upių ir upeliukų duomenis, tada nurodysime upių žemupius, nuo kurių reikės „lipti“ aukštyn upe, užeinant į visus intakus. Skaičiuojant „grynus“ baseinus, Lietuvoje gausime gan neįdomų vaizdelį – ~80% Lietuvos užima Nemuno baseinas. Todėl paskaičiuosime ir kelis Nemuno intakų baseinus: Neries, Šventosios, Nevėžio ir Merkio. Tada jau gauname spalvingesni/įdomesnį rezultatą:

Upių baseinai

Skaičiavimas

Skaičiavimui naudojama PostGIS funkcija st_touches, randanti objektus, kurie liečia nurodytą objektą, ir senas geras „bangos“ principas, paprastai taikomas trumpiausio kelio iš labirinto paieškai.

Galima pastebėti, kad jei imtume ir kanalus, tai Ventos-Dubysos kanalo pagalba Nemunas „užgrobtų“ ir Ventą, na arba atvirkščiai 🙂 Na, bet kanalų mes neimame, nes skaičiuojame tik natūralius vandens kelius, taigi du skirtingi baseinai niekaip negali susijungti.

Probleminės vietos – už Lietuvos ribų išeinančios upės: Šventoji (ta kuri į Nemuną įteka), Mūša, Nemunėlis ir kitos. Galimi du sprendimo variantai:

  1. Tarkime nuo Mūšos (einant upe aukštyn) dar Latvijos pusėje atsiskiria daug kitų upių, kurios prasideda Lietuvoje. Galime visas tokias Mūšos baseino upes „surinkti“ ties Lietuvos siena ir iš karto priskirti Mūsos baseinui (darant „standartinį“ skaičiavimą upės baseiną pradedame nuo vienos atkarpos, o Mūšos atveju pradėsime nuo kelių atkarpų).
  2. Šventoji į Nemuną įteka iš Karaliaučiaus pusės, nors prasideda Lietuvoje. Galima atskirai atsisiųsti Šventosios atkarpos Karaliaučiuje duomenis ir juos rankiniu būdu susidėti į duombazę, kad atstatytume pilną upės trajektoriją (daroma prielaida, kad skaičiuojame naudodami tik Lietuvos duomenis)

Kam viso to reikia?

Toks skaičiavimas vizualizuoja kur yra kokie baseinai. Tada mes galime geriau įsivaizduoti, kad būdami 80% Lietuvos teritorijos, į upę paleidę žaislinį laivelį, jį vėliau sutiksime Rusnėje (žinoma jei jis stebuklingai peršoks visas užtvankas).

Kitas dalykas, taip mes patikriname OpenStreetMap duomenis. Jei kažkokios upės kelių atkarpos lieka nepriskirtos jokiam baseinui – reiškia yra duomenų klaidų. Gal griovys neteisingai pažymėtas kaip upeliukas, gal trūksta kažkokios upės atkarpos, gal nėra nupaišytas vandens kelias per vandens telkinius (ežerus, tvenkinius). Vizualiai klaidos atrodo taip:

Upių baseinų klaidos

Kelias per ežerus ir tvenkinius? Kam? Ogi tam, kad vėliau būtų galima daryti maršrutizavimą upėmis. Netolimuose planuose yra upių žemėlapis, kuriame būtų galima skaičiuoti baidarių, laivų, plaustų ar kokių kitų neskęstančių plaukimo priemonių maršrutą. Tam reikia, kad upių duomenys būtų teisingi, kaip kelių duomenys.

Išeities failai

Jei kas norite pabandyti patys paskaičiuoti upių baseinus, ar turite minčių, ką dar galima padaryti su tokiais skaičiavimais, susiimportuokite Lietuvos duomenis į PostgreSQL su PostGIS ir tada naudokite šiuos skriptus:

  • table.sql – pagrindinė lentelė, kurioje laikomi upių segmentų duomenys
  • sesupe.sql – Šešupės duomenys (realiai einant upe aukštyn Šešupė Lietuvoje „pasirodo“ viename taške, tai šis importas nėra būtinas, tiesiog išbandytas principas)
  • excess.sql – pertekliniai segmentai (palei sieną arba kai kurie oficialiai neregistruoti „upeliukai“, nesusijungiantys su bendru upių tinklu)
  • touch.sql – vieno bangos žingsnio skaičiavimo funkcija
  • process.sql – pagrindinė upių baseino skaičiavimo funkcija
  • upiu_baseinai.qgs – QGIS projektas rezultatų peržiūrai

Paleidimas:

psql gis < table.sql
psql gis < touch.sql
psql gis < excess.sql
psql gis < sesupe.sql
psql gis < process.sql

Ir tada QGIS’e atsidarote projekto failą upiu_baseinai.qgs. Projekte tikimasi, kad db yra localhost su standartiniu prievadu (portu) ir naudotoju gis be slaptažodžio. Jei pas jus kitokie nustatymai – pataisykite .qgs projekto failą rankomis (tai paprastas xml failas).

Tai teik su vandeniu, o algoritmą panaudosime ir kitiems tikslams… 🙂

Share

Topologijos taisyklės

Plotai su „skylėmis“

OpenStreetMap žymėtojai dažnai klausia, ką daryti, kai turime parkelį, sudarytą iš miško ir jo viduryje esančios pievos. Kaip juos teisingai pažymėti?

Tokiu atveju OpenStreetMap tikėtina turėsime du kelius: A – išorinis perimetras, B – vidinės pievos perimetras:

Jei išorinį kelią A pažymėsime tiesiog landuse=forest, o vidinį – landuse=meadow, gausime tokius geografinius objektus:

Kaip matome, miškas neturi iškirpimo. Taigi jei skaičiuosime miško plotą – gausime neteisingą rezultatą. Kuriant žemėlapį reikės pievos plotą (apskritimą) paišyti vėliau (aukščiau) už miško plotą (stačiakampį), jei norėsime, kad pieva matytųsi. Kadangi realiame žemėlapyje bus daug panašių objektų, tai vienoje vietoje „iškirpimas“ bus pieva, kitoje – miškas, trečioje vanduo, ketvirtoje ežero sala. Taigi net teoriškai neegzistuos tokia braižymo tvarka, kuri užtikrintų teisingą objektų vaizdavimą. Vienu atveju nesimatys miškai, kitu – pievos, vienu atveju nesimatys ežero salos, kitu atveju – maži ežeriukai miškuose.

Sprendimas yra sukurti multipoligoną (ryšį), kuriame A kelią nurodytume kaip „outer“ kelią, o B – kaip „inner“. Tokiu atveju gautume trečią geografinį objektą:

Gavome objektą su „išpjova“. Būtent toks ir yra miškas. Turint tokį mišką mums ir ploto skaičiavimai gausis teisingi, ir nereikės rūpintis, ką braižyti pirmą – mišką ar pievą – visada gausime teisingą rezultatą, nes figūros viena su kita nepersidengia.

Galutinis objektų sąrašas turėtų būti toks:

  • C – miško multipoligonas (landuse=forest), sudarytas iš A kaip „outer“ ir B kaip „inner“.
  • B – pievos poligonas (landues=meadow) – kelias B
  • A – parko poligonas (leisure=park) – išorinis kelias. Parkas yra viskas: ir miškas, ir pieva. Braižant žemėlapį parkas yra „virš“ visko. T.y. apačioje braižome miško/medžių ir pievos/žolės plotus, o tada virš jų, jei to reikia žemėlapiui, paišome permatomą „parko“ plotą arba tiesiog parko pavadinimą, dengiantį tiek miško, tiek pievos dalis.

Puiku. Bet ne visi žino, kad taip reikia žymėti. Ką daryti? Sukurti ir naudoti Topologijos taisykles, kurios šiuo konkrečiu atveju nurodytų, kad miško ir pievos poligonai negali persidengti.

Kas yra topologijos taisyklės?

Topologijos taisyklės apibrėžia santykį tarp skirtingų objektų geografinėje informacinėje sistemoje. Tarkime viena taisyklė gali nurodyti, kad miško poligonai negali persidengti vienas su kitu. Kita taisyklė gali nurodyti, kad miško poligonas negali persidengti su vandens poligonu. Dar kita taisyklė – kad miesto X adreso taškai turi būti miesto X administracinėse ribose.

Daugiau principinių topologijos taisyklių pavyzdžių galite rasti ESRI Topologijos taisyklių brošiūroje.

Kam reikalingos topologijos taisyklės

Apibrėžus topologijos taisykles ir jų laikantis, geografinė duomenų bazė tampa tvarkingesne. Kuriant ar keičiant duomenis aiškiau, kaip reikia teisingai braižyti. Prisiminus aukščiau aprašytą parko pavyzdį, apibrėžus taisyklę, kad miškas ir pieva negali persidengti, pasidaro aišku, kad neužteks nupaišyti pievą vidury miško, reikia tokį patį plotą „iškirpti“ iš miško.

Laikantis tokių taisyklių palengvinamas ir kartografų darbas. Jei pagal aukščiau apibrėžtą pavyzdį pievos plotas bus iškirptas iš miško, kartografui nereikės rūpintis, ką paišyti pirmiau/žemiau – mišką ar pievą. Nors šiuo konkrečiu atveju atrodytų, kad paišykime mišką žemiau, tada virš jo pievą ir viskas bus gerai, bet kas bus, jei turėsime analogišką situaciją, tik dabar jau turėsime mažą miškiuką didelėje pievoje? Jei nedarysime pievos iškirpimo pagal miško plotą, galutiniame žemėlapyje miškas nesimatys.

Nepamirškime ir plotų skaičiavimo. Tarkime norime paskaičiuoti bendrą miškų plotą. Jei pievos ar kiti miško viduje esantys plotai nebus „iškirpti“ – mes gausime neteisingą suminį plotą (bus įskaičiuotas ir pievų plotas). Susumavę visus Lietuvos miškus, pievas, gyvenamuosius plotus, vandenį ir t.t. ir pan. mes gausime didesnį skaičių nei bendras Lietuvos plotas!

OpenStreetMap

Atvirame žemėlapyje duomenims yra suteikiama labai didelė laisvė. Žymėtojai patys gali susigalvoti norimas žymas, jų reikšmes. Taip pat nėra apibrėžtos (bent jau kol kas) ir topologijos taisyklės. Taigi kas kaip sugalvoja, tas taip ir braižo. Tokia anarchija nors ir padaro braižymą lengvesniu, bet užtat tokių duomenų naudojimas yra sudėtingesnis.

Taigi kol kas yra apibrėžiamos tik regioninės topologijos taisyklės. Pavyzdžiui Lietuvoje yra apibrėžtos kelios topologijos taisyklės. Bendras jų veikimo procesas yra toks:

  1. Topologijos taisyklė yra suformuluojama, pasiūloma ir aptariama.
  2. Topologijos taisyklė patvirtinama, vykdoma taisyklės neatitinkančių objektų paieška, taisomos problemos ir tuo pačiu tikrinama, ar visur taisyklės taikymas yra logiškas. Jei kažkur taikymas nelogiškas – taisyklė arba taisoma, arba jos atsisakoma apskritai.
  3. Jei pavyksta ištaisyti visas topologijos taisyklės klaidas, taisyklė įjungiama į „stebėjimo režimą“. Tai reiškia, kad periodiškai (kasdien) yra patikrinama, ar naujai įvesti ar pakeisti objektai atitinka taisyklės reikalavimus.

Tai tiek bendros informacijos apie topologijos taisykles. Žinokite, kad toks dalykas yra, rašykite į sąrašyną (talk-lt) naujų taisyklių kūrimo ar esamų keitimo pasiūlymus!

Share