Exportez les données OpenStreetMap à l'aide de l'éditeur visuel sur rete.js

Dans mon travail, je rencontre souvent la tâche d'exporter des données depuis OpenStreetMap. OSM est une source de données incroyable à partir de laquelle vous pouvez obtenir au moins des sites touristiques , au moins des quartiers de la ville , au moins des rues pour des études sur l'accessibilité des piétons , et généralement n'importe quoi.


C'est juste que le processus de collaboration avec eux a commencé à un moment donné à m'ennuyer. Pour récupérer des données pour une demande non triviale, vous devez soit étudier le langage de demande Overpass, soit écrire des scripts et fouiller au format OSM XML.


En effectuant ces manipulations pour la centième fois, j'ai pensé à créer un outil plus simple et plus pratique. Et maintenant, il est prêt - https://yourmaps.io , l'éditeur visuel des descriptions d'exportation d'OpenStreetMap. Dans l'éditeur, vous pouvez passer la souris sur un graphique, dont chaque nœud représentera une opération ou un filtre sur un flux d'objets OSM, puis télécharger le résultat dans GeoJSON.


Voici un exemple de graphique qui sélectionne toutes les écoles d'un district municipal donné, puis construit des zones tampons de 300 mètres autour d'elles:



À la suite du travail, nous obtenons un tel ensemble de polygones au format GeoJSON, qui peut ensuite être importé dans QGIS ou un autre logiciel.


— , Rete.js, -.


Rete.js


Rete.js — JS , . , .


, Rete . OpenStreetMap — .


image


(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 .


À l'avenir, je prévois d'y ajouter encore plus - par exemple, la possibilité de télécharger des données non seulement à partir d'OSM, mais aussi à partir de mes fichiers GeoJSON, plus de types d'opérations et de filtres, etc.


Ce service m'aide personnellement personnellement. Par exemple, lorsqu'un étudiant doit afficher rapidement quelque chose sur la carte OSM - je n'ai plus besoin d'exécuter QGIS et de me souvenir du langage de requête Overpass complexe, je clique sur le graphique souhaité avec quelques mouvements de souris, il est traité en quelques secondes et vous pouvez immédiatement voir le résultat.


J'espère que cela sera utile à certains d'entre vous. Comme toujours, je suis prêt à écouter les suggestions et les souhaits soit ici dans les commentaires, soit vous pouvez les envoyer à evsmirnov@itmo.ru


All Articles