Exportar datos de OpenStreetMap usando el editor visual en rete.js

En mi trabajo, a menudo encuentro la tarea de exportar datos desde OpenStreetMap. OSM es una fuente de datos sorprendente desde donde puede obtener al menos vistas , al menos áreas de la ciudad , al menos calles para estudios de accesibilidad de peatones y, en general, cualquier cosa.


Ese es solo el proceso de trabajar con ellos en algún momento comenzó a aburrirme. Para recuperar datos de alguna solicitud no trivial, debe estudiar el lenguaje de solicitud Overpass o escribir scripts y hurgar en el formato XML de OSM.


Llevando a cabo estas manipulaciones por centésima vez, pensé en crear una herramienta más simple y conveniente. Y ahora está listo: https://yourmaps.io , el editor visual de descripciones de exportación de OpenStreetMap. En el editor, puede pasar el mouse sobre un gráfico, cada uno de los cuales representará una operación o filtro en una secuencia de objetos OSM, y luego descargará el resultado en GeoJSON.


Aquí hay un ejemplo de un gráfico que selecciona todas las escuelas dentro de un distrito municipal determinado y luego construye zonas de influencia de 300 metros a su alrededor:



Como resultado del trabajo, obtenemos un conjunto de polígonos en formato GeoJSON, que luego se pueden importar a QGIS o algún otro software.


— , Rete.js, -.


Rete.js


Rete.js — JS , . , .


, Rete . OpenStreetMap — .


imagen


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


En el futuro planeo agregar aún más allí, por ejemplo, la capacidad de descargar datos no solo de OSM, sino también de mis archivos GeoJSON, más tipos de operaciones y filtros, etc.


Este servicio me ayuda personalmente personalmente. Por ejemplo, cuando un estudiante necesita mostrar rápidamente algo en el mapa OSM, ya no necesito ejecutar QGIS y recordar el complejo lenguaje de consulta Overpass, hago clic en el gráfico deseado con un par de movimientos del mouse, se procesa en unos segundos y puede ver inmediatamente el resultado.


Espero que sea útil para algunos de ustedes. Como siempre, estoy listo para escuchar sugerencias y deseos, ya sea aquí en los comentarios, o puede enviarlo a evsmirnov@itmo.ru


All Articles