예제 #1
0
    def update_from_geojson(self,
                            geojson,
                            crs_src='epsg:4326',
                            datatype='polygon',
                            wrap=False):
        log('Setting up AOI with geojson. Wrap is {}.'.format(wrap))
        self.datatype = datatype
        # Note geojson is assumed to be in 4326
        l = QgsVectorLayer(
            "{datatype}?crs={crs}".format(datatype=self.datatype, crs=crs_src),
            "calculation boundary", "memory")
        fields = QgsJsonUtils.stringToFields(json.dumps(geojson),
                                             QTextCodec.codecForName('UTF8'))
        features = QgsJsonUtils.stringToFeatureList(
            json.dumps(geojson), fields, QTextCodec.codecForName('UTF8'))
        l.dataProvider().addFeatures(features)
        l.commitChanges()
        if not l.isValid():
            QtWidgets.QMessageBox.critical(
                None, tr("Error"),
                tr("Failed to add geojson to temporary layer."))
            log("Failed to add geojson to temporary layer.")
            return

        self.l = transform_layer(l,
                                 self.crs_dst,
                                 datatype=self.datatype,
                                 wrap=wrap)
예제 #2
0
def featuresToQgs(features):
    '''Accepts a list of geojson Features and returns a tuple of (features, fields)'''
    fc = {'type': 'FeatureCollection', 'features': features}
    fcString = json.dumps(fc)
    codec = QTextCodec.codecForName("UTF-8")
    fields = QgsJsonUtils.stringToFields(fcString, codec)
    features = QgsJsonUtils.stringToFeatureList(fcString, fields, codec)

    return (features, fields)
예제 #3
0
    def prepareAlgorithm(self, parameters, context, feedback):
        """
        Prepares the algorithm
        """
        self.engine = QJSEngine()
        js_feedback = self.engine.newQObject(feedback)
        QQmlEngine.setObjectOwnership(feedback, QQmlEngine.CppOwnership)
        self.engine.globalObject().setProperty("feedback", js_feedback)
        js = """
        function process(feature)
        {
          res = func(JSON.parse(feature))
          if ( res && res.stack && res.message )
            return res;
         return JSON.stringify(res);
        }
        """

        for param in self.parameterDefinitions():
            if param.isDestination():
                continue

            if param.name() not in parameters or parameters[param.name()] is None:
                js += '{}=None;\n'.format(param.name())
                continue

            if isinstance(param,
                            (QgsProcessingParameterField, QgsProcessingParameterString, QgsProcessingParameterFile)):
                value = self.parameterAsString(parameters, param.name(), context)
                js += '{}="{}";'.format(param.name(), value)
            elif isinstance(param, QgsProcessingParameterNumber):
                value = self.parameterAsDouble(parameters, param.name(), context)
                js += '{}={};'.format(param.name(), value)

        js += self.js_script
        result = self.engine.evaluate(js)

        user_func = self.engine.globalObject().property("func")
        if not user_func:
            raise QgsProcessingException('No \'func\' function detected in script')
        if not user_func.isCallable():
            raise QgsProcessingException('Object \'func\' is not a callable function')

        self.process_js_function = self.engine.globalObject().property("process")
        self.json_exporter = QgsJsonExporter()

        self.codec = QTextCodec.codecForName("System")

        return True
예제 #4
0
    def qgsfeature_feature_from_node(self, node: PlanetNode):

        # TODO: Resolve geometry by node_type or do that under node.geometry()?
        # geom = None
        # if node.node_type() == NodeT.DAILY_SCENE_IMAGE:
        #     geom = node.geometry()

        # TODO: Add node
        # feature_collect = {
        #     'type': 'FeatureCollection',
        #     'features': [
        #         {
        #             'type': 'Feature',
        #             'geometry': node.geometry(),
        #             'properties': {
        #                 'id': node.item_id()
        #             }
        #         }
        #     ]
        # }

        feature_collect = {
            'type': 'FeatureCollection',
            'features': [
                node.resource()
            ]
        }

        feature_collect_json = json.dumps(feature_collect)

        # noinspection PyUnusedLocal
        features = []
        # noinspection PyBroadException
        try:
            utf8 = QTextCodec.codecForName('UTF-8')
            # TODO: Add node id, properties as fields?
            fields = QgsFields()
            features = QgsJsonUtils().stringToFeatureList(
                string=feature_collect_json, fields=fields, encoding=utf8)
        except Exception:
            log.debug('Footprint GeoJSON could not be parsed')
            return

        if not len(features) > 0:
            log.debug('GeoJSON parsing created no features')
            return

        return features[0]
예제 #5
0
    def loadFields(self, vectorFile=''):
        self.zfieldCombo.clear()

        if not vectorFile:
            return

        try:
            (fields, names) = Utils.getVectorFields(vectorFile)
        except Utils.UnsupportedOGRFormat as e:
            QErrorMessage(self).showMessage(e.args[0])
            self.inSelector.setLayer(None)
            return

        ncodec = QTextCodec.codecForName(self.lastEncoding)
        for name in names:
            self.zfieldCombo.addItem(ncodec.toUnicode(name))
예제 #6
0
    def loadFields(self, vectorFile=''):
        self.zfieldCombo.clear()

        if not vectorFile:
            return

        try:
            (fields, names) = Utils.getVectorFields(vectorFile)
        except Utils.UnsupportedOGRFormat as e:
            QErrorMessage(self).showMessage(e.args[0])
            self.inSelector.setLayer(None)
            return

        ncodec = QTextCodec.codecForName(self.lastEncoding)
        for name in names:
            self.zfieldCombo.addItem(ncodec.toUnicode(name))
