Ekspor data OpenStreetMap menggunakan editor visual di rete.js

Dalam pekerjaan saya, saya sering menghadapi tugas mengekspor data dari OpenStreetMap. OSM adalah sumber data yang luar biasa dari mana Anda bisa mendapatkan setidaknya pemandangan , setidaknya wilayah kota , setidaknya jalan untuk studi aksesibilitas pejalan kaki , dan umumnya apa saja.


Itu hanya proses bekerja dengan mereka di beberapa titik mulai membuatku bosan. Untuk mengambil data untuk beberapa permintaan non-sepele, Anda harus mempelajari bahasa permintaan Abaikan, atau menulis skrip dan melihat-lihat dalam format XML OSM.


Melakukan manipulasi ini untuk keseratus kalinya, saya berpikir untuk membuat beberapa alat yang lebih sederhana dan lebih nyaman. Dan sekarang dia sudah siap - https://yourmaps.io , editor visual deskripsi ekspor OpenStreetMap. Di editor, Anda dapat mengarahkan mouse ke grafik, setiap node yang akan mewakili operasi atau filter pada aliran objek OSM, dan kemudian unduh hasilnya di GeoJSON.


Berikut adalah contoh grafik yang memilih semua sekolah di dalam distrik kota tertentu, dan kemudian membangun buffer 300 meter di sekitarnya:



Sebagai hasil dari pekerjaan, kami mendapatkan seperangkat poligon dalam format GeoJSON, yang kemudian dapat diimpor ke QGIS atau beberapa perangkat lunak lain.


— , Rete.js, -.


Rete.js


Rete.js — JS , . , .


, Rete . OpenStreetMap — .


gambar


(node), (component). , ( ). data, (, , )


Rete . : , ( ) .


, , , , - .


— , , ( ). , - , - jquery 220, . , .



InputControl Rete, .


var SelectComponent = {
    //  -  HTML ,       ,        this.root   
    template: '<select></select>',
    data() {
        return {
            value: ""
        };
    },
    methods: {
        update() {
            //        
            this.putData(this.ikey, $(this.root).val())
        }
    },
    //         
    mounted() {
        // this.root -  html ,    template, .. select   
        let jqueryRoot = $(this.root)
        //     
        for (let idx = 0; idx < this.values.length; ++idx) {
            let v = this.values[idx]
            jqueryRoot.append($("<option></option>")
                .attr("value", v[0])
                .text(v[1]));
        }
        //       -        ,  
        let currentVal = this.getData(this.ikey)
        if (currentVal === undefined) {
            currentVal = this.defaultValue
            this.putData(this.ikey, this.defaultValue)
        }
        jqueryRoot.val(currentVal);

        const _self = this;
        //          data
        jqueryRoot.change(function() {
            _self.root.update()
        })
    }
}
//          node.addControl(new SelectControl(...))
class SelectControl extends Rete.Control {
    constructor(emitter, key, values, defaultValue) {
        super(key);
        this.key = key;
        this.component = SelectComponent
        //          ,       
        this.props = { emitter, ikey: key, values: values, defaultValue: defaultValue};
    }
}

,
var AddTextFieldComponent = {
   //   -  ,        InputControl
    template: '<button type="button" class="btn btn-outline-light">' +
        '<i class="fa fa-plus-circle"></i>&nbsp;Add Value</button>',
    data() {
        return {
            value: ""
        };
    },
    methods: {
        //    ,    ,  InputControl,   id    
        getCount(node, prefix) {
            let count = 0;
            node.controls.forEach((value, key, map) => {
                if (key.startsWith(prefix) && value instanceof InputControl) {
                    ++count;
                }
            });

            return count;
        },
        //         ,     
        update(e) {
            let count = this.methods.getCount(this.node, this.prefix)
            this.node.addControl(new InputControl(this.editor, this.prefix + count))
            //     ,   Rete      
            this.node.update()
            this.emitter.view.updateConnections(this)
            //         ,      json  ,     
            this.putData(this.iKey, count + 1)
        }
    },
    mounted() {
        const _self = this;
        this.root.onclick = function(event) {
            _self.root.update()
        }
    }
};

class AddTextFieldControl extends Rete.Control {
    constructor(emitter, key, prefix, node, inputPlaceholder) {
        super(key);
        this.key = key;
        this.component = AddTextFieldComponent
        this.props = { emitter, iKey: key, prefix: prefix, node: node, inputPlaceholder: inputPlaceholder};
    }
}

class FilterByTagValueComponent extends Rete.Component {
    constructor(){
        super("Filter_by_Tag_Value");
    }

    builder(node) {
        //         ,       osm. 
        //     Rete  ,         
        var input = new Rete.Input('osm',"Map Data", osmSocket);
        var output = new Rete.Output('osm', "Filtered Map Data", osmSocket);
        //     
        var tagNameInput = new InputControl(this.editor, 'tag_name')
        //       
        var  modeControl = new SelectControl(this.editor,
            "mode",
            [["EQUAL", "=="], ["NOT_EQUAL", "!="], ["GREATER", ">"], ["LESS", "<"], ["GE", ">="], ["LE", ">="]],
            "EQUAL")
        //   
        node.addInput(input)
            .addControl(tagNameInput)
            .addControl(modeControl)
            .addControl(new AddTextFieldControl(this.editor, "tag_valueCount", "tag_value", node, "Tag Value"))
        //       json -  ,     ,    
       //  data.tag_valueCount  AddTextFieldControl,  
        let valuesCount = 1;
        if (node.data.tag_valueCount !== undefined) {
            valuesCount = node.data.tag_valueCount
        }
        //    InputControl
        node.addControl(new InputControl(this.editor, 'tag_value'))
        for (let i = 1; i < valuesCount; ++i) {
            node.addControl(new InputControl(this.editor, 'tag_value' + i))
        }

        return node
            .addOutput(output);
    }
}

:




.


, JSON ( Rete ), , .


OSM


, .


: ( leisure=park, OSM):



— , OSM , , . ( ( Java) — ), , , .


, :



: 500- :



, amenity=school, ( — ), .


, . - .


, , ? : ( ), , , Union. :



… . -, — , .. . , amenity=school , , . , .



, , - . :



. . — 4, 3. .
. .. - -, .


:




Rete.js YourMaps .


Di masa depan saya berencana untuk menambahkan lebih banyak lagi di sana - misalnya, kemampuan untuk mengunduh data tidak hanya dari OSM, tetapi juga dari file GeoJSON saya, lebih banyak jenis operasi dan filter, dll.


Layanan ini membantu saya secara pribadi. Misalnya, ketika seorang siswa perlu menunjukkan sesuatu dengan cepat di peta OSM - Saya tidak perlu menjalankan QGIS lagi dan mengingat bahasa permintaan Overpass yang kompleks, saya mengklik grafik yang diinginkan dengan beberapa gerakan mouse, itu diproses dalam beberapa detik dan Anda dapat segera melihat hasilnya.


Semoga bermanfaat bagi sebagian dari Anda. Seperti biasa, saya siap mendengarkan saran dan harapan di sini di komentar, atau Anda dapat mengirimkannya ke evsmirnov@itmo.ru


All Articles