PyQGIS दूरी मैट्रिक्स दक्षता में सुधार
मैंने एक कस्टम प्रोसेसिंग टूल लिखा है, जिसका उपयोग मैं QGIS में एक बड़े ग्राफिकल मॉडल के भीतर करता हूं। मैं इसे गति देने के लिए एक रास्ता तलाश रहा हूं।
इस प्रसंस्करण उपकरण का पहला चरण एक इनपुट परत के प्रत्येक बिंदु को दूसरे इनपुट परत के प्रत्येक बिंदु से जोड़ना और इसकी लाइन की लंबाई को मापना है। इसमें काफी समय लगता है, क्योंकि आमतौर पर दोनों परतों में 10000 से अधिक अंक होते हैं। लेकिन मैं केवल एक-दूसरे से दूरी के भीतर बिंदु जोड़े में दिलचस्पी रखता हूं। इसलिए वर्तमान में मैं बाद में उन लाइनों को हटाने जा रहा हूं, जो बहुत लंबी हैं। मुझे लगता है कि यह काफी अप्रभावी है, और इसलिए यह पूछना चाहता था कि क्या इस कदम को तेज करने के लिए एक आसान तरीका है, एक स्थानिक सूचकांक या ऐसा कुछ का उपयोग करके। मैं उपयोग करके एक बना सकता हूं index = QgsSpatialIndex(layer.getFeatures()), लेकिन मैं केवल उन बिंदुओं को कैसे आगे बढ़ाऊंगा, जिनमें मेरी दिलचस्पी है?
यह मेरे वर्तमान कोड का एक न्यूनतम हिस्सा है:
Memorylayer_VL = QgsVectorLayer(str('LineString?crs=25832')), "tmp_lines", "memory")
Memorylayer_PR = Memorylayer_VL.dataProvider()
maxdistance = 150
# iterate over stop features and create lines
for stop_feat in stop_layer.getFeatures():
point1 = QgsPoint(stop_feat.geometry().asPoint())
for source_feat in possibility_layer.getFeatures():
point2 = QgsPoint(source_feat.geometry().asPoint())
temp_feat = QgsFeature(fields)
temp_feat.setGeometry(QgsGeometry.fromPolyline([point1, point2]))
temp_feat["line_length"] = temp_feat.geometry().length()
# Only add lines shorter than maxdistance and longer than 1m (Already simplified like this thanks to @BERAs suggestion in comments)
# However, couldn't using a spatial index even have more effect?
if (temp_feat.geometry().length() < maxdistance) and (tmp_line_feat.geometry().length() > 1):
Memorylayer_PR.addFeature(temp_feat)
Memorylayer_VL.updateFields()
Memorylayer_VL.commitChanges()
# Doing more processing stuff on the just created lines layer....
जवाब
0 (बहिष्कृत) और maxdistance(बाहर भी) के बीच सभी समाधान लाइनों का चयन करने के लिए कोड के नीचे । सभी POSSIBILITYविशेषताओं को एक स्थानिक सूचकांक ( QgsSpatialIndex) के अंदर डाला जाता है । एक फिल्टर, स्थानिक सूचकांक के लिए धन्यवाद, maxdistanceपरत की विशेषता के चारों ओर एक वर्ग के साथ STOPप्रक्रिया की गति के लिए आवेदन किया जाता है और POSSIBILITYवर्ग में केवल विशेषताओं (चौराहों) का चयन किया जाता है।
यदि परत STOPऔर POSSIBILITYसमान हैं, तो नीचे दिया गया कोड डुप्लिकेट बनाता है और डुप्लिकेट के कारण बहुत कुशल नहीं है।
qgis_project = QgsProject.instance()
layers = {lyr.name(): lyr for lyr in qgis_project.mapLayers().values()}
lyr_from = layers["STOP"]
lyr_to = layers["POSSIBILITY"]
maxdistance = 150
spatial_idx_to = QgsSpatialIndex()
pr_from = lyr_from.dataProvider()
pr_to = lyr_to.dataProvider()
feats_from = pr_from.getFeatures()
feats_to = pr_to.getFeatures()
# insert destination features to the spatial index
spatial_idx_to.addFeatures(feats_to)
result_lines = []
# iterate over origin features
for ft_from in feats_from:
# find all the nearest feature thanks to the spatial index
geom_from = ft_from.geometry().asPoint()
x_from = geom_from.x()
y_from = geom_from.y()
# create a rectangle at maxdistance of the from point
rect = QgsRectangle(
QgsPointXY(x_from - maxdistance, y_from - maxdistance),
QgsPointXY(x_from + maxdistance, y_from + maxdistance)
)
# get all points in that intersects the rectangle
distance_ids = spatial_idx_to.intersects(rect)
for fid in distance_ids:
geom_to = lyr_to.getFeature(fid).geometry().asPoint()
# if the distance between origin and destination < maxdistance
if 0 < geom_from.distance(geom_to) < maxdistance:
line_feat = QgsFeature()
# create a PolylineXY from origin and destination PointXY
line_feat.setGeometry(QgsGeometry.fromPolylineXY([geom_from, geom_to]))
# append the line feature to the result list
result_lines.append(line_feat)
# create the memory layer
memlyr = QgsVectorLayer("LineString?crs=epsg:25832", "tmp_lines", "memory")
memlyr_pr = memlyr.dataProvider()
# add all resulting lines features
memlyr_pr.addFeatures(result_lines)
# finally add the line memory layer to the project
qgis_project.addMapLayer(memlyr)