예제 #7
0
    def __init__(self, qgis_utils):
        QDialog.__init__(self)
        self.setupUi(self)
        self.qgis_utils = qgis_utils
        self.check_local_help()

        self.tb_changelog.setOpenExternalLinks(True)

        if QGIS_LANG == 'en':
            file = QFile(
                ":/Asistente-LADM_COL/resources/html/Changelog_en.html")
        else:
            file = QFile(":/Asistente-LADM_COL/resources/html/Changelog.html")

        if not file.open(QIODevice.ReadOnly | QIODevice.Text):
            raise Exception(file.errorString())

        codec = QTextCodec.codecForLocale()
        stream = QTextStream(file)
        stream.setCodec(codec)
        self.tb_changelog.setHtml(stream.readAll())
예제 #8
0
                       QgsProject,
                       QgsFeature,
                       QgsField,
                       QgsFields,
                       QgsWkbTypes,
                       QgsGeometry,
                       QgsPointV2,
                       QgsLineString,
                       NULL,
                       QgsVectorLayer,
                       QgsRelation
                       )
from qgis.PyQt.QtCore import QVariant, QTextCodec

start_app()
codec = QTextCodec.codecForName("System")


class TestQgsJSONUtils(unittest.TestCase):

    def testStringToFeatureList(self):
        """Test converting json string to features"""

        fields = QgsFields()
        fields.append(QgsField("name", QVariant.String))

        # empty string
        features = QgsJSONUtils.stringToFeatureList("", fields, codec)
        self.assertEqual(features, [])

        # bad string
예제 #9
0
    def get_feature_with_form_scope(params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None:
        """ Get filtered features with a form scope
        In parameters:
            LAYER=wms-layer-name
            FILTER=An expression to filter layer
            FORM_FEATURE={"type": "Feature", "geometry": {}, "properties": {}}
            // optionals
            FIELDS=list of requested field separated by comma
            WITH_GEOMETRY=False
        """
        layer_name = params.get('LAYER', '')
        if not layer_name:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'GetFeatureWithFormScope' REQUEST: LAYER parameter is mandatory",
                400)

        # get layer
        layer = find_vector_layer(layer_name, project)
        # layer not found
        if not layer:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid LAYER parameter for 'VirtualField': {} provided".format(layer_name),
                400)

        # get filter
        exp_filter = params.get('FILTER', '')
        if not exp_filter:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'GetFeatureWithFormScope' REQUEST: FILTER parameter is mandatory",
                400)

        # get form feature
        form_feature = params.get('FORM_FEATURE', '')
        if not form_feature:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE parameter is mandatory",
                400)

        # Check features
        try:
            geojson = json.loads(form_feature)
        except Exception:
            QgsMessageLog.logMessage(
                "JSON loads form feature '{}' exception:\n{}".format(form_feature, traceback.format_exc()),
                "lizmap", Qgis.Critical)
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed".format(form_feature),
                400)

        if not geojson or not isinstance(geojson, dict):
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed".format(form_feature),
                400)

        if ('type' not in geojson) or geojson['type'] != 'Feature':
            raise ExpressionServiceError(
                "Bad request error",
                ("Invalid 'GetFeatureWithFormScope' REQUEST: FORM_FEATURE '{}' are not well formed: type not defined "
                 "or not Feature.").format(form_feature),
                400)

        # try to load form feature
        # read fields
        form_feature_fields = QgsJsonUtils.stringToFields(
            form_feature,
            QTextCodec.codecForName("UTF-8"))
        # read features
        form_feature_list = QgsJsonUtils.stringToFeatureList(
            form_feature,
            form_feature_fields,
            QTextCodec.codecForName("UTF-8"))

        # features not well formed
        if not form_feature_list:
            raise ExpressionServiceError(
                "Bad request error",
                ("Invalid FORM_FEATURE for 'GetFeatureWithFormScope': not GeoJSON feature provided\n"
                 "{}").format(form_feature),
                400)

        if len(form_feature_list) != 1:
            raise ExpressionServiceError(
                "Bad request error",
                ("Invalid FORM_FEATURE for 'GetFeatureWithFormScope': not GeoJSON feature provided\n"
                 "{}").format(form_feature),
                400)

        # Get the form feature
        form_feat = form_feature_list[0]

        # create expression context
        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(QgsExpressionContextUtils.projectScope(project))
        exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))
        exp_context.appendScope(QgsExpressionContextUtils.formScope(form_feat))

        # create distance area context
        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs(), project.transformContext())
        da.setEllipsoid(project.ellipsoid())

        # Get filter expression
        exp_f = QgsExpression(exp_filter)
        exp_f.setGeomCalculator(da)
        exp_f.setDistanceUnits(project.distanceUnits())
        exp_f.setAreaUnits(project.areaUnits())

        if exp_f.hasParserError():
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid FILTER for 'GetFeatureWithFormScope': Error \"{}\": {}".format(
                    exp_filter, exp_f.parserErrorString()),
                400)

        if not exp_f.isValid():
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid FILTER for 'GetFeatureWithFormScope': Expression not valid \"{}\"".format(exp_filter),
                400)

        exp_f.prepare(exp_context)

        req = QgsFeatureRequest(exp_f, exp_context)

        # With geometry
        with_geom = params.get('WITH_GEOMETRY', '').lower() in ['true', '1', 't']
        if not with_geom:
            req.setFlags(QgsFeatureRequest.NoGeometry)

        # Fields
        pk_attributes = layer.primaryKeyAttributes()
        attribute_list = [i for i in pk_attributes]
        fields = layer.fields()
        r_fields = [f.strip() for f in params.get('FIELDS', '').split(',') if f]
        for f in r_fields:
            attribute_list.append(fields.indexOf(f))

        # response
        response.setStatusCode(200)
        response.setHeader("Content-Type", "application/json")
        response.write('{ "type": "FeatureCollection","features":[')
        response.flush()

        json_exporter = QgsJsonExporter(layer)
        if attribute_list:
            json_exporter.setAttributes(attribute_list)

        separator = ''
        for feat in layer.getFeatures(req):
            fid = layer_name + '.' + get_server_fid(feat, pk_attributes)
            response.write(separator + json_exporter.exportFeature(feat, {}, fid))
            response.flush()
            separator = ',\n'
        response.write(']}')
        return
