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)
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)
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
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]
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))
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))
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())
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
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
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
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
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)
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)
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')
__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)
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