Kuidas uuest XGIS rakendusest geomeetria kätte saada

Käisin täna Lähte radadel suusatamas ja unustasin GPS'i maha. Ei ole veel nii moodne inimene, et telefonis Endomondot vms. sporditräkkerit kasutaksin (tegelikult teen nii harva sporti, et iga kord tuleb alles pärast pingutust meelde, et selleks on ju äppid). Enamasti träkin oma kulgemise GPS'iga ja pärast hea Garmin BaseCamp või muu analoogse tarkvaraga vaadata, kui pika maa maha uhasin ja kui kiirelt.

Täna siis suusatamas käidud kuid polnud aimugi kui pikalt suusatasin. Esimene mõte oli triviaalne: mõõdan mõnes kaardirakenduses käsitsi läbitud teekonna ära. Kuna Eesti Maa-amet avalikustas hiljuti kaasaegse(ma) versiooni oma XGIS nimelisest kaardirakendusest, siis tundus mõistlik valik seda kasutada.

Paneelilt Tegevused alt leidsin mõõtmise tööriistad ja joonistasin oma ringid kaardile. Ja tulemus: 10,2 km. Ah, käib küll, alguse asi.

Edasi tekkis ikkagi soov joonistatud geomeetria kuidagi kätte saada, et sporditegemise fakt säiliks ilmutatud kujul ning hooaja lõpus oleks hea võtta kõik GPX failid ja leida, kui palju kilomeetreid sai siis suusatatud. XGIS kaardilt geomeetriate eksportimist ei paku.

Õnneks on enamikel veebisirvijatel arendaja tööriistad.

  1. Avasin dev.tools (mac alt+cmd+c, windowsis F12)
  2. Valisin console tab'i. Veebikonsool on interaktiivne aken, mis kuvab veebilehe hoiatusi ja vigu ning lubab sisestada käsklusi. (Vt. lähemalt https://developer.mozilla.org/en-US/docs/Tools/Web_Console)

  3. Nüüd tekkis esimene kriitiline hetk. Kas XGIS on arendatud nii, et globaalselt saab rakendusele ligi? See on selline otsimine ja mõistatamine, sisestasin konsooli (käsud kinnita enter klahviga):

    console.log(window)
  4. Konsool prindib välja globaalse javascripti objekti, seal natuke ringi vaadates leidsin Dogis nimelise objekti ja sinna sisse vaadates oli selge, et tegu on XGIS rakenduse nn singleton'iga (http://www.dofactory.com/javascript/singleton-design-pattern). Leidsin paljulubava nimega funktsiooni Dogis.getMap. Proovime mis teeb:

    console.log(Dogis.getMap())

  1. ja voila! Tagastabki OpenLayers 2 kaardiolemi. Edasine vajab natuke OpenLayers'i API tundmist, et saada kätte joonistatud geomeetria. Mõõtmine on OpenLayers'i control, seega asusin kontrolle kontrollima:

    console.log(Dogis.getMap().controls)
  2. Konsool prindib välja kaardile laetud kontrollid, paraku nende hulgast mõõtmise kontrolli ei leidnud, küll aga kaks joonistamise oma. Üks joone joonistamise oma, teine pinna joonistamise oma. Kuna mõõta saab nii pikkusi kui pindalasid, siis oli lihtne järeldus, et XGIS arendajale ei piisanud mingil põhjusel OpenLayers'i mõõtmise kontrollist ja implementeeriti uued, joonistamise funktsionaalsuse abil. Joonistamise control'id:

    12: OpenLayers.Control.DrawFeature.OpenLayers.Class.initialize  
    13: OpenLayers.Control.DrawFeature.OpenLayers.Class.initialize
  3. Mina mõõtsin pikkust, seega tuli vaadata joone joonistamise kontrolli (massiivis võtmega 12) kaardikihi (layer) sisse:

    console.log(Dogis.getMap().controls[12].layer)
  4. Edasi leiame kas sellel kihil on kaardiobjekt (feature):

    console.log(Dogis.getMap().controls[12].layer.features)
  5. Tagastati massiiv pikkusega 1. Ehk sellel kihil on üks feature: Minu kaardile joonistatud joon. Et seda hiljem kasutada, salvestame ta muutujasse:

    var feature = Dogis.getMap().controls[12].layer.features[0];
  6. Kuna OpenLayers'i feature on (pseudo-)klassi olem ja seega ei ole eriti inimloetav ega tekstifaili kujul eksporditav, siis on vaja see teisendada mõnda üldtuntud vormingusse, valisin selleks GeoJSON vormingu. OpenLayers oskab GeoJSON'it lugeda ja kirjutada, selleks on vaja tekitada OpenLayers.Format.GeoJSON parseri olem:

    var format = new OpenLayers.Format.GeoJSON();
  7. Teisendame OpenLayers'i feature GeoJSON stringiks:

    format.write(feature);
  8. Olemas! Kopeeri tulemus tühja faili sisse ja talleta või vaata seda mõne GIS-tarkvaraga (QGIS).
  9. Üks asi veel: koordinaatsüsteem! GPS salvestab enamasti WGS'84 koordinaatsüsteemis koordinaadid, seega võiks ka minu suusatamise geomeetria olla samas süsteemis. Redefineerime parseri andes ette sisend- ja väljundprojektsioonid:

    var format = new OpenLayers.Format.GeoJSON({externalProjection: 'EPSG:4326', internalProjection: 'EPSG:3301'});
    format.write(feature);
  10. Ongi olemas suusatamise (ligikaudne) ruumikuju, mille pikkust saab hooaja lõpus statistikas arvestada.
  11. OpenLayers oskab ka GPX stringi genereerida, selleks saame luua GPX parseri:

    var format = new OpenLayers.Format.GPX({externalProjection: 'EPSG:4326', internalProjection: 'EPSG:3301'});
    format.write(feature);

Tulemus läbi geojson.io teenuse:

  • OpenLayers
  • hacking

Mihkel Oviir:2016-01-21
Generic placeholder image