예제 #10
0
    def replace_expression_text(params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None:
        """ Replace expression texts against layer or features
        In parameters:
            LAYER=wms-layer-name
            STRING=A string with expression between [% and %]
            or
            STRINGS=["first string with expression", "second string with expression"]
            or
            STRINGS={"key1": "first string with expression", "key2": "second string with expression"}
            // optionals
            FEATURE={"type": "Feature", "geometry": {}, "properties": {}}
            or
            FEATURES=[{"type": "Feature", "geometry": {}, "properties": {}}, {"type": "Feature", "geometry": {},
            "properties": {}}]
            FORM_SCOPE=boolean to add formScope based on provided features
        """
        layername = params.get('LAYER', '')
        if not layername:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'ReplaceExpressionText' REQUEST: LAYER parameter is mandatory",
                400)

        # get layer
        layer = find_vector_layer(layername, project)
        # layer not found
        if not layer:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid LAYER parameter for 'ReplaceExpressionText': {} provided".format(layername),
                400)

        # get strings
        strings = params.get('STRINGS', '')
        if not strings:
            the_string = params.get('STRING', '')
            if not the_string:
                raise ExpressionServiceError(
                    "Bad request error",
                    "Invalid 'ReplaceExpressionText' REQUEST: STRING or STRINGS parameter is mandatory",
                    400)
            strings = '["{}"]'.format(the_string)

        # try to load expressions list or dict
        try:
            str_json = json.loads(strings)
        except Exception:
            QgsMessageLog.logMessage(
                "JSON loads strings '{}' exception:\n{}".format(strings, traceback.format_exc()),
                "lizmap", Qgis.Critical)
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'ReplaceExpressionText' REQUEST: STRINGS '{}' are not well formed".format(strings),
                400)

        # get features
        features = params.get('FEATURES', '')
        if not features:
            feature = params.get('FEATURE', '')
            if feature:
                features = '[' + feature + ']'

        # create expression context
        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(QgsExpressionContextUtils.projectScope(project))
        exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))

        # create distance area context
        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs(), project.transformContext())
        da.setEllipsoid(project.ellipsoid())

        # organized strings
        str_map = {}
        str_items = []
        if isinstance(str_json, list):
            str_items = enumerate(str_json)
        elif isinstance(str_json, dict):
            str_items = str_json.items()
        for k, s in str_items:
            str_map[k] = s

        # create the body
        body = {
            'status': 'success',
            'results': [],
            'errors': [],
            'features': 0
        }

        # without features just replace expression string with layer context
        if not features:
            result = {}
            for k, s in str_map.items():
                value = QgsExpression.replaceExpressionText(s, exp_context, da)
                result[k] = json.loads(QgsJsonUtils.encodeValue(value))
            body['results'].append(result)
            write_json_response(body, response)
            return

        # Check features
        try:
            geojson = json.loads(features)
        except Exception:
            QgsMessageLog.logMessage(
                "JSON loads features '{}' exception:\n{}".format(features, traceback.format_exc()),
                "lizmap", Qgis.Critical)
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed".format(features),
                400)

        if not geojson or not isinstance(geojson, list) or len(geojson) == 0:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed".format(features),
                400)

        if ('type' not in geojson[0]) or geojson[0]['type'] != 'Feature':
            raise ExpressionServiceError(
                "Bad request error",
                ("Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed: type not defined or not "
                 "Feature.").format(features),
                400)

        # try to load features
        # read fields
        feature_fields = QgsJsonUtils.stringToFields(
            '{ "type": "FeatureCollection","features":' + features + '}',
            QTextCodec.codecForName("UTF-8"))
        # read features
        feature_list = QgsJsonUtils.stringToFeatureList(
            '{ "type": "FeatureCollection","features":' + features + '}',
            feature_fields,
            QTextCodec.codecForName("UTF-8"))

        # features not well formed
        if not feature_list:
            raise ExpressionServiceError(
                "Bad request error",
                ("Invalid FEATURES for 'ReplaceExpressionText': not GeoJSON features array "
                 "provided\n{}").format(features),
                400)

        # Extend layer fields with this provided in GeoJSON Features
        feat_fields = QgsFields(layer.fields())
        feat_fields.extend(feature_fields)

        # form scope
        add_form_scope = params.get('FORM_SCOPE', '').lower() in ['true', '1', 't']

        # loop through provided features to replace expression strings
        for f in feature_list:
            # clone the features with all attributes
            # those defined in layer + fields from GeoJSON Features
            feat = QgsFeature(feat_fields)
            feat.setGeometry(f.geometry())
            for field in f.fields():
                field_name = field.name()
                if feat_fields.indexOf(field_name) != -1:
                    feat.setAttribute(field_name, f[field_name])

            # Add form scope to expression context
            if add_form_scope:
                exp_context.appendScope(QgsExpressionContextUtils.formScope(feat))

            exp_context.setFeature(feat)
            exp_context.setFields(feat.fields())

            # replace expression strings with the new feature
            result = {}
            for k, s in str_map.items():
                value = QgsExpression.replaceExpressionText(s, exp_context, da)
                result[k] = json.loads(QgsJsonUtils.encodeValue(value))
            body['results'].append(result)

        write_json_response(body, response)
        return
