Add files via upload
This commit is contained in:
@@ -0,0 +1,186 @@
|
||||
from qgis.PyQt.QtCore import QCoreApplication, QVariant
|
||||
from qgis.core import (QgsProcessing,
|
||||
QgsFeatureSink,
|
||||
QgsProcessingException,
|
||||
QgsProcessingAlgorithm,
|
||||
QgsProcessingParameterFeatureSource,
|
||||
QgsProcessingParameterFeatureSink,
|
||||
QgsProcessingParameterString,
|
||||
QgsProcessingParameterEnum,
|
||||
QgsFeature,
|
||||
QgsField,
|
||||
QgsGeometry,
|
||||
QgsVectorLayer,
|
||||
QgsProject,
|
||||
QgsProcessingContext)
|
||||
from qgis import processing
|
||||
import requests
|
||||
import geopandas as gpd
|
||||
|
||||
class FetchGeoBoundaryAlgorithm(QgsProcessingAlgorithm):
|
||||
INPUT = 'INPUT'
|
||||
OUTPUT = 'OUTPUT'
|
||||
RELEASE_TYPE = 'RELEASE_TYPE'
|
||||
COUNTRY_CODE = 'COUNTRY_CODE'
|
||||
BOUNDARY_TYPE = 'BOUNDARY_TYPE'
|
||||
|
||||
def tr(self, string):
|
||||
return QCoreApplication.translate('Processing', string)
|
||||
|
||||
def createInstance(self):
|
||||
return FetchGeoBoundaryAlgorithm()
|
||||
|
||||
def name(self):
|
||||
return 'fetchgeoboundary'
|
||||
|
||||
def displayName(self):
|
||||
return self.tr('Fetch geoBoundaries')
|
||||
|
||||
def group(self):
|
||||
return self.tr('geoBoundaries')
|
||||
|
||||
def groupId(self):
|
||||
return 'geoboundaryscripts'
|
||||
|
||||
def shortHelpString(self):
|
||||
return self.tr("Fetches geoBoundaries and adds them. This is an unofficial tool by Joaquin Gottlebe. \n More information: https://www.geoboundaries.org/index.html")
|
||||
|
||||
def initAlgorithm(self, config=None):
|
||||
self.addParameter(
|
||||
QgsProcessingParameterString(
|
||||
self.COUNTRY_CODE,
|
||||
self.tr('Country Code ISO-3'),
|
||||
defaultValue='DEU'
|
||||
)
|
||||
)
|
||||
self.addParameter(
|
||||
QgsProcessingParameterEnum(
|
||||
self.BOUNDARY_TYPE,
|
||||
self.tr('Boundary Type'),
|
||||
options=['ADM0','ADM1','ADM2','ADM3','ADM4','ADM5'],
|
||||
defaultValue=0
|
||||
)
|
||||
)
|
||||
self.addParameter(
|
||||
QgsProcessingParameterEnum(
|
||||
self.RELEASE_TYPE,
|
||||
self.tr('Release Type'),
|
||||
options=['gbOpen','gbHumanitarian','gbAuthorative'],
|
||||
defaultValue='gbOpen'
|
||||
)
|
||||
)
|
||||
self.addParameter(
|
||||
QgsProcessingParameterFeatureSink(
|
||||
self.OUTPUT,
|
||||
self.tr('Output layer')
|
||||
)
|
||||
)
|
||||
|
||||
def processAlgorithm(self, parameters, context, feedback):
|
||||
|
||||
release_type_index = self.parameterAsEnum(parameters, self.RELEASE_TYPE, context)
|
||||
release_types = ['gbOpen', 'gbHumanitarian', 'gbAuthorative']
|
||||
release_type = release_types[release_type_index]
|
||||
|
||||
country_code = self.parameterAsString(parameters, self.COUNTRY_CODE, context)
|
||||
|
||||
boundary_type_index = self.parameterAsEnum(parameters, self.BOUNDARY_TYPE, context)
|
||||
boundary_types = ['ADM0','ADM1','ADM2','ADM3','ADM4','ADM5']
|
||||
boundary_type = boundary_types[boundary_type_index]
|
||||
|
||||
results = self.fetch_geoboundary(release_type, country_code, boundary_type, feedback)
|
||||
|
||||
if not results:
|
||||
raise QgsProcessingException('Failed to fetch geoBoundary')
|
||||
|
||||
total_features = sum(len(result['gdf']) for result in results)
|
||||
processed_features = 0
|
||||
|
||||
layer_name = f"{country_code}_{boundary_type}_{release_type}_geoBoundaries"
|
||||
vector_layer = QgsVectorLayer("Polygon?crs=epsg:4326", layer_name, "memory")
|
||||
pr = vector_layer.dataProvider()
|
||||
|
||||
for result in results:
|
||||
gdf = result['gdf']
|
||||
metadata = result['metadata']
|
||||
|
||||
if gdf.empty:
|
||||
feedback.reportError("Loaded GeoDataFrame is empty.")
|
||||
continue
|
||||
|
||||
for index, row in gdf.iterrows():
|
||||
if feedback.isCanceled():
|
||||
break
|
||||
|
||||
# Debugging type and attribute
|
||||
if not hasattr(row['geometry'], 'wkt'):
|
||||
feedback.reportError(f"Unexpected type for geometry: {type(row['geometry'])}. Expected shapely geometry object.")
|
||||
continue # Skip this iteration if the geometry type is unexpected
|
||||
|
||||
# Assuming row['geometry'] is a shapely.geometry object as expected
|
||||
feat = QgsFeature()
|
||||
try:
|
||||
feat.setGeometry(QgsGeometry.fromWkt(row['geometry'].wkt))
|
||||
except Exception as e:
|
||||
feedback.reportError(f"Error setting geometry from WKT: {e}")
|
||||
continue # Skip this iteration if there was an error setting the geometry
|
||||
|
||||
# Add additional feature settings and add feature to the provider as necessary
|
||||
pr.addFeature(feat)
|
||||
|
||||
vector_layer.updateExtents()
|
||||
|
||||
QgsProject.instance().addMapLayer(vector_layer)
|
||||
|
||||
feedback.pushInfo("GeoBoundary layer added to the project.")
|
||||
|
||||
return {self.OUTPUT: vector_layer.id()}
|
||||
|
||||
def fetch_geoboundary(self, release_type, country_code, boundary_type, feedback):
|
||||
api_url = f"https://www.geoboundaries.org/api/current/{release_type}/{country_code}/{boundary_type}/"
|
||||
try:
|
||||
response = requests.get(api_url)
|
||||
if response.status_code != 200:
|
||||
print(f"Failed to fetch data: HTTP Status Code {response.status_code}")
|
||||
return None
|
||||
|
||||
data = response.json()
|
||||
results = []
|
||||
|
||||
if not isinstance(data, list):
|
||||
data = [data]
|
||||
|
||||
total_countries = len(data)
|
||||
processed_countries = 0
|
||||
|
||||
for country_data in data:
|
||||
|
||||
if feedback.isCanceled():
|
||||
return None
|
||||
|
||||
if 'gjDownloadURL' not in country_data:
|
||||
feedback.reportError("'gjDownloadURL' not found in the response for" + country_data.get('boundaryISO', 'an unknown country'))
|
||||
continue
|
||||
|
||||
geojson_url = country_data['gjDownloadURL']
|
||||
gdf = gpd.read_file(geojson_url)
|
||||
if gdf.empty:
|
||||
feedback.reportError("Loaded GeoDataFrame is empty.")
|
||||
continue
|
||||
|
||||
metadata = {key: country_data.get(key, '') for key in country_data}
|
||||
|
||||
results.append({'gdf': gdf, 'metadata' : metadata})
|
||||
|
||||
processed_countries += 1
|
||||
feedback.setProgress(int((processed_countries / total_countries) * 100))
|
||||
|
||||
|
||||
return results
|
||||
|
||||
except requests.RequestException as e:
|
||||
feedback.reportError(f"Request error: {e}")
|
||||
except Exception as e:
|
||||
feedback.reportError(f"An unexpected error occurred: {e}")
|
||||
|
||||
return None
|
||||
Reference in New Issue
Block a user