def testCreateLayerMultiPoint(self): layer = QgsVectorLayer("MultiPoint?crs=epsg:3111&field=id:integer&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1, "test", 1]) f.setGeometry(QgsGeometry.fromWkt('MultiPoint(1 2, 3 4)')) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromWkt('MultiPoint(7 8)')) pr.addFeatures([f, f2, f3]) uri = '{} table="qgis_test"."new_table_multipoint" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:3111')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.MultiPoint) self.assertEqual(new_layer.crs().authid(), 'EPSG:3111') self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint']) features = [f.attributes() for f in new_layer.getFeatures()] self.assertEqual(features, [[1, 1, 'test', 1], [2, 2, 'test2', 3], [3, 3, 'test2', NULL]]) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['MultiPoint ((1 2),(3 4))', '', 'MultiPoint ((7 8))'])
def lines_to_polygons( self ): vprovider = self.vlayer.dataProvider() writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(), QGis.WKBPolygon, vprovider.crs() ) inFeat = QgsFeature() outFeat = QgsFeature() nFeat = vprovider.featureCount() nElement = 0 self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0) self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) ) fit = vprovider.getFeatures() while fit.nextFeature( inFeat ): outGeomList = [] nElement += 1 self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement ) if inFeat.geometry().isMultipart(): outGeomList = inFeat.geometry().asMultiPolyline() else: outGeomList.append( inFeat.geometry().asPolyline() ) polyGeom = self.remove_bad_lines( outGeomList ) if len( polyGeom ) != 0: outFeat.setGeometry( QgsGeometry.fromPolygon( polyGeom ) ) atMap = inFeat.attributes() outFeat.setAttributes( atMap ) writer.addFeature( outFeat ) del writer return True
def nearest_neighbour_analysis(self, vlayer): vprovider = vlayer.dataProvider() sumDist = 0.00 distance = QgsDistanceArea() A = vlayer.extent() A = float(A.width() * A.height()) index = ftools_utils.createIndex(vprovider) nFeat = vprovider.featureCount() nElement = 0 if nFeat > 0: self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0) self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat)) feat = QgsFeature() neighbour = QgsFeature() fit = vprovider.getFeatures() while fit.nextFeature(feat): neighbourID = index.nearestNeighbor(feat.geometry().asPoint(), 2)[1] vprovider.getFeatures(QgsFeatureRequest().setFilterFid(neighbourID).setSubsetOfAttributes([])).nextFeature(neighbour) nearDist = distance.measureLine(neighbour.geometry().asPoint(), feat.geometry().asPoint()) sumDist += nearDist nElement += 1 self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement) nVal = vprovider.featureCount() do = float(sumDist) / nVal de = float(0.5 / math.sqrt(nVal / A)) d = float(do / de) SE = float(0.26136 / math.sqrt((nVal * nVal) / A)) zscore = float((do - de) / SE) lstStats = [] lstStats.append(self.tr("Observed mean distance:") + unicode(do)) lstStats.append(self.tr("Expected mean distance:") + unicode(de)) lstStats.append(self.tr("Nearest neighbour index:") + unicode(d)) lstStats.append(self.tr("N:") + unicode(nVal)) lstStats.append(self.tr("Z-Score:") + unicode(zscore)) return (lstStats, [])
def linearMatrix(self, writer, provider1, provider2, index1, index2, nearest, distArea, matType, sindex, progressBar): inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() start = 15.00 add = 85.00 / provider1.featureCount() fit1 = provider1.getFeatures() while fit1.nextFeature(inFeat): inGeom = inFeat.geometry() inID = inFeat.attributes()[index1] featList = sindex.nearestNeighbor(inGeom.asPoint(), nearest) distList = [] vari = 0.00 for i in featList: provider2.getFeatures(QgsFeatureRequest().setFilterFid(int(i)).setSubsetOfAttributes([index2])).nextFeature(outFeat) outID = outFeat.attributes()[index2] outGeom = outFeat.geometry() dist = distArea.measureLine(inGeom.asPoint(), outGeom.asPoint()) if dist > 0: if matType == "Linear": writer.writerow([unicode(inID), unicode(outID), unicode(dist)]) else: distList.append(float(dist)) if matType == "Summary": mean = sum(distList) / len(distList) for i in distList: vari = vari + ((i - mean) * (i - mean)) vari = sqrt(vari / len(distList)) writer.writerow([unicode(inID), unicode(mean), unicode(vari), unicode(min(distList)), unicode(max(distList))]) start = start + add progressBar.setValue(start) del writer
def layerOmmb(self, layer, writer, progress): current = 0 fit = layer.getFeatures() inFeat = QgsFeature() total = 100.0 / layer.featureCount() newgeometry = QgsGeometry() first = True while fit.nextFeature(inFeat): if first: newgeometry = inFeat.geometry() first = False else: newgeometry = newgeometry.combine(inFeat.geometry()) current += 1 progress.setPercentage(int(current * total)) geometry, area, perim, angle, width, height = self.OMBBox(newgeometry) if geometry: outFeat = QgsFeature() outFeat.setGeometry(geometry) outFeat.setAttributes([area, perim, angle, width, height]) writer.addFeature(outFeat)
def testTriangleTINPolyhedralSurface(self): """ Test support for Triangles (mapped to Polygons) """ testsets = ( ("Triangle((0 0, 0 1, 1 1, 0 0))", QgsWkbTypes.Triangle, "Triangle ((0 0, 0 1, 1 1, 0 0))"), ("Triangle Z((0 0 1, 0 1 2, 1 1 3, 0 0 1))", QgsWkbTypes.TriangleZ, "TriangleZ ((0 0 1, 0 1 2, 1 1 3, 0 0 1))"), ("Triangle M((0 0 4, 0 1 5, 1 1 6, 0 0 4))", QgsWkbTypes.TriangleM, "TriangleM ((0 0 4, 0 1 5, 1 1 6, 0 0 4))"), ("Triangle ZM((0 0 0 1, 0 1 2 3, 1 1 4 5, 0 0 0 1))", QgsWkbTypes.TriangleZM, "TriangleZM ((0 0 0 1, 0 1 2 3, 1 1 4 5, 0 0 0 1))"), ("TIN (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))", QgsWkbTypes.MultiPolygon, "MultiPolygon (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))"), ("TIN Z(((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))", QgsWkbTypes.MultiPolygonZ, "MultiPolygonZ (((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))"), ("TIN M(((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))", QgsWkbTypes.MultiPolygonM, "MultiPolygonM (((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))"), ("TIN ZM(((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))", QgsWkbTypes.MultiPolygonZM, "MultiPolygonZM (((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))"), ("PolyhedralSurface (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))", QgsWkbTypes.MultiPolygon, "MultiPolygon (((0 0, 0 1, 1 1, 0 0)),((0 0, 1 0, 1 1, 0 0)))"), ("PolyhedralSurface Z(((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))", QgsWkbTypes.MultiPolygonZ, "MultiPolygonZ (((0 0 0, 0 1 1, 1 1 1, 0 0 0)),((0 0 0, 1 0 0, 1 1 1, 0 0 0)))"), ("PolyhedralSurface M(((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))", QgsWkbTypes.MultiPolygonM, "MultiPolygonM (((0 0 0, 0 1 2, 1 1 3, 0 0 0)),((0 0 0, 1 0 4, 1 1 3, 0 0 0)))"), ("PolyhedralSurface ZM(((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))", QgsWkbTypes.MultiPolygonZM, "MultiPolygonZM (((0 0 0 0, 0 1 1 2, 1 1 1 3, 0 0 0 0)),((0 0 0 0, 1 0 0 4, 1 1 1 3, 0 0 0 0)))") ) for row in testsets: datasource = os.path.join(self.basetestpath, 'test.csv') with open(datasource, 'wt') as f: f.write('id,WKT\n') f.write('1,"%s"' % row[0]) vl = QgsVectorLayer(datasource, 'test', 'ogr') self.assertTrue(vl.isValid()) self.assertEqual(vl.wkbType(), row[1]) f = QgsFeature() self.assertTrue(vl.getFeatures(QgsFeatureRequest(1)).nextFeature(f)) self.assertTrue(f.geometry()) self.assertEqual(f.geometry().constGet().asWkt(), row[2])
def gotFeatureForIdentification(self, pos): """Show a dialog with road information """ #pos is a rectangle self.mem_layer_obj.select() ftr = QgsFeature() ftr_ids = [] while self.mem_layer_obj.nextFeature(ftr): if ftr.geometry().intersects(pos): ftr_ids.append(ftr.id()) self.chosenFOIGeoms = [] self.info = QgsMessageViewer() if ftr_ids != []: f = QgsFeature() foi_type = self.foi_type.lower() if foi_type == 'areaofinterestdefiner': ftrData = "You have selected the following feature(s) for use as an Area of Interest:\n\n" if foi_type == 'lineofinterestdefiner': ftrData = "You have selected the following feature(s) for use as a Line of Interest:\n\n" if foi_type == 'pointofinterestdefiner': ftrData = "You have selected the following feature(s) for use as a Point of Interest:\n\n" for fid in ftr_ids: self.mem_layer_obj.dataProvider().featureAtId(fid, f, True) ftrData += f.attributeMap()[0].toString() ftrData += "\n_____________________________\n" self.chosenFOIGeoms.append(f.geometry()) id_fid = self.addGeomToMemoryLayer(f.geometry()) self.info.setMessageAsPlainText(ftrData) else: self.info.setMessageAsPlainText("no data to show") self.info.show() return
def select_feature(self, point): '''Method to select feature from map canvas based on point location.''' # Select Features function from # http://www.qgisworkshop.org/html/workshop/plugins_tutorial.html # setup the provider select to filter results based on a rectangle pntGeom = QgsGeometry.fromPoint(point) # scale-dependent buffer of 3 pixels-worth of map units pntBuff = pntGeom.buffer( (self.canvas.mapUnitsPerPixel() * 3), 0) rect = pntBuff.boundingBox() layers = qgis.utils.iface.mapCanvas().layers() nodes = str(self.ui.comboBoxInputNodes.currentText()) for layer in layers: if layer.name() == nodes: provider = layer.dataProvider() if layer.geometryType() == QGis.Point: feat = QgsFeature() # create the select statement provider.select([], rect) # the arguments mean no attributes returned and do a bbox # filter with our buffered rectangle to limit the amount #of features. while provider.nextFeature(feat): # if the feat geom returned from the selection #intersects our point then put it in selection list. if feat.geometry().intersects(rect): self.selected_nodes[self.nodetype] = feat.id() self.output.clear() self.output.insert( str(feat.geometry().asPoint().x())+',' +str(feat.geometry().asPoint().y())) layer.removeSelection() for featid in self.selected_nodes.itervalues(): if featid is not None: layer.select(featid) break # stop here to select one point only.
def load_from_layer(self, layer): # return False on failure pr = layer.dataProvider() fields = pr.fields() if fields.size() < 1: return False field = None for i, f in enumerate(fields): if f.name() == "params": field = i if field is None: return False it = pr.getFeatures() fet = QgsFeature() it.nextFeature(fet) st = fet.attribute(field) self.unserialize(base64.b64decode(st)) if self.geometry is None: self.geometry = QgsGeometry(fet.geometry()) self.orig_geometry = [QgsGeometry(fet.geometry())] return True
def regularMatrix(self, writer, provider1, provider2, index1, index2, nearest, distArea, sindex, progressBar): inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() first = True start = 15.00 add = 85.00 / provider1.featureCount() fit1 = provider1.getFeatures() while fit1.nextFeature(inFeat): inGeom = inFeat.geometry() inID = inFeat.attributes()[index1] if first: featList = sindex.nearestNeighbor(inGeom.asPoint(), nearest) first = False data = ["ID"] for i in featList: provider2.getFeatures(QgsFeatureRequest().setFilterFid(int(i)).setSubsetOfAttributes([index2])).nextFeature(outFeat) data.append(unicode(outFeat.attributes()[index2])) writer.writerow(data) data = [unicode(inID)] for j in featList: provider2.getFeatures(QgsFeatureRequest().setFilterFid(int(j))).nextFeature(outFeat) outGeom = outFeat.geometry() dist = distArea.measureLine(inGeom.asPoint(), outGeom.asPoint()) data.append(unicode(float(dist))) writer.writerow(data) start = start + add progressBar.setValue(start) del writer
def processAlgorithm(self, progress): polyLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.POLYGONS)) pointLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.POINTS)) fieldName = self.getParameterValue(self.FIELD) polyProvider = polyLayer.dataProvider() fields = polyProvider.fields() fields.append(QgsField(fieldName, QVariant.Int)) (idxCount, fieldList) = vector.findOrCreateField(polyLayer, polyLayer.pendingFields(), fieldName) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields.toList(), polyProvider.geometryType(), polyProvider.crs()) spatialIndex = vector.spatialindex(pointLayer) ftPoly = QgsFeature() ftPoint = QgsFeature() outFeat = QgsFeature() geom = QgsGeometry() current = 0 hasIntersections = False features = vector.features(polyLayer) total = 100.0 / float(len(features)) for ftPoly in features: geom = ftPoly.geometry() attrs = ftPoly.attributes() count = 0 hasIntersections = False points = spatialIndex.intersects(geom.boundingBox()) if len(points) > 0: hasIntersections = True if hasIntersections: for i in points: request = QgsFeatureRequest().setFilterFid(i) ftPoint = pointLayer.getFeatures(request).next() tmpGeom = QgsGeometry(ftPoint.geometry()) if geom.contains(tmpGeom): count += 1 outFeat.setGeometry(geom) if idxCount == len(attrs): attrs.append(count) else: attrs[idxCount] = count outFeat.setAttributes(attrs) writer.addFeature(outFeat) current += 1 progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, progress): vlayerA = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT)) vlayerB = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT2)) vproviderA = vlayerA.dataProvider() fields = vector.combineVectorFields(vlayerA, vlayerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, vproviderA.geometryType(), vproviderA.crs() ) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() index = vector.spatialindex(vlayerB) nElement = 0 selectionA = vector.features(vlayerA) nFeat = len(selectionA) for inFeatA in selectionA: nElement += 1 progress.setPercentage(nElement / float(nFeat) * 100) geom = QgsGeometry(inFeatA.geometry()) atMapA = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) for i in intersects: request = QgsFeatureRequest().setFilterFid(i) inFeatB = vlayerB.getFeatures(request).next() tmpGeom = QgsGeometry(inFeatB.geometry()) try: if geom.intersects(tmpGeom): atMapB = inFeatB.attributes() int_geom = QgsGeometry(geom.intersection(tmpGeom)) if ( int_geom.wkbType() == QGis.WKBUnknown or QgsWKBTypes.flatType(int_geom.geometry().wkbType()) == QgsWKBTypes.GeometryCollection ): int_com = geom.combine(tmpGeom) int_sym = geom.symDifference(tmpGeom) int_geom = QgsGeometry(int_com.difference(int_sym)) try: if int_geom.wkbType() in wkbTypeGroups[wkbTypeGroups[int_geom.wkbType()]]: outFeat.setGeometry(int_geom) attrs = [] attrs.extend(atMapA) attrs.extend(atMapB) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_INFO, self.tr( "Feature geometry error: One or more output features ignored due to invalid geometry." ), ) continue except: break del writer
def buffering(progress, writer, distance, field, useField, layer, dissolve, segments): if useField: field = layer.fieldNameIndex(field) outFeat = QgsFeature() inFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() current = 0 features = vector.features(layer) total = 100.0 / float(len(features)) # With dissolve if dissolve: first = True for inFeat in features: attrs = inFeat.attributes() if useField: value = attrs[field] else: value = distance inGeom = QgsGeometry(inFeat.geometry()) outGeom = inGeom.buffer(float(value), segments) if first: tempGeom = QgsGeometry(outGeom) first = False else: tempGeom = tempGeom.combine(outGeom) current += 1 progress.setPercentage(int(current * total)) outFeat.setGeometry(tempGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) else: # Without dissolve for inFeat in features: attrs = inFeat.attributes() if useField: value = attrs[field] else: value = distance inGeom = QgsGeometry(inFeat.geometry()) outGeom = inGeom.buffer(float(value), segments) outFeat.setGeometry(outGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) current += 1 progress.setPercentage(int(current * total)) del writer
def test_fix_geometries(self): polygon_layer = self._make_layer('Polygon') self.assertTrue(polygon_layer.startEditing()) f = QgsFeature(polygon_layer.fields()) f.setAttributes([1]) # Flake! f.setGeometry(QgsGeometry.fromWkt('POLYGON ((0 0, 2 2, 0 2, 2 0, 0 0))')) self.assertTrue(f.isValid()) f2 = QgsFeature(polygon_layer.fields()) f2.setAttributes([1]) f2.setGeometry(QgsGeometry.fromWkt('POLYGON((1.1 1.1, 1.1 2.1, 2.1 2.1, 2.1 1.1, 1.1 1.1))')) self.assertTrue(f2.isValid()) self.assertTrue(polygon_layer.addFeatures([f, f2])) polygon_layer.commitChanges() polygon_layer.rollBack() self.assertEqual(polygon_layer.featureCount(), 2) QgsProject.instance().addMapLayers([polygon_layer]) old_features, new_features = self._alg_tester( 'native:fixgeometries', polygon_layer, { } ) self.assertEqual(polygon_layer.featureCount(), 3) wkt1, wkt2, _ = [f.geometry().asWkt() for f in new_features] self.assertEqual(wkt1, 'Polygon ((0 0, 1 1, 2 0, 0 0))') self.assertEqual(wkt2, 'Polygon ((1 1, 0 2, 2 2, 1 1))') # Test with Z (interpolated) polygonz_layer = self._make_layer('PolygonZ') self.assertTrue(polygonz_layer.startEditing()) f3 = QgsFeature(polygonz_layer.fields()) f3.setAttributes([1]) f3.setGeometry(QgsGeometry.fromWkt('POLYGON Z((0 0 1, 2 2 1, 0 2 3, 2 0 4, 0 0 1))')) self.assertTrue(f3.isValid()) self.assertTrue(polygonz_layer.addFeatures([f3])) polygonz_layer.commitChanges() polygonz_layer.rollBack() self.assertEqual(polygonz_layer.featureCount(), 1) QgsProject.instance().addMapLayers([polygonz_layer]) old_features, new_features = self._alg_tester( 'native:fixgeometries', polygonz_layer, { } ) self.assertEqual(polygonz_layer.featureCount(), 2) wkt1, wkt2 = [f.geometry().asWkt() for f in new_features] self.assertEqual(wkt1, 'PolygonZ ((0 0 1, 1 1 2.25, 2 0 4, 0 0 1))') self.assertEqual(wkt2, 'PolygonZ ((1 1 2.25, 0 2 3, 2 2 1, 1 1 2.25))')
def checkAfter(): # check select+nextFeature f = QgsFeature() layer.select([]) assert layer.nextFeature(f) assert f.geometry().asPoint() == QgsPoint(300,400) # check feature at id f2 = QgsFeature() assert layer.featureAtId(f.id(), f2) assert f2.geometry().asPoint() == QgsPoint(300,400)
@pyqtSlot(QPoint, QObject) def showInfo(self, point, mouseButton): """ event handler for toolInfo @see QGIS tutorial for detail point-polygon search on currently selected layer """ cur_layer_name = self.ui.cb_layer_selector.currentText() if cur_layer_name.isEmpty(): return try: cur_layer_idx = self.LAYER_NAMES.index(cur_layer_name) cur_layer = self.map_layers[cur_layer_idx] # if layer is not in same projection as map canvas # need to project query point if cur_layer.crs() != self.canvas.mapRenderer().destinationCrs(): transform = QgsCoordinateTransform(self.canvas.mapRenderer().destinationCrs(), cur_layer.crs()) point = transform.transform(point) # do query provider = cur_layer.dataProvider() provider.rewind() feature = QgsFeature() colonIndexes = provider.attributeIndexes() # search using point as center of rectangle polygon search_buffer_x = self.canvas.extent().width() * self.SEARCH_BUFFER / self.canvas.width() search_buffer_y = self.canvas.extent().height() * self.SEARCH_BUFFER / self.canvas.height() provider.select(colonIndexes, QgsRectangle(point.x()-search_buffer_x, point.y()-search_buffer_y, point.x()+search_buffer_x, point.y()+search_buffer_y), True) # get selected and display in result detail dialog box selected = [] while provider.nextFeature(feature): # for polygons, only show geometry containing query point if cur_layer.geometryType() == QGis.Polygon: if feature.geometry() is not None and not feature.geometry().contains (point): continue selected.append(feature.attributeMap()) if len(selected)>0: # display result if exists if cur_layer_idx == self.EXPOSURE: self.dlgResultDetail.showExposureData(provider.fields(), selected) else: self.dlgResultDetail.showInfoData(provider.fields(), selected) self.dlgResultDetail.exec_() else: logUICall.log(get_ui_string("widget.result.info.notfound"), logUICall.WARNING) except Exception as err: # point-in-polygon search is not critical, continue on error
def test_SetGeometry(self): feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(123, 456))) myGeometry = feat.geometry() myExpectedGeometry = "!None" myMessage = '\nExpected: %s\nGot: %s' % (myExpectedGeometry, myGeometry) assert myGeometry is not None, myMessage # set from QgsAbstractGeometry feat.setGeometry(QgsPoint(12, 34)) self.assertEqual(feat.geometry().asWkt(), 'Point (12 34)')
def checkAfter(): assert len(layer.pendingFields()) == 2 # check feature f = QgsFeature() layer.select(layer.pendingAllAttributesList()) assert layer.nextFeature(f) assert f.geometry().asPoint() == QgsPoint(2,2) # check feature at id f2 = QgsFeature() assert layer.featureAtId(f.id(), f2) assert f2.geometry().asPoint() == QgsPoint(2,2)
def processAlgorithm(self, progress): polyLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.POLYGONS)) pointLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.POINTS)) fieldName = self.getParameterValue(self.FIELD) polyProvider = polyLayer.dataProvider() fields = polyProvider.fields() fields.append(QgsField(fieldName, QVariant.Int)) (idxCount, fieldList) = vector.findOrCreateField(polyLayer, polyLayer.pendingFields(), fieldName) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields.toList(), polyProvider.geometryType(), polyProvider.crs()) spatialIndex = vector.spatialindex(pointLayer) ftPoly = QgsFeature() ftPoint = QgsFeature() outFeat = QgsFeature() geom = QgsGeometry() features = vector.features(polyLayer) total = 100.0 / len(features) for current, ftPoly in enumerate(features): geom = ftPoly.geometry() engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() attrs = ftPoly.attributes() count = 0 points = spatialIndex.intersects(geom.boundingBox()) if len(points) > 0: request = QgsFeatureRequest().setFilterFids(points) fit = pointLayer.getFeatures(request) ftPoint = QgsFeature() while fit.nextFeature(ftPoint): tmpGeom = ftPoint.geometry() if engine.contains(tmpGeom.geometry()): count += 1 outFeat.setGeometry(geom) if idxCount == len(attrs): attrs.append(count) else: attrs[idxCount] = count outFeat.setAttributes(attrs) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer
def processAlgorithm(self, parameters, context, feedback): polyLayer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.POLYGONS), context) pointLayer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.POINTS), context) fieldName = self.getParameterValue(self.FIELD) fields = polyLayer.fields() fields.append(QgsField(fieldName, QVariant.Int)) (idxCount, fieldList) = vector.findOrCreateField(polyLayer, polyLayer.fields(), fieldName) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, polyLayer.wkbType(), polyLayer.crs(), context) spatialIndex = QgsProcessingUtils.createSpatialIndex(pointLayer, context) ftPoly = QgsFeature() ftPoint = QgsFeature() outFeat = QgsFeature() geom = QgsGeometry() features = QgsProcessingUtils.getFeatures(polyLayer, context) total = 100.0 / polyLayer.featureCount() if polyLayer.featureCount() else 0 for current, ftPoly in enumerate(features): geom = ftPoly.geometry() engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() attrs = ftPoly.attributes() count = 0 points = spatialIndex.intersects(geom.boundingBox()) if len(points) > 0: request = QgsFeatureRequest().setFilterFids(points).setSubsetOfAttributes([]) fit = pointLayer.getFeatures(request) ftPoint = QgsFeature() while fit.nextFeature(ftPoint): tmpGeom = ftPoint.geometry() if engine.contains(tmpGeom.geometry()): count += 1 outFeat.setGeometry(geom) if idxCount == len(attrs): attrs.append(count) else: attrs[idxCount] = count outFeat.setAttributes(attrs) writer.addFeature(outFeat, QgsFeatureSink.FastInsert) feedback.setProgress(int(current * total)) del writer
def compute(self, inPoly, inLns, inField, outPath, progressBar): polyLayer = ftools_utils.getVectorLayerByName(inPoly) lineLayer = ftools_utils.getVectorLayerByName(inLns) polyProvider = polyLayer.dataProvider() lineProvider = lineLayer.dataProvider() if polyProvider.crs() != lineProvider.crs(): QMessageBox.warning(self, self.tr("CRS warning!"), self.tr("Warning: Input layers have non-matching CRS.\nThis may cause unexpected results.")) fieldList = ftools_utils.getFieldList(polyLayer) index = polyProvider.fieldNameIndex(unicode(inField)) if index == -1: index = polyProvider.fields().count() fieldList.append(QgsField(unicode(inField), QVariant.Double, "real", 24, 15, self.tr("length field"))) sRs = polyProvider.crs() inFeat = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() distArea = QgsDistanceArea() start = 0.00 add = 100.00 / polyProvider.featureCount() check = QFile(self.shapefileName) if check.exists(): if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName): return writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fieldList, polyProvider.geometryType(), sRs) spatialIndex = ftools_utils.createIndex(lineProvider) polyFit = polyProvider.getFeatures() while polyFit.nextFeature(inFeat): inGeom = QgsGeometry(inFeat.geometry()) atMap = inFeat.attributes() lineList = [] length = 0 lineList = spatialIndex.intersects(inGeom.boundingBox()) if len(lineList) > 0: check = 0 else: check = 1 if check == 0: for i in lineList: lineProvider.getFeatures(QgsFeatureRequest().setFilterFid(int(i))).nextFeature(inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) if inGeom.intersects(tmpGeom): outGeom = inGeom.intersection(tmpGeom) length = length + distArea.measure(outGeom) outFeat.setGeometry(inGeom) atMap.append(length) outFeat.setAttributes(atMap) writer.addFeature(outFeat) start = start + 1 progressBar.setValue(start * (add)) del writer
def checkAfter(): assert layer.pendingFeatureCount() == 1 # check select+nextFeature layer.select([]) f = QgsFeature() assert layer.nextFeature(f) assert f.geometry().asPoint() == QgsPoint(1,2) # check feature at id f2 = QgsFeature() assert layer.featureAtId(f.id(), f2) assert f2.geometry().asPoint() == QgsPoint(1,2)
def createSinglePolygon(self, vlayer): provider = vlayer.dataProvider() feat = QgsFeature() geom = QgsGeometry() fit = provider.getFeatures() fit.nextFeature(feat) geom = QgsGeometry(feat.geometry()) count = 10.00 add = ( 40.00 - 10.00 ) / provider.featureCount() while fit.nextFeature(feat): geom = geom.combine(QgsGeometry( feat.geometry() )) count = count + add self.progressBar.setValue(count) return geom
def test_SetGeometry(self): feat = QgsFeature() feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(123, 456))) myGeometry = feat.geometry() myExpectedGeometry = "!None" myMessage = "\nExpected: %s\nGot: %s" % (myExpectedGeometry, myGeometry) assert myGeometry is not None, myMessage
def extract_nodes( self ): vprovider = self.vlayer.dataProvider() writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(), QGis.WKBPoint, vprovider.crs() ) inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() nFeat = vprovider.featureCount() nElement = 0 self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0 ) self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) ) fit = vprovider.getFeatures() while fit.nextFeature( inFeat ): nElement += 1 self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement ) inGeom = inFeat.geometry() atMap = inFeat.attributes() pointList = ftools_utils.extractPoints( inGeom ) outFeat.setAttributes( atMap ) for i in pointList: outFeat.setGeometry( outGeom.fromPoint( i ) ) writer.addFeature( outFeat ) del writer return True
def polygons_to_lines( self ): vprovider = self.vlayer.dataProvider() writer = QgsVectorFileWriter( self.myName, self.myEncoding, vprovider.fields(), QGis.WKBLineString, vprovider.crs() ) inFeat = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() nFeat = vprovider.featureCount() nElement = 0 self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), 0) self.emit( SIGNAL( "runRange( PyQt_PyObject )" ), ( 0, nFeat ) ) fit = vprovider.getFeatures() while fit.nextFeature( inFeat ): nElement += 1 self.emit( SIGNAL( "runStatus( PyQt_PyObject )" ), nElement ) inGeom = inFeat.geometry() atMap = inFeat.attributes() lineList = self.extractAsLine( inGeom ) outFeat.setAttributes( atMap ) for h in lineList: outFeat.setGeometry( outGeom.fromPolyline( h ) ) writer.addFeature( outFeat ) del writer return True
def loopThruPolygons(self, inLayer, numRand, design): sProvider = inLayer.dataProvider() sFeat = QgsFeature() sGeom = QgsGeometry() sPoints = [] if design == self.tr("field"): index = sProvider.fieldNameIndex(numRand) count = 10.00 add = 60.00 / sProvider.featureCount() sFit = sProvider.getFeatures() featureErrors = [] while sFit.nextFeature(sFeat): sGeom = sFeat.geometry() if design == self.tr("density"): sDistArea = QgsDistanceArea() value = int(round(numRand * sDistArea.measure(sGeom))) elif design == self.tr("field"): sAtMap = sFeat.attributes() try: value = int(sAtMap[index]) except (ValueError,TypeError): featureErrors.append(sFeat) continue else: value = numRand sExt = sGeom.boundingBox() sPoints.extend(self.simpleRandom(value, sGeom, sExt.xMinimum(), sExt.xMaximum(), sExt.yMinimum(), sExt.yMaximum())) count = count + add self.progressBar.setValue(count) return sPoints, featureErrors
def createReprojectedLayer(layer, crs): """ Creates a reprojected layer layer: layer used crs: crs used """ temp = QgsVectorLayer('%s?crs=%s'% ('Multipolygon', crs.authid()), 'temp', 'memory') if not layer.isValid(): raise GeoAlgorithmExecutionException('Problema ao criar camada reprojetada!') return None provider = temp.dataProvider() provider.addAttributes(layer.dataProvider().fields().toList()) temp.updateFields() coordinateTransformer = QgsCoordinateTransform(layer.crs(), crs) features = [] for feature in layer.getFeatures(): feat = QgsFeature(feature) geom = feat.geometry() geom.transform(coordinateTransformer) feat.setGeometry(geom) features.append(feat) provider.addFeatures(features) return temp
def testCreateLayer(self): layer = QgsVectorLayer("Point?field=id:integer&field=fldtxt:string&field=fldint:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1, "test", 1]) f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2))) f2 = QgsFeature() f2.setAttributes([2, "test2", 3]) f3 = QgsFeature() f3.setAttributes([3, "test2", NULL]) f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2))) f4 = QgsFeature() f4.setAttributes([4, NULL, 3]) f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3))) pr.addFeatures([f, f2, f3, f4]) uri = '{} table="qgis_test"."new_table" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.Point) self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint']) features = [f.attributes() for f in new_layer.getFeatures()] self.assertEqual(features, [[1, 1, 'test', 1], [2, 2, 'test2', 3], [3, 3, 'test2', NULL], [4, 4, NULL, 3]]) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['Point (1 2)', '', 'Point (3 2)', 'Point (4 3)'])
def processAlgorithm(self, context, feedback): polyLayer = dataobjects.getLayerFromString( self.getParameterValue(self.POLYGONS)) pointLayer = dataobjects.getLayerFromString( self.getParameterValue(self.POINTS)) fieldName = self.getParameterValue(self.FIELD) fieldIdx = pointLayer.fields().lookupField( self.getParameterValue(self.WEIGHT)) fields = polyLayer.fields() fields.append(QgsField(fieldName, QVariant.Int)) (idxCount, fieldList) = vector.findOrCreateField(polyLayer, polyLayer.fields(), fieldName) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields.toList(), polyLayer.wkbType(), polyLayer.crs(), context) spatialIndex = vector.spatialindex(pointLayer) ftPoint = QgsFeature() outFeat = QgsFeature() geom = QgsGeometry() features = QgsProcessingUtils.getFeatures(polyLayer, context) total = 100.0 / QgsProcessingUtils.featureCount(polyLayer, context) for current, ftPoly in enumerate(features): geom = ftPoly.geometry() engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() attrs = ftPoly.attributes() count = 0 points = spatialIndex.intersects(geom.boundingBox()) if len(points) > 0: feedback.setProgressText(str(len(points))) request = QgsFeatureRequest().setFilterFids( points).setSubsetOfAttributes([fieldIdx]) fit = pointLayer.getFeatures(request) ftPoint = QgsFeature() while fit.nextFeature(ftPoint): tmpGeom = QgsGeometry(ftPoint.geometry()) if engine.contains(tmpGeom.geometry()): weight = str(ftPoint.attributes()[fieldIdx]) try: count += float(weight) except: # Ignore fields with non-numeric values pass outFeat.setGeometry(geom) if idxCount == len(attrs): attrs.append(count) else: attrs[idxCount] = count outFeat.setAttributes(attrs) writer.addFeature(outFeat) feedback.setProgress(int(current * total)) del writer
def testClipping(self): """Test that we can clip geometries using other geometries.""" myMemoryLayer = QgsVectorLayer( ('LineString?crs=epsg:4326&field=name:string(20)&index=yes'), 'clip-in', 'memory') assert myMemoryLayer is not None, 'Provider not initialised' myProvider = myMemoryLayer.dataProvider() assert myProvider is not None myFeature1 = QgsFeature() myFeature1.setGeometry( QgsGeometry.fromPolyline([ QgsPoint(10, 10), QgsPoint(20, 10), QgsPoint(30, 10), QgsPoint(40, 10), ])) myFeature1.setAttributes(['Johny']) myFeature2 = QgsFeature() myFeature2.setGeometry( QgsGeometry.fromPolyline([ QgsPoint(10, 10), QgsPoint(20, 20), QgsPoint(30, 30), QgsPoint(40, 40), ])) myFeature2.setAttributes(['Be']) myFeature3 = QgsFeature() myFeature3.setGeometry( QgsGeometry.fromPolyline([ QgsPoint(10, 10), QgsPoint(10, 20), QgsPoint(10, 30), QgsPoint(10, 40), ])) myFeature3.setAttributes(['Good']) myResult, myFeatures = myProvider.addFeatures( [myFeature1, myFeature2, myFeature3]) assert myResult == True assert len(myFeatures) == 3 myClipPolygon = QgsGeometry.fromPolygon([[ QgsPoint(20, 20), QgsPoint(20, 30), QgsPoint(30, 30), QgsPoint(30, 20), QgsPoint(20, 20), ]]) print 'Clip: %s' % myClipPolygon.exportToWkt() writeShape(myMemoryLayer, 'clipGeometryBefore.shp') fit = myProvider.getFeatures() myFeatures = [] myFeature = QgsFeature() while fit.nextFeature(myFeature): myGeometry = myFeature.geometry() if myGeometry.intersects(myClipPolygon): # Adds nodes where the clip and the line intersec myCombinedGeometry = myGeometry.combine(myClipPolygon) # Gives you the areas inside the clip mySymmetricalGeometry = myGeometry.symDifference( myCombinedGeometry) # Gives you areas outside the clip area # myDifferenceGeometry = myCombinedGeometry.difference( # myClipPolygon) #print 'Original: %s' % myGeometry.exportToWkt() #print 'Combined: %s' % myCombinedGeometry.exportToWkt() #print 'Difference: %s' % myDifferenceGeometry.exportToWkt() print 'Symmetrical: %s' % mySymmetricalGeometry.exportToWkt() myExpectedWkt = 'LINESTRING(20 20, 30 30)' # There should only be one feature that intersects this clip # poly so this assertion should work. assert compareWkt(myExpectedWkt, mySymmetricalGeometry.exportToWkt()) myNewFeature = QgsFeature() myNewFeature.setAttributes(myFeature.attributes()) myNewFeature.setGeometry(mySymmetricalGeometry) myFeatures.append(myNewFeature) myNewMemoryLayer = QgsVectorLayer( ('LineString?crs=epsg:4326&field=name:string(20)&index=yes'), 'clip-out', 'memory') myNewProvider = myNewMemoryLayer.dataProvider() myResult, myFeatures = myNewProvider.addFeatures(myFeatures) self.assertTrue(myResult) self.assertEqual(len(myFeatures), 1) writeShape(myNewMemoryLayer, 'clipGeometryAfter.shp')
def run(self): """Run method that performs all the real work""" # Create the dialog with elements (after translation) and keep reference # Only create GUI ONCE in callback, so that it will only load when the plugin is started if self.first_start == True: self.first_start = False self.dlg = IncendieMontrealDialog() # On appelle la fonction select_input_file si le bouton toolButton_spat est cliqué self.dlg.toolButton_spat.clicked.connect(self.select_input_file) # On appelle la fonction select_output_file si le bouton toolButton_sortie est cliqué self.dlg.toolButton_sortie.clicked.connect(self.select_output_file) # On appelle la fonction select_recens_text si le bouton toolButton_text est cliqué self.dlg.toolButton_text.clicked.connect(self.select_recens_text) # Aller chercher toutes les couches présentement dans le projet layers = QgsProject.instance().layerTreeRoot().children() # Clear the contents of the comboBox from previous runs self.dlg.comboBox_recens_spat.clear() # Populate the comboBox with names of all the loaded layers self.dlg.comboBox_recens_spat.addItems( [layer.name() for layer in layers]) # j'ai enlever la boite pour le point d'intéret (remplacé par deux text box) # self.dlg.comboBox_point.clear() # self.dlg.comboBox_point.addItems([layer.name() for layer in layers]) self.dlg.comboBox_adresse.clear() self.dlg.comboBox_adresse.addItems([layer.name() for layer in layers]) self.dlg.comboBox_route.clear() self.dlg.comboBox_route.addItems([layer.name() for layer in layers]) self.dlg.Line_recens_text.clear() # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # Récupération des informations générales du projet projCrs = QgsProject.instance().crs() projEpsg = str(projCrs).split(':')[2][:-1] # Récupération des données en entrées taille_buffer = self.dlg.lineEdit_buffer.text() output_name = self.dlg.Line_sortie.text() recens_text = self.dlg.Line_recens_text.text() point_lat = self.dlg.lineEdit_buffer_2.text() point_lon = self.dlg.lineEdit_buffer_3.text() recens_spat_name = self.dlg.comboBox_recens_spat.currentText() adresse_name = self.dlg.comboBox_adresse.currentText() route_name = self.dlg.comboBox_route.currentText() # Création de la couche du point incident couche_point = QgsVectorLayer('Point?crs=epsg:4326', 'couche_point', 'memory') pointProv = couche_point.dataProvider() feat = QgsFeature() feat.setGeometry( QgsGeometry.fromWkt('Point({} {})'.format(float(point_lon), float(point_lat)))) pointProv.addFeature(feat) couche_point.updateExtents() # Couches en assumant qu'elles sont ouvertes dans le projet liste_couche_recens = QgsProject.instance().mapLayersByName( recens_spat_name) couche_recens = liste_couche_recens[0] liste_couche_adresse = QgsProject.instance().mapLayersByName( adresse_name) couche_adresse = liste_couche_adresse[0] liste_couche_route = QgsProject.instance().mapLayersByName(route_name) couche_route = liste_couche_route[0] # Reprojection des couches selon le CRS du projet def reprojectToInstanceCrs(couche_vec, type, outCrs, outName): # Définition du CRS de la couche inCrs = couche_vec.crs() # Extraction du code EPSG du CRS du projet outEpsg = str(outCrs).split(':')[2][:-1] # Création d'un objet QgsCoordinateTransform trans = QgsCoordinateTransform(inCrs, outCrs, QgsProject.instance()) # Création de la couche de sortie et de son provider outputLayer = QgsVectorLayer( '{}?crs=epsg:{}'.format(type, outEpsg), outName, 'memory') pr = outputLayer.dataProvider() # Déclaration des variables contenant les entités et les attributs de la couche en entrée couche_features = couche_vec.getFeatures() couche_fields = couche_vec.fields() # On copie les attributs de la couche en entrée dans la couche de sortie pr.addAttributes(couche_fields) outputLayer.updateFields() # parcours les entité de la couche en entrée for feature in couche_features: geom = feature.geometry() # reprojection du geom de l'entité geom.transform(trans) # On ajuste le geom de l'entité et on l'ajoute à la couche de sortie feature.setGeometry(geom) pr.addFeature(feature) # On met la couche de sortie à niveau outputLayer.updateExtents() # On affiche la couche dans le projet courant QGIS # QgsProject.instance().addMapLayer(outputLayer) # Retourne la couche de sortie return outputLayer # Pour chaque couche en entrée du plugin, on reprojette si le CRS n'est pas celui du projet courant if couche_recens.crs() != projCrs: couche_recens = reprojectToInstanceCrs(couche_recens, 'Polygon', projCrs, 'recens_reproj') if couche_route.crs() != projCrs: couche_route = reprojectToInstanceCrs(couche_route, 'MultiLineString', projCrs, 'route_reproj') if couche_adresse.crs() != projCrs: couche_adresse = reprojectToInstanceCrs(couche_adresse, 'Point', projCrs, 'adresse_reproj') if couche_point.crs() != projCrs: couche_point = reprojectToInstanceCrs(couche_point, 'Point', projCrs, 'point_reproj') QgsProject.instance().addMapLayer(couche_point) # Buffer sur le point en entrée layer = couche_point feats = layer.getFeatures() # création de la couche vectorielle buffer = QgsVectorLayer("Polygon?crs=epsg:{}".format(projEpsg), "Zone_incident", "memory") pr = buffer.dataProvider() # Création du buffer for feat in feats: geom = feat.geometry() buff = geom.buffer(int(taille_buffer), 5) feat.setGeometry(buff) pr.addFeature(feat) buffer.updateExtents() # Ajout de la couche à Qgis # QgsProject.instance().addMapLayer(buffer) # Fonction pour faire la liste des entités d'une couche qui intersect une couche de buffer def entite_intersect_buffer(couche_buffer, couche_vec, attribut_a_garder): couche = couche_vec # Déclarer les features de la couche de buffer et d'entité buff_feature = couche_buffer.getFeatures() couche_feature = couche.getFeatures() liste_intersect = [] for buff in buff_feature: geom_buff = buff.geometry() # On parcours les entités de la couche vec et on déclare leur géométrie for entite in couche_feature: geom_entite = entite.geometry() # Si l'entite intersect le buffer, ajoute les attributs voulus au dic, ajoute le dic à la liste if geom_entite.intersects(geom_buff): dic = {} for attribut in attribut_a_garder: if attribut == 'GEOMETRY': value = geom_entite else: value = entite[attribut] dic.update({attribut: value}) liste_intersect.append(dic) # retourne liste d'entités sous forme de dic avec les attributs voulus de l'entité return liste_intersect # Aller chercher les AD qui sont affectées ad_affectee = entite_intersect_buffer(buffer, couche_recens, ['ADIDU']) # print(ad_affectee) # Aller chercher la population totale affectée dans le CSV en entrée import csv path_csv = r'{}'.format(recens_text) dic_pop = {} # on ouvre le fichier CSV des AD e spécifiant l'encodage à ISO-8859-1 pour gérer les caractères spéciaux with open(path_csv, encoding='ISO-8859-1') as csv_file: # On crée le reader qui va permettre de parcourir les row comme des dictionnaires csv_reader = csv.DictReader(csv_file) # On parcours chaque row du fichier for row in csv_reader: for i in ad_affectee: for j in i.values(): # Si le ID du row égal un ID dans la liste des AD affectées, on ajoute la pop. du row # avec son ID au dictionnaire if row['ADidu'] == j: dic_pop.update({j: int(row['ADpop_2016'])}) # print(dic_pop) # On additionne toutes les populations du dictionnaire pour trouver la pop. totale pop_totale = sum(dic_pop.values()) # Aller chercher les rues qui sont affectées rue_affectee = entite_intersect_buffer( buffer, couche_route, ['CLASSE', 'TYP_VOIE', 'NOM_VOIE']) # Aller chercher les adresses affectées adr_affectee = entite_intersect_buffer( buffer, couche_adresse, ['ID_ADRESSE', 'TEXTE', 'SPECIFIQUE', 'GENERIQUE', 'GEOMETRY']) # Aller chercher l'adresse la plus proche dis = QgsDistanceArea() # On déclare les entités de la couche du point incident featInc = couche_point.getFeatures() # On parcours les entités de la couche du point incident for pointInc in featInc: # On déclare le geom de l'entité comme un point geomInc = pointInc.geometry().asPoint() # On parcours la liste des adresses affectées for adr in adr_affectee: # On déclare le geom de l'adresses affectées comme un points geomAdr = adr['GEOMETRY'].asPoint() # On calcule la distance entre le point incident et l'adresse affectée distance = dis.measureLine(geomInc, geomAdr) # On ajoute la distance comme attribut dans le dictionnaire de l'adresse adr['DIST'] = distance # On tri la liste des adresses affectées selon la distance sort_adr_aff_distance = sorted(adr_affectee, key=lambda i: i['DIST']) # On récupère l'adresse ayant la distance la plus courte adr_plus_proche = sort_adr_aff_distance[0] # Afficher les informations dans la console # Population totale print('La population totale affectée est de : {} personnes'.format( pop_totale)) # Rues affectées liste_rue_unique = [] for rue in rue_affectee: if rue not in liste_rue_unique: liste_rue_unique.append(rue) sort_rue_aff = sorted(liste_rue_unique, key=lambda i: (i['CLASSE'], i['NOM_VOIE'])) print('Les rues affectées sont:') for r in sort_rue_aff: print('nom: {}'.format(r['NOM_VOIE']), 'Type: {}'.format(r['TYP_VOIE'])) # Adresse la plus proche de l'incident print("L'adresse la plus proche de l'incident est: {} {} {}".format( adr_plus_proche['TEXTE'], adr_plus_proche['GENERIQUE'], adr_plus_proche['SPECIFIQUE'])) print('Distance: {:.2f} m'.format(adr_plus_proche['DIST'])) # Création du fichier de sortie path_output = r'C:\Users\home\Documents\Documents\Géoinformatique 2\GMQ580_TD2\output.txt' f = open(path_output, 'w') f.write('****************************************************\n') f.write("RÉSULTATS DE L'ANALYSE DE L'OUTIL'INCENDIEMONTREAL'\n") f.write('****************************************************\n') f.write('\n') # Paramètres en entrée f.write('Latitude: {}°\n'.format(point_lat)) f.write('Longitude: {}°\n'.format(point_lon)) f.write("Taille de la zone d'analyse: {} m\n".format( int(taille_buffer))) f.write('\n') # Population totale f.write('La population totale affectée est de : {} personnes\n'.format( pop_totale)) f.write('\n') # Adresse la plus proche de l'incident f.write( "L'adresse la plus proche de l'incident est: {} {} {}\n".format( adr_plus_proche['TEXTE'], adr_plus_proche['GENERIQUE'], adr_plus_proche['SPECIFIQUE'])) f.write('Distance: {:.2f} m\n'.format(adr_plus_proche['DIST'])) f.write('\n') # Rues affectées et adresses count = 0 f.write('Les adresses affectées ainsi que leur rue respective sont:\n') f.write('\n') for r in sort_rue_aff: f.write('NOM: {} TYPE: {}\n'.format(r['NOM_VOIE'], r['TYP_VOIE'])) for a in adr_affectee: if str(a['SPECIFIQUE']).lower() == str( r['NOM_VOIE']).lower() and str( a['GENERIQUE']).lower() == str( r['TYP_VOIE']).lower(): f.write('{} {} {}\n'.format(a['TEXTE'], a['GENERIQUE'], a['SPECIFIQUE'])) count += 1 f.write('\n') # Fin du document f.write('\n') f.write('***************************************************\n') f.write('FIN DES RÉSULTATS\n') f.write('***************************************************\n') f.close() # count = 0 # print('Les rues affectées sont:') # for r in sort_rue_aff: # print('nom: {}'.format(r['NOM_VOIE']), 'Type: {}'.format(r['TYP_VOIE'])) # for a in adr_affectee: # if a['SPECIFIQUE'] == r['NOM_VOIE'] and a['GENERIQUE'] == r['TYP_VOIE']: # print(a['TEXTE'], a['GENERIQUE'], a['SPECIFIQUE']) # count += 1 # print('nombre total adresses: {}'.format(len(adr_affectee))) # print('nombre adresses printées: {}'.format(count)) # 1. Faire le buffer sur la couche point # 2. Comptabiliser la population totale # 2.1 Faire une requête dans le CSV des AD avec les ID des AD à l'intérieur du buffer # 2.2 Extraire la population, faire le total # 3. Faire la liste des rues affectées # 3.1 Faire une requête dans la couche des rues, ceux qui sont contenues dans le buffer # 3.2 Ajouter les noms de rue à une liste # 4. Faire un dictionnaire des adresses affectées # 4.1 Faire une requête dans la couche des adresses, ceux qui sont contenues dans le buffer # 4.2 Ajouter les adresses comme key au dict. # 4.3 Extraire le nom de la rue et l'ajouter comme valeur au dictionnaire # 5. Formatage du fichier txt en sortie # - on affiche la population totale affectée en haut du fichier # - on affiche une rue # - on affiche toutes les adresses affectées dans la rue # 6. Sauvegarde du fichier dans le répertoire spécifié # Do something useful here - delete the line containing pass and # substitute with your code. pass
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri( self.getParameterValue(ConcaveHull.INPUT)) alpha = self.getParameterValue(self.ALPHA) holes = self.getParameterValue(self.HOLES) no_multigeom = self.getParameterValue(self.NO_MULTIGEOMETRY) # Delaunay triangulation from input point layer progress.setText(self.tr('Creating Delaunay triangles...')) delone_triangles = processing.runalg("qgis:delaunaytriangulation", layer, None)['OUTPUT'] delaunay_layer = processing.getObject(delone_triangles) # Get max edge length from Delaunay triangles progress.setText(self.tr('Computing edges max length...')) features = delaunay_layer.getFeatures() if len(features) == 0: raise GeoAlgorithmExecutionException( self.tr('No Delaunay triangles created.')) counter = 50. / len(features) lengths = [] edges = {} for feat in features: line = feat.geometry().asPolygon()[0] for i in range(len(line) - 1): lengths.append(sqrt(line[i].sqrDist(line[i + 1]))) edges[feat.id()] = max(lengths[-3:]) progress.setPercentage(feat.id() * counter) max_length = max(lengths) # Get features with longest edge longer than alpha*max_length progress.setText(self.tr('Removing features...')) counter = 50. / len(edges) i = 0 ids = [] for id, max_len in list(edges.items()): if max_len > alpha * max_length: ids.append(id) progress.setPercentage(50 + i * counter) i += 1 # Remove features delaunay_layer.selectByIds(ids) delaunay_layer.startEditing() delaunay_layer.deleteSelectedFeatures() delaunay_layer.commitChanges() # Dissolve all Delaunay triangles progress.setText(self.tr('Dissolving Delaunay triangles...')) dissolved = processing.runalg("qgis:dissolve", delaunay_layer, True, None, None)['OUTPUT'] dissolved_layer = processing.getObject(dissolved) # Save result progress.setText(self.tr('Saving data...')) feat = QgsFeature() dissolved_layer.getFeatures( QgsFeatureRequest().setFilterFid(0)).nextFeature(feat) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.fields().toList(), QgsWkbTypes.Polygon, layer.crs()) geom = feat.geometry() if no_multigeom and geom.isMultipart(): # Only singlepart geometries are allowed geom_list = geom.asMultiPolygon() for single_geom_list in geom_list: single_feature = QgsFeature() single_geom = QgsGeometry.fromPolygon(single_geom_list) if not holes: # Delete holes deleted = True while deleted: deleted = single_geom.deleteRing(1) single_feature.setGeometry(single_geom) writer.addFeature(single_feature) else: # Multipart geometries are allowed if not holes: # Delete holes deleted = True while deleted: deleted = geom.deleteRing(1) writer.addFeature(feat) del writer
def processAlgorithm(self, progress): layer = dataobjects.getObjectFromUri(self.getParameterValue( self.INPUT)) buf = self.getParameterValue(self.BUFFER) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layer.pendingFields().toList(), QGis.WKBPolygon, layer.crs()) inFeat = QgsFeature() outFeat = QgsFeature() extent = layer.extent() extraX = extent.height() * (buf / 100.0) extraY = extent.width() * (buf / 100.0) height = extent.height() width = extent.width() c = voronoi.Context() pts = [] ptDict = {} ptNdx = -1 features = vector.features(layer) for inFeat in features: geom = QgsGeometry(inFeat.geometry()) point = geom.asPoint() x = point.x() - extent.xMinimum() y = point.y() - extent.yMinimum() pts.append((x, y)) ptNdx += 1 ptDict[ptNdx] = inFeat.id() if len(pts) < 3: raise GeoAlgorithmExecutionException( self.tr('Input file should contain at least 3 points. Choose ' 'another file and try again.')) uniqueSet = Set(item for item in pts) ids = [pts.index(item) for item in uniqueSet] sl = voronoi.SiteList([ voronoi.Site(i[0], i[1], sitenum=j) for (j, i) in enumerate(uniqueSet) ]) voronoi.voronoi(sl, c) inFeat = QgsFeature() current = 0 total = 100.0 / float(len(c.polygons)) for (site, edges) in c.polygons.iteritems(): request = QgsFeatureRequest().setFilterFid(ptDict[ids[site]]) inFeat = layer.getFeatures(request).next() lines = self.clip_voronoi(edges, c, width, height, extent, extraX, extraY) geom = QgsGeometry.fromMultiPoint(lines) geom = QgsGeometry(geom.convexHull()) outFeat.setGeometry(geom) outFeat.setAttributes(inFeat.attributes()) writer.addFeature(outFeat) current += 1 progress.setPercentage(int(current * total)) del writer
def run_checks(): self.assertEqual([f.name() for f in vl.fields()], ['fid', 'type', 'value']) # expression req = QgsFeatureRequest() req.setFilterExpression("value=16") it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter fid req = QgsFeatureRequest() req.setFilterFid(5) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter fids req = QgsFeatureRequest() req.setFilterFids([5]) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # check with subset of attributes req = QgsFeatureRequest() req.setFilterFids([5]) req.setSubsetOfAttributes([2]) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes()[2], 16) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter rect and expression req = QgsFeatureRequest() req.setFilterExpression("value=16 or value=14") req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5)) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # filter rect and fids req = QgsFeatureRequest() req.setFilterFids([3, 5]) req.setFilterRect(QgsRectangle(4.5, 4.5, 5.5, 5.5)) it = vl.getFeatures(req) f = QgsFeature() self.assertTrue(it.nextFeature(f)) self.assertEqual(f.id(), 5) self.assertEqual(f.attributes(), [5, 2, 16]) self.assertEqual([field.name() for field in f.fields()], ['fid', 'type', 'value']) self.assertEqual(f.geometry().asWkt(), 'Point (5 5)') # Ensure that orig_ogc_fid is still retrieved even if attribute subset is passed req = QgsFeatureRequest() req.setSubsetOfAttributes([]) it = vl.getFeatures(req) ids = [] geoms = {} while it.nextFeature(f): ids.append(f.id()) geoms[f.id()] = f.geometry().asWkt() self.assertCountEqual(ids, [3, 4, 5]) self.assertEqual(geoms, { 3: 'Point (3 3)', 4: 'Point (4 4)', 5: 'Point (5 5)' })
def processAlgorithm(self, parameters, context, feedback): sourceA = self.parameterAsSource(parameters, self.INPUT, context) sourceB = self.parameterAsSource(parameters, self.OVERLAY, context) geomType = QgsWkbTypes.multiType(sourceA.wkbType()) fields = QgsProcessingUtils.combineFields(sourceA.fields(), sourceB.fields()) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, geomType, sourceA.sourceCrs()) featA = QgsFeature() featB = QgsFeature() outFeat = QgsFeature() indexA = QgsSpatialIndex(sourceA, feedback) indexB = QgsSpatialIndex( sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(sourceA.sourceCrs())), feedback) total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount( ) and sourceB.featureCount() else 1 count = 0 for featA in sourceA.getFeatures(): if feedback.isCanceled(): break lstIntersectingB = [] geom = featA.geometry() atMapA = featA.attributes() intersects = indexB.intersects(geom.boundingBox()) if len(intersects) < 1: try: geom.convertToMultiType() outFeat.setGeometry(geom) outFeat.setAttributes(atMapA) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: # This really shouldn't happen, as we haven't # edited the input geom at all feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) else: request = QgsFeatureRequest().setFilterFids( intersects).setSubsetOfAttributes([]) request.setDestinationCrs(sourceA.sourceCrs()) engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for featB in sourceB.getFeatures(request): atMapB = featB.attributes() tmpGeom = featB.geometry() if engine.intersects(tmpGeom.geometry()): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if not int_geom: # There was a problem creating the intersection feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) int_geom = QgsGeometry() else: int_geom = QgsGeometry(int_geom) if int_geom.wkbType( ) == QgsWkbTypes.Unknown 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: int_geom.convertToMultiType() outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) sink.addFeature( outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( 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 QgsWkbTypes.geometryType(int_geom.wkbType( )) == QgsWkbTypes.geometryType(geomType): try: int_geom.convertToMultiType() outFeat.setGeometry(int_geom) outFeat.setAttributes(atMapA + atMapB) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) # the remaining bit of featA'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( ) == QgsWkbTypes.Unknown 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: diff_geom.convertToMultiType() outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMapA) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) count += 1 feedback.setProgress(int(count * total)) length = len(sourceA.fields()) atMapA = [None] * length for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs( sourceA.sourceCrs())): if feedback.isCanceled(): break add = False geom = featA.geometry() diff_geom = QgsGeometry(geom) atMap = [None] * length atMap.extend(featA.attributes()) intersects = indexA.intersects(geom.boundingBox()) if len(intersects) < 1: try: geom.convertToMultiType() outFeat.setGeometry(geom) outFeat.setAttributes(atMap) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) else: request = QgsFeatureRequest().setFilterFids( intersects).setSubsetOfAttributes([]) request.setDestinationCrs(sourceA.sourceCrs()) # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(diff_geom.geometry()) engine.prepareGeometry() for featB in sourceA.getFeatures(request): atMapB = featB.attributes() tmpGeom = featB.geometry() if engine.intersects(tmpGeom.geometry()): add = True diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) else: try: # Ihis only happens if the bounding box # intersects, but the geometry doesn't diff_geom.convertToMultiType() outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) if add: try: diff_geom.convertToMultiType() outFeat.setGeometry(diff_geom) outFeat.setAttributes(atMap) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: feedback.pushInfo( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) count += 1 feedback.setProgress(int(count * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, feedback): lineLayer = dataobjects.getObjectFromUri( self.getParameterValue(self.LINES)) polyLayer = dataobjects.getObjectFromUri( self.getParameterValue(self.POLYGONS)) lengthFieldName = self.getParameterValue(self.LEN_FIELD) countFieldName = self.getParameterValue(self.COUNT_FIELD) (idxLength, fieldList) = vector.findOrCreateField(polyLayer, polyLayer.fields(), lengthFieldName) (idxCount, fieldList) = vector.findOrCreateField(polyLayer, fieldList, countFieldName) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fieldList.toList(), polyLayer.wkbType(), polyLayer.crs()) spatialIndex = vector.spatialindex(lineLayer) ftLine = QgsFeature() ftPoly = QgsFeature() outFeat = QgsFeature() inGeom = QgsGeometry() outGeom = QgsGeometry() distArea = QgsDistanceArea() features = vector.features(polyLayer) total = 100.0 / len(features) hasIntersections = False for current, ftPoly in enumerate(features): inGeom = ftPoly.geometry() attrs = ftPoly.attributes() count = 0 length = 0 hasIntersections = False lines = spatialIndex.intersects(inGeom.boundingBox()) engine = None if len(lines) > 0: hasIntersections = True # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(inGeom.geometry()) engine.prepareGeometry() if hasIntersections: request = QgsFeatureRequest().setFilterFids( lines).setSubsetOfAttributes([]) for ftLine in lineLayer.getFeatures(request): tmpGeom = ftLine.geometry() if engine.intersects(tmpGeom.geometry()): outGeom = inGeom.intersection(tmpGeom) length += distArea.measureLength(outGeom) count += 1 outFeat.setGeometry(inGeom) if idxLength == len(attrs): attrs.append(length) else: attrs[idxLength] = length if idxCount == len(attrs): attrs.append(count) else: attrs[idxCount] = count outFeat.setAttributes(attrs) writer.addFeature(outFeat) feedback.setProgress(int(current * total)) del writer
def processAlgorithm(self, progress): layerA = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) layerB = dataobjects.getObjectFromUri( self.getParameterValue(self.OVERLAY)) geomType = QgsWKBTypes.multiType(QGis.fromOldWkbType(layerA.wkbType())) fields = vector.combineVectorFields(layerA, layerB) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields, geomType, layerA.crs()) featB = QgsFeature() outFeat = QgsFeature() indexA = vector.spatialindex(layerB) indexB = vector.spatialindex(layerA) featuresA = vector.features(layerA) featuresB = vector.features(layerB) total = 100.0 / (len(featuresA) * len(featuresB) ) if len(featuresA) * len(featuresB) > 0 else 1 count = 0 for featA in featuresA: add = True geom = QgsGeometry(featA.geometry()) diffGeom = QgsGeometry(geom) attrs = featA.attributes() intersects = indexA.intersects(geom.boundingBox()) for i in intersects: layerB.getFeatures( QgsFeatureRequest().setFilterFid(i)).nextFeature(featB) tmpGeom = QgsGeometry(featB.geometry()) if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) if not diffGeom.isGeosValid(): ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) add = False break if add: try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_WARNING, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) continue count += 1 progress.setPercentage(int(count * total)) length = len(layerA.fields()) for featA in featuresB: add = True geom = QgsGeometry(featA.geometry()) diffGeom = QgsGeometry(geom) attrs = featA.attributes() attrs = [NULL] * length + attrs intersects = indexB.intersects(geom.boundingBox()) for i in intersects: layerA.getFeatures( QgsFeatureRequest().setFilterFid(i)).nextFeature(featB) tmpGeom = QgsGeometry(featB.geometry()) if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) if not diffGeom.isGeosValid(): ProcessingLog.addToLog( ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) add = False break if add: try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog( ProcessingLog.LOG_WARNING, self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' )) continue count += 1 progress.setPercentage(int(count * total)) del writer
def processAlgorithm(self, parameters, context, feedback): layer = self.parameterAsSource(parameters, ConcaveHull.INPUT, context) alpha = self.parameterAsDouble(parameters, self.ALPHA, context) holes = self.parameterAsBool(parameters, self.HOLES, context) no_multigeom = self.parameterAsBool(parameters, self.NO_MULTIGEOMETRY, context) # Delaunay triangulation from input point layer feedback.setProgressText(self.tr('Creating Delaunay triangles...')) delaunay_layer = processing.run("qgis:delaunaytriangulation", { 'INPUT': parameters[ConcaveHull.INPUT], 'OUTPUT': 'memory:' }, feedback=feedback, context=context)['OUTPUT'] # Get max edge length from Delaunay triangles feedback.setProgressText(self.tr('Computing edges max length...')) features = delaunay_layer.getFeatures() count = delaunay_layer.featureCount() if count == 0: raise QgsProcessingException( self.tr('No Delaunay triangles created.')) counter = 50. / count lengths = [] edges = {} for feat in features: if feedback.isCanceled(): break line = feat.geometry().asPolygon()[0] for i in range(len(line) - 1): lengths.append(sqrt(line[i].sqrDist(line[i + 1]))) edges[feat.id()] = max(lengths[-3:]) feedback.setProgress(feat.id() * counter) max_length = max(lengths) # Get features with longest edge longer than alpha*max_length feedback.setProgressText(self.tr('Removing features...')) counter = 50. / len(edges) i = 0 ids = [] for id, max_len in list(edges.items()): if feedback.isCanceled(): break if max_len > alpha * max_length: ids.append(id) feedback.setProgress(50 + i * counter) i += 1 # Remove features delaunay_layer.dataProvider().deleteFeatures(ids) # Dissolve all Delaunay triangles feedback.setProgressText(self.tr('Dissolving Delaunay triangles...')) dissolved_layer = processing.run("native:dissolve", { 'INPUT': delaunay_layer, 'OUTPUT': 'memory:' }, feedback=feedback, context=context)['OUTPUT'] # Save result feedback.setProgressText(self.tr('Saving data...')) feat = QgsFeature() dissolved_layer.getFeatures().nextFeature(feat) # Not needed anymore, free up some resources del delaunay_layer del dissolved_layer (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, layer.fields(), QgsWkbTypes.Polygon, layer.sourceCrs()) geom = feat.geometry() if no_multigeom and geom.isMultipart(): # Only singlepart geometries are allowed geom_list = geom.asGeometryCollection() for single_geom in geom_list: if feedback.isCanceled(): break single_feature = QgsFeature() if not holes: # Delete holes single_geom = single_geom.removeInteriorRings() single_feature.setGeometry(single_geom) sink.addFeature(single_feature, QgsFeatureSink.FastInsert) else: # Multipart geometries are allowed if not holes: # Delete holes geom = geom.removeInteriorRings() feat.setGeometry(geom) sink.addFeature(feat, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest_id}
def testCreateFeature(self): """ test creating a feature respecting defaults and constraints """ layer = QgsVectorLayer( "Point?field=fldtxt:string&field=fldint:integer&field=flddbl:double", "addfeat", "memory") # add a bunch of features f = QgsFeature() f.setAttributes(["test", 123, 1.0]) f1 = QgsFeature(2) f1.setAttributes(["test_1", 124, 1.1]) f2 = QgsFeature(3) f2.setAttributes(["test_2", 125, 2.4]) f3 = QgsFeature(4) f3.setAttributes(["test_3", 126, 1.7]) f4 = QgsFeature(5) f4.setAttributes(["superpig", 127, 0.8]) self.assertTrue(layer.dataProvider().addFeatures([f, f1, f2, f3, f4])) # no layer self.assertFalse(QgsVectorLayerUtils.createFeature(None).isValid()) # basic tests f = QgsVectorLayerUtils.createFeature(layer) self.assertTrue(f.isValid()) self.assertEqual(f.fields(), layer.fields()) self.assertFalse(f.hasGeometry()) self.assertEqual(f.attributes(), [NULL, NULL, NULL]) # set geometry g = QgsGeometry.fromPointXY(QgsPointXY(100, 200)) f = QgsVectorLayerUtils.createFeature(layer, g) self.assertTrue(f.hasGeometry()) self.assertEqual(f.geometry().asWkt(), g.asWkt()) # using attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'a', 2: 6.0 }) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression layer.setDefaultValueDefinition(2, QgsDefaultValue('3*4')) f = QgsVectorLayerUtils.createFeature(layer) self.assertEqual(f.attributes(), [NULL, NULL, 12]) # we do not expect the default value expression to take precedence over the attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'a', 2: 6.0 }) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression based on geometry layer.setDefaultValueDefinition(2, QgsDefaultValue('3*$x')) f = QgsVectorLayerUtils.createFeature(layer, g) #adjusted so that input value and output feature are the same self.assertEqual(f.attributes(), [NULL, NULL, 300.0]) layer.setDefaultValueDefinition(2, QgsDefaultValue(None)) # test with violated unique constraints layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintUnique) f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and sets to 128 self.assertEqual(f.attributes(), ['test_1', 128, NULL]) layer.setFieldConstraint(0, QgsFieldConstraints.ConstraintUnique) # since field 0 and 1 already have values test_1 and 123, the output must be a new unique value f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) self.assertEqual(f.attributes(), ['test_4', 128, NULL]) # test with violated unique constraints and default value expression providing unique value layer.setDefaultValueDefinition(1, QgsDefaultValue('130')) f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and adds the default value self.assertEqual(f.attributes(), ['test_4', 130, NULL]) # fallback: test with violated unique constraints and default value expression providing already existing value # add the feature with the default value: self.assertTrue(layer.dataProvider().addFeatures([f])) f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and adds the default value # and since the default value providing an already existing value (130) it generates a unique value (next int: 131) self.assertEqual(f.attributes(), ['test_5', 131, NULL]) layer.setDefaultValueDefinition(1, QgsDefaultValue(None)) # test with manually correct unique constraint f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 132 }) self.assertEqual(f.attributes(), ['test_5', 132, NULL]) """ test creating a feature respecting unique values of postgres provider """ layer = QgsVectorLayer( "Point?field=fldtxt:string&field=fldint:integer&field=flddbl:double", "addfeat", "memory") # init connection string dbconn = 'dbname=\'qgis_test\'' if 'QGIS_PGTEST_DB' in os.environ: dbconn = os.environ['QGIS_PGTEST_DB'] # create a vector layer pg_layer = QgsVectorLayer( '{} table="qgis_test"."authors" sql='.format(dbconn), "authors", "postgres") self.assertTrue(pg_layer.isValid()) # check the default clause default_clause = 'nextval(\'qgis_test.authors_pk_seq\'::regclass)' self.assertEqual(pg_layer.dataProvider().defaultValueClause(0), default_clause) # though default_clause is after the first create not unique (until save), it should fill up all the features with it pg_layer.startEditing() f = QgsVectorLayerUtils.createFeature(pg_layer) self.assertEqual(f.attributes(), [default_clause, NULL]) self.assertTrue(pg_layer.addFeatures([f])) self.assertTrue( QgsVectorLayerUtils.valueExists(pg_layer, 0, default_clause)) f = QgsVectorLayerUtils.createFeature(pg_layer) self.assertEqual(f.attributes(), [default_clause, NULL]) self.assertTrue(pg_layer.addFeatures([f])) f = QgsVectorLayerUtils.createFeature(pg_layer) self.assertEqual(f.attributes(), [default_clause, NULL]) self.assertTrue(pg_layer.addFeatures([f])) # if a unique value is passed, use it f = QgsVectorLayerUtils.createFeature(pg_layer, attributes={ 0: 40, 1: NULL }) self.assertEqual(f.attributes(), [40, NULL]) # and if a default value is configured use it as well pg_layer.setDefaultValueDefinition(0, QgsDefaultValue('11*4')) f = QgsVectorLayerUtils.createFeature(pg_layer) self.assertEqual(f.attributes(), [44, NULL]) pg_layer.rollBack()
def processAlgorithm(self, progress): useField = not self.getParameterValue(Dissolve.DISSOLVE_ALL) field_names = self.getParameterValue(Dissolve.FIELD) vlayerA = dataobjects.getObjectFromUri( self.getParameterValue(Dissolve.INPUT)) fields = vlayerA.fields() writer = self.getOutputFromName( Dissolve.OUTPUT).getVectorWriter(fields, vlayerA.wkbType(), vlayerA.crs()) outFeat = QgsFeature() features = vector.features(vlayerA) total = 100.0 / len(features) if not useField: first = True for current, inFeat in enumerate(features): progress.setPercentage(int(current * total)) if first: attrs = inFeat.attributes() tmpInGeom = QgsGeometry(inFeat.geometry()) if tmpInGeom.isGeosEmpty(): continue errors = tmpInGeom.validateGeometry() if len(errors) != 0: for error in errors: ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('ValidateGeometry()' 'error: One or more ' 'input features have ' 'invalid geometry: ') + error.what()) continue outFeat.setGeometry(tmpInGeom) first = False else: tmpInGeom = QgsGeometry(inFeat.geometry()) if tmpInGeom.isGeosEmpty(): continue tmpOutGeom = QgsGeometry(outFeat.geometry()) errors = tmpInGeom.validateGeometry() if len(errors) != 0: for error in errors: ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('ValidateGeometry()' 'error:One or more input' 'features have invalid ' 'geometry: ') + error.what()) continue try: tmpOutGeom = QgsGeometry(tmpOutGeom.combine(tmpInGeom)) outFeat.setGeometry(tmpOutGeom) except: raise GeoAlgorithmExecutionException( self.tr('Geometry exception while dissolving')) outFeat.setAttributes(attrs) writer.addFeature(outFeat) else: field_indexes = [vlayerA.fieldNameIndex(f) for f in field_names.split(';')] attribute_dict = {} geometry_dict = defaultdict(lambda: []) for inFeat in features: attrs = inFeat.attributes() index_attrs = tuple([attrs[i] for i in field_indexes]) tmpInGeom = QgsGeometry(inFeat.geometry()) if tmpInGeom.isGeosEmpty(): continue errors = tmpInGeom.validateGeometry() if len(errors) != 0: for error in errors: ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('ValidateGeometry() ' 'error: One or more input' 'features have invalid ' 'geometry: ') + error.what()) if not index_attrs in attribute_dict: # keep attributes of first feature attribute_dict[index_attrs] = attrs geometry_dict[index_attrs].append(tmpInGeom) nFeat = len(attribute_dict) nElement = 0 for key, value in geometry_dict.items(): outFeat = QgsFeature() nElement += 1 progress.setPercentage(int(nElement * 100 / nFeat)) try: tmpOutGeom = QgsGeometry.unaryUnion(value) except: raise GeoAlgorithmExecutionException( self.tr('Geometry exception while dissolving')) outFeat.setGeometry(tmpOutGeom) outFeat.setAttributes(attribute_dict[key]) writer.addFeature(outFeat) del writer
def testCreateFeature(self): """ test creating a feature respecting defaults and constraints """ layer = QgsVectorLayer( "Point?field=fldtxt:string&field=fldint:integer&field=flddbl:double", "addfeat", "memory") # add a bunch of features f = QgsFeature() f.setAttributes(["test", 123, 1.0]) f1 = QgsFeature(2) f1.setAttributes(["test_1", 124, 1.1]) f2 = QgsFeature(3) f2.setAttributes(["test_2", 125, 2.4]) f3 = QgsFeature(4) f3.setAttributes(["test_3", 126, 1.7]) f4 = QgsFeature(5) f4.setAttributes(["superpig", 127, 0.8]) self.assertTrue(layer.dataProvider().addFeatures([f, f1, f2, f3, f4])) # no layer self.assertFalse(QgsVectorLayerUtils.createFeature(None).isValid()) # basic tests f = QgsVectorLayerUtils.createFeature(layer) self.assertTrue(f.isValid()) self.assertEqual(f.fields(), layer.fields()) self.assertFalse(f.hasGeometry()) self.assertEqual(f.attributes(), [NULL, NULL, NULL]) # set geometry g = QgsGeometry.fromPoint(QgsPoint(100, 200)) f = QgsVectorLayerUtils.createFeature(layer, g) self.assertTrue(f.hasGeometry()) self.assertEqual(f.geometry().exportToWkt(), g.exportToWkt()) # using attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'a', 2: 6.0 }) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression layer.setDefaultValueExpression(2, '3*4') f = QgsVectorLayerUtils.createFeature(layer) self.assertEqual(f.attributes(), [NULL, NULL, 12.0]) # we expect the default value expression to take precedence over the attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'a', 2: 6.0 }) self.assertEqual(f.attributes(), ['a', NULL, 12.0]) # layer with default value expression based on geometry layer.setDefaultValueExpression(2, '3*$x') f = QgsVectorLayerUtils.createFeature(layer, g) self.assertEqual(f.attributes(), [NULL, NULL, 300.0]) layer.setDefaultValueExpression(2, None) # test with violated unique constraints layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintUnique) f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) self.assertEqual(f.attributes(), ['test_1', 128, NULL]) layer.setFieldConstraint(0, QgsFieldConstraints.ConstraintUnique) f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) self.assertEqual(f.attributes(), ['test_4', 128, NULL])
def processAlgorithm(self, progress): polyLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.POLYGONS)) pointLayer = dataobjects.getObjectFromUri(self.getParameterValue(self.POINTS)) fieldName = self.getParameterValue(self.FIELD) fieldIdx = pointLayer.fieldNameIndex(self.getParameterValue(self.WEIGHT)) polyProvider = polyLayer.dataProvider() fields = polyProvider.fields() fields.append(QgsField(fieldName, QVariant.Int)) (idxCount, fieldList) = vector.findOrCreateField(polyLayer, polyLayer.pendingFields(), fieldName) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( fields.toList(), polyProvider.geometryType(), polyProvider.crs()) spatialIndex = vector.spatialindex(pointLayer) ftPoint = QgsFeature() outFeat = QgsFeature() geom = QgsGeometry() current = 0 hasIntersections = False features = vector.features(polyLayer) total = 100.0 / float(len(features)) for ftPoly in features: geom = ftPoly.geometry() attrs = ftPoly.attributes() count = 0 hasIntersections = False points = spatialIndex.intersects(geom.boundingBox()) if len(points) > 0: hasIntersections = True if hasIntersections: progress.setText(str(len(points))) for i in points: request = QgsFeatureRequest().setFilterFid(i) ftPoint = pointLayer.getFeatures(request).next() tmpGeom = QgsGeometry(ftPoint.geometry()) if geom.contains(tmpGeom): weight = str(ftPoint.attributes()[fieldIdx]) try: count += float(weight) except: # Ignore fields with non-numeric values pass outFeat.setGeometry(geom) if idxCount == len(attrs): attrs.append(count) else: attrs[idxCount] = count outFeat.setAttributes(attrs) writer.addFeature(outFeat) current += 1 progress.setPercentage(int(current * total)) del writer
def _clipVectorLayer(theLayer, theExtent, theExtraKeywords=None): """Clip a Hazard or Exposure layer to the extents of the current view frame. The layer must be a vector layer or an exception will be thrown. The output layer will always be in WGS84/Geographic. Args: * theLayer - a valid QGIS vector layer in EPSG:4326 * theExtent - an array representing the exposure layer extents in the form [xmin, ymin, xmax, ymax]. It is assumed that the coordinates are in EPSG:4326 although currently no checks are made to enforce this. * theExtraKeywords - any additional keywords over and above the original keywords that should be associated with the cliplayer. Returns: Path to the output clipped layer (placed in the system temp dir). Raises: None """ if not theLayer or not theExtent: myMessage = tr('Layer or Extent passed to clip is None.') raise InvalidParameterException(myMessage) if theLayer.type() != QgsMapLayer.VectorLayer: myMessage = tr('Expected a vector layer but received a %s.' % str(theLayer.type())) raise InvalidParameterException(myMessage) myHandle, myFilename = tempfile.mkstemp('.shp', 'clip_', temp_dir()) # Ensure the file is deleted before we try to write to it # fixes windows specific issue where you get a message like this # ERROR 1: c:\temp\inasafe\clip_jpxjnt.shp is not a directory. # This is because mkstemp creates the file handle and leaves # the file open. os.close(myHandle) os.remove(myFilename) # Get the clip extents in the layer's native CRS myGeoCrs = QgsCoordinateReferenceSystem() myGeoCrs.createFromId(4326, QgsCoordinateReferenceSystem.EpsgCrsId) myXForm = QgsCoordinateTransform(myGeoCrs, theLayer.crs()) myRect = QgsRectangle(theExtent[0], theExtent[1], theExtent[2], theExtent[3]) myProjectedExtent = myXForm.transformBoundingBox(myRect) # Get vector layer myProvider = theLayer.dataProvider() if myProvider is None: myMessage = tr('Could not obtain data provider from ' 'layer "%s"' % theLayer.source()) raise Exception(myMessage) # get the layer field list, select by our extent then write to disk # .. todo:: FIXME - for different geometry types we should implement # different clipping behaviour e.g. reject polygons that # intersect the edge of the bbox. Tim myAttributes = myProvider.attributeIndexes() myFetchGeometryFlag = True myUseIntersectFlag = True myProvider.select(myAttributes, myProjectedExtent, myFetchGeometryFlag, myUseIntersectFlag) myFieldList = myProvider.fields() myWriter = QgsVectorFileWriter(myFilename, 'UTF-8', myFieldList, theLayer.wkbType(), myGeoCrs, 'ESRI Shapefile') if myWriter.hasError() != QgsVectorFileWriter.NoError: myMessage = tr('Error when creating shapefile: <br>Filename:' '%s<br>Error: %s' % (myFilename, myWriter.hasError())) raise Exception(myMessage) # Reverse the coordinate xform now so that we can convert # geometries from layer crs to geocrs. myXForm = QgsCoordinateTransform(theLayer.crs(), myGeoCrs) # Retrieve every feature with its geometry and attributes myFeature = QgsFeature() myCount = 0 while myProvider.nextFeature(myFeature): myGeometry = myFeature.geometry() # Loop through the parts adding them to the output file # we ALWAYS write out single part features myGeometryList = explodeMultiPartGeometry(myGeometry) for myPart in myGeometryList: myPart.transform(myXForm) myFeature.setGeometry(myPart) myWriter.addFeature(myFeature) myCount += 1 del myWriter # Flush to disk if myCount < 1: myMessage = tr('No features fall within the clip extents. ' 'Try panning / zooming to an area containing data ' 'and then try to run your analysis again.') raise NoFeaturesInExtentException(myMessage) myKeywordIO = KeywordIO() myKeywordIO.copyKeywords(theLayer, myFilename, theExtraKeywords=theExtraKeywords) return myFilename # Filename of created file
def testGetFeatures(self, source=None, extra_features=[], skip_features=[], changed_attributes={}, changed_geometries={}): """ Test that expected results are returned when fetching all features """ # IMPORTANT - we do not use `for f in source.getFeatures()` as we are also # testing that existing attributes & geometry in f are overwritten correctly # (for f in ... uses a new QgsFeature for every iteration) if not source: source = self.source it = source.getFeatures() f = QgsFeature() attributes = {} geometries = {} while it.nextFeature(f): # expect feature to be valid self.assertTrue(f.isValid()) # some source test datasets will include additional attributes which we ignore, # so cherry pick desired attributes attrs = [f['pk'], f['cnt'], f['name'], f['name2'], f['num_char']] # force the num_char attribute to be text - some sources (e.g., delimited text) will # automatically detect that this attribute contains numbers and set it as a numeric # field attrs[4] = str(attrs[4]) attributes[f['pk']] = attrs geometries[f['pk']] = f.hasGeometry() and f.geometry().asWkt() expected_attributes = { 5: [5, -200, NULL, 'NuLl', '5'], 3: [3, 300, 'Pear', 'PEaR', '3'], 1: [1, 100, 'Orange', 'oranGe', '1'], 2: [2, 200, 'Apple', 'Apple', '2'], 4: [4, 400, 'Honey', 'Honey', '4'] } expected_geometries = { 1: 'Point (-70.332 66.33)', 2: 'Point (-68.2 70.8)', 3: None, 4: 'Point(-65.32 78.3)', 5: 'Point(-71.123 78.23)' } for f in extra_features: expected_attributes[f[0]] = f.attributes() if f.hasGeometry(): expected_geometries[f[0]] = f.geometry().asWkt() else: expected_geometries[f[0]] = None for i in skip_features: del expected_attributes[i] del expected_geometries[i] for i, a in changed_attributes.items(): for attr_idx, v in a.items(): expected_attributes[i][attr_idx] = v for i, g, in changed_geometries.items(): if g: expected_geometries[i] = g.asWkt() else: expected_geometries[i] = None self.assertEqual( attributes, expected_attributes, 'Expected {}, got {}'.format(expected_attributes, attributes)) self.assertEqual(len(expected_geometries), len(geometries)) for pk, geom in list(expected_geometries.items()): if geom: assert compareWkt( geom, geometries[pk] ), "Geometry {} mismatch Expected:\n{}\nGot:\n{}\n".format( pk, geom, geometries[pk]) else: self.assertFalse(geometries[pk], 'Expected null geometry for {}'.format(pk))
def processAlgorithm(self, feedback): 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) for inFeatA in featuresA: feedback.setProgress(nElement / float(nFeat) * 50) nElement += 1 lstIntersectingB = [] geom = 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: request = QgsFeatureRequest().setFilterFids(intersects) engine = QgsGeometry.createGeometryEngine(geom.geometry()) engine.prepareGeometry() for inFeatB in vlayerB.getFeatures(request): count += 1 atMapB = inFeatB.attributes() tmpGeom = inFeatB.geometry() if engine.intersects(tmpGeom.geometry()): int_geom = geom.intersection(tmpGeom) lstIntersectingB.append(tmpGeom) if not int_geom: # 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( ) == QgsWkbTypes.Unknown 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.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) for inFeatA in featuresA: feedback.setProgress(nElement / float(nFeat) * 100) add = False geom = 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: request = QgsFeatureRequest().setFilterFids(intersects) # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine(diff_geom.geometry()) engine.prepareGeometry() for inFeatB in vlayerA.getFeatures(request): atMapB = inFeatB.attributes() tmpGeom = inFeatB.geometry() if engine.intersects(tmpGeom.geometry()): add = True diff_geom = QgsGeometry(diff_geom.difference(tmpGeom)) else: try: # Ihis only happens 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, parameters, context, feedback): inLayer = self.parameterAsVectorLayer(parameters, self.INPUT, context) boundary = self.parameterAsEnum(parameters, self.MODE, context) == self.MODE_BOUNDARY smallestArea = self.parameterAsEnum(parameters, self.MODE, context) == self.MODE_SMALLEST_AREA if inLayer.selectedFeatureCount() == 0: feedback.reportError( self.tr('{0}: (No selection in input layer "{1}")').format( self.displayName(), parameters[self.INPUT])) featToEliminate = [] selFeatIds = inLayer.selectedFeatureIds() (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, inLayer.fields(), inLayer.wkbType(), inLayer.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) for aFeat in inLayer.getFeatures(): if feedback.isCanceled(): break if aFeat.id() in selFeatIds: # Keep references to the features to eliminate featToEliminate.append(aFeat) else: # write the others to output sink.addFeature(aFeat, QgsFeatureSink.FastInsert) # Delete all features to eliminate in processLayer processLayer = QgsProcessingUtils.mapLayerFromString(dest_id, context) processLayer.startEditing() # ANALYZE if len(featToEliminate) > 0: # Prevent zero division start = 20.00 add = 80.00 / len(featToEliminate) else: start = 100 feedback.setProgress(start) madeProgress = True # We go through the list and see if we find any polygons we can # merge the selected with. If we have no success with some we # merge and then restart the whole story. while madeProgress: # Check if we made any progress madeProgress = False featNotEliminated = [] # Iterate over the polygons to eliminate for i in range(len(featToEliminate)): if feedback.isCanceled(): break feat = featToEliminate.pop() geom2Eliminate = feat.geometry() bbox = geom2Eliminate.boundingBox() fit = processLayer.getFeatures( QgsFeatureRequest().setFilterRect( bbox).setSubsetOfAttributes([])) mergeWithFid = None mergeWithGeom = None max = 0 min = -1 selFeat = QgsFeature() # use prepared geometries for faster intersection tests engine = QgsGeometry.createGeometryEngine( geom2Eliminate.constGet()) engine.prepareGeometry() while fit.nextFeature(selFeat): if feedback.isCanceled(): break selGeom = selFeat.geometry() if engine.intersects(selGeom.constGet()): # We have a candidate iGeom = geom2Eliminate.intersection(selGeom) if not iGeom: continue if boundary: selValue = iGeom.length() else: # area. We need a common boundary in # order to merge if 0 < iGeom.length(): selValue = selGeom.area() else: selValue = -1 if -1 != selValue: useThis = True if smallestArea: if -1 == min: min = selValue else: if selValue < min: min = selValue else: useThis = False else: if selValue > max: max = selValue else: useThis = False if useThis: mergeWithFid = selFeat.id() mergeWithGeom = QgsGeometry(selGeom) # End while fit if mergeWithFid is not None: # A successful candidate newGeom = mergeWithGeom.combine(geom2Eliminate) if processLayer.changeGeometry(mergeWithFid, newGeom): madeProgress = True else: raise QgsProcessingException( self. tr('Could not replace geometry of feature with id {0}' ).format(mergeWithFid)) start = start + add feedback.setProgress(start) else: featNotEliminated.append(feat) # End for featToEliminate featToEliminate = featNotEliminated # End while if not processLayer.commitChanges(): raise QgsProcessingException(self.tr('Could not commit changes')) for feature in featNotEliminated: if feedback.isCanceled(): break sink.addFeature(feature, QgsFeatureSink.FastInsert) return {self.OUTPUT: dest_id}
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 test_make_features_compatible_attributes(self): """Test corner cases for attributes""" # Test feature with attributes fields = QgsFields() fields.append(QgsField('int_f', QVariant.Int)) fields.append(QgsField('str_f', QVariant.String)) f1 = QgsFeature(fields) f1['int_f'] = 1 f1['str_f'] = 'str' f1.setGeometry(QgsGeometry.fromWkt('Point(9 45)')) f2 = f1 QgsVectorLayerUtils.matchAttributesToFields(f2, fields) self.assertEqual(f1.attributes(), f2.attributes()) self.assertTrue(f1.geometry().asWkt(), f2.geometry().asWkt()) # Test pad with 0 with fields f1.setAttributes([]) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 2) self.assertEqual(f1.attributes()[0], QVariant()) self.assertEqual(f1.attributes()[1], QVariant()) # Test pad with 0 without fields f1 = QgsFeature() QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 2) self.assertEqual(f1.attributes()[0], QVariant()) self.assertEqual(f1.attributes()[1], QVariant()) # Test drop extra attrs f1 = QgsFeature(fields) f1.setAttributes([1, 'foo', 'extra']) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 2) self.assertEqual(f1.attributes()[0], 1) self.assertEqual(f1.attributes()[1], 'foo') # Rearranged fields fields2 = QgsFields() fields2.append(QgsField('str_f', QVariant.String)) fields2.append(QgsField('int_f', QVariant.Int)) f1 = QgsFeature(fields2) f1.setAttributes([1, 'foo', 'extra']) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 2) self.assertEqual(f1.attributes()[0], 'foo') self.assertEqual(f1.attributes()[1], 1) # mixed fields2.append(QgsField('extra', QVariant.String)) fields.append(QgsField('extra2', QVariant.Int)) f1.setFields(fields2) f1.setAttributes([1, 'foo', 'blah']) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 3) self.assertEqual(f1.attributes()[0], 'foo') self.assertEqual(f1.attributes()[1], 1) self.assertEqual(f1.attributes()[2], QVariant()) fields.append(QgsField('extra', QVariant.Int)) f1.setAttributes([1, 'foo', 'blah']) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 4) self.assertEqual(f1.attributes()[0], 'foo') self.assertEqual(f1.attributes()[1], 1) self.assertEqual(f1.attributes()[2], QVariant()) self.assertEqual(f1.attributes()[3], 'blah') # case insensitive fields2.append(QgsField('extra3', QVariant.String)) fields.append(QgsField('EXTRA3', QVariant.Int)) f1.setFields(fields2) f1.setAttributes([1, 'foo', 'blah', 'blergh']) QgsVectorLayerUtils.matchAttributesToFields(f1, fields) self.assertEqual(len(f1.attributes()), 5) self.assertEqual(f1.attributes()[0], 'foo') self.assertEqual(f1.attributes()[1], 1) self.assertEqual(f1.attributes()[2], QVariant()) self.assertEqual(f1.attributes()[3], 'blah') self.assertEqual(f1.attributes()[4], 'blergh')
def processAlgorithm(self, progress): layer = self.getParameterValue(self.INPUT_LAYER) mapping = self.getParameterValue(self.FIELDS_MAPPING) output = self.getOutputFromName(self.OUTPUT_LAYER) layer = dataobjects.getObjectFromUri(layer) fields = [] expressions = [] da = QgsDistanceArea() da.setSourceCrs(layer.crs().srsid()) da.setEllipsoidalMode( iface.mapCanvas().mapSettings().hasCrsTransformEnabled()) da.setEllipsoid(QgsProject.instance().readEntry( 'Measure', '/Ellipsoid', GEO_NONE)[0]) exp_context = QgsExpressionContext() exp_context.appendScope(QgsExpressionContextUtils.globalScope()) exp_context.appendScope(QgsExpressionContextUtils.projectScope()) exp_context.appendScope(QgsExpressionContextUtils.layerScope(layer)) for field_def in mapping: fields.append( QgsField(name=field_def['name'], type=field_def['type'], len=field_def['length'], prec=field_def['precision'])) expression = QgsExpression(field_def['expression']) expression.setGeomCalculator(da) expression.setDistanceUnits(QgsProject.instance().distanceUnits()) expression.setAreaUnits(QgsProject.instance().areaUnits()) if expression.hasParserError(): raise GeoAlgorithmExecutionException( self.tr(u'Parser error in expression "{}": {}').format( str(field_def['expression']), str(expression.parserErrorString()))) expression.prepare(exp_context) if expression.hasEvalError(): raise GeoAlgorithmExecutionException( self.tr(u'Evaluation error in expression "{}": {}').format( str(field_def['expression']), str(expression.evalErrorString()))) expressions.append(expression) writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs()) # Create output vector layer with new attributes error = '' calculationSuccess = True inFeat = QgsFeature() outFeat = QgsFeature() features = vector.features(layer) total = 100.0 / len(features) for current, inFeat in enumerate(features): rownum = current + 1 geometry = inFeat.geometry() outFeat.setGeometry(geometry) attrs = [] for i in range(0, len(mapping)): field_def = mapping[i] expression = expressions[i] exp_context.setFeature(inFeat) exp_context.lastScope().setVariable("row_number", rownum) value = expression.evaluate(exp_context) if expression.hasEvalError(): calculationSuccess = False error = expression.evalErrorString() break attrs.append(value) outFeat.setAttributes(attrs) writer.addFeature(outFeat) progress.setPercentage(int(current * total)) del writer if not calculationSuccess: raise GeoAlgorithmExecutionException( self.tr('An error occurred while evaluating the calculation' ' string:\n') + error)
def processAlgorithm(self, progress): layerA = dataobjects.getObjectFromUri( self.getParameterValue(Clip.INPUT)) layerB = dataobjects.getObjectFromUri( self.getParameterValue(Clip.OVERLAY)) writer = self.getOutputFromName(self.OUTPUT).getVectorWriter( layerA.pendingFields(), layerA.dataProvider().geometryType(), layerA.dataProvider().crs()) inFeatA = QgsFeature() inFeatB = QgsFeature() outFeat = QgsFeature() index = vector.spatialindex(layerB) selectionA = vector.features(layerA) current = 0 total = 100.0 / float(len(selectionA)) for inFeatA in selectionA: geom = QgsGeometry(inFeatA.geometry()) attrs = inFeatA.attributes() intersects = index.intersects(geom.boundingBox()) first = True found = False if len(intersects) > 0: for i in intersects: layerB.getFeatures( QgsFeatureRequest().setFilterFid(i)).nextFeature( inFeatB) tmpGeom = QgsGeometry(inFeatB.geometry()) if tmpGeom.intersects(geom): found = True if first: outFeat.setGeometry(QgsGeometry(tmpGeom)) first = False else: try: cur_geom = QgsGeometry(outFeat.geometry()) new_geom = QgsGeometry( cur_geom.combine(tmpGeom)) outFeat.setGeometry(QgsGeometry(new_geom)) except: ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or ' 'more input features have invalid ' 'geometry.')) break if found: try: cur_geom = QgsGeometry(outFeat.geometry()) new_geom = QgsGeometry(geom.intersection(cur_geom)) if new_geom.wkbType() == 0: int_com = QgsGeometry(geom.combine(cur_geom)) int_sym = QgsGeometry(geom.symDifference(cur_geom)) new_geom = QgsGeometry(int_com.difference(int_sym)) try: outFeat.setGeometry(new_geom) outFeat.setAttributes(attrs) writer.addFeature(outFeat) except: ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('Feature geometry error: One or more ' 'output features ignored due to ' 'invalid geometry.')) continue except: ProcessingLog.addToLog(ProcessingLog.LOG_ERROR, self.tr('GEOS geoprocessing error: One or more ' 'input features have invalid geometry.')) continue current += 1 progress.setPercentage(int(current * total)) del writer
def setSelectFeaturesOrRubberband_Tas( canvas, selectGeometry, doContains = True, doDifference = False, singleSelect = False): if ( selectGeometry.type() != QGis.Polygon ): return vlayer = QgsMapToolSelectUtils.getCurrentVectorLayer( canvas ) if ( vlayer == None ): return #// toLayerCoordinates will throw an exception for any 'invalid' points in #// the rubber band. #// For example, if you project a world map onto a globe using EPSG 2163 #// and then click somewhere off the globe, an exception will be thrown. selectGeomTrans = QgsGeometry( selectGeometry ) if ( canvas.mapSettings().hasCrsTransformEnabled() ): try: ct = QgsCoordinateTransform( canvas.mapSettings().destinationCrs(), vlayer.crs() ) # print selectGeomTrans.boundingBox().xMaximum () # polygonList = [] # for polygon in selectGeomTrans1.asPolygon(): # pointList = [] # for point in polygon: # transPoint = QgisHelper.CrsTransformPoint(point.x(), point.y(), define._mapCrs, vlayer.crs()) # pointList.append(transPoint) # polygonList.extend(pointList) # selectGeomTrans = QgsGeometry.fromPolygon (pointList) selectGeomTrans.transform( ct ) except QgsCsException as cse: raise UserWarning, "Coordinate Transform Error in QgsMapToolSelectUtils\n" + cse.message QApplication.setOverrideCursor( Qt.WaitCursor ) fit = vlayer.getFeatures( QgsFeatureRequest().setFilterRect( selectGeomTrans.boundingBox() ).setFlags( QgsFeatureRequest.ExactIntersect ).setSubsetOfAttributes( [] ) ) newSelectedFeatures = [] newSelectedFeatureList = [] f = QgsFeature() closestFeatureId = 0 foundSingleFeature = False closestFeatureDist = 9.0E+10 for f in fit: g = f.geometry() if ( doContains ): 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: newSelectedFeatures.append( f.id() ) newSelectedFeatureList.append(f) if ( singleSelect and foundSingleFeature ): newSelectedFeatures.append( closestFeatureId ) featIter = vlayer.getFeatures (QgsFeatureRequest(closestFeatureId)) for feat in featIter: newSelectedFeatureList.append(feat) if ( doDifference ): layerSelectedFeatures = vlayer.selectedFeaturesIds() deselectedFeatures = [] selectedFeatures = [] for i in newSelectedFeatures.reverse(): if i in layerSelectedFeatures: deselectedFeatures.append( i ) else: selectedFeatures.append( i ) vlayer.modifySelection( selectedFeatures, deselectedFeatures ) else: vlayer.setSelectedFeatures( newSelectedFeatures ) QApplication.restoreOverrideCursor() return newSelectedFeatureList
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) if source is None: raise QgsProcessingException( self.invalidSourceError(parameters, self.INPUT)) buf = self.parameterAsDouble(parameters, self.BUFFER, context) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, source.fields(), QgsWkbTypes.Polygon, source.sourceCrs()) if sink is None: raise QgsProcessingException( self.invalidSinkError(parameters, self.OUTPUT)) outFeat = QgsFeature() extent = source.sourceExtent() extraX = extent.width() * (buf / 100.0) # Adjust the extent extent.setXMinimum(extent.xMinimum() - extraX) extent.setXMaximum(extent.xMaximum() + extraX) extraY = extent.height() * (buf / 100.0) extent.setYMinimum(extent.yMinimum() - extraY) extent.setYMaximum(extent.yMaximum() + extraY) height = extent.height() width = extent.width() c = voronoi.Context() pts = [] ptDict = {} ptNdx = -1 # Find the minimum and maximum x and y for the input points xmin = width xmax = 0 ymin = height ymax = 0 features = source.getFeatures() total = 100.0 / source.featureCount() if source.featureCount() else 0 for current, inFeat in enumerate(features): if feedback.isCanceled(): break geom = inFeat.geometry() point = geom.asPoint() x = point.x() - extent.xMinimum() y = point.y() - extent.yMinimum() pts.append((x, y)) ptNdx += 1 ptDict[ptNdx] = inFeat.id() if x < xmin: xmin = x if y < ymin: ymin = y if x > xmax: xmax = x if y > ymax: ymax = y feedback.setProgress(int(current * total)) if xmin == xmax or ymin == ymax: raise QgsProcessingException('The extent of the input points is ' 'not a polygon (all the points are ' 'on a vertical or horizontal line) ' '- cannot make a Voronoi diagram!') xyminmax = [xmin, ymin, xmax, ymax] if len(pts) < 3: raise QgsProcessingException( self.tr('Input file should contain at least 3 points. Choose ' 'another file and try again.')) # Eliminate duplicate points uniqueSet = set(item for item in pts) ids = [pts.index(item) for item in uniqueSet] sl = voronoi.SiteList([ voronoi.Site(i[0], i[1], sitenum=j) for (j, i) in enumerate(uniqueSet) ]) voronoi.voronoi(sl, c) if len(c.polygons) == 0: raise QgsProcessingException( self.tr('There were no polygons created.')) inFeat = QgsFeature() current = 0 total = 100.0 / len(c.polygons) # Clip each of the generated "polygons" for (site, edges) in list(c.polygons.items()): if feedback.isCanceled(): break request = QgsFeatureRequest().setFilterFid(ptDict[ids[site]]) inFeat = next(source.getFeatures(request)) boundarypoints = self.clip_voronoi(edges, c, width, height, extent, inFeat.geometry().asPoint(), xyminmax) ptgeom = QgsGeometry.fromMultiPointXY(boundarypoints) geom = QgsGeometry(ptgeom.convexHull()) outFeat.setGeometry(geom) outFeat.setAttributes(inFeat.attributes()) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) current += 1 feedback.setProgress(int(current * total)) return {self.OUTPUT: dest_id}
def processAlgorithm(self, feedback): 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) feedback.setProgress(int(c * total)) del writer
def processAlgorithm(self, parameters, context, feedback): sourceA = self.parameterAsSource(parameters, self.INPUT, context) sourceB = self.parameterAsSource(parameters, self.OVERLAY, context) geomType = QgsWkbTypes.multiType(sourceA.wkbType()) fields = QgsProcessingUtils.combineFields(sourceA.fields(), sourceB.fields()) (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context, fields, geomType, sourceA.sourceCrs()) featB = QgsFeature() outFeat = QgsFeature() indexA = QgsSpatialIndex(sourceA, feedback) indexB = QgsSpatialIndex( sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes( []).setDestinationCrs(sourceA.sourceCrs(), context.transformContext())), feedback) total = 100.0 / (sourceA.featureCount() * sourceB.featureCount()) if sourceA.featureCount( ) and sourceB.featureCount() else 1 count = 0 for featA in sourceA.getFeatures(): if feedback.isCanceled(): break geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() intersects = indexB.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids( intersects).setSubsetOfAttributes([]) request.setDestinationCrs(sourceA.sourceCrs(), context.transformContext()) for featB in sourceB.getFeatures(request): if feedback.isCanceled(): break tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: QgsMessageLog.logMessage( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' ), self.tr('Processing'), QgsMessageLog.WARNING) continue count += 1 feedback.setProgress(int(count * total)) length = len(sourceA.fields()) for featA in sourceB.getFeatures(QgsFeatureRequest().setDestinationCrs( sourceA.sourceCrs(), context.transformContext())): if feedback.isCanceled(): break geom = featA.geometry() diffGeom = QgsGeometry(geom) attrs = featA.attributes() attrs = [NULL] * length + attrs intersects = indexA.intersects(geom.boundingBox()) request = QgsFeatureRequest().setFilterFids( intersects).setSubsetOfAttributes([]) for featB in sourceA.getFeatures(request): if feedback.isCanceled(): break tmpGeom = featB.geometry() if diffGeom.intersects(tmpGeom): diffGeom = QgsGeometry(diffGeom.difference(tmpGeom)) try: outFeat.setGeometry(diffGeom) outFeat.setAttributes(attrs) sink.addFeature(outFeat, QgsFeatureSink.FastInsert) except: QgsMessageLog.logMessage( self. tr('Feature geometry error: One or more output features ignored due to invalid geometry.' ), self.tr('Processing'), QgsMessageLog.WARNING) continue count += 1 feedback.setProgress(int(count * total)) return {self.OUTPUT: dest_id}
def testCreateFeature(self): """ test creating a feature respecting defaults and constraints """ layer = QgsVectorLayer( "Point?field=fldtxt:string&field=fldint:integer&field=flddbl:double", "addfeat", "memory") # add a bunch of features f = QgsFeature() f.setAttributes(["test", 123, 1.0]) f1 = QgsFeature(2) f1.setAttributes(["test_1", 124, 1.1]) f2 = QgsFeature(3) f2.setAttributes(["test_2", 125, 2.4]) f3 = QgsFeature(4) f3.setAttributes(["test_3", 126, 1.7]) f4 = QgsFeature(5) f4.setAttributes(["superpig", 127, 0.8]) self.assertTrue(layer.dataProvider().addFeatures([f, f1, f2, f3, f4])) # no layer self.assertFalse(QgsVectorLayerUtils.createFeature(None).isValid()) # basic tests f = QgsVectorLayerUtils.createFeature(layer) self.assertTrue(f.isValid()) self.assertEqual(f.fields(), layer.fields()) self.assertFalse(f.hasGeometry()) self.assertEqual(f.attributes(), [NULL, NULL, NULL]) # set geometry g = QgsGeometry.fromPointXY(QgsPointXY(100, 200)) f = QgsVectorLayerUtils.createFeature(layer, g) self.assertTrue(f.hasGeometry()) self.assertEqual(f.geometry().asWkt(), g.asWkt()) # using attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'a', 2: 6.0 }) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression layer.setDefaultValueDefinition(2, QgsDefaultValue('3*4')) f = QgsVectorLayerUtils.createFeature(layer) self.assertEqual(f.attributes(), [NULL, NULL, 12]) # we do not expect the default value expression to take precedence over the attribute map f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'a', 2: 6.0 }) self.assertEqual(f.attributes(), ['a', NULL, 6.0]) # layer with default value expression based on geometry layer.setDefaultValueDefinition(2, QgsDefaultValue('3*$x')) f = QgsVectorLayerUtils.createFeature(layer, g) #adjusted so that input value and output feature are the same self.assertEqual(f.attributes(), [NULL, NULL, 300.0]) layer.setDefaultValueDefinition(2, QgsDefaultValue(None)) # test with violated unique constraints layer.setFieldConstraint(1, QgsFieldConstraints.ConstraintUnique) f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and sets to 128 self.assertEqual(f.attributes(), ['test_1', 128, NULL]) layer.setFieldConstraint(0, QgsFieldConstraints.ConstraintUnique) # since field 0 and 1 already have values test_1 and 123, the output must be a new unique value f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) self.assertEqual(f.attributes(), ['test_4', 128, NULL]) # test with violated unique constraints and default value expression providing unique value layer.setDefaultValueDefinition(1, QgsDefaultValue('130')) f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and adds the default value self.assertEqual(f.attributes(), ['test_4', 130, NULL]) # fallback: test with violated unique constraints and default value expression providing already existing value # add the feature with the default value: self.assertTrue(layer.dataProvider().addFeatures([f])) f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 123 }) # since field 1 has Unique Constraint, it ignores value 123 that already has been set and adds the default value # and since the default value providing an already existing value (130) it generates a unique value (next int: 131) self.assertEqual(f.attributes(), ['test_5', 131, NULL]) layer.setDefaultValueDefinition(1, QgsDefaultValue(None)) # test with manually correct unique constraint f = QgsVectorLayerUtils.createFeature(layer, attributes={ 0: 'test_1', 1: 132 }) self.assertEqual(f.attributes(), ['test_5', 132, NULL])
def processAlgorithm(self, feedback): layer = self.getParameterValue(self.INPUT_LAYER) mapping = self.getParameterValue(self.FIELDS_MAPPING) output = self.getOutputFromName(self.OUTPUT_LAYER) layer = dataobjects.getLayerFromString(layer) fields = [] expressions = [] da = QgsDistanceArea() da.setSourceCrs(layer.crs()) da.setEllipsoidalMode(True) da.setEllipsoid(QgsProject.instance().ellipsoid()) exp_context = layer.createExpressionContext() for field_def in mapping: fields.append( QgsField(name=field_def['name'], type=field_def['type'], len=field_def['length'], prec=field_def['precision'])) expression = QgsExpression(field_def['expression']) expression.setGeomCalculator(da) expression.setDistanceUnits(QgsProject.instance().distanceUnits()) expression.setAreaUnits(QgsProject.instance().areaUnits()) expression.prepare(exp_context) if expression.hasParserError(): raise GeoAlgorithmExecutionException( self.tr(u'Parser error in expression "{}": {}').format( str(expression.expression()), str(expression.parserErrorString()))) expressions.append(expression) writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs()) # Create output vector layer with new attributes error_exp = None inFeat = QgsFeature() outFeat = QgsFeature() features = vector.features(layer) if len(features): total = 100.0 / len(features) for current, inFeat in enumerate(features): rownum = current + 1 geometry = inFeat.geometry() outFeat.setGeometry(geometry) attrs = [] for i in range(0, len(mapping)): field_def = mapping[i] expression = expressions[i] exp_context.setFeature(inFeat) exp_context.lastScope().setVariable("row_number", rownum) value = expression.evaluate(exp_context) if expression.hasEvalError(): error_exp = expression break attrs.append(value) outFeat.setAttributes(attrs) writer.addFeature(outFeat) feedback.setProgress(int(current * total)) else: feedback.setProgress(100) del writer if error_exp is not None: raise GeoAlgorithmExecutionException( self.tr(u'Evaluation error in expression "{}": {}').format( str(error_exp.expression()), str(error_exp.parserErrorString())))
def processAlgorithm(self, progress): inLayer = dataobjects.getObjectFromUri( self.getParameterValue(self.INPUT)) boundary = self.getParameterValue(self.MODE) == self.MODE_BOUNDARY smallestArea = self.getParameterValue( self.MODE) == self.MODE_SMALLEST_AREA keepSelection = self.getParameterValue(self.KEEPSELECTION) processLayer = vector.duplicateInMemory(inLayer) if not keepSelection: # Make a selection with the values provided attribute = self.getParameterValue(self.ATTRIBUTE) comparison = self.comparisons[self.getParameterValue( self.COMPARISON)] comparisonvalue = self.getParameterValue(self.COMPARISONVALUE) selectindex = vector.resolveFieldIndex(processLayer, attribute) selectType = processLayer.fields()[selectindex].type() selectionError = False if selectType == 2: try: y = int(comparisonvalue) except ValueError: selectionError = True msg = self.tr('Cannot convert "%s" to integer' % unicode(comparisonvalue)) elif selectType == 6: try: y = float(comparisonvalue) except ValueError: selectionError = True msg = self.tr('Cannot convert "%s" to float' % unicode(comparisonvalue)) elif selectType == 10: # 10: string, boolean try: y = unicode(comparisonvalue) except ValueError: selectionError = True msg = self.tr('Cannot convert "%s" to unicode' % unicode(comparisonvalue)) elif selectType == 14: # date dateAndFormat = comparisonvalue.split(' ') if len(dateAndFormat) == 1: # QDate object y = QLocale.system().toDate(dateAndFormat[0]) if y.isNull(): msg = self.tr( 'Cannot convert "%s" to date with system date format %s' % (unicode(dateAndFormat), QLocale.system().dateFormat())) elif len(dateAndFormat) == 2: y = QDate.fromString(dateAndFormat[0], dateAndFormat[1]) if y.isNull(): msg = self.tr( 'Cannot convert "%s" to date with format string "%s"' % (unicode(dateAndFormat[0]), dateAndFormat[1])) else: y = QDate() msg = '' if y.isNull(): # Conversion was unsuccessfull selectionError = True msg += self.tr( 'Enter the date and the date format, e.g. "07.26.2011" "MM.dd.yyyy".' ) if (comparison == 'begins with' or comparison == 'contains') \ and selectType != 10: selectionError = True msg = self.tr('"%s" can only be used with string fields' % comparison) selected = [] if selectionError: raise GeoAlgorithmExecutionException( self.tr('Error in selection input: %s' % msg)) else: for feature in processLayer.getFeatures(): aValue = feature.attributes()[selectindex] if aValue is None: continue if selectType == 2: x = int(aValue) elif selectType == 6: x = float(aValue) elif selectType == 10: # 10: string, boolean x = unicode(aValue) elif selectType == 14: # date x = aValue # should be date match = False if comparison == '==': match = x == y elif comparison == '!=': match = x != y elif comparison == '>': match = x > y elif comparison == '>=': match = x >= y elif comparison == '<': match = x < y elif comparison == '<=': match = x <= y elif comparison == 'begins with': match = x.startswith(y) elif comparison == 'contains': match = x.find(y) >= 0 if match: selected.append(feature.id()) processLayer.selectByIds(selected) if processLayer.selectedFeatureCount() == 0: ProcessingLog.addToLog( ProcessingLog.LOG_WARNING, self.tr('%s: (No selection in input layer "%s")' % (self.commandLineName(), self.getParameterValue(self.INPUT)))) # Keep references to the features to eliminate featToEliminate = [] for aFeat in processLayer.selectedFeatures(): featToEliminate.append(aFeat) # Delete all features to eliminate in processLayer (we won't save this) processLayer.startEditing() processLayer.deleteSelectedFeatures() # ANALYZE if len(featToEliminate) > 0: # Prevent zero division start = 20.00 add = 80.00 / len(featToEliminate) else: start = 100 progress.setPercentage(start) madeProgress = True # We go through the list and see if we find any polygons we can # merge the selected with. If we have no success with some we # merge and then restart the whole story. while madeProgress: # Check if we made any progress madeProgress = False featNotEliminated = [] # Iterate over the polygons to eliminate for i in range(len(featToEliminate)): feat = featToEliminate.pop() geom2Eliminate = feat.geometry() bbox = geom2Eliminate.boundingBox() fit = processLayer.getFeatures( QgsFeatureRequest().setFilterRect(bbox)) mergeWithFid = None mergeWithGeom = None max = 0 min = -1 selFeat = QgsFeature() while fit.nextFeature(selFeat): selGeom = selFeat.geometry() if geom2Eliminate.intersects(selGeom): # We have a candidate iGeom = geom2Eliminate.intersection(selGeom) if not iGeom: continue if boundary: selValue = iGeom.length() else: # area. We need a common boundary in # order to merge if 0 < iGeom.length(): selValue = selGeom.area() else: selValue = -1 if -1 != selValue: useThis = True if smallestArea: if -1 == min: min = selValue else: if selValue < min: min = selValue else: useThis = False else: if selValue > max: max = selValue else: useThis = False if useThis: mergeWithFid = selFeat.id() mergeWithGeom = QgsGeometry(selGeom) # End while fit if mergeWithFid is not None: # A successful candidate newGeom = mergeWithGeom.combine(geom2Eliminate) if processLayer.changeGeometry(mergeWithFid, newGeom): madeProgress = True else: raise GeoAlgorithmExecutionException( self. tr('Could not replace geometry of feature with id %s' % mergeWithFid)) start = start + add progress.setPercentage(start) else: featNotEliminated.append(feat) # End for featToEliminate featToEliminate = featNotEliminated # End while # Create output output = self.getOutputFromName(self.OUTPUT) writer = output.getVectorWriter(processLayer.fields(), processLayer.wkbType(), processLayer.crs()) # Write all features that are left over to output layer iterator = processLayer.getFeatures() for feature in iterator: writer.addFeature(feature) # Leave processLayer untouched processLayer.rollBack() for feature in featNotEliminated: writer.addFeature(feature)
def sampling(self, outPath, tableName): # main process # open sampling points layer pointLayer = self.sampItems[str(self.inSample.currentText())][0] pointProvider = pointLayer.dataProvider() allAttrs = pointProvider.attributeIndexes() sRs = pointLayer.crs() # create destination layer: first create list of selected fields fieldList = QgsFields() for i in range(len(self.fields)): if self.fields[i][0] == "point": #copying fields from source layer field = pointProvider.fields()[pointProvider.fieldNameIndex( self.sampItems[self.fields[i][1]][self.fields[i][2]][0])] field.setName( self.sampItems[self.fields[i][1]][self.fields[i][2]][1]) elif self.fields[i][ 0] == "poly": #copying fields from polygon layers polyLayer = self.polyItems[self.fields[i][1]][0] polyProvider = polyLayer.dataProvider() field = polyProvider.fields()[polyProvider.fieldNameIndex( self.polyItems[self.fields[i][1]][self.fields[i][2]][0])] field.setName( self.polyItems[self.fields[i][1]][self.fields[i][2]][1]) else: #creating fields for raster layers field = QgsField( self.rastItems[self.fields[i][1]][self.fields[i][2]][1], QVariant.Double, "real", 20, 5, "") ##### Better data type fit will be implemented in next versions fieldList.append(field) # create temporary memory layer (as it's currently impossible to set GPKG table name when writting features to QgsVectorFileWriter directly) memLayer = QgsVectorLayer("Point?crs=epsg:%d" % sRs.postgisSrid(), 'temp layer', 'memory') memLayer.startEditing() for field in fieldList: memLayer.addAttribute(field) memLayer.commitChanges() self.statusLabel.setText("Writing data to the new layer...") self.repaint() # process point after point... pointFeat = QgsFeature() np = 0 snp = pointProvider.featureCount() for pointFeat in pointProvider.getFeatures(): np += 1 if snp < 100 or (snp < 5000 and (np // 10.0 == np / 10.0)) or ( np // 100.0 == np / 100.0): # display each or every 10th or every 100th point: self.statusLabel.setText("Processing point %s of %s" % (np, snp)) self.repaint() # convert multipoint[0] to point pointGeom = pointFeat.geometry() if pointGeom.wkbType() == QgsWkbTypes.MultiPoint: pointPoint = pointGeom.asMultiPoint()[0] else: pointPoint = pointGeom.asPoint() outFeat = QgsFeature() outFeat.setGeometry(pointGeom) # ...and next loop inside: field after field bBox = QgsRectangle( pointPoint.x() - 0.001, pointPoint.y() - 0.001, pointPoint.x() + 0.001, pointPoint.y() + 0.001) # reuseable rectangle buffer around the point feature previousPolyLayer = None # reuse previous feature if it's still the same layer previousPolyFeat = None # reuse previous feature if it's still the same layer previousRastLayer = None # reuse previous raster multichannel sample if it's still the same layer previousRastSample = None # reuse previous raster multichannel sample if it's still the same layer attrs = [] for i in range(len(self.fields)): field = self.fields[i] if field[0] == "point": attr = pointFeat.attributes()[pointProvider.fieldNameIndex( self.sampItems[field[1]][field[2]][0])] attrs += [attr] elif field[0] == "poly": polyLayer = self.polyItems[field[1]][0] polyProvider = polyLayer.dataProvider() if polyLayer == previousPolyLayer: polyFeat = previousPolyFeat else: polyFeat = None pointGeom = QgsGeometry().fromPointXY(pointPoint) for iFeat in polyProvider.getFeatures( QgsFeatureRequest().setFilterRect(bBox)): if pointGeom.intersects(iFeat.geometry()): polyFeat = iFeat if polyFeat: attr = polyFeat.attributes()[ polyProvider.fieldNameIndex( self.polyItems[field[1]][field[2]][0])] else: attr = None attrs += [ attr ] #only last one if more polygons overlaps!! This way we avoid attribute list overflow previousPolyLayer = polyLayer previousPolyFeat = polyFeat else: # field source is raster rastLayer = self.rastItems[field[1]][0] if rastLayer == previousRastLayer: rastSample = previousRastSample else: rastSample = rastLayer.dataProvider().identify( pointPoint, QgsRaster.IdentifyFormatValue).results() try: #bandName = self.rastItems[field[1]][field[2]][0] #depreciated bandNo = field[2] attr = float( rastSample[bandNo] ) ##### !! float() - I HAVE TO IMPLEMENT RASTER TYPE HANDLING!!!! except: # point is out of raster extent attr = None attrs += [attr] previousRastLayer = rastLayer previousRastSample = rastSample outFeat.initAttributes(len(attrs)) outFeat.setAttributes(attrs) memLayer.dataProvider().addFeature(outFeat) # write the memlayer to the output file so = QgsVectorFileWriter.SaveVectorOptions() so.fileEncoding = 'UTF-8' if outPath.upper().endswith('SHP'): so.driverName = "ESRI Shapefile" elif outPath.upper().endswith('CSV'): so.driverName = "CSV" else: so.driverName = "GPKG" if tableName: so.actionOnExistingFile = QgsVectorFileWriter.CreateOrOverwriteLayer so.layerName = tableName result, errMsg = QgsVectorFileWriter.writeAsVectorFormat( memLayer, outPath, so) if result: QMessageBox.critical(self, "Point sampling tool", errMsg) return False else: del memLayer self.statusLabel.setText("The new layer has been created.") return True
def testInsertPolygonInMultiPolygon(self): layer = QgsVectorLayer("MultiPolygon?crs=epsg:4326&field=id:integer", "addfeat", "memory") pr = layer.dataProvider() f = QgsFeature() f.setAttributes([1]) f.setGeometry(QgsGeometry.fromWkt('MultiPolygon(((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))')) pr.addFeatures([f]) uri = '{} table="qgis_test"."new_table_multipolygon" sql='.format(self.dbconn) error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326')) self.assertEqual(error, QgsVectorLayerExporter.NoError) new_layer = QgsVectorLayer(uri, 'new', 'mssql') self.assertTrue(new_layer.isValid()) self.assertEqual(new_layer.wkbType(), QgsWkbTypes.MultiPolygon) geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))']) # add single part f2 = QgsFeature() f2.setAttributes([2]) f2.setGeometry(QgsGeometry.fromWkt('Polygon((30 0, 31 0, 31 1, 30 1, 30 0))')) self.assertTrue(new_layer.dataProvider().addFeatures([f2])) # should become multipart geom = [f.geometry().asWkt() for f in new_layer.getFeatures()] self.assertEqual(geom, ['MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))', 'MultiPolygon (((30 0, 31 0, 31 1, 30 1, 30 0)))'])