在rete.js上使用可视化编辑器导出OpenStreetMap数据

在我的工作中,我经常遇到从OpenStreetMap导出数据的任务。OSM是一个了不起的数据源,您可以从中至少获取景点,至少城市区域,至少街道以研究行人通行能力,以及所有其他信息。


那只是与他们一起工作的过程开始让我感到无聊。要检索一些非平凡请求的数据,您需要学习Overpass请求语言,或者编写脚本并以OSM XML格式四处浏览。


第一百次进行这些操作时,我考虑过要创建一些更简单,更方便的工具。而现在,他已经准备好- https://yourmaps.io,OpenStreetMap的出口描述的可视化编辑器。在编辑器中,您可以将鼠标悬停在一个图形上,该图形的每个节点将代表OSM对象流上的一个操作或过滤器,然后将结果下载到GeoJSON中。


这是一个图形示例,该图形选择给定市政区内的所有学校,然后在它们周围建立300米的缓冲区:



作为工作的结果,我们获得 GeoJSON格式的多边形集,然后可以将其导入QGIS或其他软件。


— , Rete.js, -.


Rete.js


Rete.js — JS , . , .


, Rete . OpenStreetMap — .


图片


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


将来,我计划在其中添加更多内容-例如,不仅可以从OSM下载数据,还可以从我的GeoJSON文件,更多类型的操作和过滤器等下载数据。


这项服务可以帮助我个人。例如,当学生需要在OSM卡上快速显示某些内容时-我不再需要运行QGIS并记住复杂的Overpass查询语言,我只需几次鼠标移动就可以单击所需的图形,只需几秒钟即可对其进行处理,您可以立即看到结果。


希望对您中的某些人有用。与往常一样,我随时准备在评论中听取建议和希望,或者您可以将其发送至evsmirnov@itmo.ru


All Articles