コード例 #1
0
ファイル: functions.py プロジェクト: lmotta/ibama_expressions
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()
コード例 #2
0
 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}
コード例 #3
0
    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
コード例 #5
0
ファイル: serializers.py プロジェクト: g3w-suite/g3w-admin
    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
コード例 #6
0
ファイル: serializers.py プロジェクト: leolami/g3w-admin
    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
コード例 #7
0
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
コード例 #8
0
    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}
コード例 #9
0
ファイル: serializers.py プロジェクト: g3w-suite/g3w-admin
    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
コード例 #10
0
    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
コード例 #11
0
ファイル: views.py プロジェクト: nstoykov/g3w-admin
    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)