পাইথন প্লাগইন থেকে কিউজিআইএস-এ বৈশিষ্ট্যগুলি সম্পাদনার গতি


9

আমি QGIS পাইথন প্লাগইন ব্যবহার করে একটি স্তরের প্রতিটি বৈশিষ্ট্যের জন্য একটি বৈশিষ্ট্যের মান সম্পাদনা করার চেষ্টা করছি। আমি দেখতে পেয়েছি যে সম্পাদনা মোডের বাইরে এটি সম্পাদনা করার সময় (এমনকি সম্পাদনাগুলি সম্পাদন করা সহ) তুলনায় অনেক ধীর। নীচের কোডটি দেখুন (লুপগুলিতে একই পয়েন্টে বিনিময়যোগ্য)। আমার নমুনা ডেটাসেটের গতির পার্থক্য 2 সেকেন্ড (সম্পাদনা মোড) বনাম 72 সেকেন্ড (সম্পাদনা মোড নয়)।

সম্পাদনা মোডে একটি গুণাবলী পরিবর্তন করা:

layer.changeAttributeValue(feature.id(), 17, QtCore.QVariant(value))

সম্পাদনা মোডের বাইরে একটি বৈশিষ্ট্য পরিবর্তন করা:

layer.dataProvider().changeAttributeValues({ feature.id() : { 17 : QtCore.QVariant(value) } })

এটি কি প্রত্যাশিত আচরণ? পরিবর্তনগুলি পূর্বাবস্থায় ফিরিয়ে আনতে সক্ষম হওয়ার জন্য আমার ব্যবহারকারীর দরকার নেই, তাই আমি সম্পাদনা মোডটি ব্যবহার করা দরকার বলে মনে করি না।

সম্পাদনা 1: উভয় সংস্করণ অন্তর্ভুক্ত সহ পুরো কোডটি দেখুন (তবে মন্তব্য করা হয়েছে):

def run(self):
    try:
        # create spatial index of buffered layer
        index = QgsSpatialIndex()
        self.layer_buffered.select()
        for feature in self.layer_buffered:
            index.insertFeature(feature)

        # enable editing
        #was_editing = self.layer_target.isEditable()
        #if was_editing is False:
        #    self.layer_target.startEditing()

        # check intersections
        self.layer_target.select()
        self.feature_count = self.layer_target.featureCount()
        for feature in self.layer_target:
            distance_min = None
            fids = index.intersects(feature.geometry().boundingBox())
            for fid in fids:
                # feature's bounding box and buffer bounding box intersect
                feature_buffered = QgsFeature()
                self.layer_buffered.featureAtId(fid, feature_buffered)
                if feature.geometry().intersects(feature_buffered.geometry()):
                    # feature intersects buffer
                    attrs = feature_buffered.attributeMap()
                    distance = attrs[0].toPyObject()
                    if distance_min is None or distance < distance_min:
                        distance_min = distance
                if self.abort is True: break
            if self.abort is True: break

            # update feature's distance attribute
            self.layer_target.dataProvider().changeAttributeValues({feature.id(): {self.field_index: QtCore.QVariant(distance_min)}})
            #self.layer_target.changeAttributeValue(feature.id(), self.field_index, QtCore.QVariant(distance_min))

            self.calculate_progress()

        # disable editing
        #if was_editing is False:
        #    self.layer_target.commitChanges()

    except:
        import traceback
        self.error.emit(traceback.format_exc())
    self.progress.emit(100)
    self.finished.emit(self.abort)

উভয় পদ্ধতি একই ফলাফল উত্পন্ন করে, তবে ডেটা সরবরাহকারীর মাধ্যমে লেখা অনেক বেশি সময় নেয়। ফাংশনটি প্রাক-তৈরি বাফারগুলি (ব্রাউন-ইশ) ব্যবহার করে নিকটস্থ ক্ষেত্রগুলিতে (বেগুনি) বিল্ডিং বৈশিষ্ট্যগুলির নৈকট্যকে শ্রেণিবদ্ধ করে। নৈকট্য


1
এটা ঠিক মনে হচ্ছে না। আপনি কি আপনার কোডের আরও কিছু ভাগ করতে পারেন।
নাথান ডব্লিউ

@ নাথানডাব্লু আমি সম্পূর্ণ ফাংশন যোগ করেছি। ছেদগুলির জন্য দুটি স্তর যাচাই করার জন্য ধারণাটি রয়েছে, তারপরে কোনও ছেদ পাওয়া গেলে অন্য স্তরটির বৈশিষ্ট্য সহ একটি স্তর আপডেট করুন।
স্নোরফালোরপাগাস

আপনি কোন ডেটা টাইপ ব্যবহার করছেন?
নাথান ডব্লিউ

উভয় স্তর একটি ইএসআরআই শেফিলস (বহুভুজ)। লেয়ার_টারেজেটে 905 টি বৈশিষ্ট্য (বিল্ডিং) রয়েছে, লেয়ার_ফার্ডারে 1155 টি বৈশিষ্ট্য রয়েছে (খোলা স্পেস) ওভারল্যাপিং বহুভুজগুলি বিভিন্ন বাফারগুলিকে উপস্থাপন করে (100 মি, 50 মি, 20 মি, 10 মি, 5 মি) - সুতরাং 'দূরত্ব' বৈশিষ্ট্য।
স্নোরফলোরপাগাস

1
আপনি কিভাবে তথ্য অ্যাক্সেস করা হয়? (অর্থাত্ নেটওয়ার্ক, ট্র্যাডিশনাল ডিস্ক, এসএসডি)? এটা কি সম্ভব যে, একক রাইটিং অপারেশনের জন্য I / O ওভারহেড সময় সাপেক্ষ? পরীক্ষা হিসাবে: আপনি কি আপনার সমস্ত পরিবর্তিত বৈশিষ্ট্যগুলিকে মেমোরিতে বাফার করার চেষ্টা করতে পারেন এবং তারপরে শেষে একবার ডেটাপ্রোভিডার.ক্যাঞ্জ অ্যাট্রিবিউটভ্যালু () কল করতে পারেন।
মাথিয়াস কুহন

উত্তর:


7

সমস্যাটি ছিল, প্রতিটি QgsDataProvider.changeAttributeValues()কলই সম্পর্কিত সমস্ত ওভারহেডের সাথে একটি নতুন লেনদেন শুরু করে (ডেটা সরবরাহকারী এবং সিস্টেম কনফিগারেশনের উপর নির্ভর করে)

বৈশিষ্ট্যগুলি যখন স্তরটিতে প্রথমে পরিবর্তিত হয় (যেমন হয় QgsVectorLayer.changeAttributeValue()) সমস্ত পরিবর্তনগুলি মেমরিতে ক্যাশে করা হয়, যা খুব দ্রুত এবং তারপরে শেষ পর্যন্ত একটি একক লেনদেনে প্রতিশ্রুতিবদ্ধ হয়।

একই বাফারিং স্ক্রিপ্টের মধ্যে অর্জন করা যেতে পারে, (যেমন ভেক্টর স্তর সম্পাদনা বাফারের বাইরে) এবং তারপরে QgsDataProvider.changeAttributeValues()লুপের বাইরে একবার কল করে একটি লেনদেনে প্রতিশ্রুতিবদ্ধ ।

সাম্প্রতিক কিউজিআইএস সংস্করণগুলিতে এর জন্য একটি সহজ শর্টকাটও রয়েছে:

with edit(layer):
    for fid in fids:
        layer.changeAttributeValue(fid, idx, value)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.