예제 #11
0
    def evaluate(params: Dict[str, str], response: QgsServerResponse, project: QgsProject) -> None:
        """ Evaluate expressions against layer or features
        In parameters:
            LAYER=wms-layer-name
            EXPRESSION=An expression to evaluate
            or
            EXPRESSIONS=["first expression", "second expression"]
            or
            EXPRESSIONS={"key1": "first expression", "key2": "second expression"}
            // optionals
            FEATURE={"type": "Feature", "geometry": {}, "properties": {}}
            or
            FEATURES=[{"type": "Feature", "geometry": {}, "properties": {}}, {"type": "Feature", "geometry": {},
            "properties": {}}]
            FORM_SCOPE=boolean to add formScope based on provided features
        """

        layername = params.get('LAYER', '')
        if not layername:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'Evaluate' REQUEST: LAYER parameter is mandatory",
                400)

        # get layer
        layer = find_vector_layer(layername, project)
        # layer not found
        if not layer:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid LAYER parameter for 'Evaluate': {} provided".format(layername),
                400)

        # get expressions
        expressions = params.get('EXPRESSIONS', '')
        if not expressions:
            expression = params.get('EXPRESSION', '')
            if not expression:
                raise ExpressionServiceError(
                    "Bad request error",
                    "Invalid 'Evaluate' REQUEST: EXPRESSION or EXPRESSIONS parameter is mandatory",
                    400)
            expressions = '["{}"]'.format(expression)

        # try to load expressions list or dict
        try:
            exp_json = json.loads(expressions)
        except Exception:
            QgsMessageLog.logMessage(
                "JSON loads expressions '{}' exception:\n{}".format(expressions, traceback.format_exc()),
                "lizmap", Qgis.Critical)
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'Evaluate' REQUEST: EXPRESSIONS '{}' are not well formed".format(expressions),
                400)

        # create expression context
        exp_context = QgsExpressionContext()
        exp_context.appendScope(QgsExpressionContextUtils.globalScope())
        exp_context.appendScope(QgsExpressionContextUtils.projectScope(project))
        exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer))

        # create distance area context
        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs(), project.transformContext())
        da.setEllipsoid(project.ellipsoid())

        # parse expressions
        exp_map = {}
        exp_parser_errors = []
        exp_items = []
        if isinstance(exp_json, list):
            exp_items = enumerate(exp_json)
        elif isinstance(exp_json, dict):
            exp_items = exp_json.items()
        for k, e in exp_items:
            exp = QgsExpression(e)
            exp.setGeomCalculator(da)
            exp.setDistanceUnits(project.distanceUnits())
            exp.setAreaUnits(project.areaUnits())

            if exp.hasParserError():
                exp_parser_errors.append('Error "{}": {}'.format(e, exp.parserErrorString()))
                continue

            if not exp.isValid():
                exp_parser_errors.append('Expression not valid "{}"'.format(e))
                continue

            exp.prepare(exp_context)
            exp_map[k] = exp

        # expression parser errors found
        if exp_parser_errors:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid EXPRESSIONS for 'Evaluate':\n{}".format('\n'.join(exp_parser_errors)),
                400)

        # get features
        features = params.get('FEATURES', '')
        if not features:
            feature = params.get('FEATURE', '')
            if feature:
                features = '[' + feature + ']'

        # create the body
        body = {
            'status': 'success',
            'results': [],
            'errors': [],
            'features': 0
        }

        # without features just evaluate expression with layer context
        if not features:
            result = {}
            error = {}
            for k, exp in exp_map.items():
                value = exp.evaluate(exp_context)
                if exp.hasEvalError():
                    result[k] = None
                    error[k] = exp.evalErrorString()
                else:
                    result[k] = json.loads(QgsJsonUtils.encodeValue(value))
            body['results'].append(result)
            body['errors'].append(error)
            write_json_response(body, response)
            return

        # Check features
        try:
            geojson = json.loads(features)
        except Exception:
            QgsMessageLog.logMessage(
                "JSON loads features '{}' exception:\n{}".format(features, traceback.format_exc()),
                "lizmap", Qgis.Critical)
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed".format(features),
                400)

        if not geojson or not isinstance(geojson, list) or len(geojson) == 0:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed".format(features),
                400)

        if 'type' not in geojson[0] or geojson[0]['type'] != 'Feature':
            raise ExpressionServiceError(
                "Bad request error",
                ("Invalid 'Evaluate' REQUEST: FEATURES '{}' are not well formed: type not defined or not "
                 "Feature.").format(features),
                400)

        # try to load features
        # read fields
        feature_fields = QgsJsonUtils.stringToFields(
            '{ "type": "FeatureCollection","features":' + features + '}',
            QTextCodec.codecForName("UTF-8"))
        # read features
        feature_list = QgsJsonUtils.stringToFeatureList(
            '{ "type": "FeatureCollection","features":' + features + '}',
            feature_fields,
            QTextCodec.codecForName("UTF-8"))

        # features not well formed
        if not feature_list:
            raise ExpressionServiceError(
                "Bad request error",
                "Invalid FEATURES for 'Evaluate': not GeoJSON features array provided\n{}".format(features),
                400)

        # Extend layer fields with this provided in GeoJSON Features
        feat_fields = QgsFields(layer.fields())
        feat_fields.extend(feature_fields)

        # form scope
        add_form_scope = params.get('FORM_SCOPE', '').lower() in ['true', '1', 't']

        # loop through provided features to evaluate expressions
        for f in feature_list:
            # clone the features with all attributes
            # those defined in layer + fields from GeoJSON Features
            feat = QgsFeature(feat_fields)
            feat.setGeometry(f.geometry())
            for field in f.fields():
                fname = field.name()
                if feat_fields.indexOf(fname) != -1:
                    feat.setAttribute(fname, f[fname])

            # Add form scope to expression context
            if add_form_scope:
                exp_context.appendScope(QgsExpressionContextUtils.formScope(feat))

            exp_context.setFeature(feat)
            exp_context.setFields(feat.fields())

            # Evaluate expressions with the new feature
            result = {}
            error = {}
            for k, exp in exp_map.items():
                if add_form_scope:
                    # need to prepare the expression because the context has been updated with a new scope
                    exp.prepare(exp_context)
                value = exp.evaluate(exp_context)
                if exp.hasEvalError():
                    result[k] = None
                    error[k] = exp.evalErrorString()
                else:
                    result[k] = json.loads(QgsJsonUtils.encodeValue(value))
                    error[k] = exp.expression()
            body['results'].append(result)
            body['errors'].append(error)

        write_json_response(body, response)
        return
