تصدير بيانات OpenStreetMap باستخدام المحرر المرئي على rete.js

في عملي ، أواجه غالبًا مهمة تصدير البيانات من OpenStreetMap. OSM هو مصدر بيانات مذهل من حيث يمكنك الحصول على مشاهد على الأقل ، وعلى الأقل مناطق من المدينة ، وعلى الأقل شوارع لدراسة إمكانية الوصول للمشاة ، وبشكل عام أي شيء.


هذه مجرد عملية للعمل معهم في مرحلة ما بدأت تشعرني بالملل. لاسترداد البيانات لبعض الطلبات غير العادية ، تحتاج إما إلى دراسة لغة طلب التجاوز ، أو كتابة البرامج النصية والتنقل بتنسيق 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 بعد الآن وتذكر لغة الاستعلام المتراكبة المعقدة ، أنقر على الرسم البياني المطلوب مع حركات الماوس ، تتم معالجته في بضع ثوانٍ ويمكنك رؤية النتيجة على الفور.


آمل أن تكون مفيدة لبعضكم. كما هو الحال دائمًا ، أنا على استعداد للاستماع إلى الاقتراحات والرغبات سواء هنا في التعليقات ، أو يمكنك إرسالها إلى evsmirnov@itmo.ru


All Articles