3. تحميل الطبقات¶
تلميح
تحتاج مقتطفات الشيفرة في هذه الصفحة إلى عمليات الاستيراد التالية:
import os # This is needed in the pyqgis console also
from qgis.core import (
QgsVectorLayer
)
لنفتح بعض الطبقات التي تحتوي على بيانات. يتعرّف QGIS على الطبقات المتجهية والشبكية. وتتوفر بالإضافة إلى ذلك أنواع طبقات مخصّصة، لكننا لن نناقشها هنا.
3.1. الطبقات المتجهية¶
لإنشاء نسخة من طبقة متجهية وإضافتها إلى المشروع، حدّد معرّف مصدر بيانات الطبقة. معرّف مصدر البيانات سلسلة نصية خاصة بكل مزوّد بيانات متجهية. ويُستخدم اسم اختياري للطبقة لتمييزها في اللوحة Layers. ومن المهم التحقق من تحميل الطبقة بنجاح، فإن لم تُحمَّل، تُرجَع نسخة طبقة غير صالحة.
لطبقة متجهية من نوع geopackage:
1# get the path to a geopackage
2path_to_gpkg = "testdata/data/data.gpkg"
3# append the layername part
4gpkg_airports_layer = path_to_gpkg + "|layername=airports"
5vlayer = QgsVectorLayer(gpkg_airports_layer, "Airports layer", "ogr")
6if not vlayer.isValid():
7 print("Layer failed to load!")
8else:
9 QgsProject.instance().addMapLayer(vlayer)
أسرع طريقة لفتح طبقة متجهية وعرضها في QGIS هي الدالة addVectorLayer() من الصنف QgisInterface:
vlayer = iface.addVectorLayer(gpkg_airports_layer, "Airports layer", "ogr")
if not vlayer:
print("Layer failed to load!")
ينشئ هذا طبقة جديدة ويضيفها إلى مشروع QGIS الحالي (فتظهر في قائمة الطبقات) في خطوة واحدة. وتُرجع الدالة نسخة الطبقة أو None إذا تعذّر تحميل الطبقة.
توضح القائمة التالية كيفية الوصول إلى مصادر بيانات مختلفة باستخدام مزوّدي البيانات المتجهية:
يدعم المزوّد ogr من مكتبة GDAL مجموعة واسعة من الصيغ، وتُسمّى أيضًا مشغّلات (drivers) في مصطلحات GDAL. ومن أمثلتها ESRI Shapefile و Geopackage و Flatgeobuf و Geojson، ... وفي الصيغ أحادية الملف يكفي عادةً مسار الملف بوصفه uri. أما في geopackage أو dxf، فتتيح لاحقة مفصولة بالرمز | تحديد الطبقة المراد تحميلها.
لملف ESRI Shapefile:
uri = "testdata/airports.shp" vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr") QgsProject.instance().addMapLayer(vlayer)
لملف Geopackage (لاحظ الخيارات الداخلية في uri مصدر البيانات):
uri = "testdata/data/data.gpkg|layername=airports" vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr") QgsProject.instance().addMapLayer(vlayer)
لاحظ أنه إذا كان ملف GeoPackage يحتوي على علاقات بين الطبقات، فإن مجرد استخدام
addMapLayerلا ينشئ هذه العلاقات تلقائيًا بين الطبقات في مشروع QGIS. أضف الشيفرة التالية للعثور تلقائيًا على العلاقات في قاعدة البيانات وإضافة المناسب منها إلى خصائص المشروع.1from qgis.core import QgsRelationManager 2 3project = QgsProject.instance() 4relation_manager = project.relationManager() 5existing_relations = list(relation_manager.relations().values()) 6 7layers = [ 8 layer for layer in project.mapLayers().values() if layer.type() == layer.VectorLayer 9] 10 11discovered_relations = QgsRelationManager.discoverRelations(existing_relations, layers) 12for relation in discovered_relations: 13 relation_manager.addRelation(relation)
لملف dxf (لاحظ الخيارات الداخلية في uri مصدر البيانات):
uri = "testdata/sample.dxf|layername=entities|geometrytype=Polygon" vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr") QgsProject.instance().addMapLayer(vlayer)
قاعدة بيانات PostGIS - مصدر البيانات سلسلة نصية تحتوي على جميع المعلومات اللازمة لإنشاء اتصال بقاعدة بيانات PostgreSQL.
يمكن للصنف
QgsDataSourceUriتوليد هذه السلسلة لك. لاحظ أنه يجب بناء QGIS مع دعم Postgres، وإلا فلن يكون هذا المزوّد متاحًا:1uri = QgsDataSourceUri() 2# set host name, port, database name, username and password 3uri.setConnection("localhost", "5432", "dbname", "johny", "xxx") 4# set database schema, table name, geometry column and optionally 5# subset (WHERE clause) 6uri.setDataSource("public", "roads", "the_geom", "cityid = 2643", "primary_key_field") 7 8vlayer = QgsVectorLayer(uri.uri(False), "layer name you like", "postgres")
ملاحظة
يمنع الوسيط
Falseالمُمرَّر إلىuri.uri(False)توسيع معاملات إعدادات المصادقة، وإن لم تكن تستخدم أي إعدادات مصادقة فلن يُحدث هذا الوسيط أي فرق.
ملفات CSV أو غيرها من الملفات النصية المحدَّدة بفواصل --- لفتح ملف يستخدم الفاصلة المنقوطة فاصلًا، مع الحقل "x" للإحداثي X والحقل "y" للإحداثي Y، تستخدم شيئًا كهذا:
uri = "file://{}/testdata/delimited_xy.csv?delimiter={}&xField={}&yField={}".format(os.getcwd(), ";", "x", "y") vlayer = QgsVectorLayer(uri, "layer name you like", "delimitedtext") QgsProject.instance().addMapLayer(vlayer)
ملاحظة
سلسلة المزوّد مبنية على هيئة URL، لذا يجب أن يسبق المسارَ
file://. كما تتيح استخدام الأشكال الهندسية بصيغة WKT (well known text) بديلًا عن الحقلينxوy، وتسمح بتحديد نظام الإحداثيات المرجعي. على سبيل المثال:uri = "file:///some/path/file.csv?delimiter={}&crs=epsg:4723&wktField={}".format(";", "shape")
ملفات GPX --- يقرأ مزوّد البيانات "gpx" المسارات (tracks) والطرق (routes) ونقاط الطريق (waypoints) من ملفات gpx. ولفتح ملف، يجب تحديد النوع (track/route/waypoint) جزءًا من url:
uri = "testdata/layers.gpx?type=track" vlayer = QgsVectorLayer(uri, "layer name you like", "gpx") QgsProject.instance().addMapLayer(vlayer)
قاعدة بيانات SpatiaLite --- كما في قواعد بيانات PostGIS، يمكن استخدام
QgsDataSourceUriلتوليد معرّف مصدر البيانات:1uri = QgsDataSourceUri() 2uri.setDatabase('/home/martin/test-2.3.sqlite') 3schema = '' 4table = 'Towns' 5geom_column = 'Geometry' 6uri.setDataSource(schema, table, geom_column) 7 8display_name = 'Towns' 9vlayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite') 10QgsProject.instance().addMapLayer(vlayer)
الأشكال الهندسية المعتمدة على WKB في MySQL، عبر GDAL --- مصدر البيانات هو سلسلة الاتصال بالجدول:
uri = "MySQL:dbname,host=localhost,port=3306,user=root,password=xxx|layername=my_table" vlayer = QgsVectorLayer( uri, "my table", "ogr" ) QgsProject.instance().addMapLayer(vlayer)
اتصال WFS: يُعرَّف الاتصال باستخدام URI والمزوّد
WFS:uri = "https://demo.mapserver.org/cgi-bin/wfs?service=WFS&version=2.0.0&request=GetFeature&typename=ms:cities" vlayer = QgsVectorLayer(uri, "my wfs layer", "WFS")
يمكن إنشاء uri باستخدام المكتبة القياسية
urllib:1import urllib 2 3params = { 4 'service': 'WFS', 5 'version': '2.0.0', 6 'request': 'GetFeature', 7 'typename': 'ms:cities', 8 'srsname': "EPSG:4326" 9} 10uri2 = 'https://demo.mapserver.org/cgi-bin/wfs?' + urllib.parse.unquote(urllib.parse.urlencode(params))
ملاحظة
يمكنك تغيير مصدر بيانات طبقة موجودة باستدعاء setDataSource() على نسخة من QgsVectorLayer، كما في المثال التالي:
1uri = "https://demo.mapserver.org/cgi-bin/wfs?service=WFS&version=2.0.0&request=GetFeature&typename=ms:cities"
2provider_options = QgsDataProvider.ProviderOptions()
3# Use project's transform context
4provider_options.transformContext = QgsProject.instance().transformContext()
5vlayer.setDataSource(uri, "layer name you like", "WFS", provider_options)
6
7del(vlayer)
3.2. الطبقات الشبكية¶
تُستخدم مكتبة GDAL للوصول إلى الملفات الشبكية، وهي تدعم طيفًا واسعًا من صيغ الملفات. إذا واجهت مشكلات في فتح بعض الملفات، فتحقق من أن GDAL لديك يدعم تلك الصيغة تحديدًا (فليست كل الصيغ متاحة افتراضيًا). لتحميل طبقة شبكية من ملف، حدّد اسم الملف واسم العرض:
1# get the path to a tif file e.g. /home/project/data/srtm.tif
2path_to_tif = "qgis-projects/python_cookbook/data/srtm.tif"
3rlayer = QgsRasterLayer(path_to_tif, "SRTM layer name")
4if not rlayer.isValid():
5 print("Layer failed to load!")
لتحميل طبقة شبكية من geopackage:
1# get the path to a geopackage e.g. /home/project/data/data.gpkg
2path_to_gpkg = os.path.join(os.getcwd(), "testdata", "sublayers.gpkg")
3# gpkg_raster_layer = "GPKG:/home/project/data/data.gpkg:srtm"
4gpkg_raster_layer = "GPKG:" + path_to_gpkg + ":srtm"
5
6rlayer = QgsRasterLayer(gpkg_raster_layer, "layer name you like", "gdal")
7
8if not rlayer.isValid():
9 print("Layer failed to load!")
كما في الطبقات المتجهية، يمكن تحميل الطبقات الشبكية باستخدام الدالة addRasterLayer من الكائن QgisInterface:
iface.addRasterLayer(path_to_tif, "layer name you like")
ينشئ هذا طبقة جديدة ويضيفها إلى المشروع الحالي (فتظهر في قائمة الطبقات) في خطوة واحدة.
لتحميل طبقة شبكية من PostGIS:
يمكن إضافة الطبقات الشبكية من PostGIS إلى المشروع باستخدام سلسلة URI، كما في الطبقات المتجهية من PostGIS. ومن الفعّال الاحتفاظ بقاموس قابل لإعادة الاستخدام لمعاملات الاتصال بقاعدة البيانات، مما يسهّل تعديل القاموس بحسب الاتصال المطلوب. ثم يُرمَّز القاموس إلى URI باستخدام كائن البيانات الوصفية للمزوّد 'postgresraster'. وبعد ذلك يمكن إضافة الطبقة الشبكية إلى المشروع.
1uri_config = {
2 # database parameters
3 'dbname':'gis_db', # The PostgreSQL database to connect to.
4 'host':'localhost', # The host IP address or localhost.
5 'port':'5432', # The port to connect on.
6 'sslmode':QgsDataSourceUri.SslDisable, # SslAllow, SslPrefer, SslRequire, SslVerifyCa, SslVerifyFull
7 # user and password are not needed if stored in the authcfg or service
8 'authcfg':'QconfigId', # The QGIS athentication database ID holding connection details.
9 'service': None, # The PostgreSQL service to be used for connection to the database.
10 'username':None, # The PostgreSQL user name.
11 'password':None, # The PostgreSQL password for the user.
12 # table and raster column details
13 'schema':'public', # The database schema that the table is located in.
14 'table':'my_rasters', # The database table to be loaded.
15 'geometrycolumn':'rast',# raster column in PostGIS table
16 'sql':None, # An SQL WHERE clause. It should be placed at the end of the string.
17 'key':None, # A key column from the table.
18 'srid':None, # A string designating the SRID of the coordinate reference system.
19 'estimatedmetadata':'False', # A boolean value telling if the metadata is estimated.
20 'type':None, # A WKT string designating the WKB Type.
21 'selectatid':None, # Set to True to disable selection by feature ID.
22 'options':None, # other PostgreSQL connection options not in this list.
23 'enableTime': None,
24 'temporalDefaultTime': None,
25 'temporalFieldIndex': None,
26 'mode':'2', # GDAL 'mode' parameter, 2 unions raster tiles, 1 adds tiles separately (may require user input)
27}
28# remove any NULL parameters
29uri_config = {key:val for key, val in uri_config.items() if val is not None}
30# get the metadata for the raster provider and configure the URI
31md = QgsProviderRegistry.instance().providerMetadata('postgresraster')
32uri = QgsDataSourceUri(md.encodeUri(uri_config))
33
34# the raster can then be loaded into the project
35rlayer = iface.addRasterLayer(uri.uri(False), "raster layer name", "postgresraster")
يمكن أيضًا إنشاء طبقات شبكية من خدمة WCS:
layer_name = 'modis'
url = "https://demo.mapserver.org/cgi-bin/wcs?identifier={}".format(layer_name)
rlayer = QgsRasterLayer(uri, 'my wcs layer', 'wcs')
فيما يلي وصف للمعاملات التي يمكن أن يحتويها WCS URI:
يتكون WCS URI من أزواج key=value مفصولة بالرمز &. وهي الصيغة نفسها لسلسلة الاستعلام في URL، وتُرمَّز بالطريقة نفسها. ينبغي استخدام QgsDataSourceUri لبناء URI لضمان ترميز المحارف الخاصة ترميزًا صحيحًا.
url (مطلوب): عنوان URL لخادم WCS. لا تستخدم VERSION في URL، لأن كل إصدار من WCS يستخدم اسم معامل مختلفًا لإصدار GetCapabilities، انظر المعامل version.
identifier (مطلوب): اسم التغطية (Coverage)
time (اختياري): موضع زمني أو فترة زمنية (beginPosition/endPosition[/timeResolution])
format (اختياري): اسم صيغة مدعومة. القيمة الافتراضية هي أول صيغة مدعومة يتضمن اسمها tif أو أول صيغة مدعومة.
crs (اختياري): نظام الإحداثيات المرجعي بالصيغة AUTHORITY:ID، مثل EPSG:4326. القيمة الافتراضية EPSG:4326 إن كان مدعومًا، أو أول CRS مدعوم.
username (اختياري): اسم المستخدم للمصادقة الأساسية.
password (اختياري): كلمة المرور للمصادقة الأساسية.
IgnoreGetMapUrl (اختياري، حل التفافي): إذا حُدّد (بالقيمة 1)، يُتجاهل عنوان GetCoverage URL المُعلَن في GetCapabilities. قد يكون ضروريًا إذا لم يكن الخادم مُعدًّا بشكل صحيح.
InvertAxisOrientation (اختياري، حل التفافي): إذا حُدّد (بالقيمة 1)، يُبدَّل المحوران في طلب GetCoverage. قد يكون ضروريًا مع أنظمة الإحداثيات الجغرافية إذا كان الخادم يستخدم ترتيب محاور خاطئًا.
IgnoreAxisOrientation (اختياري، حل التفافي): إذا حُدّد (بالقيمة 1)، لا يُعكَس اتجاه المحاور وفق معيار WCS لأنظمة الإحداثيات الجغرافية.
cache (اختياري): التحكم في التحميل من ذاكرة التخزين المؤقت، كما هو موصوف في QNetworkRequest::CacheLoadControl، لكن الطلب يُعاد إرساله بالقيمة PreferCache إذا فشل مع AlwaysCache. القيم المسموح بها: AlwaysCache و PreferCache و PreferNetwork و AlwaysNetwork. القيمة الافتراضية AlwaysCache.
يمكنك بدلًا من ذلك تحميل طبقة شبكية من خادم WMS. لكن لا يمكن حاليًا الوصول إلى استجابة GetCapabilities من خلال API --- يجب أن تعرف الطبقات التي تريدها:
urlWithParams = "crs=EPSG:4326&format=image/png&layers=continents&styles&url=https://demo.mapserver.org/cgi-bin/wms"
rlayer = QgsRasterLayer(urlWithParams, 'some layer name', 'wms')
if not rlayer.isValid():
print("Layer failed to load!")
3.3. نسخة QgsProject¶
إذا أردت استخدام الطبقات المفتوحة في الرسم، فلا تنسَ إضافتها إلى نسخة QgsProject. تتولى نسخة QgsProject ملكية الطبقات، ويمكن الوصول إليها لاحقًا من أي جزء من التطبيق بواسطة معرّفها الفريد. وعند إزالة الطبقة من المشروع، تُحذف هي أيضًا. يمكن للمستخدم إزالة الطبقات من واجهة QGIS، أو عبر Python باستخدام الدالة removeMapLayer().
تتم إضافة طبقة إلى المشروع الحالي باستخدام الدالة addMapLayer():
QgsProject.instance().addMapLayer(rlayer)
لإضافة طبقة في موضع مطلق:
1# first add the layer without showing it
2QgsProject.instance().addMapLayer(rlayer, False)
3# obtain the layer tree of the top-level group in the project
4layerTree = iface.layerTreeCanvasBridge().rootGroup()
5# the position is a number starting from 0, with -1 an alias for the end
6layerTree.insertChildNode(-1, QgsLayerTreeLayer(rlayer))
إذا أردت حذف الطبقة فاستخدم الدالة removeMapLayer():
# QgsProject.instance().removeMapLayer(layer_id)
QgsProject.instance().removeMapLayer(rlayer.id())
في الشيفرة أعلاه يُمرَّر معرّف الطبقة (يمكنك الحصول عليه باستدعاء الدالة id() للطبقة)، لكن يمكنك أيضًا تمرير كائن الطبقة نفسه.
للحصول على قائمة بالطبقات المحمّلة ومعرّفاتها، استخدم الدالة mapLayers():
QgsProject.instance().mapLayers()