예제 #12
0
    def handle_add_layer(self):
        """Create a new layer by name (rev_lyr)"""

        slds = self.get_sld()

        selected_name = self.dlg.mComboBox.currentText()
        selected_id = self.dataset_dictionary[selected_name]

        # Group name equals selected dataset name
        group = self.create_group(selected_name)

        # Get metadata and features from NgisOpenAPI
        try:
            metadata_from_api = self.client.getDatasetMetadata(selected_id)
            epsg = metadata_from_api.crs_epsg
            features_from_api = self.client.getDatasetFeatures(
                metadata_from_api.id, metadata_from_api.bbox, epsg)
        except Exception as e:
            error = ApiError("Nedlasting av data mislyktes",
                             "Kunne ikke laste ned datasett", e)
            self.iface.messageBar().pushMessage(error.title,
                                                error.detail,
                                                error.show_more,
                                                level=2,
                                                duration=10)
            return
        crs_from_api = features_from_api['crs']['properties']['name']
        features_by_type = {}

        # Extract features from GeoJSON into dictionary
        for feature in features_from_api['features']:
            feature_type = feature['properties']['featuretype']
            features_by_type.setdefault(feature_type, []).append(feature)

        features_from_api['features'] = None

        for feature_type, features_list in features_by_type.items():
            # Create a new GeoJSON object containing a single featuretype
            features_dict = features_from_api.copy()
            features_dict['features'] = features_list

            features_json = json.dumps(features_dict, ensure_ascii=False)

            # Identify fields and features from GeoJSON
            codec = QTextCodec.codecForName("UTF-8")
            fields = QgsJsonUtils.stringToFields(features_json, codec)
            newFeatures = QgsJsonUtils.stringToFeatureList(
                features_json, fields, codec)

            # If different geometry types are identified, separate them into individual layers
            geometry_dict = {}
            if newFeatures:
                for feature in newFeatures:

                    featuretype = feature.attribute('featuretype')
                    geom_type = feature.geometry()
                    geom_type = QgsWkbTypes.displayString(
                        int(geom_type.wkbType()))
                    if geom_type not in geometry_dict:
                        geometry_dict[geom_type] = {}
                    if featuretype not in geometry_dict[geom_type]:
                        geometry_dict[geom_type][featuretype] = []

                    geometry_dict[geom_type][featuretype].append(feature)

            for geom_type, feature_types in geometry_dict.items():
                for feature_type, features in feature_types.items():
                    lyr = QgsVectorLayer(f'{geom_type}?crs={crs_from_api}',
                                         f'{feature_type}-{geom_type}',
                                         "memory")
                    #lyr = QgsVectorLayer(f'{geom_type}?crs=EPSG:25832', f'{feature_type}-{geom_type}', "memory") #TODO Remove
                    QgsProject.instance().addMapLayer(lyr, False)

                    lyr.startEditing()

                    add_fields_to_layer(lyr, fields, feature_type)

                    lyr.commitChanges()
                    l_d = lyr.dataProvider()
                    l_d.addFeatures(features)
                    # update the extent of rev_lyr
                    lyr.updateExtents()
                    # save changes made in 'rev_lyr'
                    lyr.commitChanges()
                    group.addLayer(lyr)

                    #lyr.committedFeaturesAdded.connect(self.handleCommitedAddedFeatures)
                    #lyr.committedFeaturesRemoved.connect(self.handleCommittedFeaturesRemoved)
                    #lyr.featuresDeleted.connect(self.handleDeletedFeatures)
                    #lyr.committedGeometriesChanges(self.ee)

                    lyr.beforeCommitChanges.connect(
                        self.handle_before_commitchanges)

                    if feature_type in slds:
                        lyr.loadSldStyle(slds[feature_type])

                    self.dataset_dictionary[lyr.id()] = selected_id
                    self.feature_type_dictionary[lyr.id()] = feature_type
 def addFeature(self):
     text = self.lineEdit.text().strip()
     if text == "":
         return
     layer = self.iface.activeLayer()
     if layer == None:
         return
     try:
         if (self.inputProjection == 0) or (text[0] == '{'):
             # If this is GeoJson it does not matter what inputProjection is
             if text[0] == '{': # This may be a GeoJSON point
                 codec = QTextCodec.codecForName("UTF-8")
                 fields = QgsJsonUtils.stringToFields(text, codec)
                 fet = QgsJsonUtils.stringToFeatureList(text, fields, codec)
                 if (len(fet) == 0) or not fet[0].isValid():
                     raise ValueError('Invalid Coordinates')
                 
                 geom = fet[0].geometry()
                 if geom.isEmpty() or (geom.wkbType() != QgsWkbTypes.Point):
                     raise ValueError('Invalid GeoJSON Geometry')
                 pt = geom.asPoint()
                 lat = pt.y()
                 lon = pt.x()
             elif re.search(r'POINT\(', text) != None:
                 m = re.findall(r'POINT\(\s*([+-]?\d*\.?\d*)\s+([+-]?\d*\.?\d*)', text)
                 if len(m) != 1:
                     raise ValueError('Invalid Coordinates')
                 lon = float(m[0][0])
                 lat = float(m[0][1])
             else:
                 lat, lon = LatLon.parseDMSString(text, self.inputXYOrder)
             srcCrs = epsg4326
         elif self.inputProjection == 1:
             # This is an MGRS coordinate
             text = re.sub(r'\s+', '', unicode(text)) # Remove all white space
             lat, lon = mgrs.toWgs(text)
             srcCrs = epsg4326
         elif self.inputProjection == 4:
             text = text.strip()
             coord = olc.decode(text)
             lat = coord.latitudeCenter
             lon = coord.longitudeCenter
             srcCrs = epsg4326
         else: # Is either the project or custom CRS
             if re.search(r'POINT\(', text) == None:
                 coords = re.split(r'[\s,;:]+', text, 1)
                 if len(coords) < 2:
                     raise ValueError('Invalid Coordinates')
                 if self.inputXYOrder == 0: # Y, X Order
                     lat = float(coords[0])
                     lon = float(coords[1])
                 else:
                     lon = float(coords[0])
                     lat = float(coords[1])
             else:
                 m = re.findall(r'POINT\(\s*([+-]?\d*\.?\d*)\s+([+-]?\d*\.?\d*)', text)
                 if len(m) != 1:
                     raise ValueError('Invalid Coordinates')
                 lon = float(m[0][0])
                 lat = float(m[0][1])
             if self.inputProjection == 2: # Project CRS
                 srcCrs = self.canvas.mapSettings().destinationCrs()
             else:
                 srcCrs = QgsCoordinateReferenceSystem(self.inputCustomCRS)
     except:
         #traceback.print_exc()
         self.iface.messageBar().pushMessage("", "Invalid Coordinate" , level=Qgis.Warning, duration=2)
         return
     self.lineEdit.clear()
     caps = layer.dataProvider().capabilities()
     if caps & QgsVectorDataProvider.AddFeatures:
         destCRS = layer.crs() # Get the CRS of the layer we are adding a point toWgs
         transform = QgsCoordinateTransform(srcCrs, destCRS, QgsProject.instance())
         # Transform the input coordinate projection to the layer CRS
         x, y = transform.transform(float(lon), float(lat))
         feat = QgsFeature(layer.fields())
         feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(x, y)))
         if layer.fields().count() == 0:
             layer.addFeature(feat)
             self.lltools.zoomTo(srcCrs, lat, lon)
         else:
             if self.iface.openFeatureForm(layer, feat):
                 layer.addFeature(feat)
                 self.lltools.zoomTo(srcCrs, lat, lon)
