def area_crs(crs_id, feature, parent, context): """ <h4>Return</h4>Area using the CRS ID <p><h4>Syntax</h4>area_crs(CRS ID)</p> <p><h4>Argument</h4>CRS ID</p> <p><h4>Example</h4>area_crs('EPSG:5671')</p> """ geom = QgsGeometry(feature.geometry()) if not isinstance(crs_id, str): raise Exception("Enter with ID CRS with string type(Ex.: 'EPSG:4326')") crsDest = QgsCoordinateReferenceSystem(crs_id) if not crsDest.isValid(): msg = "ID EPSG '{}' is not valid".format(crs_id) raise Exception(msg) if crsDest.isGeographic(): msg = "ID CRS '{}' is Geographic".format(crs_id) raise Exception(msg) layer_id = context.variable('layer_id') crsLayer = getCRSLayer(layer_id) if not crsDest == crsLayer: ct = QgsCoordinateTransform(crsLayer, crsDest, QgsCoordinateTransformContext()) geom.transform(ct) return geom.area()
def getAuthority(crs): if not isinstance(crs, QgsCoordinateReferenceSystem): defCRS = "WKT:{}".format(crs) crs = QgsCoordinateReferenceSystem(defCRS) isProjected = not crs.isGeographic() return {'auth': crs.authid(), 'isProjected': isProjected}
def _crud_baselayer(self, form): """ CRUD base layer """ if form.cleaned_data['as_base_layer']: # Create/update base layer if self.base_layer: # update self.base_layer.title = form.cleaned_data['base_layer_title'] self.base_layer.description = form.cleaned_data['base_layer_desc'] property = eval(self.base_layer.property) property['attributions'] = form.cleaned_data['base_layer_attr'] self.base_layer.property = property self.base_layer.save() else: # create # create OL config data # i.e.: # { # "crs": { # "epsg": 32632, # "proj4": '+proj=utm +zone=32 +datum=WGS84 +units=m +no_defs', # "geographic": False, # "axisinverted": False # }, # "url": "https://dev.g3wsuite.it/caching/api/qdjango30/{z}/{x}/{y}.png", # "servertype": "TMS", # "attributions": "Ortofoto Piemonte AGEA 2015" # } crs = QgsCoordinateReferenceSystem(f'EPSG:{self.layer.project.group.srid.srid}') property = { "crs": { "epsg": self.layer.project.group.srid.srid, "proj4": crs.toProj4(), "geographic": crs.isGeographic(), "axisinverted": crs.hasAxisInverted() }, "url": f"/caching/api/{self.layer._meta.app_label}{self.layer.pk}/"+"{z}/{x}/{y}.png", "servertype": "TMS", "attributions": form.cleaned_data['base_layer_attr'] } kwargs = { 'name': f'bl_from_cached_layer_{self.layer.pk}', 'title': form.cleaned_data['base_layer_title'], 'description': form.cleaned_data['base_layer_desc'], 'property': property } self.base_layer = BaseLayer(**kwargs) self.base_layer.save() # update caching layer config record self.activated.baselayer_id = self.base_layer.pk self.activated.save() else: # Delete base layer if self.base_layer and self.base_layer.pk: self.base_layer.delete() if self.activated.baselayer_id: self.activated.baselayer_id = None self.activated.save()
def processAlgorithm(self, parameters, context, model_feedback): # Use a multi-step feedback, so that individual child algorithm progress reports are adjusted for the # overall progress through the model feedback = QgsProcessingMultiStepFeedback(13, model_feedback) results = {} outputs = {} input_layer = self.parameterAsVectorLayer(parameters, "inputlayer", context) overlay_layer = self.parameterAsVectorLayer(parameters, "overlaylayer", context) input_epsg_code = input_layer.crs().authid() overlay_epsg_code = overlay_layer.crs().authid() crs_input = QgsCoordinateReferenceSystem(input_epsg_code) crs_overlay = QgsCoordinateReferenceSystem(overlay_epsg_code) if crs_input.isGeographic(): feedback.reportError( "CRS of the Input Layer is Geographic. Results accuracy may get impacted. For most accurate results, both input and overlay layers should be in the same Projected CRS\n" ) if crs_overlay.isGeographic(): feedback.reportError( "CRS of the Input Layer is Geographic. Results accuracy may get impacted. For most accurate results, both input and overlay layers should be in the same Projected CRS\n" ) if input_epsg_code == overlay_epsg_code: pass else: feedback.reportError( "Input and Overlay Layers are in different CRS. For most accurate results, both input and overlay layers should be in the same Projected CRS\n" ) # add_ID_field to input layer alg_params = { "FIELD_NAME": "input_feat_id", "GROUP_FIELDS": [""], "INPUT": parameters["inputlayer"], "SORT_ASCENDING": True, "SORT_EXPRESSION": "", "SORT_NULLS_FIRST": False, "START": 1, "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["Add_id_field"] = processing.run( "native:addautoincrementalfield", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(1) if feedback.isCanceled(): return {} # add_area_field to input layer alg_params = { "FIELD_LENGTH": 0, "FIELD_NAME": "area_awa", "FIELD_PRECISION": 0, "FIELD_TYPE": 0, "FORMULA": "area($geometry)", "INPUT": outputs["Add_id_field"]["OUTPUT"], "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["Add_area_field"] = processing.run( "qgis:fieldcalculator", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(2) if feedback.isCanceled(): return {} # dissolve all overlay fields so as not to repeat record in reporting alg_params = { "FIELD": [parameters["fieldtoaverage"]] + [ field for field in parameters["additionalfields"] if field != str(parameters["fieldtoaverage"]) ], "INPUT": parameters["overlaylayer"], "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["Dissolve"] = processing.run( "native:dissolve", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(3) if feedback.isCanceled(): return {} # intersection between input and overlay layer # delete no field in input layer and all fields in overlay layer # except field to average and additional fields alg_params = { "INPUT": outputs["Add_area_field"]["OUTPUT"], "INPUT_FIELDS": [""], "OVERLAY": outputs["Dissolve"]["OUTPUT"], "OVERLAY_FIELDS": [str(parameters["fieldtoaverage"])] + parameters["additionalfields"], "OVERLAY_FIELDS_PREFIX": "", "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["Intersection"] = processing.run( "native:intersection", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(4) if feedback.isCanceled(): return {} # add_Weight alg_params = { "FIELD_LENGTH": 0, "FIELD_NAME": parameters["fieldtoaverage"] + "_area", "FIELD_PRECISION": 0, "FIELD_TYPE": 0, "FORMULA": ' "' + parameters["fieldtoaverage"] + '" * area($geometry)', "INPUT": outputs["Intersection"]["OUTPUT"], "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["Add_Weight"] = processing.run( "qgis:fieldcalculator", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(5) if feedback.isCanceled(): return {} # area_average weighted_field = "weighted_" + parameters["fieldtoaverage"] alg_params = { "FIELD_LENGTH": 0, "FIELD_NAME": weighted_field, "FIELD_PRECISION": 0, "FIELD_TYPE": 0, "FORMULA": ' sum("' + parameters["fieldtoaverage"] + "_area" '","input_feat_id")/"area_awa"', "INPUT": outputs["Add_Weight"]["OUTPUT"], "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["area_average"] = processing.run( "qgis:fieldcalculator", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(6) if feedback.isCanceled(): return {} # remerge input layer elements alg_params = { "FIELD": ["input_feat_id"], "INPUT": outputs["area_average"]["OUTPUT"], "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["Dissolve2"] = processing.run( "native:dissolve", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(7) if feedback.isCanceled(): return {} input_layer = self.parameterAsVectorLayer(parameters, "inputlayer", context) result_name = input_layer.name() + "_" + parameters["fieldtoaverage"] parameters["result"].destinationName = result_name # drop field(s) for Result alg_params = { "COLUMN": ["input_feat_id", "area_awa"] + [parameters["fieldtoaverage"]] + [ field for field in parameters["additionalfields"] if field != str(parameters["fieldtoaverage"]) ] + [parameters["fieldtoaverage"] + "_area"], "INPUT": outputs["Dissolve2"]["OUTPUT"], "OUTPUT": parameters["result"], } outputs["Drop1"] = processing.run( "qgis:deletecolumn", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(8) if feedback.isCanceled(): return {} results["result"] = outputs["Drop1"]["OUTPUT"] # Reporting # Drop field(s) for Report int_layer = context.takeResultLayer(outputs["area_average"]["OUTPUT"]) all_fields = [f.name() for f in int_layer.fields()] fields_to_keep = (["input_feat_id", weighted_field] + [ field for field in parameters["additionalfields"] if field != str(parameters["fieldtoaverage"]) ] + [parameters["fieldtoaverage"]] + [parameters["identifierfieldforreport"]]) fields_to_drop = [f for f in all_fields if f not in fields_to_keep] alg_params = { "COLUMN": fields_to_drop, "INPUT": int_layer, "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["Drop2"] = processing.run( "qgis:deletecolumn", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(9) if feedback.isCanceled(): return {} # update area alg_params = { "FIELD_LENGTH": 20, "FIELD_NAME": "area_crs_units", "FIELD_PRECISION": 5, "FIELD_TYPE": 0, "FORMULA": "round(area($geometry),5)", "INPUT": outputs["Drop2"]["OUTPUT"], "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["update_area"] = processing.run( "qgis:fieldcalculator", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(10) if feedback.isCanceled(): return {} parameters["reportaslayer"].destinationName = "Report as Layer" # add area % alg_params = { "FIELD_LENGTH": 9, "FIELD_NAME": "area_prcnt", "FIELD_PRECISION": 5, "FIELD_TYPE": 0, "FORMULA": ' round("area_crs_units" *100/ sum( "area_crs_units" , "input_feat_id" ),5)', "INPUT": outputs["update_area"]["OUTPUT"], "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["area_prcnt"] = processing.run( "qgis:fieldcalculator", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(11) if feedback.isCanceled(): return {} # Order by expression alg_params = { "ASCENDING": True, "EXPRESSION": ' "input_feat_id" + area_prcnt" ', "INPUT": outputs["area_prcnt"]["OUTPUT"], "NULLS_FIRST": False, "OUTPUT": parameters["reportaslayer"], } outputs["OrderByExpression"] = processing.run( "native:orderbyexpression", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(12) if feedback.isCanceled(): return {} results["reportaslayer"] = outputs["OrderByExpression"]["OUTPUT"] output_file = self.parameterAsFileOutput(parameters, "reportasHTML", context) # create HTML report if output_file: try: try: import pandas as pd except ImportError: feedback.pushInfo( "Python library pandas was not found. Installing pandas to QGIS python ..." ) import pathlib as pl import subprocess qgis_Path = pl.Path(sys.executable) qgis_python_path = (qgis_Path.parent / "python3.exe").as_posix() subprocess.check_call([ qgis_python_path, "-m", "pip", "install", "--user", "pandas" ]) import pandas as pd feedback.pushInfo( "Python library pandas was successfully installed for QGIS python" ) except: feedback.reportError( "Failed to import pandas. Tried installing pandas but failed.\nPlease manually install pandas for the python that comes with your QGIS.", True, ) return results # Drop geometries alg_params = { "INPUT": outputs["area_prcnt"]["OUTPUT"], "OUTPUT": QgsProcessing.TEMPORARY_OUTPUT, } outputs["DropGeometries"] = processing.run( "native:dropgeometries", alg_params, context=context, feedback=feedback, is_child_algorithm=True, ) feedback.setCurrentStep(13) if feedback.isCanceled(): return {} with tempfile.TemporaryDirectory() as td: f_name = os.path.join(td, "report_df.csv") report_layer = context.takeResultLayer( outputs["DropGeometries"]["OUTPUT"]) QgsVectorFileWriter.writeAsVectorFormat( report_layer, f_name, fileEncoding="utf-8", driverName="CSV", ) df = pd.read_csv(f_name) total_FIDs = df["input_feat_id"].max() ident_name = parameters["identifierfieldforreport"] html = "" df.sort_values(by="area_prcnt", ascending=False, inplace=True) pd.set_option("display.float_format", "{:.5f}".format) for i in range(1, total_FIDs + 1): df_sub = df.loc[df["input_feat_id"] == i] df_sub.reset_index(inplace=True, drop=True) avg_value = df_sub.at[0, weighted_field] if ident_name: feature_name = df_sub.at[0, ident_name] df_sub.drop( columns=["input_feat_id", ident_name, weighted_field], inplace=True, ) html += f"<p><b>{i}. {feature_name}</b><br>{weighted_field}: {avg_value}<br>count of distinct intersecting features: {len(df_sub.index)}<br></p>\n" else: df_sub.drop(columns=["input_feat_id", weighted_field], inplace=True) html += f"<p><b>Feature ID: {i}</b><br>{weighted_field}: {avg_value}<br>count of distinct intersecting features: {len(df_sub.index)}<br></p>\n" html += f"{df_sub.to_html(bold_rows=False, index=False, na_rep='Null',justify='left')}<br>\n" with codecs.open(output_file, "w", encoding="utf-8") as f: f.write("<html><head>\n") f.write( '<meta http-equiv="Content-Type" content="text/html; \ charset=utf-8" /></head><body>\n') f.write(html) f.write("</body></html>\n") results["reportasHTML"] = output_file # log usage with open(os.path.join(cmd_folder, "usage_counter.log"), "r+") as f: counter = int(f.readline()) f.seek(0) f.write(str(counter + 1)) # check if counter is a milestone if (counter + 1) % 25 == 0: appeal_file = NamedTemporaryFile("w", suffix=".html", delete=False) self.createHTML(appeal_file.name, counter + 1) results["Message"] = appeal_file.name return results
def to_representation(self, instance): ret = super(GroupSerializer, self).to_representation(instance) # add header_logo # before check macrogroups and groups number also if is equal to 1 use it try: macrogroup = instance.macrogroups.get(use_logo_client=True) ret['header_logo_img'] = macrogroup.logo_img.name except: ret['header_logo_img'] = instance.header_logo_img.name try: macrogroup = instance.macrogroups.get(use_title_client=True) ret['name'] = macrogroup.title except: # change groupData name with title for i18n app ret['name'] = instance.title # add crs: crs = QgsCoordinateReferenceSystem(f'EPSG:{self.instance.srid.srid}') # Patch for Proj4 > 4.9.3 version if self.instance.srid.srid == 3003: proj4 = settings.PROJ4_EPSG_3003 else: proj4 = crs.toProj4() ret['crs'] = { 'epsg': crs.postgisSrid(), 'proj4': proj4, 'geographic': crs.isGeographic(), 'axisinverted': crs.hasAxisInverted() } # map controls ret['mapcontrols'] = [ mapcontrol.name for mapcontrol in instance.mapcontrols.all() ] # add projects to group ret['projects'] = [] self.projects = {} anonymous_user = get_user_model().get_anonymous() for g3wProjectApp in settings.G3WADMIN_PROJECT_APPS: Project = apps.get_app_config(g3wProjectApp).get_model('project') projects = get_objects_for_user(self.request.user, '{}.view_project'.format(g3wProjectApp), Project) \ .filter(group=instance) projects_anonymous = get_objects_for_user( anonymous_user, '{}.view_project'.format(g3wProjectApp), Project).filter(group=instance) projects = list(set(projects) | set(projects_anonymous)) for project in projects: self.projects[g3wProjectApp + '-' + str(project.id)] = project if project.pk == int( self.projectId) and g3wProjectApp == self.projectType: self.project = project # project thumbnail project_thumb = project.thumbnail.name if bool(project.thumbnail.name) \ else '{}client/images/FakeProjectThumb.png'.format(settings.STATIC_URL) # Get project url if project.url_alias: url = reverse('group-project-map-alias', args=[project.url_alias])[1:] else: url = reverse( 'group-project-map', args=[project.group.slug, g3wProjectApp, project.pk])[1:] ret['projects'].append({ 'id': project.id, 'title': project.title, 'description': project.description, 'thumbnail': project_thumb, 'type': g3wProjectApp, 'gid': "{}:{}".format(g3wProjectApp, project.id), 'modified': project.modified.timestamp() if hasattr( project, 'modified') else 0, 'url': url }) # baselayers ret['baselayers'] = [] baselayers = instance.baselayers.all().order_by('order') for baselayer in baselayers: ret['baselayers'].append(BaseLayerSerializer(baselayer).data) # add vendorkeys if it is set into settings if settings.VENDOR_KEYS: ret['vendorkeys'] = settings.VENDOR_KEYS # add initproject and overviewproject ret['initproject'] = "{}:{}".format(self.projectType, self.projectId) # add overviewproject is present overviewproject = instance.project_panoramic.all() if overviewproject: overviewproject = overviewproject[0] ret['overviewproject'] = { 'id': int(overviewproject.project_id), 'type': overviewproject.project_type, 'gid': "{}:{}".format(overviewproject.project_type, overviewproject.project_id) } else: ret['overviewproject'] = None ret['plugins'] = {} # Plugins/Module data # Data from plugins can be instance of dict or list # - dict results are used only for update 'plugins' API return data # - list results are more verbose and action on 'plugins' API section is declared, ie: # { # 'mode': 'delete', # 'data': [<list_plugins_section_to_remove>] # }, # { # 'mode': 'update', # 'data': { # '<lugins_name>: { # ... # } # } # } plugins = initconfig_plugin_start.send(sender=self, project=self.projectId, projectType=self.projectType) for data_plugin in plugins: if data_plugin[1] and isinstance(data_plugin[1], dict): ret['plugins'] = copy(ret['plugins']) ret['plugins'].update(data_plugin[1]) elif data_plugin[1] and isinstance(data_plugin[1], list): for dp in data_plugin[1]: if dp['mode'] == 'delete': ret['plugins'] = copy(ret['plugins']) for k in dp['data']: try: ret['plugins'].pop(k) except: pass elif dp['mode'] == 'update': ret['plugins'] = copy(ret['plugins']) ret['plugins'].update(dp['data']) # powerd_by ret['powered_by'] = settings.G3WSUITE_POWERD_BY # header customs links header_custom_links = getattr(settings, 'G3W_CLIENT_HEADER_CUSTOM_LINKS', None) ret['header_custom_links'] = [] if header_custom_links: # check for possible callback for head_link in header_custom_links: if callable(head_link): ret['header_custom_links'].append(head_link(self.request)) else: ret['header_custom_links'].append(head_link) # custom layout ret['layout'] = {} # add legend settings if set to layout layout_legend = getattr(settings, 'G3W_CLIENT_LEGEND', None) if layout_legend: ret['layout']['legend'] = layout_legend # Check if G3W_CLIENT_LEGEND['layertitle'] set it tu false if self.project.legend_position == 'toc': if layout_legend: ret['layout']['legend']['layertitle'] = False else: ret['layout']['legend'] = {'layertitle': False} # add legend settings if set to layout layout_right_panel = getattr(settings, 'G3W_CLIENT_RIGHT_PANEL', None) if layout_right_panel: ret['layout']['rightpanel'] = layout_right_panel return ret
def to_representation(self, instance): ret = super(LayerSerializer, self).to_representation(instance) qgs_maplayer = self.qgs_project.mapLayers()[instance.qgs_layer_id] group = instance.project.group # add attributes/fields ret['fields'] = self.get_attributes(instance) # add infoformat and infourl ret['infoformat'] = '' ret['infourl'] = '' lidname = instance.qgs_layer_id if instance.project.wms_use_layer_ids else instance.name # add bbox if instance.geometrytype != QGIS_LAYER_TYPE_NO_GEOM: if instance.extent: ret['bbox'] = instance.extent_rect else: # get from QgsMapLayer instance extent = qgs_maplayer.extent() ret['bbox'] = {} ret['bbox']['minx'] = extent.xMinimum() ret['bbox']['miny'] = extent.yMinimum() ret['bbox']['maxx'] = extent.xMaximum() ret['bbox']['maxy'] = extent.yMaximum() # add capabilities ret['capabilities'] = get_capabilities4layer(qgs_maplayer) # add styles # FIXME: restore in the future for styles map management #ret['styles'] = self.qgis_projectsettings_wms.layers[lidname]['styles'] ret['source'] = {'type': instance.layer_type} # add options for wms layer if instance.layer_type in [ Layer.TYPES.wms, Layer.TYPES.arcgismapserver ]: if instance.layer_type == Layer.TYPES.wms: datasourceWMS = QueryDict(instance.datasource) else: datasourceWMS = datasourcearcgis2dict(instance.datasource) if ('username' not in ret['source'] or 'password' not in ret['source']) and 'type=xyz' \ not in instance.datasource: # rebuild the dict for paramenters repeat n times i.e. 'layers' and 'styles' if isinstance(datasourceWMS, QueryDict): for p in datasourceWMS.lists(): if p[0] in ('layers', 'styles'): ret['source'].update({p[0]: ','.join(p[1])}) else: ret['source'].update({p[0]: datasourceWMS[p[0]]}) else: ret['source'].update(datasourceWMS) ret['source']['external'] = instance.external # replace crs property if is not none with dict structure if ret['crs']: crs = QgsCoordinateReferenceSystem(f'EPSG:{ret["crs"]}') ret['crs'] = { 'epsg': crs.postgisSrid(), 'proj4': crs.toProj4(), 'geographic': crs.isGeographic(), 'axisinverted': crs.hasAxisInverted() } # add metadata ret['metadata'] = self.get_metadata(instance, qgs_maplayer) # eval editor_form_structure if ret['editor_form_structure']: ret['editor_form_structure'] = eval(instance.editor_form_structure) # add ows ret['ows'] = self.get_ows(instance) return ret
def build_layer_table(layer_list=None, only_raster_boundingbox=True): """Build a table of layer properties. Can be used in conjunction with selecting layers to exclude from mapcomboboxes Layer_list: default None if None then it will build the table from all layers in the QGIS project otherwise it will use the list. only_raster_boundingbox: default False create a bounding box from the raster data ie removing nodata from polygon. This will slow it down if large numbers of rasters are present. """ dest_crs = QgsProject.instance().crs() gdf_layers = gpd.GeoDataFrame(columns=[ 'layer', 'layer_name', 'layer_id', 'layer_type', 'source', 'format', 'epsg', 'crs_name', 'is_projected', 'extent', 'provider', 'geometry' ], geometry='geometry', crs=dest_crs.authid()) # pd.DataFrame() if layer_list is None or len(layer_list) == 0: layermap = QgsProject.instance().mapLayers().values() else: layermap = layer_list new_rows = [] for layer in layermap: if layer.type() not in [ QgsMapLayer.VectorLayer, QgsMapLayer.RasterLayer ]: continue if layer.providerType() not in ['ogr', 'gdal', 'delimitedtext']: continue if layer.type() == QgsMapLayer.VectorLayer: format = layer.dataProvider().storageType() else: format = None if layer.crs().isValid() and layer.crs().authid() == '': # Try and convert older style coordinates systems # were correctly definied in QGIS 2 as GDA94 / MGA zone 54 # but get interpreted in QGIS 3 as Unknown CRS: BOUNDCRS[SOURCECRS[PROJCRS["GDA94 / MGA zone 54",..... layer_crs = QgsCoordinateReferenceSystem() if not layer_crs.createFromProj(layer.crs().toWkt()): #print('Could not match a coordinate system for {}'.format(layer.id())) layer_crs = layer.crs() # could apply to the layer, but what if it's wrong.... #layer.setCrs(layer_crs) else: layer_crs = layer.crs() # project the bounding box extents to be the same as the qgis project. if layer_crs.authid() != dest_crs.authid(): transform = QgsCoordinateTransform(layer_crs, dest_crs, QgsProject.instance()) prj_ext = transform.transformBoundingBox(layer.extent()) else: prj_ext = layer.extent() row_dict = { 'layer': layer, 'layer_name': layer.name(), 'layer_id': layer.id(), 'layer_type': layerTypes[layer.type()], 'format': format, 'source': get_layer_source(layer), 'epsg': layer_crs.authid(), 'crs_name': layer_crs.description(), 'is_projected': not layer_crs.isGeographic(), 'provider': layer.providerType(), 'geometry': wkt.loads(prj_ext.asWktPolygon()) } # 'extent': prj_ext.asWktPolygon(), if layer.type() == QgsMapLayer.RasterLayer: pixel_size = get_pixel_size(layer) if not only_raster_boundingbox: with rasterio.open(get_layer_source(layer)) as src: msk = src.dataset_mask() # 0 = nodata 255=valid rast_shapes = rasterio.features.shapes( np.ma.masked_equal(np.where(msk > 0, 1, 0), 0), transform=src.transform) try: results = ({ 'properties': { 'raster_val': v }, 'geometry': s } for i, (s, v) in enumerate(rast_shapes)) geoms = list(results) gpd_rPoly = gpd.GeoDataFrame.from_features( geoms, crs=layer.crs().authid()) dest_crs.authid().replace('epgs:', '') gpd_rPoly.to_crs(dest_crs.authid().replace('epgs:', ''), inplace=True) row_dict.update({'geometry': gpd_rPoly.unary_union}) del gpd_rPoly, results, msk, rast_shapes except: pass row_dict.update({ 'bandcount': layer.bandCount(), 'datatype': dataTypes[layer.dataProvider().dataType(1)], 'pixel_size': pixel_size[0], 'pixel_text': '{} {}'.format(*pixel_size), }) new_rows.append(row_dict) # gdf_layers = gpd.GeoDataFrame(new_rows, geometry='extent') if len(new_rows) == 0: return gdf_layers # for pandas 0.23.4 add sort=False to prevent row and column orders to change. try: gdf_layers = gdf_layers.append(new_rows, ignore_index=True, sort=False) except: gdf_layers = gdf_layers.append(new_rows, ignore_index=True) #df_layers.set_geometry('geometry') return gdf_layers
def processAlgorithm(self, parameters, context, feedback): # inputs rasters = self.parameterAsLayerList(parameters, self.RASTERLIST, context) if rasters is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.RASTERLIST)) reamostragem = self.parameterAsEnum(parameters, self.RESAMPLING, context) reamostragem = ['nearest', 'bilinear', 'bicubic'][reamostragem] sobrep = self.parameterAsEnum(parameters, self.OVERLAP, context) muda_res = self.parameterAsBool(parameters, self.CHANGERESOLUTION, context) resolucao = self.parameterAsDouble(parameters, self.RESOLUTION, context) valor_nulo = self.parameterAsDouble(parameters, self.NULLVALUE, context) moldura = self.parameterAsDouble(parameters, self.CLIP, context) if moldura: vlayer = self.parameterAsVectorLayer(parameters, self.FRAME, context) if vlayer is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.FRAME)) # output Output = self.parameterAsFileOutput(parameters, self.MOSAIC, context) Carregar = self.parameterAsBool(parameters, self.OPEN, context) lista = [] for raster_lyr in rasters: lista += [raster_lyr.dataProvider().dataSourceUri()] if len(lista) < 1: raise QgsProcessingException( self.tr('At least one raster must be selected!', 'Pelo menos um raster deve ser selecionado!')) if len(lista) == 1: sobrep = 0 # apenas um raster (sem sobreposicao) # Gerar geometria para cada raster geoms = [] SRC = [] n_bands = [] GDT = [] nulos = [] XRES, YRES = [], [] for item in lista: image = gdal.Open(item) SRC += [QgsCoordinateReferenceSystem(image.GetProjection())] # wkt ulx, xres, xskew, uly, yskew, yres = image.GetGeoTransform() cols = image.RasterXSize rows = image.RasterYSize n_bands += [image.RasterCount] GDT += [image.GetRasterBand(1).DataType] nulos += [image.GetRasterBand(1).GetNoDataValue()] XRES += [xres] YRES += [yres] image = None # Close image # Creating BBox coord = [[ QgsPointXY(ulx, uly), QgsPointXY(ulx + cols * xres, uly), QgsPointXY(ulx + cols * xres, uly + rows * yres), QgsPointXY(ulx, uly + rows * yres), QgsPointXY(ulx, uly) ]] geom = QgsGeometry.fromPolygonXY(coord) geoms += [geom] ## Validar dados de entrada # Mesmo numero de bandas if not n_bands.count(n_bands[0]) == len(n_bands): raise QgsProcessingException( self.tr('The images must have the same number of bands!', 'As imagens devem ter o mesmo número de bandas!')) # Mesmo SRC if not SRC.count(SRC[0]) == len(SRC): raise QgsProcessingException( self.tr('The images must have the same CRS!', 'As imagens devem ter o mesmo SRC!')) # Mesmo GDT if not GDT.count(GDT[0]) == len(GDT): raise QgsProcessingException( self.tr('The images must have the same data type!', 'As imagens devem ter o tipo de dado!')) # Mesmo valor nulo if not nulos.count(nulos[0]) == len(nulos): raise QgsProcessingException( self.tr( 'The images must have the same definied null value!', 'As imagens devem ter o mesmo valor para definir pixel nulo!' )) # Dados para o raster de saída prj = SRC[0].toWkt() n_bands = n_bands[0] GDT = GDT[0] xres = np.mean(XRES) yres = np.mean(YRES) NULO = valor_nulo if valor_nulo == -1: valor_nulo = nulos[0] if nulos[0] is not None else 0 if moldura: # Pegar extensão X e Y da moldura # SRC da moldura deve ser o mesmo dos raster if vlayer.sourceCrs() != QgsCoordinateReferenceSystem(prj): raise QgsProcessingException( self.tr( "The frame's CRS must be iqual to the rasters' CRS!", 'O SRC da moldura deve ser igual ao SRC dos rasters!')) for feat in vlayer.getFeatures(): moldura_geom = feat.geometry() break moldura_rect = moldura_geom.boundingBox() y_min = moldura_rect.yMinimum() y_max = moldura_rect.yMaximum() x_min = moldura_rect.xMinimum() x_max = moldura_rect.xMaximum() else: # Mesclar geometrias e obter a extensão new_geom = QgsGeometry() new_geom = new_geom.unaryUnion(geoms) extensao = new_geom.boundingBox() # Coodenadas máxima e mínima da extensão y_min = extensao.yMinimum() y_max = extensao.yMaximum() x_min = extensao.xMinimum() x_max = extensao.xMaximum() # Transformar resolucao de metros para graus, se o SRC for Geográfico src_qgis = QgsCoordinateReferenceSystem(prj) if src_qgis.isGeographic(): EPSG = int(src_qgis.authid().split(':')[-1]) proj_crs = CRS.from_epsg(EPSG) a = proj_crs.ellipsoid.semi_major_metre f = 1 / proj_crs.ellipsoid.inverse_flattening e2 = f * (2 - f) N = a / np.sqrt(1 - e2 * (np.sin( (y_min + y_max) / 2))**2) # Raio de curvatura 1º vertical M = a * (1 - e2) / (1 - e2 * (np.sin((y_min + y_max) / 2))**2)**( 3 / 2.) # Raio de curvatura meridiana R = np.sqrt(M * N) # Raio médio de Gauss theta = resolucao / R resolucao = np.degrees(theta) # Radianos para graus # Definir n_col, n_lin e resolucao if moldura: if muda_res: n_lin = round((y_max - y_min) / abs(resolucao)) n_col = round((x_max - x_min) / abs(resolucao)) else: n_lin = round((y_max - y_min) / abs(yres)) n_col = round((x_max - x_min) / abs(xres)) xres = (x_max - x_min) / n_col yres = -(y_max - y_min) / n_lin else: if muda_res: n_lin = round((y_max - y_min) / abs(resolucao)) n_col = round((x_max - x_min) / abs(resolucao)) xres = resolucao yres = -resolucao else: n_lin = round((y_max - y_min) / abs(yres)) n_col = round((x_max - x_min) / abs(xres)) xres = (x_max - x_min) / n_col yres = -(y_max - y_min) / n_lin feedback.pushInfo( self.tr('Resolution: ', 'Resolução: ') + str(n_lin) + 'x' + str(n_col)) # Geotransform do Mosaico ulx = x_min uly = y_max xskew, yskew = 0, 0 geotransform = [ulx, xres, xskew, uly, yskew, yres] origem = (ulx, uly) resol_X = abs(xres) resol_Y = abs(yres) # Numeração das Imagens valores = list(range(1, len(lista) + 1)) # Definição de áreas de varredura feedback.pushInfo( self.tr('Defining mosaic filling areas...', 'Definindo áreas de preenchimento do mosaico...')) # Gerar combinações dos Rasters if sobrep != 0: combs = [] feedback.pushInfo( self.tr('Creating combinations...', 'Gerando combinações...')) for k in range(1, 5): combs += list(combinations(valores, k)) if feedback.isCanceled(): break # Armazenar geometrias exclusivas de cada combinação classes = {} feedback.pushInfo( self.tr('Indentifying combinations...', 'Identificando combinações...')) Percent = 100.0 / (len(combs)) current = 0 for comb in combs: if len(comb) == 1: geom1 = geoms[comb[0] - 1] lista_outras = [] for geom in geoms: if geom1 != geom: lista_outras += [geom] outras = QgsGeometry() outras = outras.unaryUnion(lista_outras) diferença = geom1.difference(outras) if not diferença.isEmpty(): classes[comb] = {'geom': diferença} elif len(comb) < len(valores): intersecao = geoms[comb[0] - 1] sentinela = True for ind in comb[1:]: geom = geoms[ind - 1] if geom.intersects(intersecao): intersecao = intersecao.intersection(geom) else: sentinela = False continue lista_outras = [] for valor in valores: if valor not in comb: lista_outras += [geoms[valor - 1]] outras = QgsGeometry() outras = outras.unaryUnion(lista_outras) if sentinela: diferença = intersecao.difference(outras) if not diferença.isEmpty(): classes[comb] = {'geom': diferença} else: intersecao = geoms[comb[0] - 1] sentinela = True for ind in comb[1:]: geom = geoms[ind - 1] if geom.intersects(intersecao): intersecao = intersecao.intersection(geom) else: sentinela = False continue if sentinela: classes[comb] = {'geom': intersecao} if feedback.isCanceled(): break current += 1 feedback.setProgress(int(current * Percent)) else: # Gerar geometrias por área sem cálculo de sobreposição ("first") combs = np.array(valores)[:, np.newaxis] classes = {} acumulado = geoms[combs[0][0] - 1] classes[(1, )] = {'geom': acumulado} for k in range(1, len(combs)): comb = combs[k] geom = geoms[comb[0] - 1] diferenca = geom.difference(acumulado) classes[(comb[0], )] = {'geom': diferenca} acumulado = acumulado.combine(geom) if feedback.isCanceled(): break # Gerar lista com os valores classificados Percent = 100.0 / (len(classes)) current = 0 for classe in classes: feedback.pushInfo( (self.tr('Classifying class {}...', 'Classificando classe {}...')).format(str(classe))) geom = classes[classe]['geom'] if moldura: geom = geom.intersection(moldura_geom) if geom.type() == 2: if geom.isMultipart(): coords = geom.asMultiPolygon()[0][0] else: coords = geom.asPolygon()[0] else: del classes[classe] continue caminho = [] for ponto in coords: linha = (origem[1] - ponto.y()) / resol_Y coluna = (ponto.x() - origem[0]) / resol_X caminho += [(linha, coluna)] p = path.Path(caminho) box = geom.boundingBox() uly = box.yMaximum() lry = box.yMinimum() ulx = box.xMinimum() lrx = box.xMaximum() # Limites de Varredura row_ini = int(round((origem[1] - uly) / resol_Y - 0.5)) - 1 row_fim = int(round((origem[1] - lry) / resol_Y - 0.5)) + 1 col_ini = int(round((ulx - origem[0]) / resol_X - 0.5)) - 1 col_fim = int(round((lrx - origem[0]) / resol_X - 0.5)) + 1 lin, col = np.meshgrid(np.arange(row_ini, row_fim), np.arange(col_ini, col_fim)) LIN = lin.flatten()[:, np.newaxis] + 0.5 # centro do pixel COL = col.flatten()[:, np.newaxis] + 0.5 pixels_center = np.hstack((LIN, COL)) # Verificando pixels dentro de poligono flags = p.contains_points(pixels_center) pixels_x = LIN.flatten() * flags pixels_y = COL.flatten() * flags pixels_x = (pixels_x[pixels_x > 0] - 0.5).astype('int')[:, np.newaxis] pixels_y = (pixels_y[pixels_y > 0] - 0.5).astype('int')[:, np.newaxis] pixels = np.hstack((pixels_x, pixels_y)) classes[classe]['pixels'] = pixels current += 1 feedback.setProgress(int(current * Percent)) # Criar Raster Driver = gdal.GetDriverByName('GTiff').Create(Output, n_col, n_lin, n_bands, GDT) Driver.SetGeoTransform(geotransform) Driver.SetProjection(prj) # Mosaicar por banda Percent = 100.0 / (n_lin * n_col * n_bands) current = 0 for k in range(n_bands): feedback.pushInfo( (self.tr('Creating band {}...', 'Criando banda {}...')).format(str(k + 1))) # Criar Array do mosaico tipo = gdal_array.GDALTypeCodeToNumericTypeCode(GDT) inteiro = True if GDT in (gdal.GDT_Byte, gdal.GDT_UInt16, gdal.GDT_Int16, gdal.GDT_UInt32, gdal.GDT_Int32) else False banda = np.ones( (n_lin, n_col), dtype=tipo) * (int(valor_nulo) if inteiro else valor_nulo) imgs = {} # Para cada classe abrir banda da(s) imagem(ns) for classe in classes: # Deixando somente imagens a serem utilizadas for item in valores: if (item not in classe) and (item in imgs): del imgs[item] # Preenchendo dados da imagem no dicionário for img in classe: if img not in imgs or len(lista) == 1: img_path = lista[img - 1] image = gdal.Open(img_path) ulx, xres, xskew, uly, yskew, yres = image.GetGeoTransform( ) img_origem = (ulx, uly) img_resol_X = abs(xres) img_resol_Y = abs(yres) img_band = image.GetRasterBand(k + 1).ReadAsArray() imgs[img] = { 'band': img_band, 'xres': img_resol_X, 'yres': img_resol_Y, 'origem': img_origem } image = None if sobrep == 0: # Se for "primeiro", interpolar apenas da primeira img da comb, caso contrário img = classe[0] # Para cada pixel da classe for px in classes[classe]['pixels']: lin, col = px X = origem[0] + resol_X * (col + 0.5) Y = origem[1] - resol_Y * (lin + 0.5) Interpolado = self.Interpolar(X, Y, imgs[img]['band'], imgs[img]['origem'], imgs[img]['xres'], imgs[img]['yres'], reamostragem, valor_nulo) if Interpolado != valor_nulo: banda[lin][col] = round( Interpolado) if inteiro else Interpolado if feedback.isCanceled(): break current += 1 feedback.setProgress(int(current * Percent)) else: # Para cada pixel da classe interpolar o valor da banda de cada img for px in classes[classe]['pixels']: lin, col = px X = origem[0] + resol_X * (col + 0.5) Y = origem[1] - resol_Y * (lin + 0.5) interp_values = [] for img in imgs: Interpolado = self.Interpolar( X, Y, imgs[img]['band'], imgs[img]['origem'], imgs[img]['xres'], imgs[img]['yres'], reamostragem, valor_nulo) if Interpolado != valor_nulo: interp_values += [Interpolado] # Calcular o valor agregado (0:first, 1:average, 2:median, 3:min, 4:max) e inserir na banda (se byte, arredondar) if interp_values: if sobrep == 1: result = np.mean(interp_values) elif sobrep == 2: result = np.median(interp_values) elif sobrep == 3: result = np.min(interp_values) elif sobrep == 4: result = np.max(interp_values) banda[lin][col] = round( result) if inteiro else result if feedback.isCanceled(): break current += 1 feedback.setProgress(int(current * Percent)) # Salvar banda outband = Driver.GetRasterBand(k + 1) feedback.pushInfo( self.tr('Writing Band {}...'.format(k + 1), 'Escrevendo Banda {}...'.format(k + 1))) outband.WriteArray(banda) if NULO != -1: outband.SetNoDataValue(valor_nulo) # Salvar e Fechar Raster Driver.FlushCache() # Escrever no disco Driver = None # Salvar e fechar feedback.pushInfo( self.tr('Operation completed successfully!', 'Operação finalizada com sucesso!')) feedback.pushInfo('Leandro França - Eng Cart') self.CAMINHO = Output self.CARREGAR = Carregar return {self.MOSAIC: Output}
def to_representation(self, instance): ret = super(LayerSerializer, self).to_representation(instance) qgs_maplayer = self.qgs_project.mapLayers()[instance.qgs_layer_id] # add attributes/fields ret['fields'] = self.get_attributes(instance) # add infoformat and infourl ret['infoformat'] = '' ret['infourl'] = '' #lidname = instance.qgs_layer_id if instance.project.wms_use_layer_ids else instance.name # add bbox if instance.geometrytype != QGIS_LAYER_TYPE_NO_GEOM: if instance.extent: ret['bbox'] = instance.extent_rect else: # get from QgsMapLayer instance extent = qgs_maplayer.extent() ret['bbox'] = {} ret['bbox']['minx'] = extent.xMinimum() ret['bbox']['miny'] = extent.yMinimum() ret['bbox']['maxx'] = extent.xMaximum() ret['bbox']['maxy'] = extent.yMaximum() # add capabilities ret['capabilities'] = get_capabilities4layer(qgs_maplayer) # add styles # FIXME: restore in the future for styles map management #ret['styles'] = self.qgis_projectsettings_wms.layers[lidname]['styles'] ret['source'] = {'type': instance.layer_type} # add options for wms layer if instance.layer_type in [ Layer.TYPES.wms, Layer.TYPES.arcgismapserver ]: if instance.layer_type == Layer.TYPES.wms: datasource_wms = QueryDict(instance.datasource) else: datasource_wms = datasourcearcgis2dict(instance.datasource) if ('username' not in ret['source'] or 'password' not in ret['source']) and 'type=xyz' \ not in instance.datasource: # rebuild the dict for paramenters repeat n times i.e. 'layers' and 'styles' if isinstance(datasource_wms, QueryDict): for p in datasource_wms.lists(): if p[0] in ('layers', 'styles'): ret['source'].update({p[0]: ','.join(p[1])}) else: ret['source'].update({p[0]: datasource_wms[p[0]]}) else: ret['source'].update(datasource_wms) ret['source']['external'] = instance.external if instance.external and instance.layer_type == Layer.TYPES.wms: try: wms = WebMapService(ret['source']['url'], version='1.3.0') format_options = wms.getOperationByName( 'GetFeatureInfo').formatOptions if format_options: # Filter format by supported by G3W-CLIENT formats = list( set(format_options).intersection( set(settings.EXTERNAL_WMS_INFOFORMATS_SUPPORTED ))) if formats: ret['infoformat'] = formats[0] ret['infoformats'] = formats except Exception as e: logger.debug( f'WMS layer GetFeatureInfo formats available: {e}') # replace crs property if is not none with dict structure if ret['crs']: crs = QgsCoordinateReferenceSystem(f'EPSG:{ret["crs"]}') # Patch for Proj4 > 4.9.3 version if ret["crs"] == 3003: proj4 = "+proj=tmerc +lat_0=0 +lon_0=9 +k=0.9996 +x_0=1500000 +y_0=0 +ellps=intl " \ "+towgs84=-104.1,-49.1,-9.9,0.971,-2.917,0.714,-11.68 +units=m +no_defs" else: proj4 = crs.toProj4() ret['crs'] = { 'epsg': crs.postgisSrid(), 'proj4': proj4, 'geographic': crs.isGeographic(), 'axisinverted': crs.hasAxisInverted() } # add metadata ret['metadata'] = self.get_metadata(instance, qgs_maplayer) # eval editor_form_structure if ret['editor_form_structure']: ret['editor_form_structure'] = eval(instance.editor_form_structure) # add ows ret['ows'] = self.get_ows(instance) # For temporal properties if instance.temporal_properties: ret['qtimeseries'] = json.loads(instance.temporal_properties) if ret['qtimeseries'] and ret['qtimeseries'][ 'mode'] == 'FeatureDateTimeInstantFromField': # Add start_date end end_date: findex = qgs_maplayer.dataProvider().fieldNameIndex( ret['qtimeseries']['field']) ret['qtimeseries']['start_date'] = qgs_maplayer.minimumValue( findex) ret['qtimeseries']['end_date'] = qgs_maplayer.maximumValue( findex) if isinstance(ret['qtimeseries']['start_date'], QDate) or isinstance( ret['qtimeseries']['start_date'], QDateTime): if not hasattr(QDate, 'isoformat'): QDate.isoformat = lambda d: d.toString(Qt.ISODate) if not hasattr(QDateTime, 'isoformat'): QDateTime.isoformat = lambda d: d.toString( Qt.ISODateWithMs) ret['qtimeseries']['start_date'] = ret['qtimeseries'][ 'start_date'].isoformat() ret['qtimeseries']['end_date'] = ret['qtimeseries'][ 'end_date'].isoformat() return ret
def to_representation(self, instance): ret = super(GroupSerializer, self).to_representation(instance) # add header_logo # before check macrogroups and groups number also if is equal to 1 use it try: macrogroup = instance.macrogroups.get(use_logo_client=True) ret['header_logo_img'] = macrogroup.logo_img.name except: ret['header_logo_img'] = instance.header_logo_img.name try: macrogroup = instance.macrogroups.get(use_title_client=True) ret['name'] = macrogroup.title except: # change groupData name with title for i18n app ret['name'] = instance.title # add crs: crs = QgsCoordinateReferenceSystem(f'EPSG:{self.instance.srid.srid}') ret['crs'] = { 'epsg': crs.postgisSrid(), 'proj4': crs.toProj4(), 'geographic': crs.isGeographic(), 'axisinverted': crs.hasAxisInverted() } # map controls ret['mapcontrols'] = [ mapcontrol.name for mapcontrol in instance.mapcontrols.all() ] # add projects to group ret['projects'] = [] self.projects = {} anonymous_user = get_user_model().get_anonymous() for g3wProjectApp in settings.G3WADMIN_PROJECT_APPS: Project = apps.get_app_config(g3wProjectApp).get_model('project') projects = get_objects_for_user(self.request.user, '{}.view_project'.format(g3wProjectApp), Project) \ .filter(group=instance) projects_anonymous = get_objects_for_user( anonymous_user, '{}.view_project'.format(g3wProjectApp), Project).filter(group=instance) projects = list(set(projects) | set(projects_anonymous)) print(projects) for project in projects: self.projects[g3wProjectApp + '-' + str(project.id)] = project if project.pk == int( self.projectId) and g3wProjectApp == self.projectType: self.project = project # project thumbnail project_thumb = project.thumbnail.name if bool(project.thumbnail.name) \ else '{}client/images/FakeProjectThumb.png'.format(settings.STATIC_URL) ret['projects'].append({ 'id': project.id, 'title': project.title, 'description': project.description, 'thumbnail': project_thumb, 'type': g3wProjectApp, 'gid': "{}:{}".format(g3wProjectApp, project.id), 'modified': project.modified.timestamp() if hasattr( project, 'modified') else 0 }) # baselayers ret['baselayers'] = [] baselayers = instance.baselayers.all().order_by('order') for baselayer in baselayers: ret['baselayers'].append(BaseLayerSerializer(baselayer).data) # add vendorkeys if it is set into settings if settings.VENDOR_KEYS: ret['vendorkeys'] = settings.VENDOR_KEYS # add initproject and overviewproject ret['initproject'] = "{}:{}".format(self.projectType, self.projectId) # add overviewproject is present overviewproject = instance.project_panoramic.all() if overviewproject: overviewproject = overviewproject[0] ret['overviewproject'] = { 'id': int(overviewproject.project_id), 'type': overviewproject.project_type, 'gid': "{}:{}".format(overviewproject.project_type, overviewproject.project_id) } else: ret['overviewproject'] = None ret['plugins'] = {} # plugins/module data dataPlugins = initconfig_plugin_start.send( sender=self, project=self.projectId, projectType=self.projectType) for dataPlugin in dataPlugins: if dataPlugin[1]: ret['plugins'] = copy(ret['plugins']) ret['plugins'].update(dataPlugin[1]) # powerd_by ret['powered_by'] = settings.G3WSUITE_POWERD_BY # header customs links header_custom_links = getattr(settings, 'G3W_CLIENT_HEADER_CUSTOM_LINKS', None) ret['header_custom_links'] = [] if header_custom_links: # check for possible callback for head_link in header_custom_links: if callable(head_link): ret['header_custom_links'].append(head_link(self.request)) else: ret['header_custom_links'].append(head_link) # custom layout ret['layout'] = {} # add legend settings if set to layout layout_legend = getattr(settings, 'G3W_CLIENT_LEGEND', None) if layout_legend: ret['layout']['legend'] = layout_legend # Check if G3W_CLIENT_LEGEND['layertitle'] set it tu false if self.project.legend_position == 'toc': if layout_legend: ret['layout']['legend']['layertitle'] = False else: ret['layout']['legend'] = {'layertitle': False} # add legend settings if set to layout layout_right_panel = getattr(settings, 'G3W_CLIENT_RIGHT_PANEL', None) if layout_right_panel: ret['layout']['rightpanel'] = layout_right_panel return ret
def post(self, request, **kwargs): # Check for content type accept only 'application/json' if request.content_type != 'application/json': return APIException( "Interface OWS accept only 'application/json request'") post_data = json.loads(request.body) # Required url = post_data.get('url') if not url: raise APIException("'url' parameter must be provided.") service = post_data.get('service') if not service: raise APIException("'service' parameter must be provided.") service = service.lower() if service not in self._service_available.keys(): raise APIException(f"Service '{service}' is not available.") # Not required: version = post_data.get('version', '1.3.0') ows = self._service_available[service](url, version=version) # Identification # ----------------------------------- self.results.results.update({ 'title': ows.identification.title, 'abstract': ows.identification.abstract }) # Map formats # ----------------------------------- self.results.results.update( {'map_formats': ows.getOperationByName('GetMap').formatOptions}) # Info formats # ----------------------------------- self.results.results.update({ 'info_formats': ows.getOperationByName('GetFeatureInfo').formatOptions }) # Layers # ----------------------------------- available_layers = list(ows.contents) # add styles for every layer layers = [] for al in available_layers: # Build crs crss = [] for srid in ows[al].crsOptions: crs = QgsCoordinateReferenceSystem(srid) if crs.postgisSrid() == 3003: proj4 = settings.PROJ4_EPSG_3003 else: proj4 = crs.toProj4() crss.append({ 'epsg': crs.postgisSrid(), 'proj4': proj4, 'geographic': crs.isGeographic(), 'axisinverted': crs.hasAxisInverted() }) layers.append({ 'name': al, 'title': ows[al].title, 'abstract': ows[al].abstract, 'crss': crss, 'styles': ows[al].styles, 'parent': ows[al].parent.id if ows[al].parent else None }) self.results.results.update({'layers': layers}) return Response(self.results.results)