Example #1
1
    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))'])
Example #2
0
  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
Example #3
0
 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, [])
Example #4
0
 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)
Example #6
0
    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])
Example #7
0
 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. 
Example #9
0
    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
Example #10
0
 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
Example #11
0
    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
Example #12
0
    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
Example #13
0
File: Buffer.py Project: Ariki/QGIS
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))')
Example #15
0
 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)
Example #16
0
    @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 
Example #17
0
    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)')
Example #18
0
 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)
Example #19
0
    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
Example #20
0
    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
Example #21
0
 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
Example #22
0
        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)
Example #23
0
 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
Example #24
0
 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
Example #25
0
 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
Example #26
0
  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
Example #27
0
 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
Example #28
0
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
Example #29
0
    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)'])
Example #30
0
    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
Example #31
0
    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')
Example #32
0
    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
Example #33
0
    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
Example #34
0
    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
Example #35
0
        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)'
            })
Example #36
0
    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}
Example #37
0
    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
Example #39
0
    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}
Example #40
0
    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()
Example #41
0
    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
Example #42
0
    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])
Example #43
0
    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
Example #44
0
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
Example #45
0
    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))
Example #46
0
    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
Example #47
0
    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}
Example #48
0
    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'))
Example #49
0
    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')
Example #50
0
    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)
Example #51
0
    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
Example #52
0
    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
Example #53
0
    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}
Example #54
0
    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
Example #55
0
    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}
Example #56
0
    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])
Example #57
0
    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())))
Example #58
0
    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)
Example #59
0
    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
Example #60
-1
    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)))'])