예제 #14
0
    def addFeature(self):
        text = self.lineEdit.text().strip()
        if text == "":
            return
        layer = self.iface.activeLayer()
        if layer is None:
            return
        try:
            if (self.inputProjection == 0) or (text[0] == '{'):
                # If this is GeoJson it does not matter what inputProjection is
                if text[0] == '{':  # This may be a GeoJSON point
                    codec = QTextCodec.codecForName("UTF-8")
                    fields = QgsJsonUtils.stringToFields(text, codec)
                    fet = QgsJsonUtils.stringToFeatureList(text, fields, codec)
                    if (len(fet) == 0) or not fet[0].isValid():
                        raise ValueError('Invalid Coordinates')

                    geom = fet[0].geometry()
                    if geom.isEmpty() or (geom.wkbType() != QgsWkbTypes.Point):
                        raise ValueError('Invalid GeoJSON Geometry')
                    pt = geom.asPoint()
                    lat = pt.y()
                    lon = pt.x()
                elif re.search(r'POINT\(', text) is not None:
                    m = re.findall(
                        r'POINT\(\s*([+-]?\d*\.?\d*)\s+([+-]?\d*\.?\d*)', text)
                    if len(m) != 1:
                        raise ValueError('Invalid Coordinates')
                    lon = float(m[0][0])
                    lat = float(m[0][1])
                else:
                    lat, lon = LatLon.parseDMSString(text, self.inputXYOrder)
                srcCrs = epsg4326
            elif self.inputProjection == 1:
                # This is an MGRS coordinate
                text = re.sub(r'\s+', '',
                              unicode(text))  # Remove all white space
                lat, lon = mgrs.toWgs(text)
                srcCrs = epsg4326
            elif self.inputProjection == 4:
                text = text.strip()
                coord = olc.decode(text)
                lat = coord.latitudeCenter
                lon = coord.longitudeCenter
                srcCrs = epsg4326
            else:  # Is either the project or custom CRS
                if re.search(r'POINT\(', text) is None:
                    coords = re.split(r'[\s,;:]+', text, 1)
                    if len(coords) < 2:
                        raise ValueError('Invalid Coordinates')
                    if self.inputXYOrder == 0:  # Y, X Order
                        lat = float(coords[0])
                        lon = float(coords[1])
                    else:
                        lon = float(coords[0])
                        lat = float(coords[1])
                else:
                    m = re.findall(
                        r'POINT\(\s*([+-]?\d*\.?\d*)\s+([+-]?\d*\.?\d*)', text)
                    if len(m) != 1:
                        raise ValueError('Invalid Coordinates')
                    lon = float(m[0][0])
                    lat = float(m[0][1])
                if self.inputProjection == 2:  # Project CRS
                    srcCrs = self.canvas.mapSettings().destinationCrs()
                else:
                    srcCrs = QgsCoordinateReferenceSystem(self.inputCustomCRS)
        except Exceptions:
            # traceback.print_exc()
            self.iface.messageBar().pushMessage("",
                                                "Invalid Coordinate",
                                                level=Qgis.Warning,
                                                duration=2)
            return
        self.lineEdit.clear()
        caps = layer.dataProvider().capabilities()
        if caps & QgsVectorDataProvider.AddFeatures:
            destCRS = layer.crs(
            )  # Get the CRS of the layer we are adding a point toWgs
            transform = QgsCoordinateTransform(srcCrs, destCRS,
                                               QgsProject.instance())
            # Transform the input coordinate projection to the layer CRS
            x, y = transform.transform(float(lon), float(lat))
            feat = QgsFeature(layer.fields())
            feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(x, y)))
            if layer.fields().count() == 0:
                layer.addFeature(feat)
                self.lltools.zoomTo(srcCrs, lat, lon)
            else:
                if self.iface.openFeatureForm(layer, feat):
                    layer.addFeature(feat)
                    self.lltools.zoomTo(srcCrs, lat, lon)
