def bbToMap(self, fullWkt=False): '''takes bounding box coords and puts them on the map''' #if self.foi_type == "AreaOfInterestDefiner": if not fullWkt: ix = self.bbMinXText.text() iy = self.bbMinYText.text() ax = self.bbMaxXText.text() ay = self.bbMaxYText.text() wkt = "POLYGON((%s %s, %s %s, %s %s, %s %s, %s %s))" % \ (ix, iy, ix, ay, ax, ay, ax, iy, ix, iy) else: wkt = self.asTxtText.toPlainText() try: errnum = 0 geom = QgsGeometry().fromWkt(wkt) print "gotGeom" if self.foi_type == "AreaOfInterestDefiner" and geom.type() != 2: errnum = 1 elif self.foi_type == "LineOfInterestDefiner" and geom.type() != 1: errnum = 1 elif self.foi_type == "PointOfInterestDefiner" and geom.type() != 0: errnum = 1 else: print "attempting to add geometry to mem layer" self.addGeomToMemoryLayer(geom) if errnum == 1: raise ModuleError(self, "Incorrect Geometry Type chosen") except: raise ModuleError(self, "Could not generate Geometry from text provided")
def qGeometry(feature): try: geom = QgsGeometry(feature.geometry()) fid = feature.id() if not geom.isMultipart(): if not geom.convertToMultiType(): raise Exception("unable to extract feature geometry (invalid geometry type)") if geom.type() == 0: return qPoints(geom.asMultiPoint()) elif geom.type() == 1: return qLines(geom.asMultiPolyline(), fid) elif geom.type() == 2: return qPolygons(geom.asMultiPolygon(), fid) else: raise Exception("unable to extract feature geometry (unknown geometry type)") except Exception, e: raise Exception("unable to extract feature geometry: %s" % unicode(e))
def checkGeom(self, expected_type): '''Check the geom to see if it can be instantiated as the expected type - enum of {'point','line','polygon'}''' testGeom = QgsGeometry().fromWkt(self.wkt) if expected_type == 'point': if testGeom.type() == 0: return True else: return False if expected_type == 'line': if testGeom.type() == 1: return True else: return False if expected_type == 'polygon': if testGeom.type() == 2: return True else: return False
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue( self.INPUT)) fieldName = self.getParameterValue(self.FIELD) geomType = self.singleToMultiGeom(layer.wkbType()) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.fields().toList(), geomType, layer.crs()) inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() index = layer.fields().lookupField(fieldName) unique = vector.getUniqueValues(layer, index) current = 0 features = vector.features(layer) total = 100.0 / (len(features) * len(unique)) if not len(unique) == layer.featureCount(): for i in unique: multi_feature = [] first = True features = vector.features(layer) for inFeat in features: atMap = inFeat.attributes() idVar = atMap[index] if str(idVar).strip() == str(i).strip(): if first: attrs = atMap first = False inGeom = inFeat.geometry() vType = inGeom.type() feature_list = self.extractAsMulti(inGeom) multi_feature.extend(feature_list) current += 1 progress.setPercentage(int(current * total)) outFeat.setAttributes(attrs) outGeom = QgsGeometry( self.convertGeometry(multi_feature, vType)) outFeat.setGeometry(outGeom) writer.addFeature(outFeat) del writer else: raise GeoAlgorithmExecutionException( self.tr('At least two features must have same attribute ' 'value! Please choose another field...'))
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) fieldName = self.getParameterValue(self.FIELD) geomType = self.singleToMultiGeom(layer.wkbType()) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.fields().toList(), geomType, layer.crs()) inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() index = layer.fields().lookupField(fieldName) unique = vector.getUniqueValues(layer, index) current = 0 features = vector.features(layer) total = 100.0 / (len(features) * len(unique)) if not len(unique) == layer.featureCount(): for i in unique: multi_feature = [] first = True features = vector.features(layer) for inFeat in features: atMap = inFeat.attributes() idVar = atMap[index] if str(idVar).strip() == str(i).strip(): if first: attrs = atMap first = False inGeom = inFeat.geometry() vType = inGeom.type() feature_list = self.extractAsMulti(inGeom) multi_feature.extend(feature_list) current += 1 progress.setPercentage(int(current * total)) outFeat.setAttributes(attrs) outGeom = QgsGeometry(self.convertGeometry(multi_feature, vType)) outFeat.setGeometry(outGeom) writer.addFeature(outFeat) del writer else: raise GeoAlgorithmExecutionException( self.tr('At least two features must have same attribute ' 'value! Please choose another field...'))
def highlight(self, geometry: QgsGeometry): self.rubber_band.reset(geometry.type()) self.rubber_band.addGeometry(geometry, None) rect = geometry.boundingBox() if not self.settings.value('keep_scale'): if rect.isEmpty(): current_extent = self.map_canvas.extent() rect = current_extent.scaled(self.settings.value( 'point_scale')/self.map_canvas.scale(), rect.center()) else: rect.scale(4) self.map_canvas.setExtent(rect) self.map_canvas.refresh()
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue( self.INPUT)) fieldName = self.getParameterValue(self.FIELD) geomType = QgsWkbTypes.multiType(layer.wkbType()) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.fields().toList(), geomType, layer.crs()) inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() index = layer.fields().lookupField(fieldName) collection_geom = {} collection_attrs = {} features = vector.features(layer) current = 0 total = 100.0 / (len(features)) features = vector.features(layer) for inFeat in features: atMap = inFeat.attributes() idVar = atMap[index] key = str(idVar).strip() if not key in collection_geom: collection_geom[key] = [] collection_attrs[key] = atMap inGeom = inFeat.geometry() vType = inGeom.type() collection_geom[key].append(inGeom) current += 1 progress.setPercentage(int(current * total)) for key, geoms in collection_geom.items(): outFeat.setAttributes(collection_attrs[key]) outFeat.setGeometry(QgsGeometry.collectGeometry(geoms)) writer.addFeature(outFeat) del writer
def zoom(self, error, crs): if not error: return geo = error.geo mapSettings = self.mapCanvas.mapSettings() if isProjectCrsEnabled() and getProjectCrs() != crs: geo = QgsGeometry(error.geo) transform = QgsCoordinateTransform(crs, QgsProject().instance().crs()) geo.transform(transform) if geo.type() == QgsWkbTypes.PointGeometry: p = geo.asPoint() bufferCrs = getProjectCrs() if isProjectCrsEnabled() else crs b = 2000 if not bufferCrs.isGeographic() else 2000 / 100000 # buffer extent = QgsRectangle(p.x() - b, p.y() - b, p.x() + b, p.y() + b) else: # line extent = geo.boundingBox() extent.scale(2) self.mapCanvas.setExtent(extent) self.mapCanvas.refresh();
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ spatialRealtionsHandler = SpatialRelationsHandler() inputLyr = self.parameterAsVectorLayer(parameters, self.INPUT, context) if inputLyr is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) onlySelected = self.parameterAsBool(parameters, self.SELECTED, context) heightFieldName = self.parameterAsFields(parameters, self.CONTOUR_ATTR, context)[0] threshold = self.parameterAsDouble(parameters, self.CONTOUR_INTERVAL, context) geoBoundsLyr = self.parameterAsVectorLayer(parameters, self.GEOGRAPHIC_BOUNDS, context) point_flagSink, point_flag_id = self.prepareAndReturnFlagSink( parameters, inputLyr, QgsWkbTypes.Point, context, self.POINT_FLAGS) line_flagSink, line_flag_id = self.prepareAndReturnFlagSink( parameters, inputLyr, QgsWkbTypes.LineString, context, self.LINE_FLAGS) invalidDict = spatialRealtionsHandler.validateTerrainModel( contourLyr=inputLyr, onlySelected=onlySelected, heightFieldName=heightFieldName, threshold=threshold, geoBoundsLyr=geoBoundsLyr, feedback=feedback) for flagGeom, text in invalidDict.items(): geom = QgsGeometry() geom.fromWkb(flagGeom) flagSink = line_flagSink if geom.type( ) == QgsWkbTypes.LineGeometry else point_flagSink self.flagFeature(geom, text, fromWkb=False, sink=flagSink) return {self.POINT_FLAGS: point_flag_id, self.LINE_FLAGS: line_flag_id}
def highlight(self, geometry: QgsGeometry): self.clearPreviousResults() if geometry is None: return self.rubber_band.reset(geometry.type()) self.rubber_band.addGeometry(geometry, None) rect = geometry.boundingBox() if not self.settings.value('keep_scale'): if rect.isEmpty(): current_extent = self.map_canvas.extent() rect = current_extent.scaled( self.settings.value('point_scale') / self.map_canvas.scale(), rect.center()) else: rect.scale(4) self.map_canvas.setExtent(rect) self.map_canvas.refresh() self.current_timer = QTimer() self.current_timer.timeout.connect(self.clearPreviousResults) self.current_timer.setSingleShot(True) self.current_timer.start(5000)
def get_features(layername, ftype=None, selected=False): """ Create a list of selected or all features from a given layer possibly with given type. :param layername: name of the layer :param ftype: type of features to add to the list (if None - all features) :param selected: if True only selected features will be added to the list :returns: list of feature geometries (QgsGeometry list) """ w = [] lay = get_layer_by_name(layername) if lay is None: return None if selected: features = lay.selectedFeatures() else: features = lay.getFeatures() for feat in features: geom = QgsGeometry(feat.geometry()) if type is None or geom.type() == ftype: w.append(geom) if len(w): return w return None
def compute(self, inName, joinName, outName, summary, sumList, keep, progressBar): layer1 = ftools_utils.getVectorLayerByName(inName) provider1 = layer1.dataProvider() fieldList1 = ftools_utils.getFieldList(layer1) layer2 = ftools_utils.getVectorLayerByName(joinName) provider2 = layer2.dataProvider() fieldList2 = ftools_utils.getFieldList(layer2) fieldList = QgsFields() if provider1.crs() != provider2.crs(): QMessageBox.warning( self, self.tr("CRS warning!"), self. tr("Warning: Input layers have non-matching CRS.\nThis may cause unexpected results." )) if not summary: fieldList2 = ftools_utils.testForUniqueness(fieldList1, fieldList2) seq = range(0, len(fieldList1) + len(fieldList2)) fieldList1.extend(fieldList2) fieldList1 = dict(zip(seq, fieldList1)) else: numFields = {} for j in xrange(len(fieldList2)): if fieldList2[j].type() == QVariant.Int or fieldList2[j].type( ) == QVariant.Double: numFields[j] = [] for i in sumList: field = QgsField(i + unicode(fieldList2[j].name()), QVariant.Double, "real", 24, 16, self.tr("Summary field")) fieldList.append(field) field = QgsField("COUNT", QVariant.Double, "real", 24, 16, self.tr("Summary field")) fieldList.append(field) fieldList2 = ftools_utils.testForUniqueness(fieldList1, fieldList) fieldList1.extend(fieldList) seq = range(0, len(fieldList1)) fieldList1 = dict(zip(seq, fieldList1)) sRs = provider1.crs() progressBar.setValue(13) check = QFile(self.shapefileName) if check.exists(): if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName): QMessageBox.warning( self, self.tr('Error deleting shapefile'), self.tr("Can't delete existing shapefile\n%s") % (self.shapefileName)) return False fields = QgsFields() for f in fieldList1.values(): fields.append(f) writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fields, provider1.geometryType(), sRs) #writer = QgsVectorFileWriter(outName, "UTF-8", fieldList1, provider1.geometryType(), sRs) inFeat = QgsFeature() outFeat = QgsFeature() inFeatB = QgsFeature() inGeom = QgsGeometry() progressBar.setValue(15) start = 15.00 add = 85.00 / provider1.featureCount() index = ftools_utils.createIndex(provider2) # cache all features from provider2 to avoid huge number of feature requests in the inner loop mapP2 = {} for f in provider2.getFeatures(): mapP2[f.id()] = QgsFeature(f) fit1 = provider1.getFeatures() while fit1.nextFeature(inFeat): inGeom = inFeat.geometry() atMap1 = inFeat.attributes() outFeat.setGeometry(inGeom) none = True joinList = [] if inGeom.type() == QGis.Point: #(check, joinList) = layer2.featuresInRectangle(inGeom.buffer(10,2).boundingBox(), True, True) #layer2.select(inGeom.buffer(10,2).boundingBox(), False) #joinList = layer2.selectedFeatures() joinList = index.intersects(inGeom.buffer(10, 2).boundingBox()) if len(joinList) > 0: check = 0 else: check = 1 else: #(check, joinList) = layer2.featuresInRectangle(inGeom.boundingBox(), True, True) #layer2.select(inGeom.boundingBox(), False) #joinList = layer2.selectedFeatures() joinList = index.intersects(inGeom.boundingBox()) if len(joinList) > 0: check = 0 else: check = 1 if check == 0: count = 0 for i in joinList: inFeatB = mapP2[i] # cached feature from provider2 if inGeom.intersects(inFeatB.geometry()): count = count + 1 none = False atMap2 = inFeatB.attributes() if not summary: atMap = atMap1 atMap2 = atMap2 atMap.extend(atMap2) atMap = dict(zip(seq, atMap)) break else: for j in numFields.keys(): numFields[j].append(atMap2[j]) if summary and not none: atMap = atMap1 for j in numFields.keys(): for k in sumList: if k == "SUM": atMap.append(sum(filter_null(numFields[j]))) elif k == "MEAN": try: nn_count = sum( 1 for _ in filter_null(numFields[j])) atMap.append( sum(filter_null(numFields[j])) / nn_count) except ZeroDivisionError: atMap.append(NULL) elif k == "MIN": try: atMap.append(min(filter_null( numFields[j]))) except ValueError: atMap.append(NULL) elif k == "MED": atMap.append(myself(numFields[j])) else: try: atMap.append(max(filter_null( numFields[j]))) except ValueError: atMap.append(NULL) numFields[j] = [] atMap.append(count) atMap = dict(zip(seq, atMap)) if none: outFeat.setAttributes(atMap1) else: outFeat.setAttributes(atMap.values()) if keep: # keep all records writer.addFeature(outFeat) else: # keep only matching records if not none: writer.addFeature(outFeat) start = start + add progressBar.setValue(start) del writer return True
def processAlgorithm(self, progress): vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT)) vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2)) GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = vlayerA.dataProvider() fields = vector.combineVectorFields(vlayerA, vlayerB) names = [field.name() for field in fields] ProcessingLog.addToLog(ProcessingLog.LOG_INFO, str(names)) writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter( fields, vproviderA.geometryType(), vproviderA.crs() ) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() indexA = vector.spatialindex(vlayerB) indexB = vector.spatialindex(vlayerA) count = 0 nElement = 0 featuresA = vector.features(vlayerA) nFeat = len(featuresA) for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 50) nElement += 1 found = False geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMapA = inFeatA.attributes() intersects = indexA.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: # This really shouldn't happen, as we haven't # edited the input geom at all raise GeoAlgorithmExecutionException(self.tr("Feature exception while computing union")) else: for id in intersects: count += 1 request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerB.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if geom.intersects(tmpGeom): found = True int_geom = geom.intersection(tmpGeom) if int_geom is None: # There was a problem creating the intersection raise GeoAlgorithmExecutionException( self.tr("Geometry exception while computing " "intersection") ) else: int_geom = QgsGeometry(int_geom) if diff_geom.intersects(tmpGeom): diff_geom = diff_geom.difference(tmpGeom) if diff_geom is None: # It's possible there was an error here? diff_geom = QgsGeometry() else: diff_geom = QgsGeometry(diff_geom) if int_geom.wkbType() == 0: # Intersection produced different geomety types temp_list = int_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): int_geom = QgsGeometry(i) try: outFeat.setGeometry(int_geom) attrs = [] attrs.extend(atMapA) attrs.extend(atMapB) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except Exception, err: raise GeoAlgorithmExecutionException(self.tr("Feature exception while computing union")) else: # This only happends if the bounding box intersects, # but the geometry doesn't try: outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: # Also shoudn't ever happen raise GeoAlgorithmExecutionException(self.tr("Feature exception while computing union")) if found: try: if diff_geom.wkbType() == 0: temp_list = diff_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): diff_geom = QgsGeometry(i) outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except Exception, err: raise GeoAlgorithmExecutionException(self.tr("Feature exception while computing union"))
def processAlgorithm(self, parameters, context, feedback): if DEBUG_MODE: logMessage( "processAlgorithm(): {}".format(self.__class__.__name__), False) clayer = self.parameterAsLayer(parameters, self.INPUT, context) title_field = self.parameterAsString(parameters, self.TITLE_FIELD, context) cf_filter = self.parameterAsBool(parameters, self.CF_FILTER, context) fixed_scale = self.parameterAsEnum(parameters, self.SCALE, context) # == 1 buf = self.parameterAsDouble(parameters, self.BUFFER, context) tex_width = self.parameterAsInt(parameters, self.TEX_WIDTH, context) orig_tex_height = self.parameterAsInt(parameters, self.TEX_HEIGHT, context) header_exp = QgsExpression( self.parameterAsExpression(parameters, self.HEADER, context)) footer_exp = QgsExpression( self.parameterAsExpression(parameters, self.FOOTER, context)) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.layerScope(clayer)) out_dir = self.parameterAsString(parameters, self.OUTPUT, context) if not QDir(out_dir).exists(): QDir().mkpath(out_dir) if DEBUG_MODE: openDirectory(out_dir) mapSettings = self.controller.settings.mapSettings baseExtent = self.controller.settings.baseExtent rotation = mapSettings.rotation() orig_size = mapSettings.outputSize() if cf_filter: cf_layer = QgsMemoryProviderUtils.createMemoryLayer( "current feature", clayer.fields(), clayer.wkbType(), clayer.crs()) layers = [ cf_layer if lyr == clayer else lyr for lyr in mapSettings.layers() ] mapSettings.setLayers(layers) doc = QDomDocument("qgis") clayer.exportNamedStyle(doc) cf_layer.importNamedStyle(doc) total = clayer.featureCount() for current, feature in enumerate(clayer.getFeatures()): if feedback.isCanceled(): break if cf_filter: cf_layer.startEditing() cf_layer.deleteFeatures( [f.id() for f in cf_layer.getFeatures()]) cf_layer.addFeature(feature) cf_layer.commitChanges() title = feature.attribute(title_field) feedback.setProgressText("({}/{}) Exporting {}...".format( current + 1, total, title)) logMessage("Exporting {}...".format(title), False) # extent geometry = QgsGeometry(feature.geometry()) geometry.transform(self.transform) center = geometry.centroid().asPoint() if fixed_scale or geometry.type() == QgsWkbTypes.PointGeometry: tex_height = orig_tex_height or int( tex_width * orig_size.height() / orig_size.width()) rect = RotatedRect(center, baseExtent.width(), baseExtent.width() * tex_height / tex_width, rotation).scale(1 + buf / 100) else: geometry.rotate(rotation, center) rect = geometry.boundingBox().scaled(1 + buf / 100) center = RotatedRect.rotatePoint(rect.center(), rotation, center) if orig_tex_height: tex_height = orig_tex_height tex_ratio = tex_width / tex_height rect_ratio = rect.width() / rect.height() if tex_ratio > rect_ratio: rect = RotatedRect(center, rect.height() * tex_ratio, rect.height(), rotation) else: rect = RotatedRect(center, rect.width(), rect.width() / tex_ratio, rotation) else: # fit to buffered geometry bounding box rect = RotatedRect(center, rect.width(), rect.height(), rotation) tex_height = tex_width * rect.height() / rect.width() rect.toMapSettings(mapSettings) mapSettings.setOutputSize(QSize(tex_width, tex_height)) self.controller.settings.setMapSettings(mapSettings) # labels exp_context.setFeature(feature) self.controller.settings.setHeaderLabel( header_exp.evaluate(exp_context)) self.controller.settings.setFooterLabel( footer_exp.evaluate(exp_context)) self.export(title, out_dir, feedback) feedback.setProgress(int(current / total * 100)) if P_OPEN_DIRECTORY and not DEBUG_MODE: openDirectory(out_dir) return {}
def single_to_multi( self ): vprovider = self.vlayer.dataProvider() allValid = True geomType = self.singleToMultiGeom( vprovider.geometryType() ) writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(), geomType, vprovider.crs() ) inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() index = vprovider.fieldNameIndex( self.myField ) if not index == -1: unique = ftools_utils.getUniqueValues( vprovider, int( index ) ) else: unique = [ "" ] nFeat = vprovider.featureCount() * len( unique ) nElement = 0 self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 ) self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) ) merge_all = self.myField == "--- " + self.tr( "Merge all" ) + " ---" if not len( unique ) == self.vlayer.featureCount() or merge_all: for i in unique: # Strip spaces for strings, so " A " and "A" will be grouped # TODO: Make this optional (opt-out to keep it easy for beginners) if isinstance( i, basestring ): iMod = i.strip() else: iMod = i multi_feature= [] first = True fit = vprovider.getFeatures() while fit.nextFeature( inFeat ): atMap = inFeat.attributes() if not merge_all: idVar = atMap[ index ] if isinstance( idVar, basestring ): idVarMod = idVar.strip() else: idVarMod = idVar else: idVarMod = "" if idVarMod == iMod or merge_all: if first: atts = atMap first = False inGeom = QgsGeometry( inFeat.geometry() ) vType = inGeom.type() feature_list = self.extractAsMulti( inGeom ) multi_feature.extend( feature_list ) nElement += 1 self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement ) if not first: outFeat.setAttributes( atts ) outGeom = QgsGeometry( self.convertGeometry( multi_feature, vType ) ) if not outGeom.isGeosValid(): allValid = "valid_error" outFeat.setGeometry( outGeom ) writer.addFeature( outFeat ) del writer else: return "attr_error" return allValid
def in_mask(self, feature, srid=None): if feature is None: # expression overview return False if self.layer is None: return False try: # layer is not None but destroyed ? self.layer.id() except: self.reset_mask_layer() return False # mask layer empty due to unloaded memlayersaver plugin > no filtering if self.layer.featureCount() == 0: return True mask_geom, bbox = self.mask_geometry() geom = QgsGeometry(feature.geometry()) if not geom.isGeosValid(): geom = geom.buffer(0.0, 1) if geom is None: return False if srid is not None and self.layer.crs().postgisSrid() != srid: src_crs = QgsCoordinateReferenceSystem(srid) dest_crs = self.layer.crs() xform = QgsCoordinateTransform(src_crs, dest_crs, QgsProject.instance()) try: geom.transform(xform) except: # transformation error. Check layer projection. pass if geom.type() == QgsWkbTypes.PolygonGeometry: if self.parameters.polygon_mask_method == 2 and not self.has_point_on_surface: self.parameters.polygon_mask_method = 1 if self.parameters.polygon_mask_method == 0: # this method can only work when no geometry simplification is involved return (mask_geom.overlaps(geom) or mask_geom.contains(geom)) elif self.parameters.polygon_mask_method == 1: # the fastest method, but with possible inaccuracies pt = geom.vertexAt(0) return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(geom.centroid()) elif self.parameters.polygon_mask_method == 2: # will always work pt = geom.vertexAt(0) return bbox.contains(QgsPointXY(pt)) and mask_geom.contains(geom.pointOnSurface()) else: return False elif geom.type() == QgsWkbTypes.LineGeometry: if self.parameters.line_mask_method == 0: return mask_geom.intersects(geom) elif self.parameters.line_mask_method == 1: return mask_geom.contains(geom) else: return False elif geom.type() == QgsWkbTypes.PointGeometry: return mask_geom.intersects(geom) else: return False
def compute(self, inName, joinName, outName, summary, sumList, keep, progressBar): layer1 = ftools_utils.getVectorLayerByName(inName) provider1 = layer1.dataProvider() fieldList1 = ftools_utils.getFieldList(layer1) layer2 = ftools_utils.getVectorLayerByName(joinName) provider2 = layer2.dataProvider() fieldList2 = ftools_utils.getFieldList(layer2) fieldList = QgsFields() if provider1.crs() != provider2.crs(): QMessageBox.warning(self, self.tr("CRS warning!"), self.tr("Warning: Input layers have non-matching CRS.\nThis may cause unexpected results.")) if not summary: fieldList2 = ftools_utils.testForUniqueness(fieldList1, fieldList2) seq = range(0, len(fieldList1) + len(fieldList2)) fieldList1.extend(fieldList2) fieldList1 = dict(zip(seq, fieldList1)) else: numFields = {} for j in xrange(len(fieldList2)): if fieldList2[j].type() == QVariant.Int or fieldList2[j].type() == QVariant.Double: numFields[j] = [] for i in sumList: field = QgsField(i + unicode(fieldList2[j].name()), QVariant.Double, "real", 24, 16, self.tr("Summary field")) fieldList.append(field) field = QgsField("COUNT", QVariant.Double, "real", 24, 16, self.tr("Summary field")) fieldList.append(field) fieldList2 = ftools_utils.testForUniqueness(fieldList1, fieldList) fieldList1.extend(fieldList) seq = range(0, len(fieldList1)) fieldList1 = dict(zip(seq, fieldList1)) sRs = provider1.crs() progressBar.setValue(13) check = QFile(self.shapefileName) if check.exists(): if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName): QMessageBox.warning( self, self.tr('Error deleting shapefile'), self.tr("Can't delete existing shapefile\n%s") % (self.shapefileName)) return False fields = QgsFields() for f in fieldList1.values(): fields.append(f) writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fields, provider1.geometryType(), sRs) #writer = QgsVectorFileWriter(outName, "UTF-8", fieldList1, provider1.geometryType(), sRs) inFeat = QgsFeature() outFeat = QgsFeature() inFeatB = QgsFeature() inGeom = QgsGeometry() progressBar.setValue(15) start = 15.00 add = 85.00 / provider1.featureCount() index = ftools_utils.createIndex(provider2) # cache all features from provider2 to avoid huge number of feature requests in the inner loop mapP2 = {} for f in provider2.getFeatures(): mapP2[f.id()] = QgsFeature(f) fit1 = provider1.getFeatures() while fit1.nextFeature(inFeat): inGeom = inFeat.geometry() atMap1 = inFeat.attributes() outFeat.setGeometry(inGeom) none = True joinList = [] if inGeom.type() == QGis.Point: #(check, joinList) = layer2.featuresInRectangle(inGeom.buffer(10,2).boundingBox(), True, True) #layer2.select(inGeom.buffer(10,2).boundingBox(), False) #joinList = layer2.selectedFeatures() joinList = index.intersects(inGeom.buffer(10, 2).boundingBox()) if len(joinList) > 0: check = 0 else: check = 1 else: #(check, joinList) = layer2.featuresInRectangle(inGeom.boundingBox(), True, True) #layer2.select(inGeom.boundingBox(), False) #joinList = layer2.selectedFeatures() joinList = index.intersects(inGeom.boundingBox()) if len(joinList) > 0: check = 0 else: check = 1 if check == 0: count = 0 for i in joinList: inFeatB = mapP2[i] # cached feature from provider2 if inGeom.intersects(inFeatB.geometry()): count = count + 1 none = False atMap2 = inFeatB.attributes() if not summary: atMap = atMap1 atMap2 = atMap2 atMap.extend(atMap2) atMap = dict(zip(seq, atMap)) break else: for j in numFields.keys(): numFields[j].append(atMap2[j]) if summary and not none: atMap = atMap1 for j in numFields.keys(): for k in sumList: if k == "SUM": atMap.append(sum(filter_null(numFields[j]))) elif k == "MEAN": try: nn_count = sum(1 for _ in filter_null(numFields[j])) atMap.append(sum(filter_null(numFields[j])) / nn_count) except ZeroDivisionError: atMap.append(NULL) elif k == "MIN": try: atMap.append(min(filter_null(numFields[j]))) except ValueError: atMap.append(NULL) elif k == "MED": atMap.append(myself(numFields[j])) else: try: atMap.append(max(filter_null(numFields[j]))) except ValueError: atMap.append(NULL) numFields[j] = [] atMap.append(count) atMap = dict(zip(seq, atMap)) if none: outFeat.setAttributes(atMap1) else: outFeat.setAttributes(atMap.values()) if keep: # keep all records writer.addFeature(outFeat) else: # keep only matching records if not none: writer.addFeature(outFeat) start = start + add progressBar.setValue(start) del writer return True
def getMatchingFeatures(self, geometry, contains, singleSelect): newFeatures = [] if geometry.type() != QgsWkbTypes.PolygonGeometry: return newFeatures layer = self.canvas.currentLayer() if layer is None: return newFeatures selectGeomTrans = QgsGeometry(geometry) try: ct = QgsCoordinateTransform(self.canvas.mapSettings().destinationCrs(), layer.crs(), QgsProject.instance()) if not ct.isShortCircuited() and selectGeomTrans.type() == QgsWkbTypes.PolygonGeometry: poly = selectGeomTrans.asPolygon() if len(poly) == 1 and len(poly[0]) == 5: ringIn = poly[0] ringOut = [] ringOut.append(ringIn[0]) i = 1 for j in range(1, 5): v = QgsVector((ringIn[j] - ringIn[j - 1]) / 10.0) for k in range(9): ringOut.append(ringOut[i - 1] + v) i += 1 ringOut.append(ringIn[j]) i += 1 selectGeomTrans = QgsGeometry.fromPolygonXY([ringOut]) selectGeomTrans.transform(ct) except QgsCsException as e: QgsMessageLog.logMessage("Selection extends beyond layer's coordinate system") return newFeatures context = QgsRenderContext.fromMapSettings(self.canvas.mapSettings()) context.expressionContext().appendScope(QgsExpressionContextUtils.layerScope(layer)) r = None if layer.renderer(): r = layer.renderer().clone() r.startRender(context, layer.fields()) request = QgsFeatureRequest() request.setFilterRect(selectGeomTrans.boundingBox()) request.setFlags(QgsFeatureRequest.ExactIntersect) if r: request.setSubsetOfAttributes(r.usedAttributes(context), layer.fields()) else: request.setSubsetOfAttributes([]) closestFeatureId = 0 foundSingleFeature = False closestFeatureDist = sys.float_info.max for f in layer.getFeatures(request): context.expressionContext().setFeature(f) if r and not r.willRenderFeature(f, context): continue g = f.geometry() if contains: if not selectGeomTrans.contains(g): continue else: if not selectGeomTrans.intersects(g): continue if singleSelect: foundSingleFeature = True distance = g.distance(selectGeomTrans) if distance <= closestFeatureDist: closestFeatureDist = distance closestFeatureId = f.id() else: newFeatures.append(f.id()) if singleSelect and foundSingleFeature: newFeatures.append(closestFeatureId) if r: r.stopRender(context) return newFeatures
class GeometryCopier: def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = QFileInfo(QgsApplication.qgisUserDbFilePath()).path() + "/python/plugins/geometry_copier" # initialize locale locale_path = "" if sip.getapi("QVariant") > 1: # new API style locale = QSettings().value("locale/userLocale")[0:2] else: # the old API style locale = QSettings().value("locale/userLocale").toString()[0:2] if QFileInfo(self.plugin_dir).exists(): locale_path = self.plugin_dir + "/i18n/geometry_copier_" + locale + ".qm" if QFileInfo(locale_path).exists(): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) self._geom_buffer = None def initGui(self): # Create action that will start plugin configuration self.copy_action = QAction( QIcon(':/plugins/geometrycopier/mActionEditCopyGeom.png'), self.tr(u"Copy geometry"), self.iface.mainWindow()) self.insert_action = QAction( QIcon(':/plugins/geometrycopier/mActionEditPasteGeom.png'), self.tr(u"Insert geometry"), self.iface.mainWindow()) # connect the action to the run method QObject.connect(self.copy_action, SIGNAL("triggered()"), self.copy_geometry) QObject.connect(self.insert_action, SIGNAL("triggered()"), self.insert_geometry) # Add hotkeys self.iface.registerMainWindowAction(self.copy_action, "F7") self.iface.registerMainWindowAction(self.insert_action, "F8") # Add toolbar button and menu item self.iface.digitizeToolBar().addAction(self.copy_action) self.iface.digitizeToolBar().addAction(self.insert_action) self.iface.addPluginToVectorMenu(u"&Geometry copier", self.copy_action) self.iface.addPluginToVectorMenu(u"&Geometry copier", self.insert_action) # Add global signals QObject.connect(self.iface, SIGNAL('currentLayerChanged(QgsMapLayer *)'), self.check_buttons_state) QObject.connect(self.iface.mapCanvas(), SIGNAL('selectionChanged(QgsMapLayer *)'), self.check_buttons_state) QObject.connect(self.iface.actionToggleEditing(), SIGNAL('triggered()'), self.check_buttons_state) #iface.actionToggleEditing().triggered # init state self.check_buttons_state(None) def unload(self): self.iface.unregisterMainWindowAction(self.copy_action) self.iface.unregisterMainWindowAction(self.insert_action) self.iface.removePluginVectorMenu(u"&Geometry copier", self.copy_action) self.iface.removePluginVectorMenu(u"&Geometry copier", self.insert_action) self.iface.digitizeToolBar().removeAction(self.copy_action) self.iface.digitizeToolBar().removeAction(self.insert_action) QObject.disconnect(self.iface, SIGNAL('currentLayerChanged(QgsMapLayer *)'), self.check_buttons_state) QObject.disconnect(self.iface.mapCanvas(), SIGNAL('selectionChanged(QgsMapLayer *)'), self.check_buttons_state) QObject.disconnect(self.iface.actionToggleEditing(), SIGNAL('triggered()'), self.check_buttons_state) def check_buttons_state(self, layer=None): layer = self.iface.activeLayer() if not isinstance(layer, QgsVectorLayer): self.copy_action.setDisabled(True) self.insert_action.setDisabled(True) return sel_feat_count = layer.selectedFeatureCount() if sel_feat_count != 1: self.copy_action.setDisabled(True) self.insert_action.setDisabled(True) return self.copy_action.setEnabled(True) # copy button can be pressed! if not layer.isEditable() or not self._geom_buffer or self._geom_buffer.type() != layer.geometryType(): self.insert_action.setDisabled(True) return self.insert_action.setEnabled(True) # insert button can be pressed! (type geom??) def copy_geometry(self): layer = self.iface.activeLayer() if not isinstance(layer, QgsVectorLayer): QMessageBox.information(None, self.tr('Geometry was not copied'), self.tr('Select any vector layer and feature!')) return sel_feat_count = layer.selectedFeatureCount() if sel_feat_count != 1: QMessageBox.information(None, self.tr('Geometry was not copied'), self.tr('Select one feature!')) return feature = layer.selectedFeatures()[0] self._geom_buffer = QgsGeometry(feature.geometry()) self.check_buttons_state() def insert_geometry(self): layer = self.iface.activeLayer() if not isinstance(layer, QgsVectorLayer): QMessageBox.information(None, self.tr('Geometry can\'t be inserted'), self.tr('Select any vector layer and feature for inserting geom!')) return if not self._geom_buffer: QMessageBox.information(None, self.tr('Geometry can\'t be inserted'), self.tr('Buffer is empty!')) return if not layer.isEditable(): QMessageBox.critical(None, self.tr('Geometry can\'t be inserted'), self.tr('Layer is not editable!')) return if self._geom_buffer.type() != layer.geometryType(): # and layer.geometryType() != 2: QMessageBox.critical(None, self.tr('Geometry can\'t be inserted'), self.tr('Target layer has other geometry type!')) return sel_feat_count = layer.selectedFeatureCount() if sel_feat_count != 1: QMessageBox.critical(None, self.tr('Geometry can\'t be inserted'), self.tr('Select one feature for inserting geom!')) return feature = layer.selectedFeatures()[0] layer.changeGeometry(feature.id(), QgsGeometry(self._geom_buffer)) self.iface.mapCanvas().refresh() def tr(self, text): return QCoreApplication.translate('GeometryCopier', text)
class ConflictDialog(WIDGET, BASE): LOCAL, REMOTE, DELETE = 1, 2, 3 def __init__(self, conflicts): super(ConflictDialog, self).__init__(None, Qt.WindowSystemMenuHint | Qt.WindowTitleHint) self.solved = False self.resolvedConflicts = {} self.conflicts = conflicts self.setupUi(self) self.setWindowFlags(self.windowFlags() | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint) self.zoomButton.clicked.connect(self.zoomToFullExtent) self.solveButton.clicked.connect(self.solve) self.conflictsTree.itemClicked.connect(self.treeItemClicked) self.attributesTable.cellClicked.connect(self.cellClicked) self.solveAllLocalButton.clicked.connect(self.solveAllLocal) self.solveAllRemoteButton.clicked.connect(self.solveAllRemote) self.solveLocalButton.clicked.connect(self.solveLocal) self.solveRemoteButton.clicked.connect(self.solveRemote) self.showRemoteCheck.stateChanged.connect(self.showGeoms) self.showLocalCheck.stateChanged.connect(self.showGeoms) self.lastSelectedItem = None self.currentPath = None self.currentConflict = None self.theirsLayer = None self.oursLayer = None settings = QSettings() horizontalLayout = QHBoxLayout() horizontalLayout.setSpacing(0) horizontalLayout.setMargin(0) self.mapCanvas = QgsMapCanvas() self.mapCanvas.setCanvasColor(Qt.white) self.mapCanvas.enableAntiAliasing( settings.value("/qgis/enable_anti_aliasing", False, type=bool)) self.mapCanvas.useImageToRender( settings.value("/qgis/use_qimage_to_render", False, type=bool)) self.mapCanvas.mapRenderer().setProjectionsEnabled(True) action = settings.value("/qgis/wheel_action", 0, type=float) zoomFactor = settings.value("/qgis/zoom_factor", 2, type=float) self.mapCanvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor) horizontalLayout.addWidget(self.mapCanvas) self.canvasWidget.setLayout(horizontalLayout) self.panTool = QgsMapToolPan(self.mapCanvas) self.mapCanvas.setMapTool(self.panTool) self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) self.fillConflictsTree() def fillConflictsTree(self): topTreeItems = {} for c in self.conflicts: path = os.path.dirname(c.path) if path in topTreeItems: topItem = topTreeItems[path] else: topItem = QTreeWidgetItem() topItem.setText(0, path) topItem.setIcon(0, layerIcon) topTreeItems[path] = topItem conflictItem = ConflictItem(c) topItem.addChild(conflictItem) for item in list(topTreeItems.values()): self.conflictsTree.addTopLevelItem(item) def cellClicked(self, row, col): if col > 2: return value = self.attributesTable.item(row, col).value geoms = (self.oursgeom, self.theirsgeom) self.attributesTable.setItem(row, 4, ValueItem(value, False, geoms)) self.attributesTable.item(row, 0).setBackgroundColor(Qt.white) self.attributesTable.item(row, 1).setBackgroundColor(Qt.white) self.attributesTable.item(row, 2).setBackgroundColor(Qt.white) attrib = self.attributesTable.item(row, 3).text() if attrib in self.conflicted: self.conflicted.remove(attrib) self.updateSolveButton() self.showGeoms() def treeItemClicked(self): item = self.conflictsTree.selectedItems()[0] if self.lastSelectedItem == item: return if isinstance(item, ConflictItem): self.lastSelectedItem = item self.currentPath = item.conflict.path self.updateCurrentPath() self.solveLocalButton.setEnabled(True) self.solveRemoteButton.setEnabled(True) self.solveButton.setEnabled(False) def updateCurrentPath(self): self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) self.cleanCanvas() self.showFeatureAttributes() self.createLayers() self.showGeoms() self.zoomToFullExtent() def zoomToFullExtent(self): layers = [ lay.extent() for lay in self.mapCanvas.layers() if lay.type() == lay.VectorLayer ] if layers: ext = layers[0] for layer in layers[1:]: ext.combineExtentWith(layer) self.mapCanvas.setExtent(ext) self.mapCanvas.refresh() def cleanCanvas(self): self.mapCanvas.setLayerSet([]) layers = [self.oursLayer, self.theirsLayer] for layer in layers: if layer is not None: QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) self.oursLayer = None self.theirsLayer = None def solveAllRemote(self): ret = QMessageBox.warning( self, "Solve conflict", "Are you sure you want to solve all conflicts using the 'To merge' version?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if ret == QMessageBox.Yes: self.solved = True self.resolvedConflicts = { c.path: self.REMOTE for c in self.conflicts } self.close() def solveAllLocal(self): ret = QMessageBox.warning( self, "Solve conflict", "Are you sure you want to solve all conflict using the 'Local' version?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if ret == QMessageBox.Yes: self.solved = True self.resolvedConflicts = { c.path: self.LOCAL for c in self.conflicts } self.close() def _afterSolve(self, remove=True): if remove: parent = self.lastSelectedItem.parent() parent.removeChild(self.lastSelectedItem) self.lastSelectedItem = None if parent.childCount() == 0: self.conflictsTree.invisibleRootItem().removeChild(parent) if self.conflictsTree.topLevelItemCount() == 0: self.solved = True self.close() self.attributesTable.setRowCount(0) self.cleanCanvas() self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) def solveLocal(self): self.resolvedConflicts[self.currentPath] = self.LOCAL self._afterSolve() def solveRemote(self): self.resolvedConflicts[self.currentPath] = self.REMOTE self._afterSolve() def solve(self): attribs = {} for i in range(self.attributesTable.rowCount()): value = self.attributesTable.item(i, 4).value name = str(self.attributesTable.item(i, 3).text()) attribs[name] = value self.resolvedConflicts[self.currentPath] = attribs self._afterSolve() def updateSolveButton(self): self.solveButton.setEnabled(len(self.conflicted) == 0) def showFeatureAttributes(self): conflictItem = self.lastSelectedItem self.oursgeom = None self.theirsgeom = None geoms = (self.oursgeom, self.theirsgeom) self.currentConflictedAttributes = [] attribs = list(conflictItem.origin.keys()) self.attributesTable.setRowCount(len(attribs)) self.conflicted = [] for idx, name in enumerate(attribs): font = QFont() font.setBold(True) font.setWeight(75) item = QTableWidgetItem(name) item.setFont(font) self.attributesTable.setItem(idx, 3, item) self.attributesTable.setItem(idx, 4, ValueItem(None, False)) try: values = (conflictItem.origin[name], conflictItem.local[name], conflictItem.remote[name]) except Exception: #Local has been deleted self._afterSolve(False) self.solveModifyAndDelete(conflictItem.conflict.path, self.REMOTE) return except TypeError: #Remote has been deleted self._afterSolve(False) self.solveModifyAndDelete(conflictItem.conflict.path, self.LOCAL) return try: geom = QgsGeometry.fromWkt(values[0]) except: geom = None if geom is not None: self.theirsgeom = QgsGeometry().fromWkt(values[1]) self.oursgeom = QgsGeometry.fromWkt(values[2]) geoms = (self.oursgeom, self.theirsgeom) ok = values[0] == values[1] or values[1] == values[2] or values[ 0] == values[2] for i, v in enumerate(values): self.attributesTable.setItem(idx, i, ValueItem(v, not ok, geoms)) if not ok: self.conflicted.append(name) else: if values[0] == values[1]: newvalue = values[2] else: newvalue = values[1] self.attributesTable.setItem(idx, 4, ValueItem(newvalue, False, geoms)) self.attributesTable.resizeRowsToContents() self.attributesTable.horizontalHeader().setMinimumSectionSize(150) self.attributesTable.horizontalHeader().setStretchLastSection(True) def solveModifyAndDelete(self, path, modified): msgBox = QMessageBox() msgBox.setText( "The feature has been modified in one version and deleted in the other one.\n" "How do you want to solve the conflict?") msgBox.addButton(QPushButton('Modify'), QMessageBox.YesRole) msgBox.addButton(QPushButton('Delete'), QMessageBox.NoRole) msgBox.addButton(QPushButton('Cancel'), QMessageBox.RejectRole) ret = msgBox.exec_() if ret == 0: self.resolvedConflicts[path] = modified self._afterSolve() elif ret == 1: self.resolvedConflicts[path] = self.DELETE self._afterSolve() else: pass def createLayers(self): types = [("Point", ptOursStyle, ptTheirsStyle), ("LineString", lineOursStyle, lineTheirsStyle), ("Polygon", polygonOursStyle, polygonTheirsStyle)] if self.oursgeom is not None: geomtype = types[int(self.oursgeom.type())][0] style = types[int(self.oursgeom.type())][1] self.oursLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "ours", "memory") pr = self.oursLayer.dataProvider() feat = QgsFeature() feat.setGeometry(self.oursgeom) pr.addFeatures([feat]) self.oursLayer.loadNamedStyle(style) self.oursLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(self.oursLayer, False) else: self.oursLayer = None if self.theirsgeom is not None: geomtype = types[int(self.theirsgeom.type())][0] style = types[int(self.theirsgeom.type())][2] self.theirsLayer = loadLayerNoCrsDialog( geomtype + "?crs=EPSG:4326", "theirs", "memory") pr = self.theirsLayer.dataProvider() feat = QgsFeature() feat.setGeometry(self.theirsgeom) pr.addFeatures([feat]) self.theirsLayer.loadNamedStyle(style) self.theirsLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(self.theirsLayer, False) else: self.theirsLayer = None def showGeoms(self): checks = [self.showRemoteCheck, self.showLocalCheck] layers = [self.oursLayer, self.theirsLayer] toShow = [] for lay, chk in zip(layers, checks): if lay is not None and chk.isChecked(): toShow.append(lay) self.mapCanvas.setRenderFlag(False) self.mapCanvas.setLayerSet( [QgsMapCanvasLayer(layer) for layer in toShow]) self.mapCanvas.setRenderFlag(True) def closeEvent(self, evnt): if not self.solved: ret = QMessageBox.warning( self, "Conflict resolution", "There are unsolved conflicts.\n" "Do you really want to exit and abort the sync operation?", QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.No: evnt.ignore() return self.cleanCanvas()
def processAlgorithm(self, progress): target = dataobjects.getObjectFromUri( self.getParameterValue(self.TARGET)) join = dataobjects.getObjectFromUri( self.getParameterValue(self.JOIN)) predicates = self.getParameterValue(self.PREDICATE) precision = self.getParameterValue(self.PRECISION) summary = self.getParameterValue(self.SUMMARY) == 1 keep = self.getParameterValue(self.KEEP) == 1 sumList = self.getParameterValue(self.STATS).lower().split(',') targetFields = target.fields() joinFields = join.fields() fieldList = QgsFields() if not summary: joinFields = vector.testForUniqueness(targetFields, joinFields) seq = list(range(len(targetFields) + len(joinFields))) targetFields.extend(joinFields) targetFields = dict(list(zip(seq, targetFields))) else: numFields = {} for j in range(len(joinFields)): if joinFields[j].type() in [QVariant.Int, QVariant.Double, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]: numFields[j] = [] for i in sumList: field = QgsField(i + str(joinFields[j].name()), QVariant.Double, '', 24, 16) fieldList.append(field) field = QgsField('count', QVariant.Double, '', 24, 16) fieldList.append(field) joinFields = vector.testForUniqueness(targetFields, fieldList) targetFields.extend(fieldList) seq = list(range(len(targetFields))) targetFields = dict(list(zip(seq, targetFields))) fields = QgsFields() for f in list(targetFields.values()): fields.append(f) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, target.wkbType(), target.crs()) outFeat = QgsFeature() inFeatB = QgsFeature() inGeom = QgsGeometry() index = vector.spatialindex(join) mapP2 = dict() features = vector.features(join) for f in features: mapP2[f.id()] = QgsFeature(f) features = vector.features(target) total = 100.0 / len(features) for c, f in enumerate(features): atMap1 = f.attributes() outFeat.setGeometry(f.geometry()) inGeom = vector.snapToPrecision(f.geometry(), precision) none = True joinList = [] if inGeom.type() == QgsWkbTypes.PointGeometry: bbox = inGeom.buffer(10, 2).boundingBox() else: bbox = inGeom.boundingBox() bufferedBox = vector.bufferedBoundingBox(bbox, 0.51 * precision) joinList = index.intersects(bufferedBox) if len(joinList) > 0: count = 0 for i in joinList: inFeatB = mapP2[i] inGeomB = vector.snapToPrecision(inFeatB.geometry(), precision) res = False for predicate in predicates: if predicate == 'intersects': res = inGeom.intersects(inGeomB) elif predicate == 'contains': res = inGeom.contains(inGeomB) elif predicate == 'equals': res = inGeom.equals(inGeomB) elif predicate == 'touches': res = inGeom.touches(inGeomB) elif predicate == 'overlaps': res = inGeom.overlaps(inGeomB) elif predicate == 'within': res = inGeom.within(inGeomB) elif predicate == 'crosses': res = inGeom.crosses(inGeomB) if res: break if res: count = count + 1 none = False atMap2 = inFeatB.attributes() if not summary: atMap = atMap1 atMap2 = atMap2 atMap.extend(atMap2) atMap = dict(list(zip(seq, atMap))) break else: for j in list(numFields.keys()): numFields[j].append(atMap2[j]) if summary and not none: atMap = atMap1 for j in list(numFields.keys()): for k in sumList: if k == 'sum': atMap.append(sum(self._filterNull(numFields[j]))) elif k == 'mean': try: nn_count = sum(1 for _ in self._filterNull(numFields[j])) atMap.append(sum(self._filterNull(numFields[j])) / nn_count) except ZeroDivisionError: atMap.append(NULL) elif k == 'min': try: atMap.append(min(self._filterNull(numFields[j]))) except ValueError: atMap.append(NULL) elif k == 'median': atMap.append(self._median(numFields[j])) else: try: atMap.append(max(self._filterNull(numFields[j]))) except ValueError: atMap.append(NULL) numFields[j] = [] atMap.append(count) atMap = dict(list(zip(seq, atMap))) if none: outFeat.setAttributes(atMap1) else: outFeat.setAttributes(list(atMap.values())) if keep: writer.addFeature(outFeat) else: if not none: writer.addFeature(outFeat) progress.setPercentage(int(c * total)) del writer
def addFeatures(self, layerid, features, fields, points=None, lines=None, polygons=None, permissions={}, add_empty=False, addToMap=True): """ Add DIVI layer to QGIS """ qgis_fields = [ QgsField(field['key'], self.TYPES_MAP.get(field['type'], QVariant.String)) for field in fields ] #print (qgis_fields) #print (points, lines, polygons) if points is not None: points_pr = points.dataProvider() if points_pr.fields(): points_pr.deleteAttributes(list(range(len(points_pr.fields())))) points_pr.addAttributes(qgis_fields) points.updateFields() if lines is not None: lines_pr = lines.dataProvider() if lines_pr.fields(): lines_pr.deleteAttributes(list(range(len(lines_pr.fields())))) lines_pr.addAttributes(qgis_fields) lines.updateFields() if polygons is not None: polygons_pr = polygons.dataProvider() if polygons_pr.fields(): polygons_pr.deleteAttributes(list(range(len(polygons_pr.fields())))) x = polygons_pr.addAttributes(qgis_fields) polygons.updateFields() #Lists of QGIS features points_list = [] lines_list = [] polygons_list = [] count = float(len(features)) points_ids = [] lines_ids = [] polygons_ids = [] for i, feature in enumerate(features, start=1): #Geometria w formacie WKB zakodowanym przez base64 geom = QgsGeometry() geom.fromWkb(b64decode(feature['geometry'])) f = QgsFeature() f.setGeometry(geom) f.setAttributes([ feature['properties'].get(field['key']) for field in fields ]) #Add feature to list by geometry type if geom.type() == QgsWkbTypes.PointGeometry: points_list.append(f) points_ids.append(feature['id']) elif geom.type() == QgsWkbTypes.LineGeometry: lines_list.append(f) lines_ids.append(feature['id']) elif geom.type() == QgsWkbTypes.PolygonGeometry: polygons_list.append(f) polygons_ids.append(feature['id']) else: continue if self.msgBar is not None: #self.msgBar.setProgress(i/count) pass QgsApplication.processEvents() if self.msgBar.aborted: #Użytkownik anulował operację return [] #Add only layers that have features result = [] register = partial(self.registerLayer, layerid=layerid, permissions=permissions, addToMap=addToMap, fields=fields) if points is not None and (points_list or add_empty): lyr, added = register(layer=points, features=points_list) result.append(lyr) self.ids_map[points.id()] = dict(list(zip(added, points_ids))) if lines is not None and (lines_list or add_empty): lyr, added = register(layer=lines, features=lines_list) result.append(lyr) self.ids_map[lines.id()] = dict(list(zip(added, lines_ids))) if polygons is not None and (polygons_list or add_empty): lyr, added = register(layer=polygons, features=polygons_list) result.append(lyr) self.ids_map[polygons.id()] = dict(list(zip(added, polygons_ids))) return result
def processAlgorithm(self, progress): vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT)) vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2)) vproviderA = vlayerA.dataProvider() geomType = vproviderA.geometryType() fields = vector.combineVectorFields(vlayerA, vlayerB) writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields, geomType, vproviderA.crs()) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() indexA = vector.spatialindex(vlayerB) indexB = vector.spatialindex(vlayerA) count = 0 nElement = 0 featuresA = vector.features(vlayerA) nFeat = len(featuresA) for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 50) nElement += 1 lstIntersectingB = [] geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = indexA.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: # This really shouldn't happen, as we haven't # edited the input geom at all ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) else: for id in intersects: count += 1 request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerB.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if geom.intersects(tmpGeom): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if int_geom is None: # There was a problem creating the intersection ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.')) int_geom = QgsGeometry() else: int_geom = QgsGeometry(int_geom) if int_geom.wkbType() == Qgis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection: # Intersection produced different geomety types temp_list = int_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): int_geom = QgsGeometry(i) try: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) else: # Geometry list: prevents writing error # in geometries of different types # produced by the intersection # fix #3549 if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]: try: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) # the remaining bit of inFeatA's geometry # if there is nothing left, this will just silently fail and we're good diff_geom = QgsGeometry(geom) if len(lstIntersectingB) != 0: intB = QgsGeometry.unaryUnion(lstIntersectingB) diff_geom = diff_geom.difference(intB) if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid(): ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.')) if diff_geom.wkbType() == 0 or QgsWKBTypes.flatType(diff_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection: temp_list = diff_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): diff_geom = QgsGeometry(i) try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) length = len(vproviderA.fields()) atMapA = [None] * length featuresA = vector.features(vlayerB) nFeat = len(featuresA) for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 100) add = False geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMap = [None] * length atMap.extend(inFeatA.attributes()) intersects = indexB.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) else: for id in intersects: request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerA.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if diff_geom.intersects(tmpGeom): add = True diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid(): ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.')) else: try: # Ihis only happends if the bounding box # intersects, but the geometry doesn't outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) nElement += 1 del writer
def intersection(source, mask, callback=None): """Intersect two layers. Issue https://github.com/inasafe/inasafe/issues/3186 Note : This algorithm is copied from : https://github.com/qgis/QGIS/blob/master/python/plugins/processing/algs/ qgis/Intersection.py :param source: The vector layer to clip. :type source: QgsVectorLayer :param mask: The vector layer to use for clipping. :type mask: QgsVectorLayer :param callback: A function to all to indicate progress. The function should accept params 'current' (int), 'maximum' (int) and 'step' (str). Defaults to None. :type callback: function :return: The clip vector layer. :rtype: QgsVectorLayer .. versionadded:: 4.0 """ output_layer_name = intersection_steps['output_layer_name'] output_layer_name = output_layer_name % ( source.keywords['layer_purpose']) processing_step = intersection_steps['step_name'] fields = source.fields() fields.extend(mask.fields()) writer = create_memory_layer( output_layer_name, source.geometryType(), source.crs(), fields ) writer.startEditing() # Begin copy/paste from Processing plugin. # Please follow their code as their code is optimized. # The code below is not following our coding standards because we want to # be able to track any diffs from QGIS easily. out_feature = QgsFeature() index = create_spatial_index(mask) # Todo callback # total = 100.0 / len(selectionA) for current, in_feature in enumerate(source.getFeatures()): # progress.setPercentage(int(current * total)) geom = in_feature.geometry() attributes = in_feature.attributes() intersects = index.intersects(geom.boundingBox()) for i in intersects: request = QgsFeatureRequest().setFilterFid(i) feature_mask = next(mask.getFeatures(request)) tmp_geom = feature_mask.geometry() if geom.intersects(tmp_geom): mask_attributes = feature_mask.attributes() int_geom = QgsGeometry(geom.intersection(tmp_geom)) if int_geom.wkbType() == QgsWKBTypes.Unknown\ or QgsWKBTypes.flatType( int_geom.geometry().wkbType()) ==\ QgsWKBTypes.GeometryCollection: int_com = geom.combine(tmp_geom) int_geom = QgsGeometry() if int_com: int_sym = geom.symDifference(tmp_geom) int_geom = QgsGeometry(int_com.difference(int_sym)) if int_geom.isGeosEmpty() or not int_geom.isGeosValid(): # LOGGER.debug( # tr('GEOS geoprocessing error: One or more input ' # 'features have invalid geometry.')) pass try: geom_types = wkb_type_groups[ wkb_type_groups[int_geom.wkbType()]] if int_geom.wkbType() in geom_types: if int_geom.type() == source.geometryType(): # We got some features which have not the same # kind of geometry. We want to skip them. out_feature.setGeometry(int_geom) attrs = [] attrs.extend(attributes) attrs.extend(mask_attributes) out_feature.setAttributes(attrs) writer.addFeature(out_feature) except: LOGGER.debug( tr('Feature geometry error: One or more output ' 'features ignored due to invalid geometry.')) continue # End copy/paste from Processing plugin. writer.commitChanges() writer.keywords = dict(source.keywords) writer.keywords['title'] = output_layer_name writer.keywords['layer_purpose'] = layer_purpose_exposure_summary['key'] writer.keywords['inasafe_fields'] = dict(source.keywords['inasafe_fields']) writer.keywords['inasafe_fields'].update(mask.keywords['inasafe_fields']) writer.keywords['hazard_keywords'] = dict(mask.keywords['hazard_keywords']) writer.keywords['exposure_keywords'] = dict(source.keywords) writer.keywords['aggregation_keywords'] = dict( mask.keywords['aggregation_keywords']) check_layer(writer) return writer
class GeometryCopier: def __init__(self, iface): # Save reference to the QGIS interface self.iface = iface # initialize plugin directory self.plugin_dir = QFileInfo(QgsApplication.qgisUserDbFilePath()).path( ) + "/python/plugins/geometry_copier" # initialize locale locale_path = "" if sip.getapi("QVariant") > 1: # new API style locale = QSettings().value("locale/userLocale")[0:2] else: # the old API style locale = QSettings().value("locale/userLocale").toString()[0:2] if QFileInfo(self.plugin_dir).exists(): locale_path = self.plugin_dir + "/i18n/geometry_copier_" + locale + ".qm" if QFileInfo(locale_path).exists(): self.translator = QTranslator() self.translator.load(locale_path) if qVersion() > '4.3.3': QCoreApplication.installTranslator(self.translator) self._geom_buffer = None def initGui(self): # Create action that will start plugin configuration self.copy_action = QAction( QIcon(':/plugins/geometrycopier/mActionEditCopyGeom.png'), self.tr(u"Copy geometry"), self.iface.mainWindow()) self.insert_action = QAction( QIcon(':/plugins/geometrycopier/mActionEditPasteGeom.png'), self.tr(u"Insert geometry"), self.iface.mainWindow()) # connect the action to the run method QObject.connect(self.copy_action, SIGNAL("triggered()"), self.copy_geometry) QObject.connect(self.insert_action, SIGNAL("triggered()"), self.insert_geometry) # Add hotkeys self.iface.registerMainWindowAction(self.copy_action, "F7") self.iface.registerMainWindowAction(self.insert_action, "F8") # Add toolbar button and menu item self.iface.digitizeToolBar().addAction(self.copy_action) self.iface.digitizeToolBar().addAction(self.insert_action) self.iface.addPluginToVectorMenu(u"&Geometry copier", self.copy_action) self.iface.addPluginToVectorMenu(u"&Geometry copier", self.insert_action) # Add global signals QObject.connect(self.iface, SIGNAL('currentLayerChanged(QgsMapLayer *)'), self.check_buttons_state) QObject.connect(self.iface.mapCanvas(), SIGNAL('selectionChanged(QgsMapLayer *)'), self.check_buttons_state) QObject.connect(self.iface.actionToggleEditing(), SIGNAL('triggered()'), self.check_buttons_state) #iface.actionToggleEditing().triggered # init state self.check_buttons_state(None) def unload(self): self.iface.unregisterMainWindowAction(self.copy_action) self.iface.unregisterMainWindowAction(self.insert_action) self.iface.removePluginVectorMenu(u"&Geometry copier", self.copy_action) self.iface.removePluginVectorMenu(u"&Geometry copier", self.insert_action) self.iface.digitizeToolBar().removeAction(self.copy_action) self.iface.digitizeToolBar().removeAction(self.insert_action) QObject.disconnect(self.iface, SIGNAL('currentLayerChanged(QgsMapLayer *)'), self.check_buttons_state) QObject.disconnect(self.iface.mapCanvas(), SIGNAL('selectionChanged(QgsMapLayer *)'), self.check_buttons_state) QObject.disconnect(self.iface.actionToggleEditing(), SIGNAL('triggered()'), self.check_buttons_state) def check_buttons_state(self, layer=None): layer = self.iface.activeLayer() if not isinstance(layer, QgsVectorLayer): self.copy_action.setDisabled(True) self.insert_action.setDisabled(True) return sel_feat_count = layer.selectedFeatureCount() if sel_feat_count != 1: self.copy_action.setDisabled(True) self.insert_action.setDisabled(True) return self.copy_action.setEnabled(True) # copy button can be pressed! if not layer.isEditable( ) or not self._geom_buffer or self._geom_buffer.type( ) != layer.geometryType(): self.insert_action.setDisabled(True) return self.insert_action.setEnabled( True) # insert button can be pressed! (type geom??) def copy_geometry(self): layer = self.iface.activeLayer() if not isinstance(layer, QgsVectorLayer): QMessageBox.information( None, self.tr('Geometry was not copied'), self.tr('Select any vector layer and feature!')) return sel_feat_count = layer.selectedFeatureCount() if sel_feat_count != 1: QMessageBox.information(None, self.tr('Geometry was not copied'), self.tr('Select one feature!')) return feature = layer.selectedFeatures()[0] self._geom_buffer = QgsGeometry(feature.geometry()) self.check_buttons_state() def insert_geometry(self): layer = self.iface.activeLayer() if not isinstance(layer, QgsVectorLayer): QMessageBox.information( None, self.tr('Geometry can\'t be inserted'), self.tr( 'Select any vector layer and feature for inserting geom!')) return if not self._geom_buffer: QMessageBox.information(None, self.tr('Geometry can\'t be inserted'), self.tr('Buffer is empty!')) return if not layer.isEditable(): QMessageBox.critical(None, self.tr('Geometry can\'t be inserted'), self.tr('Layer is not editable!')) return if self._geom_buffer.type() != layer.geometryType( ): # and layer.geometryType() != 2: QMessageBox.critical( None, self.tr('Geometry can\'t be inserted'), self.tr('Target layer has other geometry type!')) return sel_feat_count = layer.selectedFeatureCount() if sel_feat_count != 1: QMessageBox.critical( None, self.tr('Geometry can\'t be inserted'), self.tr('Select one feature for inserting geom!')) return feature = layer.selectedFeatures()[0] layer.changeGeometry(feature.id(), QgsGeometry(self._geom_buffer)) self.iface.mapCanvas().refresh() def tr(self, text): return QCoreApplication.translate('GeometryCopier', text)
def processAlgorithm(self, parameters, context, feedback): if DEBUG_MODE: logMessage("processAlgorithm(): {}".format( self.__class__.__name__)) source = self.parameterAsSource(parameters, self.INPUT, context) source_layer = self.parameterAsLayer(parameters, self.INPUT, context) title_field = self.parameterAsString(parameters, self.TITLE_FIELD, context) cf_filter = self.parameterAsBool(parameters, self.CF_FILTER, context) fixed_scale = self.parameterAsEnum(parameters, self.SCALE, context) # == 1 buf = self.parameterAsDouble(parameters, self.BUFFER, context) tex_width = self.parameterAsInt(parameters, self.TEX_WIDTH, context) orig_tex_height = self.parameterAsInt(parameters, self.TEX_HEIGHT, context) out_dir = self.parameterAsString(parameters, self.OUTPUT, context) mapSettings = self.controller.settings.mapSettings baseExtent = self.controller.settings.baseExtent rotation = mapSettings.rotation() orig_size = mapSettings.outputSize() if cf_filter: #TODO: FIX ME #cf_layer = QgsMemoryProviderUtils.createMemoryLayer("current feature", # source_layer.fields(), # source_layer.wkbType(), # source_layer.crs()) doc = QDomDocument("qgis") source_layer.exportNamedStyle(doc) orig_layers = mapSettings.layers() total = source.featureCount() for current, feature in enumerate(source.getFeatures()): if feedback.isCanceled(): break if cf_filter: cf_layer = QgsMemoryProviderUtils.createMemoryLayer( "current feature", source_layer.fields(), source_layer.wkbType(), source_layer.crs()) cf_layer.startEditing() cf_layer.addFeature(feature) cf_layer.commitChanges() cf_layer.importNamedStyle(doc) layers = [ cf_layer if lyr == source_layer else lyr for lyr in orig_layers ] mapSettings.setLayers(layers) title = feature.attribute(title_field) feedback.setProgressText("({}/{}) Exporting {}...".format( current + 1, total, title)) # extent geometry = QgsGeometry(feature.geometry()) geometry.transform(self.transform) center = geometry.centroid().asPoint() if fixed_scale or geometry.type() == QgsWkbTypes.PointGeometry: tex_height = orig_tex_height or int( tex_width * orig_size.height() / orig_size.width()) rect = RotatedRect(center, baseExtent.width(), baseExtent.width() * tex_height / tex_width, rotation).scale(1 + buf / 100) else: geometry.rotate(rotation, center) rect = geometry.boundingBox().scaled(1 + buf / 100) center = RotatedRect.rotatePoint(rect.center(), rotation, center) if orig_tex_height: tex_height = orig_tex_height tex_ratio = tex_width / tex_height rect_ratio = rect.width() / rect.height() if tex_ratio > rect_ratio: rect = RotatedRect(center, rect.height() * tex_ratio, rect.height(), rotation) else: rect = RotatedRect(center, rect.width(), rect.width() / tex_ratio, rotation) else: # fit to buffered geometry bounding box rect = RotatedRect(center, rect.width(), rect.height(), rotation) tex_height = tex_width * rect.height() / rect.width() rect.toMapSettings(mapSettings) mapSettings.setOutputSize(QSize(tex_width, tex_height)) self.controller.settings.setMapSettings(mapSettings) self.export(title, out_dir, feedback) feedback.setProgress(int(current / total * 100)) return {}
class ConflictDialog(WIDGET, BASE): LOCAL, REMOTE, DELETE = 1,2, 3 def __init__(self, conflicts): super(ConflictDialog, self).__init__(None, Qt.WindowSystemMenuHint | Qt.WindowTitleHint) self.solved = False self.resolvedConflicts = {} self.conflicts = conflicts self.setupUi(self) self.setWindowFlags(self.windowFlags() | Qt.WindowSystemMenuHint | Qt.WindowMinMaxButtonsHint) self.zoomButton.clicked.connect(self.zoomToFullExtent) self.solveButton.clicked.connect(self.solve) self.conflictsTree.itemClicked.connect(self.treeItemClicked) self.attributesTable.cellClicked.connect(self.cellClicked) self.solveAllLocalButton.clicked.connect(self.solveAllLocal) self.solveAllRemoteButton.clicked.connect(self.solveAllRemote) self.solveLocalButton.clicked.connect(self.solveLocal) self.solveRemoteButton.clicked.connect(self.solveRemote) self.showRemoteCheck.stateChanged.connect(self.showGeoms) self.showLocalCheck.stateChanged.connect(self.showGeoms) self.lastSelectedItem = None self.currentPath = None self.currentConflict = None self.theirsLayer = None self.oursLayer = None settings = QSettings() horizontalLayout = QHBoxLayout() horizontalLayout.setSpacing(0) horizontalLayout.setMargin(0) self.mapCanvas = QgsMapCanvas() self.mapCanvas.setCanvasColor(Qt.white) self.mapCanvas.enableAntiAliasing(settings.value("/qgis/enable_anti_aliasing", False, type = bool)) self.mapCanvas.useImageToRender(settings.value("/qgis/use_qimage_to_render", False, type = bool)) self.mapCanvas.mapRenderer().setProjectionsEnabled(True) action = settings.value("/qgis/wheel_action", 0, type = float) zoomFactor = settings.value("/qgis/zoom_factor", 2, type = float) self.mapCanvas.setWheelAction(QgsMapCanvas.WheelAction(action), zoomFactor) horizontalLayout.addWidget(self.mapCanvas) self.canvasWidget.setLayout(horizontalLayout) self.panTool = QgsMapToolPan(self.mapCanvas) self.mapCanvas.setMapTool(self.panTool) self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) self.fillConflictsTree() def fillConflictsTree(self): topTreeItems = {} for c in self.conflicts: path = os.path.dirname(c.path) if path in topTreeItems: topItem = topTreeItems[path] else: topItem = QTreeWidgetItem() topItem.setText(0, path) topItem.setIcon(0, layerIcon) topTreeItems[path] = topItem conflictItem = ConflictItem(c) topItem.addChild(conflictItem) for item in list(topTreeItems.values()): self.conflictsTree.addTopLevelItem(item) def cellClicked(self, row, col): if col > 2: return value = self.attributesTable.item(row, col).value geoms = (self.oursgeom, self.theirsgeom) self.attributesTable.setItem(row, 4, ValueItem(value, False, geoms)); self.attributesTable.item(row, 0).setBackgroundColor(Qt.white); self.attributesTable.item(row, 1).setBackgroundColor(Qt.white); self.attributesTable.item(row, 2).setBackgroundColor(Qt.white); attrib = self.attributesTable.item(row, 3).text() if attrib in self.conflicted: self.conflicted.remove(attrib) self.updateSolveButton() self.showGeoms() def treeItemClicked(self): item = self.conflictsTree.selectedItems()[0] if self.lastSelectedItem == item: return if isinstance(item, ConflictItem): self.lastSelectedItem = item self.currentPath = item.conflict.path self.updateCurrentPath() self.solveLocalButton.setEnabled(True) self.solveRemoteButton.setEnabled(True) self.solveButton.setEnabled(False) def updateCurrentPath(self): self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) self.cleanCanvas() self.showFeatureAttributes() self.createLayers() self.showGeoms() self.zoomToFullExtent() def zoomToFullExtent(self): layers = [lay.extent() for lay in self.mapCanvas.layers() if lay.type() == lay.VectorLayer] if layers: ext = layers[0] for layer in layers[1:]: ext.combineExtentWith(layer) self.mapCanvas.setExtent(ext) self.mapCanvas.refresh() def cleanCanvas(self): self.mapCanvas.setLayerSet([]) layers = [self.oursLayer, self.theirsLayer] for layer in layers: if layer is not None: QgsMapLayerRegistry.instance().removeMapLayer(layer.id()) self.oursLayer = None self.theirsLayer = None def solveAllRemote(self): ret = QMessageBox.warning(self, "Solve conflict", "Are you sure you want to solve all conflicts using the 'To merge' version?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes); if ret == QMessageBox.Yes: self.solved = True self.resolvedConflicts = {c.path:self.REMOTE for c in self.conflicts} self.close() def solveAllLocal(self): ret = QMessageBox.warning(self, "Solve conflict", "Are you sure you want to solve all conflict using the 'Local' version?", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes); if ret == QMessageBox.Yes: self.solved = True self.resolvedConflicts = {c.path:self.LOCAL for c in self.conflicts} self.close() def _afterSolve(self, remove = True): if remove: parent = self.lastSelectedItem.parent() parent.removeChild(self.lastSelectedItem) self.lastSelectedItem = None if parent.childCount() == 0: self.conflictsTree.invisibleRootItem().removeChild(parent) if self.conflictsTree.topLevelItemCount() == 0: self.solved = True self.close() self.attributesTable.setRowCount(0) self.cleanCanvas() self.solveButton.setEnabled(False) self.solveLocalButton.setEnabled(False) self.solveRemoteButton.setEnabled(False) def solveLocal(self): self.resolvedConflicts[self.currentPath] = self.LOCAL self._afterSolve() def solveRemote(self): self.resolvedConflicts[self.currentPath] = self.REMOTE self._afterSolve() def solve(self): attribs = {} for i in range(self.attributesTable.rowCount()): value = self.attributesTable.item(i, 4).value name = str(self.attributesTable.item(i, 3).text()) attribs[name] = value self.resolvedConflicts[self.currentPath] = attribs self._afterSolve() def updateSolveButton(self): self.solveButton.setEnabled(len(self.conflicted) == 0) def showFeatureAttributes(self): conflictItem = self.lastSelectedItem self.oursgeom = None self.theirsgeom = None geoms = (self.oursgeom, self.theirsgeom) self.currentConflictedAttributes = [] attribs = list(conflictItem.origin.keys()) self.attributesTable.setRowCount(len(attribs)) self.conflicted = [] for idx, name in enumerate(attribs): font = QFont() font.setBold(True) font.setWeight(75) item = QTableWidgetItem(name) item.setFont(font) self.attributesTable.setItem(idx, 3, item); self.attributesTable.setItem(idx, 4, ValueItem(None, False)); try: values = (conflictItem.origin[name], conflictItem.local[name], conflictItem.remote[name]) except Exception: #Local has been deleted self._afterSolve(False) self.solveModifyAndDelete(conflictItem.conflict.path, self.REMOTE) return except TypeError: #Remote has been deleted self._afterSolve(False) self.solveModifyAndDelete(conflictItem.conflict.path,self.LOCAL) return try: geom = QgsGeometry.fromWkt(values[0]) except: geom = None if geom is not None: self.theirsgeom = QgsGeometry().fromWkt(values[1]) self.oursgeom = QgsGeometry.fromWkt(values[2]) geoms = (self.oursgeom, self.theirsgeom) ok = values[0] == values[1] or values[1] == values[2] or values[0] == values[2] for i, v in enumerate(values): self.attributesTable.setItem(idx, i, ValueItem(v, not ok, geoms)); if not ok: self.conflicted.append(name) else: if values[0] == values[1]: newvalue = values[2] else: newvalue = values[1] self.attributesTable.setItem(idx, 4, ValueItem(newvalue, False, geoms)); self.attributesTable.resizeRowsToContents() self.attributesTable.horizontalHeader().setMinimumSectionSize(150) self.attributesTable.horizontalHeader().setStretchLastSection(True) def solveModifyAndDelete(self, path, modified): msgBox = QMessageBox() msgBox.setText("The feature has been modified in one version and deleted in the other one.\n" "How do you want to solve the conflict?") msgBox.addButton(QPushButton('Modify'), QMessageBox.YesRole) msgBox.addButton(QPushButton('Delete'), QMessageBox.NoRole) msgBox.addButton(QPushButton('Cancel'), QMessageBox.RejectRole) ret = msgBox.exec_() if ret == 0: self.resolvedConflicts[path] = modified self._afterSolve() elif ret == 1: self.resolvedConflicts[path] = self.DELETE self._afterSolve() else: pass def createLayers(self): types = [("Point", ptOursStyle, ptTheirsStyle), ("LineString", lineOursStyle, lineTheirsStyle), ("Polygon", polygonOursStyle, polygonTheirsStyle)] if self.oursgeom is not None: geomtype = types[int(self.oursgeom.type())][0] style = types[int(self.oursgeom.type())][1] self.oursLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "ours", "memory") pr = self.oursLayer.dataProvider() feat = QgsFeature() feat.setGeometry(self.oursgeom) pr.addFeatures([feat]) self.oursLayer.loadNamedStyle(style) self.oursLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(self.oursLayer, False) else: self.oursLayer = None if self.theirsgeom is not None: geomtype = types[int(self.theirsgeom.type())][0] style = types[int(self.theirsgeom.type())][2] self.theirsLayer = loadLayerNoCrsDialog(geomtype + "?crs=EPSG:4326", "theirs", "memory") pr = self.theirsLayer.dataProvider() feat = QgsFeature() feat.setGeometry(self.theirsgeom) pr.addFeatures([feat]) self.theirsLayer.loadNamedStyle(style) self.theirsLayer.updateExtents() QgsMapLayerRegistry.instance().addMapLayer(self.theirsLayer, False) else: self.theirsLayer = None def showGeoms(self): checks = [self.showRemoteCheck, self.showLocalCheck] layers = [self.oursLayer, self.theirsLayer] toShow = [] for lay, chk in zip(layers, checks): if lay is not None and chk.isChecked(): toShow.append(lay) self.mapCanvas.setRenderFlag(False) self.mapCanvas.setLayerSet([QgsMapCanvasLayer(layer) for layer in toShow]) self.mapCanvas.setRenderFlag(True) def closeEvent(self, evnt): if not self.solved: ret = QMessageBox.warning(self, "Conflict resolution", "There are unsolved conflicts.\n" "Do you really want to exit and abort the sync operation?", QMessageBox.Yes | QMessageBox.No) if ret == QMessageBox.No: evnt.ignore() return self.cleanCanvas()
def load_complex_gml(self, xml_uri, is_remote, attributes = {}, geometry_mapping = None, logger = None, swap_xy = False): """ :param xml_uri: the XML URI :param is_remote: True if it has to be fetched by http :param attributes: { 'attr1' : ( '//xpath/expression', QVariant.Int ) } :param geometry_mapping: XPath expression to a gml geometry node :param swap_xy: True if X/Y coordinates must be swapped :returns: the created layer """ if is_remote: xml = remote_open_from_qgis(xml_uri) else: # Open the file in binary mode, this means returning bytes # instead of a string whose encoding would have to be interpreted # it is up to the XML parser to determine which encoding it is xml = open(xml_uri, 'rb') src = ComplexFeatureSource(xml, attributes, geometry_mapping, logger) attr_list = [ (k, v[1]) for k, v in attributes.items() ] # first feature id, fid, g, xml, attrs = next(src.getFeatures()) qgsgeom = None if g is None: layer = self._create_layer('none', None, attr_list, src.title) else: wkb, srid = g qgsgeom = QgsGeometry() qgsgeom.fromWkb(wkb) if qgsgeom and qgsgeom.type() == QgsWkbTypes.PointGeometry: layer = self._create_layer('point', srid, attr_list, src.title + " (points)") elif qgsgeom and qgsgeom.type() == QgsWkbTypes.LineGeometry: layer = self._create_layer('linestring', srid, attr_list, src.title + " (lines)") elif qgsgeom and qgsgeom.type() == QgsWkbTypes.PolygonGeometry: layer = self._create_layer('polygon', srid, attr_list, src.title + " (polygons)") # add metadata self._add_properties_to_layer(layer, xml_uri, is_remote, attributes, geometry_mapping) # collect features features = [] for id, fid, g, xml, attrs in src.getFeatures(): qgsgeom = None wkb, srid = g qgsgeom = QgsGeometry() qgsgeom.fromWkb(wkb) if qgsgeom and qgsgeom.type() == QgsWkbTypes.PointGeometry: if swap_xy: p = qgsgeom.asPoint() qgsgeom = QgsGeometry.fromPoint(QgsPointXY(p[1], p[0])) elif qgsgeom and qgsgeom.type() == QgsWkbTypes.LineGeometry: if swap_xy: pl = qgsgeom.asPolyline() qgsgeom = QgsGeometry.fromPolyline([QgsPointXY(p[1],p[0]) for p in pl]) elif qgsgeom and qgsgeom.type() == QgsWkbTypes.PolygonGeometry: if swap_xy: pl = qgsgeom.asPolygon() qgsgeom = QgsGeometry.fromPolygon([[QgsPointXY(p[1],p[0]) for p in r] for r in pl]) f = QgsFeature(layer.dataProvider().fields(), id) if qgsgeom: f.setGeometry(qgsgeom) f.setAttribute("id", str(id)) f.setAttribute("fid", fid) f.setAttribute("_xml_", ET.tostring(xml).decode('utf8')) for k, v in attrs.items(): r = f.setAttribute(k, v) features.append(f) # write features if len(features) > 0: layer.dataProvider().addFeatures(features) return layer
def single_to_multi(self): vprovider = self.vlayer.dataProvider() allValid = True geomType = self.singleToMultiGeom(vprovider.geometryType()) writer = QgsVectorFileWriter(self.myName, self.myEncoding, vprovider.fields(), geomType, vprovider.crs()) inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() index = vprovider.fieldNameIndex(self.myField) if not index == -1: unique = ftools_utils.getUniqueValues(vprovider, int(index)) else: unique = [""] nFeat = vprovider.featureCount() * len(unique) nElement = 0 self.emit(SIGNAL("runStatus( PyQt_PyObject )"), 0) self.emit(SIGNAL("runRange( PyQt_PyObject )"), (0, nFeat)) merge_all = self.myField == "--- " + self.tr("Merge all") + " ---" if not len(unique) == self.vlayer.featureCount() or merge_all: for i in unique: # Strip spaces for strings, so " A " and "A" will be grouped # TODO: Make this optional (opt-out to keep it easy for beginners) if isinstance(i, basestring): iMod = i.strip() else: iMod = i multi_feature = [] first = True fit = vprovider.getFeatures() while fit.nextFeature(inFeat): atMap = inFeat.attributes() if not merge_all: idVar = atMap[index] if isinstance(idVar, basestring): idVarMod = idVar.strip() else: idVarMod = idVar else: idVarMod = "" if idVarMod == iMod or merge_all: if first: atts = atMap first = False inGeom = QgsGeometry(inFeat.geometry()) vType = inGeom.type() feature_list = self.extractAsMulti(inGeom) multi_feature.extend(feature_list) nElement += 1 self.emit(SIGNAL("runStatus( PyQt_PyObject )"), nElement) if not first: outFeat.setAttributes(atts) outGeom = QgsGeometry(self.convertGeometry(multi_feature, vType)) if not outGeom.isGeosValid(): allValid = "valid_error" outFeat.setGeometry(outGeom) writer.addFeature(outFeat) del writer else: return "attr_error" return allValid
def processAlgorithm(self, progress): vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT)) vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2)) GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = vlayerA.dataProvider() fields = vector.combineVectorFields(vlayerA, vlayerB) names = [field.name() for field in fields] ProcessingLog.addToLog(ProcessingLog.LOG_INFO, unicode(names)) writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields, vproviderA.geometryType(), vproviderA.crs()) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() indexA = vector.spatialindex(vlayerB) indexB = vector.spatialindex(vlayerA) count = 0 nElement = 0 featuresA = vector.features(vlayerA) nFeat = len(featuresA) for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 50) nElement += 1 lstIntersectingB = [] geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = indexA.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: # This really shouldn't happen, as we haven't # edited the input geom at all raise GeoAlgorithmExecutionException( self.tr('Feature exception while computing union')) else: for id in intersects: count += 1 request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerB.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if geom.intersects(tmpGeom): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if int_geom is None: # There was a problem creating the intersection raise GeoAlgorithmExecutionException( self.tr('Geometry exception while computing ' 'intersection')) else: int_geom = QgsGeometry(int_geom) if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection: # Intersection produced different geomety types temp_list = int_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): int_geom = QgsGeometry(i) try: outFeat.setGeometry(int_geom) attrs = [] attrs.extend(atMapA) attrs.extend(atMapB) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except Exception as err: raise GeoAlgorithmExecutionException( self.tr('Feature exception while computing union')) try: # the remaining bit of inFeatA's geometry # if there is nothing left, this will just silently fail and we're good diff_geom = QgsGeometry(geom) if len(lstIntersectingB) != 0: intB = QgsGeometry.unaryUnion(lstIntersectingB) diff_geom = diff_geom.difference(intB) if diff_geom.wkbType() == 0 or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection: temp_list = diff_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): diff_geom = QgsGeometry(i) outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except Exception as err: raise GeoAlgorithmExecutionException( self.tr('Feature exception while computing union')) length = len(vproviderA.fields()) featuresA = vector.features(vlayerB) nFeat = len(featuresA) for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 100) add = False geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMap = [None] * length atMap.extend(inFeatA.attributes()) intersects = indexB.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except Exception as err: raise GeoAlgorithmExecutionException( self.tr('Feature exception while computing union')) else: for id in intersects: request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerA.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) try: if diff_geom.intersects(tmpGeom): add = True diff_geom = QgsGeometry( diff_geom.difference(tmpGeom)) else: # Ihis only happends if the bounding box # intersects, but the geometry doesn't outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except Exception as err: raise GeoAlgorithmExecutionException( self.tr('Geometry exception while computing intersection')) if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except Exception as err: raise err FEATURE_EXCEPT = False nElement += 1 del writer if not GEOS_EXCEPT: ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, self.tr('Geometry exception while computing intersection')) if not FEATURE_EXCEPT: ProcessingLog.addToLog(ProcessingLog.LOG_WARNING, self.tr('Feature exception while computing intersection'))
def processAlgorithm(self, progress): target = dataobjects.getObjectFromUri( self.getParameterValue(self.TARGET)) join = dataobjects.getObjectFromUri( self.getParameterValue(self.JOIN)) predicates = self.getParameterValue(self.PREDICATE) summary = self.getParameterValue(self.SUMMARY) == 1 keep = self.getParameterValue(self.KEEP) == 1 sumList = self.getParameterValue(self.STATS).lower().split(',') targetProvider = target.dataProvider() joinProvider = join.dataProvider() targetFields = targetProvider.fields() joinFields = joinProvider.fields() fieldList = QgsFields() if not summary: joinFields = vector.testForUniqueness(targetFields, joinFields) seq = range(0, len(targetFields) + len(joinFields)) targetFields.extend(joinFields) targetFields = dict(zip(seq, targetFields)) else: numFields = {} for j in xrange(len(joinFields)): if joinFields[j].type() in [QVariant.Int, QVariant.Double]: numFields[j] = [] for i in sumList: field = QgsField(i + unicode(joinFields[j].name()), QVariant.Double, '', 24, 16) fieldList.append(field) field = QgsField('count', QVariant.Double, '', 24, 16) fieldList.append(field) joinFields = vector.testForUniqueness(targetFields, fieldList) targetFields.extend(fieldList) seq = range(0, len(targetFields)) targetFields = dict(zip(seq, targetFields)) fields = QgsFields() for f in targetFields.values(): fields.append(f) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, targetProvider.geometryType(), targetProvider.crs()) outFeat = QgsFeature() inFeatB = QgsFeature() inGeom = QgsGeometry() index = vector.spatialindex(join) mapP2 = dict() features = vector.features(join) for f in features: mapP2[f.id()] = QgsFeature(f) features = vector.features(target) total = 100.0 / len(features) for c, f in enumerate(features): inGeom = f.geometry() atMap1 = f.attributes() outFeat.setGeometry(inGeom) none = True joinList = [] if inGeom.type() == QGis.Point: joinList = index.intersects(inGeom.buffer(10, 2).boundingBox()) if len(joinList) > 0: check = 0 else: check = 1 else: joinList = index.intersects(inGeom.boundingBox()) if len(joinList) > 0: check = 0 else: check = 1 if check == 0: count = 0 for i in joinList: inFeatB = mapP2[i] inGeomB = inFeatB.geometry() res = False for predicate in predicates: if predicate == 'intersects': res = inGeom.intersects(inGeomB) elif predicate == 'contains': res = inGeom.contains(inGeomB) elif predicate == 'equals': res = inGeom.equals(inGeomB) elif predicate == 'touches': res = inGeom.touches(inGeomB) elif predicate == 'overlaps': res = inGeom.overlaps(inGeomB) elif predicate == 'within': res = inGeom.within(inGeomB) elif predicate == 'crosses': res = inGeom.crosses(inGeomB) if res: break if res: count = count + 1 none = False atMap2 = inFeatB.attributes() if not summary: atMap = atMap1 atMap2 = atMap2 atMap.extend(atMap2) atMap = dict(zip(seq, atMap)) break else: for j in numFields.keys(): numFields[j].append(atMap2[j]) if summary and not none: atMap = atMap1 for j in numFields.keys(): for k in sumList: if k == 'sum': atMap.append(sum(self._filterNull(numFields[j]))) elif k == 'mean': try: nn_count = sum(1 for _ in self._filterNull(numFields[j])) atMap.append(sum(self._filterNull(numFields[j])) / nn_count) except ZeroDivisionError: atMap.append(NULL) elif k == 'min': try: atMap.append(min(self._filterNull(numFields[j]))) except ValueError: atMap.append(NULL) elif k == 'median': atMap.append(self._median(numFields[j])) else: try: atMap.append(max(self._filterNull(numFields[j]))) except ValueError: atMap.append(NULL) numFields[j] = [] atMap.append(count) atMap = dict(zip(seq, atMap)) if none: outFeat.setAttributes(atMap1) else: outFeat.setAttributes(atMap.values()) if keep: writer.addFeature(outFeat) else: if not none: writer.addFeature(outFeat) progress.setPercentage(int(c * total)) del writer
def processAlgorithm(self, progress): vlayerA = dataobjects.getObjectFromUri( self.getParameterValue(Union.INPUT)) vlayerB = dataobjects.getObjectFromUri( self.getParameterValue(Union.INPUT2)) vproviderA = vlayerA.dataProvider() geomType = vproviderA.geometryType() if geomType in GEOM_25D: raise GeoAlgorithmExecutionException( self.tr('Input layer has unsupported geometry type {}').format( geomType)) fields = vector.combineVectorFields(vlayerA, vlayerB) writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter( fields, geomType, vproviderA.crs()) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() indexA = vector.spatialindex(vlayerB) indexB = vector.spatialindex(vlayerA) count = 0 nElement = 0 featuresA = vector.features(vlayerA) nFeat = len(featuresA) for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 50) nElement += 1 lstIntersectingB = [] geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = indexA.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: # This really shouldn't happen, as we haven't # edited the input geom at all ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) else: for id in intersects: count += 1 request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerB.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if geom.intersects(tmpGeom): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if int_geom is None: # There was a problem creating the intersection ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('GEOS geoprocessing error: One or more input features have invalid geometry.' )) int_geom = QgsGeometry() else: int_geom = QgsGeometry(int_geom) if int_geom.wkbType( ) == QGis.WKBUnknown or QgsWKBTypes.flatType( int_geom.geometry().wkbType( )) == QgsWKBTypes.GeometryCollection: # Intersection produced different geomety types temp_list = int_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): int_geom = QgsGeometry(i) try: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) else: # Geometry list: prevents writing error # in geometries of different types # produced by the intersection # fix #3549 if int_geom.wkbType() in wkbTypeGroups[ wkbTypeGroups[int_geom.wkbType()]]: try: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) # the remaining bit of inFeatA's geometry # if there is nothing left, this will just silently fail and we're good diff_geom = QgsGeometry(geom) if len(lstIntersectingB) != 0: intB = QgsGeometry.unaryUnion(lstIntersectingB) diff_geom = diff_geom.difference(intB) if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid(): ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self. tr('GEOS geoprocessing error: One or more input features have invalid geometry.' )) if diff_geom.wkbType() == 0 or QgsWKBTypes.flatType( diff_geom.geometry().wkbType( )) == QgsWKBTypes.GeometryCollection: temp_list = diff_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): diff_geom = QgsGeometry(i) try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) length = len(vproviderA.fields()) atMapA = [None] * length featuresA = vector.features(vlayerB) nFeat = len(featuresA) for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 100) add = False geom = QgsGeometry(inFeatA.geometry()) diff_geom = QgsGeometry(geom) atMap = [None] * length atMap.extend(inFeatA.attributes()) intersects = indexB.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) else: for id in intersects: request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerA.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if diff_geom.intersects(tmpGeom): add = True diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) if diff_geom.isGeosEmpty( ) or not diff_geom.isGeosValid(): ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self. tr('GEOS geoprocessing error: One or more input features have invalid geometry.' )) else: try: # Ihis only happends if the bounding box # intersects, but the geometry doesn't outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) if add: try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) nElement += 1 del writer
def processAlgorithm(self, progress): vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT)) vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(Union.INPUT2)) geomType = vlayerA.wkbType() fields = vector.combineVectorFields(vlayerA, vlayerB) writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter(fields, geomType, vlayerA.crs()) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() indexA = vector.spatialindex(vlayerB) indexB = vector.spatialindex(vlayerA) count = 0 nElement = 0 featuresA = vector.features(vlayerA) nFeat = len(featuresA) if len(featuresA) > 0 else 1 for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 50) nElement += 1 lstIntersectingB = [] geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = indexA.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: # This really shouldn't happen, as we haven't # edited the input geom at all ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) else: for id in intersects: count += 1 request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerB.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if geom.intersects(tmpGeom): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if int_geom is None: # There was a problem creating the intersection ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.')) int_geom = QgsGeometry() else: int_geom = QgsGeometry(int_geom) # TODO: the result may have a different dimension (e.g. intersection of two polygons may result in a single point) # or the result may be a collection of geometries (e.g. intersection of two polygons results in three polygons and one linestring). # We need to filter out all acceptable geometries into a single (possibly multi-part) geometry - and we need # to do it consistently also in the code further below if int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection: # Intersection produced different geomety types temp_list = int_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): int_geom = QgsGeometry(i) try: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) else: # Geometry list: prevents writing error # in geometries of different types # produced by the intersection # fix #3549 if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]: try: outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) # the remaining bit of inFeatA's geometry # if there is nothing left, this will just silently fail and we're good diff_geom = QgsGeometry(geom) if len(lstIntersectingB) != 0: intB = QgsGeometry.unaryUnion(lstIntersectingB) diff_geom = diff_geom.difference(intB) if diff_geom is None: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.')) diff_geom = QgsGeometry() if diff_geom.isGeosEmpty() or not diff_geom.isGeosValid(): ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.')) # TODO: correctly handly different output geometry types (see todo above) if diff_geom.wkbType() == 0 or QgsWKBTypes.flatType(diff_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection: temp_list = diff_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): diff_geom = QgsGeometry(i) try: outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) length = len(vlayerA.fields()) atMapA = [None] * length featuresA = vector.features(vlayerB) nFeat = len(featuresA) if len(featuresA) else 1 for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 100) add = False geom = QgsGeometry(inFeatA.geometry()) atMap = [None] * length atMap.extend(inFeatA.attributes()) intersects = indexB.intersects(geom.boundingBox()) lstIntersectingA = [] for id in intersects: request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerA.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if geom.intersects(tmpGeom): lstIntersectingA.append(tmpGeom) if len(lstIntersectingA) == 0: res_geom = geom else: intA = QgsGeometry.unaryUnion(lstIntersectingA) res_geom = geom.difference(intA) if res_geom is None: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.')) res_geom = QgsGeometry() if res_geom.isGeosEmpty() or not res_geom.isGeosValid(): ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or more input features have invalid geometry.')) # TODO: correctly handly different output geometry types (see todo above) try: outFeat.setGeometry(res_geom) outFeat.setAttributes(atMap) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_INFO, self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.')) nElement += 1 del writer
def processAlgorithm(self, progress): vlayerA = dataobjects.getObjectFromUri( self.getParameterValue(Union.INPUT)) vlayerB = dataobjects.getObjectFromUri( self.getParameterValue(Union.INPUT2)) GEOS_EXCEPT = True FEATURE_EXCEPT = True vproviderA = vlayerA.dataProvider() fields = vector.combineVectorFields(vlayerA, vlayerB) names = [field.name() for field in fields] ProcessingLog.addToLog(ProcessingLog.LOG_INFO, str(names)) writer = self.getOutputFromName(Union.OUTPUT).getVectorWriter( fields, vproviderA.geometryType(), vproviderA.crs()) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() indexA = vector.spatialindex(vlayerB) indexB = vector.spatialindex(vlayerA) count = 0 nElement = 0 featuresA = vector.features(vlayerA) nFeat = len(featuresA) for inFeatA in featuresA: progress.setPercentage(nElement / float(nFeat) * 50) nElement += 1 lstIntersectingB = [] geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = indexA.intersects(geom.boundingBox()) if len(intersects) < 1: try: outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except: # This really shouldn't happen, as we haven't # edited the input geom at all raise GeoAlgorithmExecutionException( self.tr('Feature exception while computing union')) else: for id in intersects: count += 1 request = QgsFeatureRequest().setFilterFid(id) inFeatB = vlayerB.getFeatures(request).next() atMapB = inFeatB.attributes() tmpGeom = QgsGeometry(inFeatB.geometry()) if geom.intersects(tmpGeom): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if int_geom is None: # There was a problem creating the intersection raise GeoAlgorithmExecutionException( self.tr('Geometry exception while computing ' 'intersection')) else: int_geom = QgsGeometry(int_geom) if int_geom.wkbType() == 0: # Intersection produced different geomety types temp_list = int_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): int_geom = QgsGeometry(i) try: outFeat.setGeometry(int_geom) attrs = [] attrs.extend(atMapA) attrs.extend(atMapB) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except Exception, err: raise GeoAlgorithmExecutionException( self.tr( 'Feature exception while computing union')) try: # the remaining bit of inFeatA's geometry # if there is nothing left, this will just silently fail and we're good diff_geom = QgsGeometry(geom) if len(lstIntersectingB) != 0: intB = QgsGeometry.unaryUnion(lstIntersectingB) diff_geom = diff_geom.difference(intB) if diff_geom.wkbType() == 0: temp_list = diff_geom.asGeometryCollection() for i in temp_list: if i.type() == geom.type(): diff_geom = QgsGeometry(i) outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) writer.addFeature(outFeat) except Exception, err: raise GeoAlgorithmExecutionException( self.tr('Feature exception while computing union'))
def processAlgorithm(self, progress): target = dataobjects.getObjectFromUri( self.getParameterValue(self.TARGET)) join = dataobjects.getObjectFromUri(self.getParameterValue(self.JOIN)) summary = self.getParameterValue(self.SUMMARY) == 1 keep = self.getParameterValue(self.KEEP) == 1 sumList = self.getParameterValue(self.STATS).lower().split(',') targetProvider = target.dataProvider() joinProvider = join.dataProvider() targetFields = targetProvider.fields() joinFields = joinProvider.fields() fieldList = QgsFields() if not summary: joinFields = vector.testForUniqueness(targetFields, joinFields) seq = range(0, len(targetFields) + len(joinFields)) targetFields.extend(joinFields) targetFields = dict(zip(seq, targetFields)) else: numFields = {} for j in xrange(len(joinFields)): if joinFields[j].type() in [QVariant.Int, QVariant.Double]: numFields[j] = [] for i in sumList: field = QgsField(i + unicode(joinFields[j].name()), QVariant.Double, '', 24, 16) fieldList.append(field) field = QgsField('count', QVariant.Double, '', 24, 16) fieldList.append(field) joinFields = vector.testForUniqueness(targetFields, fieldList) targetFields.extend(fieldList) seq = range(0, len(targetFields)) targetFields = dict(zip(seq, targetFields)) fields = QgsFields() for f in targetFields.values(): fields.append(f) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, targetProvider.geometryType(), targetProvider.crs()) outFeat = QgsFeature() inFeatB = QgsFeature() inGeom = QgsGeometry() index = vector.spatialindex(join) mapP2 = dict() features = vector.features(join) for f in features: mapP2[f.id()] = QgsFeature(f) features = vector.features(target) total = 100.0 / len(features) for c, f in enumerate(features): inGeom = f.geometry() atMap1 = f.attributes() outFeat.setGeometry(inGeom) none = True joinList = [] if inGeom.type() == QGis.Point: joinList = index.intersects(inGeom.buffer(10, 2).boundingBox()) if len(joinList) > 0: check = 0 else: check = 1 else: joinList = index.intersects(inGeom.boundingBox()) if len(joinList) > 0: check = 0 else: check = 1 if check == 0: count = 0 for i in joinList: inFeatB = mapP2[i] if inGeom.intersects(inFeatB.geometry()): count = count + 1 none = False atMap2 = inFeatB.attributes() if not summary: atMap = atMap1 atMap2 = atMap2 atMap.extend(atMap2) atMap = dict(zip(seq, atMap)) break else: for j in numFields.keys(): numFields[j].append(atMap2[j]) if summary and not none: atMap = atMap1 for j in numFields.keys(): for k in sumList: if k == 'sum': atMap.append( sum(self._filterNull(numFields[j]))) elif k == 'mean': try: nn_count = sum(1 for _ in self._filterNull( numFields[j])) atMap.append( sum(self._filterNull(numFields[j])) / nn_count) except ZeroDivisionError: atMap.append(NULL) elif k == 'min': try: atMap.append( min(self._filterNull(numFields[j]))) except ValueError: atMap.append(NULL) elif k == 'median': atMap.append(self._median(numFields[j])) else: try: atMap.append( max(self._filterNull(numFields[j]))) except ValueError: atMap.append(NULL) numFields[j] = [] atMap.append(count) atMap = dict(zip(seq, atMap)) if none: outFeat.setAttributes(atMap1) else: outFeat.setAttributes(atMap.values()) if keep: writer.addFeature(outFeat) else: if not none: writer.addFeature(outFeat) progress.setPercentage(int(c * total)) del writer
def processAlgorithm(self, progress): target = dataobjects.getObjectFromUri( self.getParameterValue(self.TARGET)) join = dataobjects.getObjectFromUri( self.getParameterValue(self.JOIN)) predicates = self.getParameterValue(self.PREDICATE) precision = self.getParameterValue(self.PRECISION) summary = self.getParameterValue(self.SUMMARY) == 1 keep = self.getParameterValue(self.KEEP) == 1 sumList = self.getParameterValue(self.STATS).lower().split(',') targetFields = target.fields() joinFields = join.fields() fieldList = QgsFields() if not summary: joinFields = vector.testForUniqueness(targetFields, joinFields) seq = list(range(len(targetFields) + len(joinFields))) targetFields.extend(joinFields) targetFields = dict(list(zip(seq, targetFields))) else: numFields = {} for j in range(len(joinFields)): if joinFields[j].type() in [QVariant.Int, QVariant.Double, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]: numFields[j] = [] for i in sumList: field = QgsField(i + str(joinFields[j].name()), QVariant.Double, '', 24, 16) fieldList.append(field) field = QgsField('count', QVariant.Double, '', 24, 16) fieldList.append(field) joinFields = vector.testForUniqueness(targetFields, fieldList) targetFields.extend(fieldList) seq = list(range(len(targetFields))) targetFields = dict(list(zip(seq, targetFields))) fields = QgsFields() for f in list(targetFields.values()): fields.append(f) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, target.wkbType(), target.crs()) outFeat = QgsFeature() inFeatB = QgsFeature() inGeom = QgsGeometry() index = vector.spatialindex(join) mapP2 = dict() features = vector.features(join) for f in features: mapP2[f.id()] = QgsFeature(f) features = vector.features(target) total = 100.0 / len(features) for c, f in enumerate(features): atMap1 = f.attributes() outFeat.setGeometry(f.geometry()) inGeom = vector.snapToPrecision(f.geometry(), precision) none = True joinList = [] if inGeom.type() == QgsWkbTypes.PointGeometry: bbox = inGeom.buffer(10, 2).boundingBox() else: bbox = inGeom.boundingBox() bufferedBox = vector.bufferedBoundingBox(bbox, 0.51 * precision) joinList = index.intersects(bufferedBox) if len(joinList) > 0: count = 0 for i in joinList: inFeatB = mapP2[i] inGeomB = vector.snapToPrecision(inFeatB.geometry(), precision) res = False for predicate in predicates: res = getattr(inGeom, predicate)(inGeomB) if res: break if res: count = count + 1 none = False atMap2 = inFeatB.attributes() if not summary: atMap = atMap1 atMap2 = atMap2 atMap.extend(atMap2) atMap = dict(list(zip(seq, atMap))) break else: for j in list(numFields.keys()): numFields[j].append(atMap2[j]) if summary and not none: atMap = atMap1 for j in list(numFields.keys()): for k in sumList: if k == 'sum': atMap.append(sum(self._filterNull(numFields[j]))) elif k == 'mean': try: nn_count = sum(1 for _ in self._filterNull(numFields[j])) atMap.append(sum(self._filterNull(numFields[j])) / nn_count) except ZeroDivisionError: atMap.append(NULL) elif k == 'min': try: atMap.append(min(self._filterNull(numFields[j]))) except ValueError: atMap.append(NULL) elif k == 'median': atMap.append(self._median(numFields[j])) else: try: atMap.append(max(self._filterNull(numFields[j]))) except ValueError: atMap.append(NULL) numFields[j] = [] atMap.append(count) atMap = dict(list(zip(seq, atMap))) if none: outFeat.setAttributes(atMap1) else: outFeat.setAttributes(list(atMap.values())) if keep: writer.addFeature(outFeat) else: if not none: writer.addFeature(outFeat) progress.setPercentage(int(c * total)) del writer
def in_mask(self, feature, srid=None): if feature is None: # expression overview return False if self.layer is None: return False try: # layer is not None but destroyed ? self.layer.id() except: self.reset_mask_layer() return False # mask layer empty due to unloaded memlayersaver plugin > no filtering if self.layer.featureCount() == 0: return True mask_geom, bbox = self.mask_geometry() geom = QgsGeometry(feature.geometry()) if not geom.isGeosValid(): geom = geom.buffer(0.0, 1) if geom is None: return False if srid is not None and self.layer.crs().postgisSrid() != srid: src_crs = QgsCoordinateReferenceSystem(srid) dest_crs = self.layer.crs() xform = QgsCoordinateTransform(src_crs, dest_crs, QgsProject.instance()) try: geom.transform(xform) except Exception as e: for m in e.args: QgsMessageLog.logMessage("in_mask - {}".format(m), "Extensions") # transformation error. Check layer projection. pass if geom.type() == QgsWkbTypes.PolygonGeometry: if (self.parameters.polygon_mask_method == 2 and not self.has_point_on_surface): self.parameters.polygon_mask_method = 1 if self.parameters.polygon_mask_method == 0: # this method can only work when no geometry simplification is involved return mask_geom.overlaps(geom) or mask_geom.contains(geom) elif self.parameters.polygon_mask_method == 1: # the fastest method, but with possible inaccuracies pt = geom.vertexAt(0) return bbox.contains(QgsPointXY(pt)) and mask_geom.contains( geom.centroid()) elif self.parameters.polygon_mask_method == 2: # will always work pt = geom.vertexAt(0) return bbox.contains(QgsPointXY(pt)) and mask_geom.contains( geom.pointOnSurface()) else: return False elif geom.type() == QgsWkbTypes.LineGeometry: if self.parameters.line_mask_method == 0: return mask_geom.intersects(geom) elif self.parameters.line_mask_method == 1: return mask_geom.contains(geom) else: return False elif geom.type() == QgsWkbTypes.PointGeometry: return mask_geom.intersects(geom) else: return False