5. استخدام الطبقات الشبكية (رستر)¶
تلميح
تحتاج مقتطفات الشيفرة في هذه الصفحة إلى عبارات الاستيراد التالية إن كنت خارج وحدة تحكم pyqgis:
1from qgis.core import (
2 QgsRasterLayer,
3 QgsProject,
4 QgsPointXY,
5 QgsRaster,
6 QgsRasterShader,
7 QgsColorRampShader,
8 QgsSingleBandPseudoColorRenderer,
9 QgsSingleBandColorDataRenderer,
10 QgsSingleBandGrayRenderer,
11)
12
13from qgis.PyQt.QtGui import (
14 QColor,
15)
5.1. تفاصيل الطبقة¶
تتكون الطبقة الشبكية من نطاق شبكي واحد أو أكثر --- ويُشار إليها بالطبقات الشبكية أحادية النطاق ومتعددة النطاقات. يمثل النطاق الواحد مصفوفة من القيم. الصورة الملونة (مثل الصورة الجوية) طبقة شبكية مكونة من نطاقات الأحمر والأزرق والأخضر. تمثل الطبقات الشبكية أحادية النطاق عادةً متغيرات متصلة (مثل الارتفاع) أو متغيرات منفصلة (مثل استخدامات الأراضي). وفي بعض الحالات تأتي الطبقة الشبكية مع لوحة ألوان، وتشير القيم الشبكية إلى الألوان المخزنة في لوحة الألوان.
تفترض الشيفرة التالية أن rlayer كائن من نوع QgsRasterLayer.
rlayer = QgsProject.instance().mapLayersByName('srtm')[0]
# get the resolution of the raster in layer unit
print(rlayer.width(), rlayer.height())
919 619
# get the extent of the layer as QgsRectangle
print(rlayer.extent())
<QgsRectangle: 20.06856808199999875 -34.27001076999999896, 20.83945284300000012 -33.75077500700000144>
# get the extent of the layer as Strings
print(rlayer.extent().toString())
20.0685680819999988,-34.2700107699999990 : 20.8394528430000001,-33.7507750070000014
# get the raster type: 0 = GrayOrUndefined (single band), 1 = Palette (single band), 2 = Multiband
print(rlayer.rasterType())
RasterLayerType.GrayOrUndefined
# get the total band count of the raster
print(rlayer.bandCount())
1
# get the first band name of the raster
print(rlayer.bandName(1))
Band 1: Height
# get all the available metadata as a QgsLayerMetadata object
print(rlayer.metadata())
<qgis._core.QgsLayerMetadata object at 0x13711d558>
5.2. أداة الرسم (Renderer)¶
عند تحميل طبقة شبكية، تحصل على أداة رسم افتراضية بحسب نوعها. ويمكن تغييرها إما من خصائص الطبقة أو برمجيًا.
للاستعلام عن أداة الرسم الحالية:
print(rlayer.renderer())
<qgis._core.QgsSingleBandGrayRenderer object at 0x7f471c1da8a0>
print(rlayer.renderer().type())
singlebandgray
لتعيين أداة رسم، استخدم الدالة setRenderer() الخاصة بالصنف QgsRasterLayer. وهناك عدد من أصناف أدوات الرسم (المشتقة من QgsRasterRenderer):
QgsHillshadeRendererQgsMultiBandColorRendererQgsPalettedRasterRendererQgsRasterContourRendererQgsSingleBandColorDataRendererQgsSingleBandGrayRendererQgsSingleBandPseudoColorRenderer
يمكن رسم الطبقات الشبكية أحادية النطاق إما بدرجات الرمادي (القيم المنخفضة = أسود، والقيم المرتفعة = أبيض) أو بخوارزمية ألوان زائفة (pseudocolor) تُسند الألوان إلى القيم. كما يمكن رسم الطبقات الشبكية أحادية النطاق التي تملك لوحة ألوان باستخدام تلك اللوحة. أما الطبقات متعددة النطاقات فتُرسم عادةً بربط النطاقات بألوان RGB. ومن الممكن أيضًا استخدام نطاق واحد فقط للرسم.
5.2.1. الطبقات الشبكية أحادية النطاق¶
لنفترض أننا نريد رسم طبقة شبكية أحادية النطاق بألوان تتدرج من الأخضر إلى الأصفر (مقابل قيم البكسل من 0 إلى 255). في المرحلة الأولى سنُعِدّ كائنًا من نوع QgsRasterShader ونضبط دالة التظليل الخاصة به:
1fcn = QgsColorRampShader()
2fcn.setColorRampType(QgsColorRampShader.Interpolated)
3lst = [ QgsColorRampShader.ColorRampItem(0, QColor(0,255,0)),
4 QgsColorRampShader.ColorRampItem(255, QColor(255,255,0)) ]
5fcn.setColorRampItemList(lst)
6shader = QgsRasterShader()
7shader.setRasterShaderFunction(fcn)
يربط المظلِّل (shader) الألوان وفق خريطة الألوان المحددة له. وتُقدَّم خريطة الألوان على شكل قائمة من قيم البكسل مع الألوان المرتبطة بها. وهناك ثلاثة أنماط للاستيفاء:
خطي (
Interpolated): يُستوفى اللون خطيًا من مدخلات خريطة الألوان التي تقع فوق قيمة البكسل وتحتهامنفصل (
Discrete): يؤخذ اللون من أقرب مُدخل في خريطة الألوان ذي قيمة مساوية أو أعلىمطابق (
Exact): لا يُستوفى اللون، ولا تُرسم إلا البكسلات التي تساوي قيمها مدخلات خريطة الألوان
في الخطوة الثانية سنربط هذا المظلِّل بالطبقة الشبكية:
renderer = QgsSingleBandPseudoColorRenderer(rlayer.dataProvider(), 1, shader)
rlayer.setRenderer(renderer)
الرقم 1 في الشيفرة أعلاه هو رقم النطاق (تُرقَّم نطاقات الطبقة الشبكية بدءًا من الواحد).
أخيرًا علينا استخدام الدالة triggerRepaint() لرؤية النتائج:
rlayer.triggerRepaint()
5.2.2. الطبقات الشبكية متعددة النطاقات¶
افتراضيًا، يربط QGIS النطاقات الثلاثة الأولى بالأحمر والأخضر والأزرق لإنشاء صورة ملونة (وهذا هو نمط الرسم MultiBandColor). وقد ترغب في بعض الحالات في تجاوز هذه الإعدادات. تبدّل الشيفرة التالية بين النطاق الأحمر (1) والنطاق الأخضر (2):
rlayer_multi = QgsProject.instance().mapLayersByName('multiband')[0]
rlayer_multi.renderer().setGreenBand(1)
rlayer_multi.renderer().setRedBand(2)
إذا كان نطاق واحد فقط ضروريًا لعرض الطبقة الشبكية، فيمكن اختيار الرسم أحادي النطاق، إما بدرجات الرمادي أو بالألوان الزائفة.
علينا استخدام triggerRepaint() لتحديث الخريطة ورؤية النتيجة:
rlayer_multi.triggerRepaint()
5.3. الاستعلام عن القيم¶
يمكن الاستعلام عن قيم الطبقة الشبكية باستخدام الدالة sample() من الصنف QgsRasterDataProvider. عليك تحديد QgsPointXY ورقم نطاق الطبقة الشبكية الذي تريد الاستعلام عنه. وتُعيد الدالة صفًّا (tuple) يحتوي على القيمة و True أو False بحسب النتائج:
val, res = rlayer.dataProvider().sample(QgsPointXY(20.50, -34), 1)
ومن الطرق الأخرى للاستعلام عن قيم الطبقة الشبكية استخدام الدالة identify() التي تُعيد كائنًا من نوع QgsRasterIdentifyResult.
ident = rlayer.dataProvider().identify(QgsPointXY(20.5, -34), QgsRaster.IdentifyFormatValue)
if ident.isValid():
print(ident.results())
{1: 323.0}
في هذه الحالة، تُعيد الدالة results() قاموسًا مفاتيحه أرقام النطاقات وقيمه قيم النطاقات. على سبيل المثال، شيء مثل {1: 323.0}
5.4. تحرير بيانات الطبقات الشبكية¶
يمكنك إنشاء طبقة شبكية باستخدام الصنف QgsRasterBlock. على سبيل المثال، لإنشاء كتلة شبكية بحجم 2x2 ببايت واحد لكل بكسل:
block = QgsRasterBlock(Qgis.Byte, 2, 2)
block.setData(b'\xaa\xbb\xcc\xdd')
يمكن الكتابة فوق بكسلات الطبقة الشبكية بفضل الدالة writeBlock(). للكتابة فوق بيانات الطبقة الشبكية الموجودة عند الموضع 0,0 بالكتلة 2x2:
provider = rlayer.dataProvider()
provider.setEditable(True)
provider.writeBlock(block, 1, 0, 0)
provider.setEditable(False)