예제 #15
0
    def show_output(self, byte_array):

        codec = QTextCodec.codecForLocale()
        unicode_text = codec.toUnicode(byte_array)

        self.report_progress(unicode_text)
    def convertCoordinate(self, text):
        try:
            if self.settings.zoomToProjIsMGRS():
                # An MGRS coordinate only format has been specified. This will result in an exception
                # if it is not a valid MGRS coordinate
                text2 = re.sub(r'\s+', '', str(text))  # Remove all white space
                lat, lon = mgrs.toWgs(text2)
                return (lat, lon, epsg4326)

            if self.settings.zoomToProjIsPlusCodes():
                # A Plus Codes coordinate has been selected. This will result in an exception
                # if it is not a valid plus codes coordinate.
                coord = olc.decode(text)
                lat = coord.latitudeCenter
                lon = coord.longitudeCenter
                return (lat, lon, epsg4326)

            if self.settings.zoomToProjIsStandardUtm():
                # A Standard UTM coordinate has been selected. This will result in an exception
                # if it is not a valid utm coordinate.
                pt = utmString2Crs(text)
                return (pt.y(), pt.x(), epsg4326)

            if self.settings.zoomToProjIsGeohash():
                # A Geohash coordinate has been selected. This will result in an exception
                # if it is not a valid Geohash coordinate.
                (lat, lon) = geohash.decode(text)
                return (float(lat), float(lon), epsg4326)

            # Check for other formats
            if text[0] == '{':  # This may be a GeoJSON point
                codec = QTextCodec.codecForName("UTF-8")
                fields = QgsJsonUtils.stringToFields(text, codec)
                fet = QgsJsonUtils.stringToFeatureList(text, fields, codec)
                if (len(fet) == 0) or not fet[0].isValid():
                    raise ValueError('Invalid Coordinates')

                geom = fet[0].geometry()
                if geom.isEmpty() or (geom.wkbType() != QgsWkbTypes.Point):
                    raise ValueError('Invalid GeoJSON Geometry')
                pt = geom.asPoint()
                return (pt.y(), pt.x(), epsg4326)

            # Check to see if it is standard UTM
            if isUtm(text):
                pt = utmString2Crs(text)
                return (pt.y(), pt.x(), epsg4326)

            # Check to see if it is an MGRS coordinate
            try:
                text2 = re.sub(r'\s+', '', str(text))
                lat, lon = mgrs.toWgs(text2)
                return (lat, lon, epsg4326)
            except Exception:
                pass

            # Check to see if it is a plus codes string
            try:
                coord = olc.decode(text)
                lat = coord.latitudeCenter
                lon = coord.longitudeCenter
                return (lat, lon, epsg4326)
            except Exception:
                pass

            # Check to see if it is a WKT POINT format
            if re.search(r'POINT\(', text) is not None:
                m = re.findall(
                    r'POINT\(\s*([+-]?\d*\.?\d*)\s+([+-]?\d*\.?\d*)', text)
                if len(m) != 1:
                    raise ValueError('Invalid Coordinates')
                lon = float(m[0][0])
                lat = float(m[0][1])
                if self.settings.zoomToProjIsWgs84():
                    srcCrs = epsg4326
                elif self.settings.zoomToProjIsProjectCRS():
                    srcCrs = self.canvas.mapSettings().destinationCrs()
                else:
                    srcCrs = self.settings.zoomToCustomCRS()
                return (lat, lon, srcCrs)

            # We are left with either DMS or decimal degrees in one of the projections
            if self.settings.zoomToProjIsWgs84():
                lat, lon = parseDMSString(text, self.settings.zoomToCoordOrder)
                return (lat, lon, epsg4326)

            # We are left with a non WGS 84 decimal projection
            coords = re.split(r'[\s,;:]+', text, 1)
            if len(coords) < 2:
                raise ValueError('Invalid Coordinates')
            if self.settings.zoomToCoordOrder == self.settings.OrderYX:
                lat = float(coords[0])
                lon = float(coords[1])
            else:
                lon = float(coords[0])
                lat = float(coords[1])
            if self.settings.zoomToProjIsProjectCRS():
                srcCrs = self.canvas.mapSettings().destinationCrs()
            else:
                srcCrs = self.settings.zoomToCustomCRS()
            return (lat, lon, srcCrs)

        except Exception:
            raise ValueError('Invalid Coordinates')
예제 #17
0
__copyright__ = 'Copyright 2016, The QGIS Project'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '9345f3301e032094c63dcb8ac0eeb27f0f5ebee4'

import qgis  # NOQA

from qgis.testing import unittest, start_app
from qgis.core import (QgsJsonUtils, QgsJsonExporter,
                       QgsCoordinateReferenceSystem, QgsProject, QgsFeature,
                       QgsField, QgsFields, QgsWkbTypes, QgsGeometry, QgsPoint,
                       QgsLineString, NULL, QgsVectorLayer, QgsRelation,
                       QgsEditorWidgetSetup)
from qgis.PyQt.QtCore import QVariant, QTextCodec

start_app()
codec = QTextCodec.codecForName("System")


class TestQgsJsonUtils(unittest.TestCase):
    def testStringToFeatureList(self):
        """Test converting json string to features"""

        fields = QgsFields()
        fields.append(QgsField("name", QVariant.String))

        # empty string
        features = QgsJsonUtils.stringToFeatureList("", fields, codec)
        self.assertEqual(features, [])

        # bad string
        features = QgsJsonUtils.stringToFeatureList("asdasdas", fields, codec)
예제 #18
0
    def zoomToPressed(self):
        try:
            text = self.coordTxt.text().strip()
            if text[0] == '{':  # This may be a GeoJSON point
                codec = QTextCodec.codecForName("UTF-8")
                fields = QgsJsonUtils.stringToFields(text, codec)
                fet = QgsJsonUtils.stringToFeatureList(text, fields, codec)
                if (len(fet) == 0) or not fet[0].isValid():
                    raise ValueError('Invalid Coordinates')

                geom = fet[0].geometry()
                if geom.isEmpty() or (geom.wkbType() != QgsWkbTypes.Point):
                    raise ValueError('Invalid GeoJSON Geometry')
                pt = geom.asPoint()
                lat = pt.y()
                lon = pt.x()
                srcCrs = epsg4326
            elif self.settings.zoomToProjIsWgs84():
                if re.search(r'POINT\(', text) == None:
                    lat, lon = LatLon.parseDMSString(
                        text, self.settings.zoomToCoordOrder)
                else:
                    m = re.findall(
                        r'POINT\(\s*([+-]?\d*\.?\d*)\s+([+-]?\d*\.?\d*)', text)
                    if len(m) != 1:
                        raise ValueError('Invalid Coordinates')
                    lon = float(m[0][0])
                    lat = float(m[0][1])
                srcCrs = epsg4326
            elif self.settings.zoomToProjIsPlusCodes() and olc.isValid(text):
                # This looks like a Plus Codes coordinate
                coord = olc.decode(text)
                srcCrs = epsg4326
                lat = coord.latitudeCenter
                lon = coord.longitudeCenter
            elif self.settings.zoomToProjIsMGRS():
                # This is an MGRS coordinate
                text = re.sub(r'\s+', '', str(text))  # Remove all white space
                lat, lon = mgrs.toWgs(text)
                srcCrs = epsg4326
            else:  # Is either the project or custom CRS
                if re.search(r'POINT\(', text) == None:
                    coords = re.split(r'[\s,;:]+', text, 1)
                    if len(coords) < 2:
                        raise ValueError('Invalid Coordinates')
                    if self.settings.zoomToCoordOrder == self.settings.OrderYX:
                        lat = float(coords[0])
                        lon = float(coords[1])
                    else:
                        lon = float(coords[0])
                        lat = float(coords[1])
                else:
                    m = re.findall(
                        r'POINT\(\s*([+-]?\d*\.?\d*)\s+([+-]?\d*\.?\d*)', text)
                    if len(m) != 1:
                        raise ValueError('Invalid Coordinates')
                    lon = float(m[0][0])
                    lat = float(m[0][1])
                if self.settings.zoomToProjIsProjectCRS():
                    srcCrs = self.canvas.mapSettings().destinationCrs()
                else:
                    srcCrs = self.settings.zoomToCustomCRS()

            pt = self.lltools.zoomTo(srcCrs, lat, lon)
            if self.settings.persistentMarker:
                if self.marker is None:
                    self.marker = QgsVertexMarker(self.canvas)
                self.marker.setCenter(pt)
                self.marker.setIconSize(18)
                self.marker.setPenWidth(2)
                self.marker.setIconType(QgsVertexMarker.ICON_CROSS)
            elif self.marker is not None:
                self.removeMarker()
        except:
            #traceback.print_exc()
            self.iface.messageBar().pushMessage("",
                                                "Invalid Coordinate",
                                                level=Qgis.Warning,
                                                duration=2)
            return