Ejemplo n.º 1
1
def save2PointShape(shapePath, geodata, attribName,
                    attribData, label, spatialRef):
    """
    :param label:
    :param shapePath: Pfad wo Shapefile agespeichert wird
    :param geodata: Koordinaten der Punkte
    :param attribName: Attributname (Feldname) von zusätzlichen Werten
    :param attribData: Werte für Attribute
    :param spatialRef: Räumliche Referenz
    """

    # define fields for feature attributes. A QgsFields object is needed
    fields = QgsFields()
    fields.append(QgsField("StuetzenNr", QVariant.String))
    fields.append(QgsField(attribName, QVariant.Int))
    writer = QgsVectorFileWriter(shapePath, "UTF8", fields, QgsWkbTypes.PointZ,
                                 spatialRef, "ESRI Shapefile")

    if writer.hasError() != QgsVectorFileWriter.NoError:
        # TODO
        raise Exception("Vector Writer")

    for idx, (coords, attrib) in enumerate(zip(geodata, attribData)):
        feature = QgsFeature()
        feature.setFields(fields)
        # TODO: Nicht 3D weil Methode fromPoint() nicht existiert. Wird evtl. in der Zukunft implementiert
        feature.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(coords[0], coords[1])))
        feature.setId(idx)
        feature.setAttribute("StuetzenNr", label[idx])
        feature.setAttribute(attribName, attrib)
        writer.addFeature(feature)
        del feature

    # delete the writer to flush features to disk
    del writer
Ejemplo n.º 2
1
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)

        extent = self.parameterAsExtent(parameters, self.TARGET_AREA, context)
        target_crs = self.parameterAsCrs(parameters, self.TARGET_AREA_CRS, context)

        target_geom = QgsGeometry.fromRect(extent)

        fields = QgsFields()
        fields.append(QgsField('auth_id', QVariant.String, '', 20))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())

        # make intersection tests nice and fast
        engine = QgsGeometry.createGeometryEngine(target_geom.constGet())
        engine.prepareGeometry()

        layer_bounds = QgsGeometry.fromRect(source.sourceExtent())

        crses_to_check = QgsCoordinateReferenceSystem.validSrsIds()
        total = 100.0 / len(crses_to_check)

        found_results = 0

        transform_context = QgsCoordinateTransformContext()
        for current, srs_id in enumerate(crses_to_check):
            if feedback.isCanceled():
                break

            candidate_crs = QgsCoordinateReferenceSystem.fromSrsId(srs_id)
            if not candidate_crs.isValid():
                continue

            transform_candidate = QgsCoordinateTransform(candidate_crs, target_crs, transform_context)
            transformed_bounds = QgsGeometry(layer_bounds)
            try:
                if not transformed_bounds.transform(transform_candidate) == 0:
                    continue
            except:
                continue

            try:
                if engine.intersects(transformed_bounds.constGet()):
                    feedback.pushInfo(self.tr('Found candidate CRS: {}').format(candidate_crs.authid()))
                    f = QgsFeature(fields)
                    f.setAttributes([candidate_crs.authid()])
                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    found_results += 1
            except:
                continue

            feedback.setProgress(int(current * total))

        if found_results == 0:
            feedback.reportError(self.tr('No matching projections found'))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 3
0
    def test1(self):
        d = QgsVirtualLayerDefinition()
        self.assertEqual(d.toString(), "")
        d.setFilePath("/file")
        self.assertEqual(d.toString(), "file:///file")
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).filePath(), "/file")
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).filePath(), "/file")
        d.setFilePath(os.path.join("C:/", "file"))
        self.assertEqual(d.toString(), "file:///C:/file")
        # self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).filePath(), os.path.join('C:/', 'file'))
        d.setQuery("SELECT * FROM mytable")
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).query(), "SELECT * FROM mytable")
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).query(), "SELECT * FROM mytable")

        q = "SELECT * FROM tableéé /*:int*/"
        d.setQuery(q)
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).query(), q)
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).query(), q)

        s1 = "file://foo&bar=okié"
        d.addSource("name", s1, "provider", "utf8")
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).sourceLayers()[0].source(), s1)
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).sourceLayers()[0].source(), s1)

        n1 = "éé ok"
        d.addSource(n1, s1, "provider")
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).sourceLayers()[1].name(), n1)
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).sourceLayers()[1].name(), n1)

        d.addSource("ref1", "id0001")
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).sourceLayers()[2].reference(), "id0001")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).sourceLayers()[2].reference(), "id0001"
        )

        s = "dbname='C:\\tt' table=\"test\" (geometry) sql="
        d.addSource("nn", s, "spatialite")
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).sourceLayers()[3].source(), s)
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).sourceLayers()[3].source(), s)

        d.setGeometryField("geom")
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).geometryField(), "geom")
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).geometryField(), "geom")

        d.setGeometryWkbType(QgsWkbTypes.Point)
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).geometryWkbType(), QgsWkbTypes.Point)
        self.assertEqual(QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).geometryWkbType(), QgsWkbTypes.Point)

        f = QgsFields()
        f.append(QgsField("a", QVariant.Int))
        f.append(QgsField("f", QVariant.Double))
        f.append(QgsField("s", QVariant.String))
        d.setFields(f)
        f2 = QgsVirtualLayerDefinition.fromUrl(d.toUrl()).fields()
        self.assertEqual(f[0].name(), f2[0].name())
        self.assertEqual(f[0].type(), f2[0].type())
        self.assertEqual(f[1].name(), f2[1].name())
        self.assertEqual(f[1].type(), f2[1].type())
        self.assertEqual(f[2].name(), f2[2].name())
        self.assertEqual(f[2].type(), f2[2].type())
Ejemplo n.º 4
0
 def _loadLogLayer(self):
     fullLayerPath = os.path.join(self._projectPath, self._settings.logPath)
     filePath = QFileInfo(fullLayerPath)
     layer = None
     if filePath.exists():
         layer = layers.loadShapefileLayer(fullLayerPath, self._settings.logName)
     else:
         if not filePath.dir().exists():
             os.makedirs(filePath.dir().absolutePath())
         fields = QgsFields()
         fields.append(QgsField('timestamp', QVariant.String, '', 10, 0, 'timestamp'))
         fields.append(QgsField('event', QVariant.String, '', 6, 0, 'event'))
         fields.extend(self.fields)
         layer = layers.createShapefile(fullLayerPath,
                                        self._settings.logName,
                                        self.layer.wkbType(),
                                        self._settings.crs,
                                        fields)
     if layer and layer.isValid():
         layer.editFormConfig().setSuppress(QgsEditFormConfig.SuppressOn)
         self.logLayer = layer
         self.logLayerId = layer.id()
     else:
         self.logLayer = None
         self.logLayerId = ''
Ejemplo n.º 5
0
    def testProxyFeatureSink(self):
        fields = QgsFields()
        fields.append(QgsField('fldtxt', QVariant.String))
        fields.append(QgsField('fldint', QVariant.Int))

        store = QgsFeatureStore(fields, QgsCoordinateReferenceSystem())
        proxy = QgsProxyFeatureSink(store)
        self.assertEqual(proxy.destinationSink(), store)

        self.assertEqual(len(store), 0)

        f = QgsFeature()
        f.setAttributes(["test", 123])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(100, 200)))
        proxy.addFeature(f)
        self.assertEqual(len(store), 1)
        self.assertEqual(store.features()[0]['fldtxt'], 'test')

        f2 = QgsFeature()
        f2.setAttributes(["test2", 457])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(200, 200)))
        f3 = QgsFeature()
        f3.setAttributes(["test3", 888])
        f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(300, 200)))
        proxy.addFeatures([f2, f3])
        self.assertEqual(len(store), 3)
        self.assertEqual(store.features()[1]['fldtxt'], 'test2')
        self.assertEqual(store.features()[2]['fldtxt'], 'test3')
Ejemplo n.º 6
0
def to_shp(path, any_features_list, layer_fields, crs, name, encoding, geom_type):
    if path is None:
        if geom_type == 0:
            network = QgsVectorLayer('Point?crs=' + crs.toWkt(), name, "memory")
        else:
            network = QgsVectorLayer('LineString?crs=' + crs.toWkt(), name, "memory")
    else:
        fields = QgsFields()
        for field in layer_fields:
            fields.append(field)
        file_writer = QgsVectorFileWriter(path, encoding, fields, geom_type, crs, "ESRI Shapefile")
        if file_writer.hasError() != QgsVectorFileWriter.NoError:
            print "Error when creating shapefile: ", file_writer.errorMessage()
        del file_writer
        network = QgsVectorLayer(path, name, "ogr")
    pr = network.dataProvider()
    if path is None:
        pr.addAttributes(layer_fields)
    new_features = []
    for i in any_features_list:
        new_feat = QgsFeature()
        new_feat.setFeatureId(i[0])
        new_feat.setAttributes([attr[0] for attr in i[1]])
        new_feat.setGeometry(QgsGeometry(QgsGeometry.fromWkt(str(i[2]))))
        #QgsGeometry()
        new_features.append(new_feat)
    network.startEditing()
    pr.addFeatures(new_features)
    network.commitChanges()
    return network
Ejemplo n.º 7
0
def create_points_at(startpoint, endpoint, distance, geom, fid, force, divide):
    """Creating Points at coordinates along the line
    """
    length = geom.length()  
  
    def distance_fn():
        if divide > 0:
            return length / divide
        else:
            import random
            return distance * random.uniform(0.5,2.5)
    
    feats = []

    if endpoint > 0:
        length = endpoint

    # set the first point at startpoint
    point = geom.interpolate(startpoint)

    field_id = QgsField(name="id", type=QVariant.Int)
    field = QgsField(name="dist", type=QVariant.Double)
    fields = QgsFields()

    fields.append(field_id)
    fields.append(field)

    feature = QgsFeature(fields)
    feature['dist'] = startpoint
    feature['id'] = fid

    feature.setGeometry(point)
    feats.append(feature)

    current_distance = 0

    while startpoint + current_distance <= length:
        step = distance_fn()
        # Get a point along the line at the current distance
        point = geom.interpolate(startpoint + current_distance)
        # Create a new QgsFeature and assign it the new geometry
        feature = QgsFeature(fields)
        feature['dist'] = (startpoint + step)
        feature['id'] = fid
        feature.setGeometry(point)
        feats.append(feature)
        # Increase the distance
        current_distance = current_distance + step

    # set the last point at endpoint if wanted
    if force is True:
        end = geom.length()
        point = geom.interpolate(end)
        feature = QgsFeature(fields)
        feature['dist'] = end
        feature['id'] = fid
        feature.setGeometry(point)
        feats.append(feature)

    return feats
Ejemplo n.º 8
0
    def processAlgorithm(self, feedback):
        extent = str(self.getParameterValue(self.EXTENT)).split(',')

        spacing = float(self.getParameterValue(self.SPACING))
        inset = float(self.getParameterValue(self.INSET))
        randomize = self.getParameterValue(self.RANDOMIZE)
        isSpacing = self.getParameterValue(self.IS_SPACING)
        crsId = self.getParameterValue(self.CRS)
        crs = QgsCoordinateReferenceSystem()
        crs.createFromUserInput(crsId)

        extent = QgsRectangle(float(extent[0]), float(extent[2]),
                              float(extent[1]), float(extent[3]))

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.Point, crs)

        if randomize:
            seed()

        area = extent.width() * extent.height()
        if isSpacing:
            pSpacing = spacing
        else:
            pSpacing = sqrt(area / spacing)

        f = QgsFeature()
        f.initAttributes(1)
        f.setFields(fields)

        count = 0
        total = 100.0 / (area / pSpacing)
        y = extent.yMaximum() - inset

        extent_geom = QgsGeometry.fromRect(extent)
        extent_engine = QgsGeometry.createGeometryEngine(extent_geom.geometry())
        extent_engine.prepareGeometry()

        while y >= extent.yMinimum():
            x = extent.xMinimum() + inset
            while x <= extent.xMaximum():
                if randomize:
                    geom = QgsGeometry().fromPoint(QgsPoint(
                        uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)),
                        uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0))))
                else:
                    geom = QgsGeometry().fromPoint(QgsPoint(x, y))

                if extent_engine.intersects(geom.geometry()):
                    f.setAttribute('id', count)
                    f.setGeometry(geom)
                    writer.addFeature(f)
                    x += pSpacing
                    count += 1
                    feedback.setProgress(int(count * total))
            y = y - pSpacing
        del writer
Ejemplo n.º 9
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context)
        minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context)

        bbox = source.sourceExtent()
        sourceIndex = QgsSpatialIndex(source, feedback)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.Point, source.sourceCrs())

        nPoints = 0
        nIterations = 0
        maxIterations = pointCount * 200
        total = 100.0 / pointCount if pointCount else 1

        index = QgsSpatialIndex()
        points = dict()

        random.seed()

        while nIterations < maxIterations and nPoints < pointCount:
            if feedback.isCanceled():
                break

            rx = bbox.xMinimum() + bbox.width() * random.random()
            ry = bbox.yMinimum() + bbox.height() * random.random()

            p = QgsPointXY(rx, ry)
            geom = QgsGeometry.fromPointXY(p)
            ids = sourceIndex.intersects(geom.buffer(5, 5).boundingBox())
            if len(ids) > 0 and \
                    vector.checkMinDistance(p, index, minDistance, points):
                request = QgsFeatureRequest().setFilterFids(ids).setSubsetOfAttributes([])
                for f in source.getFeatures(request):
                    if feedback.isCanceled():
                        break

                    tmpGeom = f.geometry()
                    if geom.within(tmpGeom):
                        f = QgsFeature(nPoints)
                        f.initAttributes(1)
                        f.setFields(fields)
                        f.setAttribute('id', nPoints)
                        f.setGeometry(geom)
                        sink.addFeature(f, QgsFeatureSink.FastInsert)
                        index.insertFeature(f)
                        points[nPoints] = p
                        nPoints += 1
                        feedback.setProgress(int(nPoints * total))
            nIterations += 1

        if nPoints < pointCount:
            feedback.pushInfo(self.tr('Could not generate requested number of random points. '
                                      'Maximum number of attempts exceeded.'))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 10
0
    def processAlgorithm(self, parameters, context, feedback):
        idx = self.parameterAsEnum(parameters, self.TYPE, context)

        hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context)
        vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context)
        hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context)
        vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context)

        crs = self.parameterAsCrs(parameters, self.CRS, context)
        bbox = self.parameterAsExtent(parameters, self.EXTENT, context, crs)

        if hSpacing <= 0 or vSpacing <= 0:
            raise QgsProcessingException(
                self.tr('Invalid grid spacing: {0}/{1}').format(hSpacing, vSpacing))

        if bbox.width() < hSpacing:
            raise QgsProcessingException(
                self.tr('Horizontal spacing is too large for the covered area'))

        if hSpacing <= hOverlay or vSpacing <= vOverlay:
            raise QgsProcessingException(
                self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))

        if bbox.height() < vSpacing:
            raise QgsProcessingException(
                self.tr('Vertical spacing is too large for the covered area'))

        fields = QgsFields()
        fields.append(QgsField('left', QVariant.Double, '', 24, 16))
        fields.append(QgsField('top', QVariant.Double, '', 24, 16))
        fields.append(QgsField('right', QVariant.Double, '', 24, 16))
        fields.append(QgsField('bottom', QVariant.Double, '', 24, 16))
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        if idx == 0:
            outputWkb = QgsWkbTypes.Point
        elif idx == 1:
            outputWkb = QgsWkbTypes.LineString
        else:
            outputWkb = QgsWkbTypes.Polygon
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, outputWkb, crs)

        if idx == 0:
            self._pointGrid(
                sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
        elif idx == 1:
            self._lineGrid(
                sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
        elif idx == 2:
            self._rectangleGrid(
                sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
        elif idx == 3:
            self._diamondGrid(
                sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback)
        elif idx == 4:
            self._hexagonGrid(
                sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay, feedback)

        return {self.OUTPUT: dest_id}
Ejemplo n.º 11
0
 def testExportLayerToExistingDatabase(self):
     fields = QgsFields()
     fields.append(QgsField('f1', QVariant.Int))
     tmpfile = os.path.join(self.basetestpath, 'testCreateNewGeopackage.gpkg')
     options = {}
     options['update'] = True
     options['driverName'] = 'GPKG'
     options['layerName'] = 'table1'
     exporter = QgsVectorLayerExporter(tmpfile, "ogr", fields, QgsWkbTypes.Polygon, QgsCoordinateReferenceSystem(3111), False, options)
     self.assertFalse(exporter.errorCode(),
                      'unexpected export error {}: {}'.format(exporter.errorCode(), exporter.errorMessage()))
     options['layerName'] = 'table2'
     exporter = QgsVectorLayerExporter(tmpfile, "ogr", fields, QgsWkbTypes.Point, QgsCoordinateReferenceSystem(3113), False, options)
     self.assertFalse(exporter.errorCode(),
                      'unexpected export error {} : {}'.format(exporter.errorCode(), exporter.errorMessage()))
     del exporter
     # make sure layers exist
     lyr = QgsVectorLayer('{}|layername=table1'.format(tmpfile), "lyr1", "ogr")
     self.assertTrue(lyr.isValid())
     self.assertEqual(lyr.crs().authid(), 'EPSG:3111')
     self.assertEqual(lyr.wkbType(), QgsWkbTypes.Polygon)
     lyr2 = QgsVectorLayer('{}|layername=table2'.format(tmpfile), "lyr2", "ogr")
     self.assertTrue(lyr2.isValid())
     self.assertEqual(lyr2.crs().authid(), 'EPSG:3113')
     self.assertEqual(lyr2.wkbType(), QgsWkbTypes.Point)
Ejemplo n.º 12
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        field_name = self.parameterAsString(parameters, self.FIELD_NAME, context)
        values = source.uniqueValues(source.fields().lookupField(field_name))

        fields = QgsFields()
        field = source.fields()[source.fields().lookupField(field_name)]
        field.setName('VALUES')
        fields.append(field)
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())
        results = {}
        if sink:
            for value in values:
                if feedback.isCanceled():
                    break

                f = QgsFeature()
                f.setAttributes([value])
                sink.addFeature(f, QgsFeatureSink.FastInsert)
            results[self.OUTPUT] = dest_id

        output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context)
        if output_file:
            self.createHTML(output_file, values)
            results[self.OUTPUT_HTML_FILE] = output_file

        results[self.TOTAL_VALUES] = len(values)
        results[self.UNIQUE_VALUES] = ';'.join([str(v) for v in
                                                values])
        return results
Ejemplo n.º 13
0
    def processAlgorithm(self, parameters, context, feedback):
        spacing = self.parameterAsDouble(parameters, self.SPACING, context)
        inset = self.parameterAsDouble(parameters, self.INSET, context)
        randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context)
        isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context)
        crs = self.parameterAsCrs(parameters, self.CRS, context)
        extent = self.parameterAsExtent(parameters, self.EXTENT, context, crs)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.Point, crs)
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        if randomize:
            seed()

        area = extent.width() * extent.height()
        if isSpacing:
            pSpacing = spacing
        else:
            pSpacing = sqrt(area / spacing)

        f = QgsFeature()
        f.initAttributes(1)
        f.setFields(fields)

        count = 0
        total = 100.0 / (area / pSpacing)
        y = extent.yMaximum() - inset

        extent_geom = QgsGeometry.fromRect(extent)
        extent_engine = QgsGeometry.createGeometryEngine(extent_geom.constGet())
        extent_engine.prepareGeometry()

        while y >= extent.yMinimum():
            x = extent.xMinimum() + inset
            while x <= extent.xMaximum():
                if feedback.isCanceled():
                    break

                if randomize:
                    geom = QgsGeometry().fromPointXY(QgsPointXY(
                        uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)),
                        uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0))))
                else:
                    geom = QgsGeometry().fromPointXY(QgsPointXY(x, y))

                if extent_engine.intersects(geom.constGet()):
                    f.setAttribute('id', count)
                    f.setGeometry(geom)
                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    x += pSpacing
                    count += 1
                    feedback.setProgress(int(count * total))
            y = y - pSpacing

        return {self.OUTPUT: dest_id}
Ejemplo n.º 14
0
    def populate_catalogue_layer(self, catalogue):
        """
        Populate the catalogue vector layer with data got from `catalogue`

        :param catalogue:
            a :class:`hmtk.seismicity.catalogue.Catalogue` instance
        """
        vl = self.catalogue_layer
        pr = vl.dataProvider()
        vl.startEditing()

        # Set field types (the schema of the vector layer)
        fields = []
        mock_attributes = ["_magnitude"]

        for key in catalogue.data.keys() + mock_attributes:
            if key in mock_attributes:
                key_norm = key[1:]
            else:
                key_norm = key
            if isinstance(key_norm, numpy.ndarray):
                fields.append(QgsField(key, QVariant.Double))
            else:
                fields.append(QgsField(key, QVariant.String))

        pr.addAttributes(fields)

        qgs_fields = QgsFields()
        for f in fields:
            qgs_fields.append(f)

        # Create the features
        features = []
        for i in range(catalogue.get_number_events()):
            fet = QgsFeature()
            fet.setFields(qgs_fields)

            x = catalogue.data['longitude'][i]
            y = catalogue.data['latitude'][i]
            fet.setGeometry(QgsGeometry.fromPoint(QgsPoint(x, y)))

            for key in catalogue.data:
                event_data = catalogue.data[key]
                if len(event_data):
                    if isinstance(catalogue.data[key], numpy.ndarray):
                        fet[key] = float(event_data[i])
                    else:
                        fet[key] = str(event_data[i])
            fet['_magnitude'] = fet['magnitude'] ** 2
            features.append(fet)
        pr.addFeatures(features)
        vl.commitChanges()

        self.event_feature_ids = dict([
            (f['eventID'], f.id()) for f in vl.getFeatures()])

        # Set the canvas extent to avoid projection problems and to
        # pan to the loaded events
        vl.updateExtents()
    def testLegendKeysWhileCounting(self):
        # test determining legend keys for features, while counting features
        fields = QgsFields()
        fields.append(QgsField('x'))

        # setup renderer
        renderer = QgsCategorizedSymbolRenderer()
        renderer.setClassAttribute('x')

        symbol_a = createMarkerSymbol()
        symbol_a.setColor(QColor(255, 0, 0))
        renderer.addCategory(QgsRendererCategory('a', symbol_a, 'a'))
        symbol_b = createMarkerSymbol()
        symbol_b.setColor(QColor(0, 255, 0))
        renderer.addCategory(QgsRendererCategory('b', symbol_b, 'b'))
        symbol_c = createMarkerSymbol()
        symbol_c.setColor(QColor(0, 0, 255))
        renderer.addCategory(QgsRendererCategory('c', symbol_c, 'c', False))
        symbol_d = createMarkerSymbol()
        symbol_d.setColor(QColor(255, 0, 255))
        renderer.addCategory(QgsRendererCategory(['d', 'e'], symbol_d, 'de'))
        # add default category
        default_symbol = createMarkerSymbol()
        default_symbol.setColor(QColor(255, 255, 255))
        renderer.addCategory(QgsRendererCategory('', default_symbol, 'default'))

        context = QgsRenderContext()
        context.setRendererScale(0) # simulate counting
        renderer.startRender(context, fields)

        f = QgsFeature(fields)
        f.setAttributes(['a'])

        keys = renderer.legendKeysForFeature(f, context)
        self.assertEqual(keys, {'0'})

        f.setAttributes(['b'])
        keys = renderer.legendKeysForFeature(f, context)
        self.assertEqual(keys, {'1'})

        # hidden category, should still return keys
        f.setAttributes(['c'])
        keys = renderer.legendKeysForFeature(f, context)
        self.assertEqual(keys, {'2'})

        # list
        f.setAttributes(['d'])
        keys = renderer.legendKeysForFeature(f, context)
        self.assertEqual(keys, {'3'})
        f.setAttributes(['e'])
        keys = renderer.legendKeysForFeature(f, context)
        self.assertEqual(keys, {'3'})

        # no matching category
        f.setAttributes(['xxx'])
        keys = renderer.legendKeysForFeature(f, context)
        self.assertFalse(keys)

        renderer.stopRender(context)
Ejemplo n.º 16
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))

        field_names = self.parameterAsFields(parameters, self.FIELDS, context)

        fields = QgsFields()
        field_indices = []
        for field_name in field_names:
            field_index = source.fields().lookupField(field_name)
            if field_index < 0:
                feedback.reportError(self.tr('Invalid field name {}').format(field_name))
                continue
            field = source.fields()[field_index]
            fields.append(field)
            field_indices.append(field_index)
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())

        results = {}
        values = set()
        if len(field_indices) == 1:
            # one field, can use provider optimised method
            values = tuple([v] for v in source.uniqueValues(field_indices[0]))
        else:
            # have to scan whole table
            # TODO - add this support to QgsVectorDataProvider so we can run it on
            # the backend
            request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
            request.setSubsetOfAttributes(field_indices)
            total = 100.0 / source.featureCount() if source.featureCount() else 0
            for current, f in enumerate(source.getFeatures(request, QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)):
                if feedback.isCanceled():
                    break

                value = tuple(f.attribute(i) for i in field_indices)
                values.add(value)
                feedback.setProgress(int(current * total))

        if sink:
            for value in values:
                if feedback.isCanceled():
                    break

                f = QgsFeature()
                f.setAttributes([attr for attr in value])
                sink.addFeature(f, QgsFeatureSink.FastInsert)
            results[self.OUTPUT] = dest_id

        output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context)
        if output_file:
            self.createHTML(output_file, values)
            results[self.OUTPUT_HTML_FILE] = output_file

        results[self.TOTAL_VALUES] = len(values)
        results[self.UNIQUE_VALUES] = ';'.join([','.join([str(attr) for attr in v]) for v in
                                                values])
        return results
Ejemplo n.º 17
0
 def test_MatchesTrueForFields(self):
     feature = QgsFeature()
     fields = QgsFields()
     fields.append(QgsField("testfield", QVariant.Int))
     feature.setFields(fields, True)
     feature["testfield"] = 20
     style = QgsConditionalStyle('"testfield" = @value')
     assert style.matches(20, feature)
Ejemplo n.º 18
0
 def new_context(self):
     feature = QgsFeature()
     fields = QgsFields()
     fields.append(QgsField("testfield", QVariant.Int))
     feature.setFields(fields, True)
     feature["testfield"] = 20
     context = QgsExpressionContextUtils.createFeatureBasedContext(feature, fields)
     return context
    def testOriginalSymbolForFeature(self):
        # test renderer with features
        fields = QgsFields()
        fields.append(QgsField('x'))

        # setup renderer
        renderer = QgsCategorizedSymbolRenderer()
        renderer.setClassAttribute('x')

        symbol_a = createMarkerSymbol()
        symbol_a.setColor(QColor(255, 0, 0))
        renderer.addCategory(QgsRendererCategory('a', symbol_a, 'a'))
        symbol_b = createMarkerSymbol()
        symbol_b.setColor(QColor(0, 255, 0))
        renderer.addCategory(QgsRendererCategory('b', symbol_b, 'b'))
        symbol_c = createMarkerSymbol()
        symbol_c.setColor(QColor(0, 0, 255))
        renderer.addCategory(QgsRendererCategory('c', symbol_c, 'c', False))
        symbol_d = createMarkerSymbol()
        symbol_d.setColor(QColor(255, 0, 255))
        renderer.addCategory(QgsRendererCategory(['d', 'e'], symbol_d, 'de'))
        # add default category
        default_symbol = createMarkerSymbol()
        default_symbol.setColor(QColor(255, 255, 255))
        renderer.addCategory(QgsRendererCategory('', default_symbol, 'default'))

        context = QgsRenderContext()
        renderer.startRender(context, fields)

        f = QgsFeature(fields)
        f.setAttributes(['a'])

        symbol = renderer.originalSymbolForFeature(f, context)
        self.assertEqual(symbol.color(), QColor(255, 0, 0))

        f.setAttributes(['b'])
        symbol = renderer.originalSymbolForFeature(f, context)
        self.assertEqual(symbol.color(), QColor(0, 255, 0))

        # list
        f.setAttributes(['d'])
        symbol = renderer.originalSymbolForFeature(f, context)
        self.assertEqual(symbol.color(), QColor(255, 0, 255))
        f.setAttributes(['e'])
        symbol = renderer.originalSymbolForFeature(f, context)
        self.assertEqual(symbol.color(), QColor(255, 0, 255))

        # hidden category
        f.setAttributes(['c'])
        symbol = renderer.originalSymbolForFeature(f, context)
        self.assertIsNone(symbol)

        # no matching category
        f.setAttributes(['xxx'])
        symbol = renderer.originalSymbolForFeature(f, context)
        self.assertEqual(symbol.color(), QColor(255, 255, 255)) # default symbol

        renderer.stopRender(context)
Ejemplo n.º 20
0
    def processAlgorithm(self, feedback):
        pointCount = int(self.getParameterValue(self.POINT_NUMBER))
        minDistance = float(self.getParameterValue(self.MIN_DISTANCE))
        extent = str(self.getParameterValue(self.EXTENT)).split(',')

        crsId = self.getParameterValue(self.CRS)
        crs = QgsCoordinateReferenceSystem()
        crs.createFromUserInput(crsId)

        xMin = float(extent[0])
        xMax = float(extent[1])
        yMin = float(extent[2])
        yMax = float(extent[3])
        extent = QgsGeometry().fromRect(
            QgsRectangle(xMin, yMin, xMax, yMax))

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.Point, crs)

        nPoints = 0
        nIterations = 0
        maxIterations = pointCount * 200
        total = 100.0 / pointCount

        index = QgsSpatialIndex()
        points = dict()

        random.seed()

        while nIterations < maxIterations and nPoints < pointCount:
            rx = xMin + (xMax - xMin) * random.random()
            ry = yMin + (yMax - yMin) * random.random()

            pnt = QgsPoint(rx, ry)
            geom = QgsGeometry.fromPoint(pnt)
            if geom.within(extent) and \
                    vector.checkMinDistance(pnt, index, minDistance, points):
                f = QgsFeature(nPoints)
                f.initAttributes(1)
                f.setFields(fields)
                f.setAttribute('id', nPoints)
                f.setGeometry(geom)
                writer.addFeature(f)
                index.insertFeature(f)
                points[nPoints] = pnt
                nPoints += 1
                feedback.setProgress(int(nPoints * total))
            nIterations += 1

        if nPoints < pointCount:
            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                   self.tr('Can not generate requested number of random points. '
                                           'Maximum number of attempts exceeded.'))

        del writer
Ejemplo n.º 21
0
 def randomize(self, inLayer, outPath, minimum, design, value):
     outFeat = QgsFeature()
     outFeat.initAttributes(1)
     if design == self.tr("unstratified"):
         ext = inLayer.extent()
         if inLayer.type() == QgsMapLayer.RasterLayer:
             points = self.simpleRandom(
                 int(value), ext, ext.xMinimum(),
                 ext.xMaximum(), ext.yMinimum(), ext.yMaximum())
         else:
             points = self.vectorRandom(
                 int(value), inLayer,
                 ext.xMinimum(), ext.xMaximum(), ext.yMinimum(), ext.yMaximum())
     else:
         points, featErrors = self.loopThruPolygons(inLayer, value, design)
         if featErrors:
             if len(featErrors) >= 10:
                 err_msg = "Too many features couldn't be calculated due to conversion error. "
                 err_msg += "Please check out message log for more info."
                 msgLogInstance = QgsMessageLog.instance()
                 msgLogInstance.logMessage("WARNING - fTools: " + self.tr("Random Points"))
                 msgLogInstance.logMessage("The following feature ids should be checked.")
                 for feat in featErrors:
                     msgLogInstance.logMessage("Feature id: %d" % feat.id())
                 msgLogInstance.logMessage("End of features to be checked.")
             else:
                 features_ids = []
                 for feat in featErrors:
                     features_ids.append(unicode(feat.id()))
                 erroneous_ids = ', '.join(features_ids)
                 err_msg = "The following features IDs couldn't be calculated due to conversion error: %s" % erroneous_ids
             self.iface.messageBar().pushMessage("Errors", err_msg)
     if len(points):
         crs = self.iface.mapCanvas().mapRenderer().destinationCrs()
         if not crs.isValid():
             crs = None
         fields = QgsFields()
         fields.append(QgsField("ID", QVariant.Int))
         outFeat.setFields(fields)
         check = QFile(self.shapefileName)
         if check.exists():
             if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName):
                 return
         writer = QgsVectorFileWriter(self.shapefileName, self.encoding, fields, QGis.WKBPoint, crs)
         idVar = 0
         count = 70.00
         add = (100.00 - 70.00) / len(points)
         for i in points:
             outFeat.setGeometry(i)
             outFeat.setAttribute(0, idVar)
             writer.addFeature(outFeat)
             idVar = idVar + 1
             count = count + add
             self.progressBar.setValue(count)
         del writer
         return True
     return False
Ejemplo n.º 22
0
 def test_MatchesTrueForFields(self):
     feature = QgsFeature()
     fields = QgsFields()
     fields.append(QgsField("testfield", QVariant.Int))
     feature.setFields(fields, True)
     feature["testfield"] = 20
     style = QgsConditionalStyle('"testfield" = @value')
     context = QgsExpressionContextUtils.createFeatureBasedContext(feature, fields)
     assert style.matches(20, context)
Ejemplo n.º 23
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.VECTOR))
        pointCount = int(self.getParameterValue(self.POINT_NUMBER))
        minDistance = float(self.getParameterValue(self.MIN_DISTANCE))

        bbox = layer.extent()
        idxLayer = vector.spatialindex(layer)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.Point, layer.crs())

        nPoints = 0
        nIterations = 0
        maxIterations = pointCount * 200
        total = 100.0 / pointCount

        index = QgsSpatialIndex()
        points = dict()

        request = QgsFeatureRequest()

        random.seed()

        while nIterations < maxIterations and nPoints < pointCount:
            rx = bbox.xMinimum() + bbox.width() * random.random()
            ry = bbox.yMinimum() + bbox.height() * random.random()

            pnt = QgsPoint(rx, ry)
            geom = QgsGeometry.fromPoint(pnt)
            ids = idxLayer.intersects(geom.buffer(5, 5).boundingBox())
            if len(ids) > 0 and \
                    vector.checkMinDistance(pnt, index, minDistance, points):
                for i in ids:
                    f = next(layer.getFeatures(request.setFilterFid(i)))
                    tmpGeom = f.geometry()
                    if geom.within(tmpGeom):
                        f = QgsFeature(nPoints)
                        f.initAttributes(1)
                        f.setFields(fields)
                        f.setAttribute('id', nPoints)
                        f.setGeometry(geom)
                        writer.addFeature(f)
                        index.insertFeature(f)
                        points[nPoints] = pnt
                        nPoints += 1
                        progress.setPercentage(int(nPoints * total))
            nIterations += 1

        if nPoints < pointCount:
            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                   self.tr('Can not generate requested number of random points. '
                                           'Maximum number of attempts exceeded.'))

        del writer
Ejemplo n.º 24
0
 def _make_layer(self, layer_wkb_name):
     fields = QgsFields()
     wkb_type = getattr(QgsWkbTypes, layer_wkb_name)
     fields.append(QgsField('int_f', QVariant.Int))
     layer = QgsMemoryProviderUtils.createMemoryLayer(
         '%s_layer' % layer_wkb_name, fields, wkb_type, QgsCoordinateReferenceSystem(4326))
     self.assertTrue(layer.isValid())
     self.assertEqual(layer.wkbType(), wkb_type)
     return layer
Ejemplo n.º 25
0
def test_replaced_with_qgsexpression_feature_attribute_lookup():
    feature = QgsFeature()
    fields = QgsFields()
    fields.append(QgsField('mycol'))
    feature.setFields(fields)
    feature['mycol'] = 'testvalue'
    default = '[% "mycol" %]'
    outdefault = roam.defaults.default_value(default, feature, None)
    assert outdefault == 'testvalue'
Ejemplo n.º 26
0
def create_memory_layer(
        layer_name, geometry, coordinate_reference_system=None, fields=None):
    """Create a vector memory layer.

    :param layer_name: The name of the layer.
    :type layer_name: str

    :param geometry: The geometry of the layer.
    :rtype geometry: QgsWkbTypes (note:
                     from C++ QgsWkbTypes::GeometryType enum)

    :param coordinate_reference_system: The CRS of the memory layer.
    :type coordinate_reference_system: QgsCoordinateReferenceSystem

    :param fields: Fields of the vector layer. Default to None.
    :type fields: QgsFields

    :return: The memory layer.
    :rtype: QgsVectorLayer
    """

    if geometry == QgsWkbTypes.PointGeometry:
        wkb_type = QgsWkbTypes.MultiPoint
    elif geometry == QgsWkbTypes.LineGeometry:
        wkb_type = QgsWkbTypes.MultiLineString
    elif geometry == QgsWkbTypes.PolygonGeometry:
        wkb_type = QgsWkbTypes.MultiPolygon
    elif geometry == QgsWkbTypes.NullGeometry:
        wkb_type = QgsWkbTypes.NoGeometry
    else:
        raise MemoryLayerCreationError(
            'Layer geometry must be one of: Point, Line, '
            'Polygon or Null, I got %s' % geometry)

    if coordinate_reference_system is None:
        coordinate_reference_system = QgsCoordinateReferenceSystem()
    if fields is None:
        fields = QgsFields()
    elif not isinstance(fields, QgsFields):
        # fields is a list
        new_fields = QgsFields()
        for f in fields:
            new_fields.append(f)
        fields = new_fields
    memory_layer = QgsMemoryProviderUtils. \
        createMemoryLayer(name=layer_name,
                          fields=fields,
                          geometryType=wkb_type,
                          crs=coordinate_reference_system)

    memory_layer.dataProvider().createSpatialIndex()
    memory_layer.keywords = {
        'inasafe_fields': {}
    }
    return memory_layer
Ejemplo n.º 27
0
    def check_geometry(self, vlayer):
        lstErrors = []
        if self.mySelection:
            layer = vlayer.selectedFeatures()
            nFeat = len(layer)
        else:
            layer = []
            ft = QgsFeature()
            fit = vlayer.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]))
            while fit.nextFeature(ft):
                layer.append(QgsFeature(ft))
            nFeat = len(layer)
        nElement = 0
        if nFeat > 0:
            self.emit(SIGNAL("runStatus(PyQt_PyObject)"), 0)
            self.emit(SIGNAL("runRange(PyQt_PyObject)"), (0, nFeat))
        for feat in layer:
            if not self.running:
                return list()
            geom = QgsGeometry(feat.geometry()) # ger reference to geometry
            self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nElement)
            nElement += 1
            # Check Add error
            if not geom.isGeosEmpty():
                lstErrors.append((feat.id(), list(geom.validateGeometry())))
        self.emit(SIGNAL("runStatus(PyQt_PyObject)"), nFeat)

        if self.writeShape:
            fields = QgsFields()
            fields.append(QgsField("FEAT_ID", QVariant.Int))
            fields.append(QgsField("ERROR", QVariant.String))

            writer = QgsVectorFileWriter(self.myName, self.myEncoding, fields,
                                         QGis.WKBPoint, vlayer.crs())
            for rec in lstErrors:
                if len(rec[1]) < 1:
                    continue
                for err in rec[1]:
                    fidItem = unicode(rec[0])
                    message = err.what()
                    if err.hasWhere():
                        locErr = err.where()
                        xP = locErr.x()
                        yP = locErr.y()
                        myPoint = QgsPoint(xP, yP)
                        geometry = QgsGeometry().fromPoint(myPoint)
                        ft = QgsFeature()
                        ft.setGeometry(geometry)
                        ft.setAttributes([fidItem, message])
                        writer.addFeature(ft)
            del writer
            return "writeShape"
        else:
            return lstErrors
Ejemplo n.º 28
0
    def processAlgorithm(self, parameters, context, feedback):
        pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context)
        minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context)
        crs = self.parameterAsCrs(parameters, self.TARGET_CRS, context)
        bbox = self.parameterAsExtent(parameters, self.EXTENT, context, crs)

        extent = QgsGeometry().fromRect(bbox)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.Point, crs)
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        nPoints = 0
        nIterations = 0
        maxIterations = pointCount * 200
        total = 100.0 / pointCount if pointCount else 1

        index = QgsSpatialIndex()
        points = dict()

        random.seed()

        while nIterations < maxIterations and nPoints < pointCount:
            if feedback.isCanceled():
                break

            rx = bbox.xMinimum() + bbox.width() * random.random()
            ry = bbox.yMinimum() + bbox.height() * random.random()

            p = QgsPointXY(rx, ry)
            geom = QgsGeometry.fromPointXY(p)
            if geom.within(extent) and \
                    vector.checkMinDistance(p, index, minDistance, points):
                f = QgsFeature(nPoints)
                f.initAttributes(1)
                f.setFields(fields)
                f.setAttribute('id', nPoints)
                f.setGeometry(geom)
                sink.addFeature(f, QgsFeatureSink.FastInsert)
                index.addFeature(f)
                points[nPoints] = p
                nPoints += 1
                feedback.setProgress(int(nPoints * total))
            nIterations += 1

        if nPoints < pointCount:
            feedback.pushInfo(self.tr('Could not generate requested number of random points. '
                                      'Maximum number of attempts exceeded.'))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 29
0
    def processAlgorithm(self, progress):
        pointCount = int(self.getParameterValue(self.POINT_NUMBER))
        minDistance = float(self.getParameterValue(self.MIN_DISTANCE))
        extent = unicode(self.getParameterValue(self.EXTENT)).split(',')

        xMin = float(extent[0])
        xMax = float(extent[1])
        yMin = float(extent[2])
        yMax = float(extent[3])
        extent = QgsGeometry().fromRect(
            QgsRectangle(xMin, yMin, xMax, yMax))

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QGis.WKBPoint, mapCRS)

        nPoints = 0
        nIterations = 0
        maxIterations = pointCount * 200
        total = 100.0 / pointCount if pointCount > 0 else 1

        index = QgsSpatialIndex()
        points = dict()

        random.seed()

        while nIterations < maxIterations and nPoints < pointCount:
            rx = xMin + (xMax - xMin) * random.random()
            ry = yMin + (yMax - yMin) * random.random()

            pnt = QgsPoint(rx, ry)
            geom = QgsGeometry.fromPoint(pnt)
            if geom.within(extent) and \
                    vector.checkMinDistance(pnt, index, minDistance, points):
                f = QgsFeature(nPoints)
                f.initAttributes(1)
                f.setFields(fields)
                f.setAttribute('id', nPoints)
                f.setGeometry(geom)
                writer.addFeature(f)
                index.insertFeature(f)
                points[nPoints] = pnt
                nPoints += 1
                progress.setPercentage(int(nPoints * total))
            nIterations += 1

        if nPoints < pointCount:
            ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                                   self.tr('Can not generate requested number of random points. '
                                           'Maximum number of attempts exceeded.'))

        del writer
Ejemplo n.º 30
0
    def processAlgorithm(self, progress):
        extent = str(self.getParameterValue(self.EXTENT)).split(",")

        spacing = float(self.getParameterValue(self.SPACING))
        inset = float(self.getParameterValue(self.INSET))
        randomize = self.getParameterValue(self.RANDOMIZE)
        isSpacing = self.getParameterValue(self.IS_SPACING)

        extent = QgsRectangle(float(extent[0]), float(extent[2]), float(extent[1]), float(extent[3]))

        fields = QgsFields()
        fields.append(QgsField("id", QVariant.Int, "", 10, 0))
        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(fields, QGis.WKBPoint, mapCRS)

        if randomize:
            seed()

        area = extent.width() * extent.height()
        if isSpacing:
            pSpacing = spacing
        else:
            pSpacing = sqrt(area / spacing)

        f = QgsFeature()
        f.initAttributes(1)
        f.setFields(fields)

        count = 0
        total = 100.00 / (area / pSpacing)
        y = extent.yMaximum() - inset
        while y >= extent.yMinimum():
            x = extent.xMinimum() + inset
            while x <= extent.xMaximum():
                if randomize:
                    geom = QgsGeometry().fromPoint(
                        QgsPoint(
                            uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)),
                            uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0)),
                        )
                    )
                else:
                    geom = QgsGeometry().fromPoint(QgsPoint(x, y))

                if geom.intersects(extent):
                    f.setAttribute("id", count)
                    f.setGeometry(geom)
                    writer.addFeature(f)
                    x += pSpacing
                    count += 1
                    progress.setPercentage(int(count * total))
            y = y - pSpacing
        del writer
Ejemplo n.º 31
0
    def test1(self):
        d = QgsVirtualLayerDefinition()
        self.assertEqual(d.toString(), "")
        d.setFilePath("/file")
        self.assertEqual(d.toString(), "file:///file")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(d.toUrl()).filePath(), "/file")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).filePath(), "/file")
        d.setFilePath(os.path.join('C:/', 'file'))
        self.assertEqual(d.toString(), "file:///C:/file")
        # self.assertEqual(QgsVirtualLayerDefinition.fromUrl(d.toUrl()).filePath(), os.path.join('C:/', 'file'))
        d.setQuery("SELECT * FROM mytable")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(d.toUrl()).query(),
            "SELECT * FROM mytable")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).query(),
            "SELECT * FROM mytable")

        q = "SELECT * FROM tableéé /*:int*/"
        d.setQuery(q)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(d.toUrl()).query(), q)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(d.toString())).query(),
            q)

        s1 = "file://foo&bar=okié"
        d.addSource("name", s1, "provider", "utf8")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(
                d.toUrl()).sourceLayers()[0].source(), s1)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).sourceLayers()[0].source(), s1)

        n1 = "éé ok"
        d.addSource(n1, s1, "provider")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(
                d.toUrl()).sourceLayers()[1].name(), n1)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).sourceLayers()[1].name(), n1)

        d.addSource("ref1", "id0001")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(
                d.toUrl()).sourceLayers()[2].reference(), "id0001")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).sourceLayers()[2].reference(), "id0001")

        s = "dbname='C:\\tt' table=\"test\" (geometry) sql="
        d.addSource("nn", s, "spatialite")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(
                d.toUrl()).sourceLayers()[3].source(), s)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).sourceLayers()[3].source(), s)

        d.setGeometryField("geom")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(d.toUrl()).geometryField(),
            "geom")
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).geometryField(), "geom")

        d.setGeometryWkbType(QgsWkbTypes.Point)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(d.toUrl()).geometryWkbType(),
            QgsWkbTypes.Point)
        self.assertEqual(
            QgsVirtualLayerDefinition.fromUrl(strToUrl(
                d.toString())).geometryWkbType(), QgsWkbTypes.Point)

        f = QgsFields()
        f.append(QgsField("a", QVariant.Int))
        f.append(QgsField("f", QVariant.Double))
        f.append(QgsField("s", QVariant.String))
        d.setFields(f)
        f2 = QgsVirtualLayerDefinition.fromUrl(d.toUrl()).fields()
        self.assertEqual(f[0].name(), f2[0].name())
        self.assertEqual(f[0].type(), f2[0].type())
        self.assertEqual(f[1].name(), f2[1].name())
        self.assertEqual(f[1].type(), f2[1].type())
        self.assertEqual(f[2].name(), f2[2].name())
        self.assertEqual(f[2].type(), f2[2].type())
Ejemplo n.º 32
0
    def processAlgorithm(self, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR), context)

        rasterPath = str(self.getParameterValue(self.INPUT_RASTER))

        rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
        geoTransform = rasterDS.GetGeoTransform()
        rasterDS = None

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('poly_id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('point_id', QVariant.Int, '', 10, 0))

        writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(
            fields, QgsWkbTypes.Point, layer.crs(), context)

        outFeature = QgsFeature()
        outFeature.setFields(fields)

        fid = 0
        polyId = 0
        pointId = 0

        features = QgsProcessingUtils.getFeatures(layer, context)
        total = 100.0 / QgsProcessingUtils.featureCount(layer, context)
        for current, f in enumerate(features):
            geom = f.geometry()
            bbox = geom.boundingBox()

            xMin = bbox.xMinimum()
            xMax = bbox.xMaximum()
            yMin = bbox.yMinimum()
            yMax = bbox.yMaximum()

            (startRow,
             startColumn) = raster.mapToPixel(xMin, yMax, geoTransform)
            (endRow, endColumn) = raster.mapToPixel(xMax, yMin, geoTransform)

            # use prepared geometries for faster intersection tests
            engine = QgsGeometry.createGeometryEngine(geom.geometry())
            engine.prepareGeometry()

            for row in range(startRow, endRow + 1):
                for col in range(startColumn, endColumn + 1):
                    (x, y) = raster.pixelToMap(row, col, geoTransform)
                    point = QgsPointV2()
                    point.setX(x)
                    point.setY(y)

                    if engine.contains(point):
                        outFeature.setGeometry(QgsGeometry(point))
                        outFeature['id'] = fid
                        outFeature['poly_id'] = polyId
                        outFeature['point_id'] = pointId

                        fid += 1
                        pointId += 1

                        writer.addFeature(outFeature)

            pointId = 0
            polyId += 1

            feedback.setProgress(int(current * total))

        del writer
Ejemplo n.º 33
0
Archivo: Merge.py Proyecto: DINKIN/QGIS
    def processAlgorithm(self, parameters, context, feedback):
        input_layers = self.parameterAsLayerList(parameters, self.LAYERS,
                                                 context)

        layers = []
        fields = QgsFields()
        totalFeatureCount = 0
        for layer in input_layers:
            if layer.type() != QgsMapLayer.VectorLayer:
                raise QgsProcessingException(
                    self.tr('All layers must be vector layers!'))

            if (len(layers) > 0):
                if (layer.wkbType() != layers[0].wkbType()):
                    raise QgsProcessingException(
                        self.tr('All layers must have same geometry type!'))

            layers.append(layer)
            totalFeatureCount += layer.featureCount()

            for sindex, sfield in enumerate(layer.fields()):
                found = None
                for dfield in fields:
                    if (dfield.name().upper() == sfield.name().upper()):
                        found = dfield
                        if (dfield.type() != sfield.type()):
                            raise QgsProcessingException(
                                self.tr(
                                    '{} field in layer {} has different '
                                    'data type than in other layers.'.format(
                                        sfield.name(), layerSource)))

                if not found:
                    fields.append(sfield)

        add_layer_field = False
        if fields.lookupField('layer') < 0:
            fields.append(QgsField('layer', QVariant.String, '', 100))
            add_layer_field = True
        add_path_field = False
        if fields.lookupField('path') < 0:
            fields.append(QgsField('path', QVariant.String, '', 200))
            add_path_field = True

        total = 100.0 / totalFeatureCount if totalFeatureCount else 1
        dest_crs = layers[0].crs()
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               layers[0].wkbType(), dest_crs)

        featureCount = 0
        for layer in layers:
            for feature in layer.getFeatures(
                    QgsFeatureRequest().setDestinationCrs(dest_crs)):
                if feedback.isCanceled():
                    break

                sattributes = feature.attributes()
                dattributes = []
                for dindex, dfield in enumerate(fields):
                    if add_layer_field and dfield.name() == 'layer':
                        dattributes.append(layer.name())
                        continue
                    if add_path_field and dfield.name() == 'path':
                        dattributes.append(layer.publicSource())
                        continue

                    if (dfield.type() == QVariant.Int, QVariant.UInt,
                            QVariant.LongLong, QVariant.ULongLong):
                        dattribute = 0
                    elif (dfield.type() == QVariant.Double):
                        dattribute = 0.0
                    else:
                        dattribute = ''

                    for sindex, sfield in enumerate(layer.fields()):
                        if (sfield.name().upper() == dfield.name().upper()):
                            if (sfield.type() != dfield.type()):
                                raise QgsProcessingException(
                                    self.tr('Attribute type mismatch'))
                            dattribute = sattributes[sindex]
                            break

                    dattributes.append(dattribute)

                feature.setAttributes(dattributes)
                sink.addFeature(feature, QgsFeatureSink.FastInsert)
                featureCount += 1
                feedback.setProgress(int(featureCount * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 34
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))

        field_names = self.parameterAsFields(parameters, self.FIELDS, context)

        fields = QgsFields()
        field_indices = []
        for field_name in field_names:
            field_index = source.fields().lookupField(field_name)
            if field_index < 0:
                feedback.reportError(
                    self.tr('Invalid field name {}').format(field_name))
                continue
            field = source.fields()[field_index]
            fields.append(field)
            field_indices.append(field_index)
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.NoGeometry,
                                               QgsCoordinateReferenceSystem())

        results = {}
        values = set()
        if len(field_indices) == 1:
            # one field, can use provider optimised method
            values = tuple([v] for v in source.uniqueValues(field_indices[0]))
        else:
            # have to scan whole table
            # TODO - add this support to QgsVectorDataProvider so we can run it on
            # the backend
            request = QgsFeatureRequest().setFlags(
                QgsFeatureRequest.NoGeometry)
            request.setSubsetOfAttributes(field_indices)
            total = 100.0 / source.featureCount() if source.featureCount(
            ) else 0
            for current, f in enumerate(
                    source.getFeatures(
                        request, QgsProcessingFeatureSource.
                        FlagSkipGeometryValidityChecks)):
                if feedback.isCanceled():
                    break

                value = tuple(f.attribute(i) for i in field_indices)
                values.add(value)
                feedback.setProgress(int(current * total))

        if sink:
            for value in values:
                if feedback.isCanceled():
                    break

                f = QgsFeature()
                f.setAttributes([attr for attr in value])
                sink.addFeature(f, QgsFeatureSink.FastInsert)
            results[self.OUTPUT] = dest_id

        output_file = self.parameterAsFileOutput(parameters,
                                                 self.OUTPUT_HTML_FILE,
                                                 context)
        if output_file:
            self.createHTML(output_file, values)
            results[self.OUTPUT_HTML_FILE] = output_file

        results[self.TOTAL_VALUES] = len(values)
        results[self.UNIQUE_VALUES] = ';'.join(
            [','.join([str(attr) for attr in v]) for v in values])
        return results
Ejemplo n.º 35
0
    def linearMatrix(self, parameters, context, source, inField, target_source, targetField,
                     matType, nPoints, feedback):
        inIdx = source.fields().lookupField(inField)
        outIdx = target_source.fields().lookupField(targetField)

        fields = QgsFields()
        input_id_field = source.fields()[inIdx]
        input_id_field.setName('InputID')
        fields.append(input_id_field)
        if matType == 0:
            target_id_field = target_source.fields()[outIdx]
            target_id_field.setName('TargetID')
            fields.append(target_id_field)
            fields.append(QgsField('Distance', QVariant.Double))
        else:
            fields.append(QgsField('MEAN', QVariant.Double))
            fields.append(QgsField('STDDEV', QVariant.Double))
            fields.append(QgsField('MIN', QVariant.Double))
            fields.append(QgsField('MAX', QVariant.Double))

        out_wkb = QgsWkbTypes.multiType(source.wkbType()) if matType == 0 else source.wkbType()
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, out_wkb, source.sourceCrs())

        index = QgsSpatialIndex(target_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([]).setDestinationCrs(source.sourceCrs(), context.transformContext())), feedback)

        distArea = QgsDistanceArea()
        distArea.setSourceCrs(source.sourceCrs(), context.transformContext())
        distArea.setEllipsoid(context.project().ellipsoid())

        features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes([inIdx]))
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break

            inGeom = inFeat.geometry()
            inID = str(inFeat.attributes()[inIdx])
            featList = index.nearestNeighbor(inGeom.asPoint(), nPoints)
            distList = []
            vari = 0.0
            request = QgsFeatureRequest().setFilterFids(featList).setSubsetOfAttributes([outIdx]).setDestinationCrs(source.sourceCrs(), context.transformContext())
            for outFeat in target_source.getFeatures(request):
                if feedback.isCanceled():
                    break

                outID = outFeat.attributes()[outIdx]
                outGeom = outFeat.geometry()
                dist = distArea.measureLine(inGeom.asPoint(),
                                            outGeom.asPoint())

                if matType == 0:
                    out_feature = QgsFeature()
                    out_geom = QgsGeometry.unaryUnion([inFeat.geometry(), outFeat.geometry()])
                    out_feature.setGeometry(out_geom)
                    out_feature.setAttributes([inID, outID, dist])
                    sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
                else:
                    distList.append(float(dist))

            if matType != 0:
                mean = sum(distList) / len(distList)
                for i in distList:
                    vari += (i - mean) * (i - mean)
                vari = math.sqrt(vari / len(distList))

                out_feature = QgsFeature()
                out_feature.setGeometry(inFeat.geometry())
                out_feature.setAttributes([inID, mean, vari, min(distList), max(distList)])
                sink.addFeature(out_feature, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 36
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context)

        raster_layer = self.parameterAsRasterLayer(parameters,
                                                   self.INPUT_RASTER, context)
        rasterPath = raster_layer.source()

        rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
        geoTransform = rasterDS.GetGeoTransform()
        rasterDS = None

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('line_id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('point_id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Point,
                                               raster_layer.crs())

        outFeature = QgsFeature()
        outFeature.setFields(fields)

        self.fid = 0
        self.lineId = 0
        self.pointId = 0

        features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(
            raster_layer.crs(), context.transformContext()))
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break
            geom = f.geometry()
            if geom.isMultipart():
                lines = geom.asMultiPolyline()
                for line in lines:
                    for i in range(len(line) - 1):
                        p1 = line[i]
                        p2 = line[i + 1]

                        (x1, y1) = raster.mapToPixel(p1.x(), p1.y(),
                                                     geoTransform)
                        (x2, y2) = raster.mapToPixel(p2.x(), p2.y(),
                                                     geoTransform)

                        self.buildLine(x1, y1, x2, y2, geoTransform, sink,
                                       outFeature)
            else:
                points = geom.asPolyline()
                for i in range(len(points) - 1):
                    p1 = points[i]
                    p2 = points[i + 1]

                    (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform)
                    (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform)

                    self.buildLine(x1, y1, x2, y2, geoTransform, sink,
                                   outFeature)

            self.pointId = 0
            self.lineId += 1

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 37
0
    def processAlgorithm(self, progress):
        extent = str(self.getParameterValue(self.EXTENT)).split(',')

        spacing = float(self.getParameterValue(self.SPACING))
        inset = float(self.getParameterValue(self.INSET))
        randomize = self.getParameterValue(self.RANDOMIZE)
        isSpacing = self.getParameterValue(self.IS_SPACING)

        extent = QgsRectangle(float(extent[0]), float(extent[2]),
                              float(extent[1]), float(extent[3]))

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.Point, mapCRS)

        if randomize:
            seed()

        area = extent.width() * extent.height()
        if isSpacing:
            pSpacing = spacing
        else:
            pSpacing = sqrt(area / spacing)

        f = QgsFeature()
        f.initAttributes(1)
        f.setFields(fields)

        count = 0
        total = 100.0 / (area / pSpacing)
        y = extent.yMaximum() - inset

        extent_geom = QgsGeometry.fromRect(extent)
        extent_engine = QgsGeometry.createGeometryEngine(
            extent_geom.geometry())
        extent_engine.prepareGeometry()

        while y >= extent.yMinimum():
            x = extent.xMinimum() + inset
            while x <= extent.xMaximum():
                if randomize:
                    geom = QgsGeometry().fromPoint(
                        QgsPoint(
                            uniform(x - (pSpacing / 2.0),
                                    x + (pSpacing / 2.0)),
                            uniform(y - (pSpacing / 2.0),
                                    y + (pSpacing / 2.0))))
                else:
                    geom = QgsGeometry().fromPoint(QgsPoint(x, y))

                if extent_engine.intersects(geom.geometry()):
                    f.setAttribute('id', count)
                    f.setGeometry(geom)
                    writer.addFeature(f)
                    x += pSpacing
                    count += 1
                    progress.setPercentage(int(count * total))
            y = y - pSpacing
        del writer
Ejemplo n.º 38
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))

        method = self.parameterAsEnum(parameters, self.METHOD, context)

        wkb_type = source.wkbType()
        fields = source.fields()

        new_fields = QgsFields()
        if QgsWkbTypes.geometryType(wkb_type) == QgsWkbTypes.PolygonGeometry:
            new_fields.append(QgsField('area', QVariant.Double))
            new_fields.append(QgsField('perimeter', QVariant.Double))
        elif QgsWkbTypes.geometryType(wkb_type) == QgsWkbTypes.LineGeometry:
            new_fields.append(QgsField('length', QVariant.Double))
            if not QgsWkbTypes.isMultiType(source.wkbType()):
                new_fields.append(QgsField('straightdis', QVariant.Double))
                new_fields.append(QgsField('sinuosity', QVariant.Double))
        else:
            if QgsWkbTypes.isMultiType(source.wkbType()):
                new_fields.append(QgsField('numparts', QVariant.Int))
            else:
                new_fields.append(QgsField('xcoord', QVariant.Double))
                new_fields.append(QgsField('ycoord', QVariant.Double))
                if QgsWkbTypes.hasZ(source.wkbType()):
                    self.export_z = True
                    new_fields.append(QgsField('zcoord', QVariant.Double))
                if QgsWkbTypes.hasM(source.wkbType()):
                    self.export_m = True
                    new_fields.append(QgsField('mvalue', QVariant.Double))

        fields = QgsProcessingUtils.combineFields(fields, new_fields)
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields, wkb_type,
                                               source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        coordTransform = None

        # Calculate with:
        # 0 - layer CRS
        # 1 - project CRS
        # 2 - ellipsoidal

        self.distance_area = QgsDistanceArea()
        if method == 2:
            self.distance_area.setSourceCrs(source.sourceCrs(),
                                            context.transformContext())
            self.distance_area.setEllipsoid(context.project().ellipsoid())
        elif method == 1:
            coordTransform = QgsCoordinateTransform(source.sourceCrs(),
                                                    context.project().crs(),
                                                    context.project())

        features = source.getFeatures()
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            outFeat = f
            attrs = f.attributes()
            inGeom = f.geometry()
            if inGeom:
                if coordTransform is not None:
                    inGeom.transform(coordTransform)

                if inGeom.type() == QgsWkbTypes.PointGeometry:
                    attrs.extend(self.point_attributes(inGeom))
                elif inGeom.type() == QgsWkbTypes.PolygonGeometry:
                    attrs.extend(self.polygon_attributes(inGeom))
                else:
                    attrs.extend(self.line_attributes(inGeom))

            # ensure consistent count of attributes - otherwise null
            # geometry features will have incorrect attribute length
            # and provider may reject them
            if len(attrs) < len(fields):
                attrs += [NULL] * (len(fields) - len(attrs))

            outFeat.setAttributes(attrs)
            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 39
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        value_field_name = self.parameterAsString(parameters,
                                                  self.VALUES_FIELD_NAME,
                                                  context)
        category_field_name = self.parameterAsString(
            parameters, self.CATEGORIES_FIELD_NAME, context)

        value_field_index = source.fields().lookupField(value_field_name)
        category_field_index = source.fields().lookupField(category_field_name)

        features = source.getFeatures(QgsFeatureRequest().setFlags(
            QgsFeatureRequest.NoGeometry))
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        values = {}
        for current, feat in enumerate(features):
            if feedback.isCanceled():
                break

            feedback.setProgress(int(current * total))
            attrs = feat.attributes()
            try:
                value = float(attrs[value_field_index])
                cat = attrs[category_field_index]
                if cat not in values:
                    values[cat] = []
                values[cat].append(value)
            except:
                pass

        fields = QgsFields()
        fields.append(source.fields().at(category_field_index))
        fields.append(QgsField('min', QVariant.Double))
        fields.append(QgsField('max', QVariant.Double))
        fields.append(QgsField('mean', QVariant.Double))
        fields.append(QgsField('stddev', QVariant.Double))
        fields.append(QgsField('sum', QVariant.Double))
        fields.append(QgsField('count', QVariant.Int))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.NoGeometry,
                                               QgsCoordinateReferenceSystem())

        stat = QgsStatisticalSummary(QgsStatisticalSummary.Min
                                     | QgsStatisticalSummary.Max
                                     | QgsStatisticalSummary.Mean
                                     | QgsStatisticalSummary.StDevSample
                                     | QgsStatisticalSummary.Sum
                                     | QgsStatisticalSummary.Count)

        for (cat, v) in list(values.items()):
            stat.calculate(v)
            f = QgsFeature()
            f.setAttributes([
                cat,
                stat.min(),
                stat.max(),
                stat.mean(),
                stat.sampleStDev(),
                stat.sum(),
                stat.count()
            ])
            sink.addFeature(f, QgsFeatureSink.FastInsert)

        return {self.OUTPUT: dest_id}
Ejemplo n.º 40
0
class Aggregate(QgisAlgorithm):

    INPUT = 'INPUT'
    GROUP_BY = 'GROUP_BY'
    AGGREGATES = 'AGGREGATES'
    DISSOLVE = 'DISSOLVE'
    OUTPUT = 'OUTPUT'

    def group(self):
        return self.tr('Vector geometry')

    def groupId(self):
        return 'vectorgeometry'

    def name(self):
        return 'aggregate'

    def displayName(self):
        return self.tr('Aggregate')

    def initAlgorithm(self, config=None):
        self.addParameter(
            QgsProcessingParameterFeatureSource(self.INPUT,
                                                self.tr('Input layer')))
        self.addParameter(
            QgsProcessingParameterExpression(
                self.GROUP_BY,
                self.tr('Group by expression (NULL to group all features)'),
                defaultValue='NULL',
                optional=False,
                parentLayerParameterName=self.INPUT))

        class ParameterAggregates(QgsProcessingParameterDefinition):
            def __init__(self,
                         name,
                         description,
                         parentLayerParameterName='INPUT'):
                super().__init__(name, description)
                self._parentLayerParameter = parentLayerParameterName

            def clone(self):
                copy = ParameterAggregates(self.name(), self.description(),
                                           self._parentLayerParameter)
                return copy

            def type(self):
                return 'aggregates'

            def checkValueIsAcceptable(self, value, context=None):
                if not isinstance(value, list):
                    return False
                for field_def in value:
                    if not isinstance(field_def, dict):
                        return False
                    if not field_def.get('input', False):
                        return False
                    if not field_def.get('aggregate', False):
                        return False
                    if not field_def.get('name', False):
                        return False
                    if not field_def.get('type', False):
                        return False
                return True

            def valueAsPythonString(self, value, context):
                return str(value)

            def asScriptCode(self):
                raise NotImplementedError()

            @classmethod
            def fromScriptCode(cls, name, description, isOptional, definition):
                raise NotImplementedError()

            def parentLayerParameter(self):
                return self._parentLayerParameter

        self.addParameter(
            ParameterAggregates(self.AGGREGATES,
                                description=self.tr('Aggregates')))
        self.parameterDefinition(self.AGGREGATES).setMetadata({
            'widget_wrapper':
            'processing.algs.qgis.ui.AggregatesPanel.AggregatesWidgetWrapper'
        })

        self.addParameter(
            QgsProcessingParameterFeatureSink(self.OUTPUT,
                                              self.tr('Aggregated')))

    def parameterAsAggregates(self, parameters, name, context):
        return parameters[name]

    def prepareAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        group_by = self.parameterAsExpression(parameters, self.GROUP_BY,
                                              context)
        aggregates = self.parameterAsAggregates(parameters, self.AGGREGATES,
                                                context)

        da = QgsDistanceArea()
        da.setSourceCrs(source.sourceCrs(), context.transformContext())
        da.setEllipsoid(context.project().ellipsoid())

        self.source = source
        self.group_by = group_by
        self.group_by_expr = self.createExpression(group_by, da, context)
        self.geometry_expr = self.createExpression(
            'collect($geometry, {})'.format(group_by), da, context)

        self.fields = QgsFields()
        self.fields_expr = []
        for field_def in aggregates:
            self.fields.append(
                QgsField(name=field_def['name'],
                         type=field_def['type'],
                         typeName="",
                         len=field_def['length'],
                         prec=field_def['precision']))
            aggregate = field_def['aggregate']
            if aggregate == 'first_value':
                expression = field_def['input']
            elif aggregate == 'concatenate':
                expression = ('{}({}, {}, {}, \'{}\')'.format(
                    field_def['aggregate'], field_def['input'], group_by,
                    'TRUE', field_def['delimiter']))
            else:
                expression = '{}({}, {})'.format(field_def['aggregate'],
                                                 field_def['input'], group_by)
            expr = self.createExpression(expression, da, context)
            self.fields_expr.append(expr)
        return True

    def processAlgorithm(self, parameters, context, feedback):
        expr_context = self.createExpressionContext(parameters, context,
                                                    self.source)
        self.group_by_expr.prepare(expr_context)

        # Group features in memory layers
        source = self.source
        count = self.source.featureCount()
        if count:
            progress_step = 50.0 / count
        current = 0
        groups = {}
        keys = []  # We need deterministic order for the tests
        feature = QgsFeature()
        for feature in self.source.getFeatures():
            expr_context.setFeature(feature)
            group_by_value = self.evaluateExpression(self.group_by_expr,
                                                     expr_context)

            # Get an hashable key for the dict
            key = group_by_value
            if isinstance(key, list):
                key = tuple(key)

            group = groups.get(key, None)
            if group is None:
                sink, id = QgsProcessingUtils.createFeatureSink(
                    'memory:', context, source.fields(), source.wkbType(),
                    source.sourceCrs())
                layer = QgsProcessingUtils.mapLayerFromString(id, context)
                group = {'sink': sink, 'layer': layer, 'feature': feature}
                groups[key] = group
                keys.append(key)

            group['sink'].addFeature(feature, QgsFeatureSink.FastInsert)

            current += 1
            feedback.setProgress(int(current * progress_step))
            if feedback.isCanceled():
                return

        (sink, dest_id) = self.parameterAsSink(
            parameters, self.OUTPUT, context, self.fields,
            QgsWkbTypes.multiType(source.wkbType()), source.sourceCrs())

        # Calculate aggregates on memory layers
        if len(keys):
            progress_step = 50.0 / len(keys)
        for current, key in enumerate(keys):
            group = groups[key]
            expr_context = self.createExpressionContext(parameters, context)
            expr_context.appendScope(
                QgsExpressionContextUtils.layerScope(group['layer']))
            expr_context.setFeature(group['feature'])

            geometry = self.evaluateExpression(self.geometry_expr,
                                               expr_context)
            if geometry is not None and not geometry.isEmpty():
                geometry = QgsGeometry.unaryUnion(
                    geometry.asGeometryCollection())
                if geometry.isEmpty():
                    raise QgsProcessingException(
                        'Impossible to combine geometries for {} = {}'.format(
                            self.group_by, group_by_value))

            attrs = []
            for fields_expr in self.fields_expr:
                attrs.append(self.evaluateExpression(fields_expr,
                                                     expr_context))

            # Write output feature
            outFeat = QgsFeature()
            if geometry is not None:
                outFeat.setGeometry(geometry)
            outFeat.setAttributes(attrs)
            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)

            feedback.setProgress(50 + int(current * progress_step))
            if feedback.isCanceled():
                return

        return {self.OUTPUT: dest_id}

    def createExpression(self, text, da, context):
        expr = QgsExpression(text)
        expr.setGeomCalculator(da)
        expr.setDistanceUnits(context.project().distanceUnits())
        expr.setAreaUnits(context.project().areaUnits())
        if expr.hasParserError():
            raise QgsProcessingException(
                self.tr(u'Parser error in expression "{}": {}').format(
                    text, expr.parserErrorString()))
        return expr

    def evaluateExpression(self, expr, context):
        value = expr.evaluate(context)
        if expr.hasEvalError():
            raise QgsProcessingException(
                self.tr(u'Evaluation error in expression "{}": {}').format(
                    expr.expression(), expr.evalErrorString()))
        return value
Ejemplo n.º 41
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context)

        raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER, context)
        rasterPath = exportRasterLayer(raster_layer)

        rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
        geoTransform = rasterDS.GetGeoTransform()

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('poly_id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('point_id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.Point, raster_layer.crs())

        outFeature = QgsFeature()
        outFeature.setFields(fields)

        fid = 0
        polyId = 0
        pointId = 0

        features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(raster_layer.crs()))
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            geom = f.geometry()
            bbox = geom.boundingBox()

            xMin = bbox.xMinimum()
            xMax = bbox.xMaximum()
            yMin = bbox.yMinimum()
            yMax = bbox.yMaximum()

            (startRow, startColumn) = raster.mapToPixel(xMin, yMax, geoTransform)
            (endRow, endColumn) = raster.mapToPixel(xMax, yMin, geoTransform)

            # use prepared geometries for faster intersection tests
            engine = QgsGeometry.createGeometryEngine(geom.geometry())
            engine.prepareGeometry()

            for row in range(startRow, endRow + 1):
                for col in range(startColumn, endColumn + 1):
                    if feedback.isCanceled():
                        break

                    (x, y) = raster.pixelToMap(row, col, geoTransform)
                    point = QgsPoint(x, y)

                    if engine.contains(point):
                        outFeature.setGeometry(QgsGeometry(point))
                        outFeature['id'] = fid
                        outFeature['poly_id'] = polyId
                        outFeature['point_id'] = pointId

                        fid += 1
                        pointId += 1

                        sink.addFeature(outFeature, QgsFeatureSink.FastInsert)

            pointId = 0
            polyId += 1

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
    def _test_operations(self, md, conn):
        """Common tests"""

        capabilities = conn.capabilities()

        # Schema operations
        if (capabilities & QgsAbstractDatabaseProviderConnection.CreateSchema
            and capabilities & QgsAbstractDatabaseProviderConnection.Schemas
                and capabilities & QgsAbstractDatabaseProviderConnection.DropSchema):

            # Start clean
            if 'myNewSchema' in conn.schemas():
                conn.dropSchema('myNewSchema', True)

            # Create
            conn.createSchema('myNewSchema')
            schemas = conn.schemas()
            self.assertTrue('myNewSchema' in schemas)

            # Create again
            with self.assertRaises(QgsProviderConnectionException) as ex:
                conn.createSchema('myNewSchema')

            # Test rename
            if capabilities & QgsAbstractDatabaseProviderConnection.RenameSchema:
                # Rename
                conn.renameSchema('myNewSchema', 'myVeryNewSchema')
                schemas = conn.schemas()
                self.assertTrue('myVeryNewSchema' in schemas)
                self.assertFalse('myNewSchema' in schemas)
                conn.renameSchema('myVeryNewSchema', 'myNewSchema')
                schemas = conn.schemas()
                self.assertFalse('myVeryNewSchema' in schemas)
                self.assertTrue('myNewSchema' in schemas)

            # Drop
            conn.dropSchema('myNewSchema')
            schemas = conn.schemas()
            self.assertFalse('myNewSchema' in schemas)

            # UTF8 schema
            conn.createSchema('myUtf8\U0001f604NewSchema')
            schemas = conn.schemas()
            conn.dropSchema('myUtf8\U0001f604NewSchema')
            schemas = conn.schemas()
            self.assertFalse('myUtf8\U0001f604NewSchema' in schemas)

        # Table operations
        schema = None
        if (capabilities & QgsAbstractDatabaseProviderConnection.CreateVectorTable
            and capabilities & QgsAbstractDatabaseProviderConnection.Tables
                and capabilities & QgsAbstractDatabaseProviderConnection.DropVectorTable):

            if capabilities & QgsAbstractDatabaseProviderConnection.CreateSchema:
                schema = 'myNewSchema'
                conn.createSchema(schema)

            elif capabilities & QgsAbstractDatabaseProviderConnection.Schemas:
                schema = self.defaultSchema

            # Start clean
            if self.myNewTable in self._table_names(conn.tables(schema)):
                conn.dropVectorTable(schema, self.myNewTable)

            fields = QgsFields()
            fields.append(QgsField("string_t", QVariant.String))
            fields.append(QgsField("long_t", QVariant.LongLong))
            fields.append(QgsField("double_t", QVariant.Double))
            fields.append(QgsField("integer_t", QVariant.Int))
            fields.append(QgsField("date_t", QVariant.Date))
            fields.append(QgsField("datetime_t", QVariant.DateTime))
            fields.append(QgsField("time_t", QVariant.Time))
            options = {}
            crs = QgsCoordinateReferenceSystem.fromEpsgId(3857)
            typ = QgsWkbTypes.LineString

            # Create
            conn.createVectorTable(schema, self.myNewTable, fields, typ, crs, True, options)
            table_names = self._table_names(conn.tables(schema))
            self.assertTrue(self.myNewTable in table_names)

            # Create UTF8 table
            conn.createVectorTable(schema, self.myUtf8Table, fields, typ, crs, True, options)
            table_names = self._table_names(conn.tables(schema))
            self.assertTrue(self.myNewTable in table_names)
            self.assertTrue(self.myUtf8Table in table_names)
            conn.dropVectorTable(schema, self.myUtf8Table)
            table_names = self._table_names(conn.tables(schema))
            self.assertFalse(self.myUtf8Table in table_names)
            self.assertTrue(self.myNewTable in table_names)

            # insert something, because otherwise some databases cannot guess
            if self.providerKey in ['hana', 'mssql', 'oracle']:
                f = QgsFeature(fields)
                f.setGeometry(QgsGeometry.fromWkt('LineString (-72.345 71.987, -80 80)'))
                vl = QgsVectorLayer(conn.tableUri(schema, self.myNewTable), 'vl', self.providerKey)
                vl.dataProvider().addFeatures([f])

            # Check table information
            table_properties = conn.tables(schema)
            table_property = self._table_by_name(table_properties, self.myNewTable)
            self.assertEqual(table_property.maxCoordinateDimensions(), 2)
            self.assertIsNotNone(table_property)
            self.assertEqual(table_property.tableName(), self.myNewTable)
            self.assertEqual(table_property.geometryColumnCount(), 1)
            self.assertEqual(table_property.geometryColumnTypes()[0].wkbType, QgsWkbTypes.LineString)
            cols = table_property.geometryColumnTypes()
            self.assertEqual(cols[0].crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(table_property.defaultName(), self.myNewTable)

            # Check aspatial tables
            conn.createVectorTable(schema, 'myNewAspatialTable', fields, QgsWkbTypes.NoGeometry, crs, True, options)
            table_properties = conn.tables(schema, QgsAbstractDatabaseProviderConnection.Aspatial)
            table_property = self._table_by_name(table_properties, 'myNewAspatialTable')
            self.assertIsNotNone(table_property)
            self.assertEqual(table_property.maxCoordinateDimensions(), 0)
            self.assertEqual(table_property.tableName(), 'myNewAspatialTable')
            self.assertEqual(table_property.geometryColumnCount(), 0)
            self.assertEqual(table_property.geometryColumn(), '')
            self.assertEqual(table_property.defaultName(), 'myNewAspatialTable')
            cols = table_property.geometryColumnTypes()
            # We always return geom col types, even when there is no geometry
            self.assertEqual(cols[0].wkbType, QgsWkbTypes.NoGeometry)
            self.assertFalse(cols[0].crs.isValid())
            self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Raster)
            self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Vector)
            self.assertTrue(table_property.flags() & QgsAbstractDatabaseProviderConnection.Aspatial)

            # Check executeSql
            if capabilities & QgsAbstractDatabaseProviderConnection.ExecuteSql:
                if schema:
                    table = "\"%s\".\"myNewAspatialTable\"" % schema
                else:
                    table = 'myNewAspatialTable'

                # MSSQL literal syntax for UTF8 requires 'N' prefix
                # Oracle date time definition needs some prefix
                sql = "INSERT INTO %s (\"string_t\", \"long_t\", \"double_t\", \"integer_t\", \"date_t\", \"datetime_t\", \"time_t\") VALUES (%s'QGIS Rocks - \U0001f604', 666, 1.234, 1234, %s '2019-07-08', %s, '12:00:13.00')" % (
                    table, 'N' if self.providerKey == 'mssql' else '',
                    "DATE" if self.providerKey == 'oracle' else '',
                    "TIMESTAMP '2019-07-08 12:00:12'" if self.providerKey == 'oracle' else "'2019-07-08T12:00:12'"
                )
                res = conn.executeSql(sql)
                self.assertEqual(res, [])
                sql = "SELECT \"string_t\", \"long_t\", \"double_t\", \"integer_t\", \"date_t\", \"datetime_t\" FROM %s" % table
                res = conn.executeSql(sql)

                expected_date = QtCore.QDate(2019, 7, 8)

                # GPKG and spatialite have no type for time
                if self.treat_date_as_string():
                    expected_date = '2019-07-08'

                # Oracle DATE type contains date and time and so returns a QDateTime object
                elif self.providerKey == 'oracle':
                    expected_date = QtCore.QDateTime(QtCore.QDate(2019, 7, 8))

                self.assertEqual(res, [['QGIS Rocks - \U0001f604', 666, 1.234, 1234, expected_date, QtCore.QDateTime(2019, 7, 8, 12, 0, 12)]])

                # Test column names
                res = conn.execSql(sql)
                rows = res.rows()
                self.assertEqual(rows, [['QGIS Rocks - \U0001f604', 666, 1.234, 1234, expected_date, QtCore.QDateTime(2019, 7, 8, 12, 0, 12)]])
                self.assertEqual(res.columns(), ['string_t', 'long_t', 'double_t', 'integer_t', 'date_t', 'datetime_t'])

                # Test iterator
                old_rows = rows
                res = conn.execSql(sql)
                rows = []
                self.assertTrue(res.hasNextRow())

                for row in res:
                    rows.append(row)

                self.assertEqual(rows, old_rows)

                # Java style
                res = conn.execSql(sql)
                rows = []
                self.assertTrue(res.hasNextRow())
                while res.hasNextRow():
                    rows.append(res.nextRow())

                self.assertFalse(res.hasNextRow())

                # Test time_t
                sql = "SELECT \"time_t\" FROM %s" % table
                res = conn.executeSql(sql)

                # This does not work in MSSQL and returns a QByteArray, we have no way to know that it is a time
                # value and there is no way we can convert it.
                if self.providerKey != 'mssql':
                    self.assertIn(res, ([[QtCore.QTime(12, 0, 13)]], [['12:00:13.00']]))

                sql = "DELETE FROM %s WHERE \"string_t\" = %s'QGIS Rocks - \U0001f604'" % (
                    table, 'N' if self.providerKey == 'mssql' else '')
                res = conn.executeSql(sql)
                self.assertEqual(res, [])
                sql = "SELECT \"string_t\", \"integer_t\" FROM %s" % table
                res = conn.executeSql(sql)
                self.assertEqual(res, [])

            # Check that we do NOT get the aspatial table when querying for vectors
            table_names = self._table_names(conn.tables(schema, QgsAbstractDatabaseProviderConnection.Vector))
            self.assertTrue(self.myNewTable in table_names)
            self.assertFalse('myNewAspatialTable' in table_names)

            # Query for rasters (in qgis_test schema or no schema for GPKG, spatialite has no support)
            if self.providerKey not in ('spatialite', 'mssql', 'hana', 'oracle'):
                table_properties = conn.tables('qgis_test', QgsAbstractDatabaseProviderConnection.Raster)
                # At least one raster should be there (except for spatialite)
                self.assertTrue(len(table_properties) >= 1)
                table_property = table_properties[0]
                self.assertTrue(table_property.flags() & QgsAbstractDatabaseProviderConnection.Raster)
                self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Vector)
                self.assertFalse(table_property.flags() & QgsAbstractDatabaseProviderConnection.Aspatial)

            if capabilities & QgsAbstractDatabaseProviderConnection.RenameVectorTable:
                # Rename
                conn.renameVectorTable(schema, self.myNewTable, self.myVeryNewTable)
                tables = self._table_names(conn.tables(schema))
                self.assertFalse(self.myNewTable in tables)
                self.assertTrue(self.myVeryNewTable in tables)
                # Rename it back
                conn.renameVectorTable(schema, self.myVeryNewTable, self.myNewTable)
                tables = self._table_names(conn.tables(schema))
                self.assertTrue(self.myNewTable in tables)
                self.assertFalse(self.myVeryNewTable in tables)

            # Vacuum
            if capabilities & QgsAbstractDatabaseProviderConnection.Vacuum:
                conn.vacuum(schema, self.myNewTable)

            # Spatial index
            spatial_index_exists = False
            # we don't initially know if a spatial index exists -- some formats may create them by default, others not
            if capabilities & QgsAbstractDatabaseProviderConnection.SpatialIndexExists:
                spatial_index_exists = conn.spatialIndexExists(schema, self.myNewTable, self.geometryColumnName)
            if capabilities & QgsAbstractDatabaseProviderConnection.DeleteSpatialIndex:
                if spatial_index_exists:
                    conn.deleteSpatialIndex(schema, self.myNewTable, self.geometryColumnName)
                if capabilities & QgsAbstractDatabaseProviderConnection.SpatialIndexExists:
                    self.assertFalse(conn.spatialIndexExists(schema, self.myNewTable, self.geometryColumnName))

            if capabilities & (QgsAbstractDatabaseProviderConnection.CreateSpatialIndex | QgsAbstractDatabaseProviderConnection.SpatialIndexExists):
                options = QgsAbstractDatabaseProviderConnection.SpatialIndexOptions()
                options.geometryColumnName = self.geometryColumnName

                if not conn.spatialIndexExists(schema, self.myNewTable, options.geometryColumnName):
                    conn.createSpatialIndex(schema, self.myNewTable, options)

                self.assertTrue(conn.spatialIndexExists(schema, self.myNewTable, self.geometryColumnName))

                # now we know for certain a spatial index exists, let's retry dropping it
                if capabilities & QgsAbstractDatabaseProviderConnection.DeleteSpatialIndex:
                    conn.deleteSpatialIndex(schema, self.myNewTable, self.geometryColumnName)
                    if capabilities & QgsAbstractDatabaseProviderConnection.SpatialIndexExists:
                        self.assertFalse(conn.spatialIndexExists(schema, self.myNewTable, self.geometryColumnName))

            if capabilities & QgsAbstractDatabaseProviderConnection.DropSchema:
                # Drop schema (should fail)
                with self.assertRaises(QgsProviderConnectionException) as ex:
                    conn.dropSchema(schema)

            # Check some column types operations
            table = self._table_by_name(conn.tables(schema), self.myNewTable)
            self.assertEqual(len(table.geometryColumnTypes()), 1)
            ct = table.geometryColumnTypes()[0]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)
            # Add a new (existing type)
            table.addGeometryColumnType(QgsWkbTypes.LineString, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(len(table.geometryColumnTypes()), 1)
            ct = table.geometryColumnTypes()[0]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)
            # Add a new one
            table.addGeometryColumnType(QgsWkbTypes.LineString, QgsCoordinateReferenceSystem.fromEpsgId(4326))
            self.assertEqual(len(table.geometryColumnTypes()), 2)
            ct = table.geometryColumnTypes()[0]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(3857))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)
            ct = table.geometryColumnTypes()[1]
            self.assertEqual(ct.crs, QgsCoordinateReferenceSystem.fromEpsgId(4326))
            self.assertEqual(ct.wkbType, QgsWkbTypes.LineString)

            # Check fields
            fields = conn.fields(schema, self.myNewTable)
            for f in ['string_t', 'long_t', 'double_t', 'integer_t', 'date_t', 'datetime_t', 'time_t']:
                self.assertTrue(f in fields.names())

            if capabilities & QgsAbstractDatabaseProviderConnection.AddField:
                field = QgsField('short_lived_field', QVariant.Int, 'integer')
                conn.addField(field, schema, self.myNewTable)
                fields = conn.fields(schema, self.myNewTable)
                self.assertTrue('short_lived_field' in fields.names())

                if capabilities & QgsAbstractDatabaseProviderConnection.DeleteField:
                    conn.deleteField('short_lived_field', schema, self.myNewTable)
                    # This fails on Travis for spatialite, for no particular reason
                    if self.providerKey == 'spatialite' and not os.environ.get('TRAVIS', False):
                        fields = conn.fields(schema, self.myNewTable)
                        self.assertFalse('short_lived_field' in fields.names())

            # Drop table
            conn.dropVectorTable(schema, self.myNewTable)
            conn.dropVectorTable(schema, 'myNewAspatialTable')
            table_names = self._table_names(conn.tables(schema))
            self.assertFalse(self.myNewTable in table_names)

            if capabilities & QgsAbstractDatabaseProviderConnection.DropSchema:
                # Drop schema
                conn.dropSchema(schema)
                self.assertFalse(schema in conn.schemas())

        conns = md.connections()
        self.assertTrue(isinstance(list(conns.values())[0], QgsAbstractDatabaseProviderConnection))

        # Remove connection
        spy_deleted = QSignalSpy(md.connectionDeleted)
        md.deleteConnection('qgis_test1')
        self.assertEqual(list(md.connections().values()), [])
        self.assertEqual(len(spy_deleted), 1)
Ejemplo n.º 43
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))

        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE,
                                             context)

        expression = QgsExpression(
            self.parameterAsString(parameters, self.EXPRESSION, context))
        if expression.hasParserError():
            raise QgsProcessingException(expression.parserErrorString())

        expressionContext = self.createExpressionContext(
            parameters, context, source)
        expression.prepare(expressionContext)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        (sink,
         dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                         fields, QgsWkbTypes.Point,
                                         source.sourceCrs(),
                                         QgsFeatureSink.RegeneratePrimaryKey)
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        da = QgsDistanceArea()
        da.setSourceCrs(source.sourceCrs(), context.transformContext())
        da.setEllipsoid(context.project().ellipsoid())

        total = 100.0 / source.featureCount() if source.featureCount() else 0
        current_progress = 0
        for current, f in enumerate(source.getFeatures()):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            current_progress = total * current
            feedback.setProgress(current_progress)

            expressionContext.setFeature(f)
            value = expression.evaluate(expressionContext)
            if expression.hasEvalError():
                feedback.pushInfo(
                    self.tr('Evaluation error for feature ID {}: {}').format(
                        f.id(), expression.evalErrorString()))
                continue

            fGeom = f.geometry()
            engine = QgsGeometry.createGeometryEngine(fGeom.constGet())
            engine.prepareGeometry()

            bbox = fGeom.boundingBox()
            if strategy == 0:
                pointCount = int(value)
            else:
                pointCount = int(round(value * da.measureArea(fGeom)))

            if pointCount == 0:
                feedback.pushInfo(
                    "Skip feature {} as number of points for it is 0.".format(
                        f.id()))
                continue

            index = QgsSpatialIndex()
            points = dict()

            nPoints = 0
            nIterations = 0
            maxIterations = pointCount * 200
            feature_total = total / pointCount if pointCount else 1

            random.seed()

            while nIterations < maxIterations and nPoints < pointCount:
                if feedback.isCanceled():
                    break

                rx = bbox.xMinimum() + bbox.width() * random.random()
                ry = bbox.yMinimum() + bbox.height() * random.random()

                p = QgsPointXY(rx, ry)
                geom = QgsGeometry.fromPointXY(p)
                if engine.contains(geom.constGet()) and \
                        vector.checkMinDistance(p, index, minDistance, points):
                    f = QgsFeature(nPoints)
                    f.initAttributes(1)
                    f.setFields(fields)
                    f.setAttribute('id', nPoints)
                    f.setGeometry(geom)
                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    index.addFeature(f)
                    points[nPoints] = p
                    nPoints += 1
                    feedback.setProgress(current_progress +
                                         int(nPoints * feature_total))
                nIterations += 1

            if nPoints < pointCount:
                feedback.pushInfo(
                    self.tr('Could not generate requested number of random '
                            'points. Maximum number of attempts exceeded.'))

        feedback.setProgress(100)

        return {self.OUTPUT: dest_id}
Ejemplo n.º 44
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR), context)

        rasterPath = str(self.getParameterValue(self.INPUT_RASTER))

        rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
        geoTransform = rasterDS.GetGeoTransform()
        rasterDS = None

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('line_id', QVariant.Int, '', 10, 0))
        fields.append(QgsField('point_id', QVariant.Int, '', 10, 0))

        writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(
            fields, QgsWkbTypes.Point, layer.crs(), context)

        outFeature = QgsFeature()
        outFeature.setFields(fields)

        self.fid = 0
        self.lineId = 0
        self.pointId = 0

        features = QgsProcessingUtils.getFeatures(layer, context)
        total = 100.0 / layer.featureCount() if layer.featureCount() else 0
        for current, f in enumerate(features):
            geom = f.geometry()
            if geom.isMultipart():
                lines = geom.asMultiPolyline()
                for line in lines:
                    for i in range(len(line) - 1):
                        p1 = line[i]
                        p2 = line[i + 1]

                        (x1, y1) = raster.mapToPixel(p1.x(), p1.y(),
                                                     geoTransform)
                        (x2, y2) = raster.mapToPixel(p2.x(), p2.y(),
                                                     geoTransform)

                        self.buildLine(x1, y1, x2, y2, geoTransform, writer,
                                       outFeature)
            else:
                points = geom.asPolyline()
                for i in range(len(points) - 1):
                    p1 = points[i]
                    p2 = points[i + 1]

                    (x1, y1) = raster.mapToPixel(p1.x(), p1.y(), geoTransform)
                    (x2, y2) = raster.mapToPixel(p2.x(), p2.y(), geoTransform)

                    self.buildLine(x1, y1, x2, y2, geoTransform, writer,
                                   outFeature)

            self.pointId = 0
            self.lineId += 1

            feedback.setProgress(int(current * total))

        del writer
Ejemplo n.º 45
0
    def processAlgorithm(self, parameters, context, feedback):
        idx = self.parameterAsEnum(parameters, self.TYPE, context)

        hSpacing = self.parameterAsDouble(parameters, self.HSPACING, context)
        vSpacing = self.parameterAsDouble(parameters, self.VSPACING, context)
        hOverlay = self.parameterAsDouble(parameters, self.HOVERLAY, context)
        vOverlay = self.parameterAsDouble(parameters, self.VOVERLAY, context)

        crs = self.parameterAsCrs(parameters, self.CRS, context)
        bbox = self.parameterAsExtent(parameters, self.EXTENT, context, crs)

        if hSpacing <= 0 or vSpacing <= 0:
            raise QgsProcessingException(
                self.tr('Invalid grid spacing: {0}/{1}').format(
                    hSpacing, vSpacing))

        if bbox.width() < hSpacing:
            raise QgsProcessingException(
                self.tr(
                    'Horizontal spacing is too large for the covered area'))

        if hSpacing <= hOverlay or vSpacing <= vOverlay:
            raise QgsProcessingException(
                self.tr('Invalid overlay: {0}/{1}').format(hOverlay, vOverlay))

        if bbox.height() < vSpacing:
            raise QgsProcessingException(
                self.tr('Vertical spacing is too large for the covered area'))

        fields = QgsFields()
        fields.append(QgsField('left', QVariant.Double, '', 24, 16))
        fields.append(QgsField('top', QVariant.Double, '', 24, 16))
        fields.append(QgsField('right', QVariant.Double, '', 24, 16))
        fields.append(QgsField('bottom', QVariant.Double, '', 24, 16))
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        if idx == 0:
            outputWkb = QgsWkbTypes.Point
        elif idx == 1:
            outputWkb = QgsWkbTypes.LineString
        else:
            outputWkb = QgsWkbTypes.Polygon
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields, outputWkb, crs)
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        if idx == 0:
            self._pointGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay,
                            feedback)
        elif idx == 1:
            self._lineGrid(sink, bbox, hSpacing, vSpacing, hOverlay, vOverlay,
                           feedback)
        elif idx == 2:
            self._rectangleGrid(sink, bbox, hSpacing, vSpacing, hOverlay,
                                vOverlay, feedback)
        elif idx == 3:
            self._diamondGrid(sink, bbox, hSpacing, vSpacing, hOverlay,
                              vOverlay, feedback)
        elif idx == 4:
            self._hexagonGrid(sink, bbox, hSpacing, vSpacing, hOverlay,
                              vOverlay, feedback)

        return {self.OUTPUT: dest_id}
    def testFilter(self):
        """Test filter creation"""
        renderer = QgsCategorizedSymbolRenderer()
        renderer.setClassAttribute('field')

        renderer.addCategory(QgsRendererCategory('a', createMarkerSymbol(), 'a'))
        renderer.addCategory(QgsRendererCategory('b', createMarkerSymbol(), 'b'))
        renderer.addCategory(QgsRendererCategory('c', createMarkerSymbol(), 'c'))
        # add default category
        renderer.addCategory(QgsRendererCategory('', createMarkerSymbol(), 'default'))

        fields = QgsFields()
        fields.append(QgsField('field', QVariant.String))
        fields.append(QgsField('num', QVariant.Double))

        self.assertEqual(renderer.filter(fields), '')
        # remove categories, leaving default
        assert renderer.updateCategoryRenderState(0, False)
        self.assertEqual(renderer.filter(fields), "(\"field\") NOT IN ('a') OR (\"field\") IS NULL")
        assert renderer.updateCategoryRenderState(1, False)
        self.assertEqual(renderer.filter(fields), "(\"field\") NOT IN ('a','b') OR (\"field\") IS NULL")
        assert renderer.updateCategoryRenderState(2, False)
        self.assertEqual(renderer.filter(fields), "(\"field\") NOT IN ('a','b','c') OR (\"field\") IS NULL")
        # remove default category
        assert renderer.updateCategoryRenderState(3, False)
        self.assertEqual(renderer.filter(fields), "FALSE")
        # add back other categories, leaving default disabled
        assert renderer.updateCategoryRenderState(0, True)
        self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a')")
        assert renderer.updateCategoryRenderState(1, True)
        self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b')")
        assert renderer.updateCategoryRenderState(2, True)
        self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b','c')")

        renderer.deleteAllCategories()
        # just default category
        renderer.addCategory(QgsRendererCategory('', createMarkerSymbol(), 'default'))
        self.assertEqual(renderer.filter(fields), '')
        assert renderer.updateCategoryRenderState(0, False)
        self.assertEqual(renderer.filter(fields), 'FALSE')

        renderer.deleteAllCategories()
        # no default category
        renderer.addCategory(QgsRendererCategory('a', createMarkerSymbol(), 'a'))
        renderer.addCategory(QgsRendererCategory('b', createMarkerSymbol(), 'b'))
        renderer.addCategory(QgsRendererCategory('c', createMarkerSymbol(), 'c'))
        self.assertEqual(renderer.filter(fields), "(\"field\") IN ('a','b','c')")
        assert renderer.updateCategoryRenderState(0, False)
        self.assertEqual(renderer.filter(fields), "(\"field\") IN ('b','c')")
        assert renderer.updateCategoryRenderState(2, False)
        self.assertEqual(renderer.filter(fields), "(\"field\") IN ('b')")
        assert renderer.updateCategoryRenderState(1, False)
        self.assertEqual(renderer.filter(fields), "FALSE")

        renderer.deleteAllCategories()
        renderer.setClassAttribute('num')
        # numeric categories
        renderer.addCategory(QgsRendererCategory(1, createMarkerSymbol(), 'a'))
        renderer.addCategory(QgsRendererCategory(2, createMarkerSymbol(), 'b'))
        renderer.addCategory(QgsRendererCategory(3, createMarkerSymbol(), 'c'))
        self.assertEqual(renderer.filter(fields), '(\"num\") IN (1,2,3)')
        assert renderer.updateCategoryRenderState(0, False)
        self.assertEqual(renderer.filter(fields), "(\"num\") IN (2,3)")
        assert renderer.updateCategoryRenderState(2, False)
        self.assertEqual(renderer.filter(fields), "(\"num\") IN (2)")
        assert renderer.updateCategoryRenderState(1, False)
        self.assertEqual(renderer.filter(fields), "FALSE")
Ejemplo n.º 47
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))

        fields = QgsFields()
        fields.append(QgsField('POINTA', QVariant.Double, '', 24, 15))
        fields.append(QgsField('POINTB', QVariant.Double, '', 24, 15))
        fields.append(QgsField('POINTC', QVariant.Double, '', 24, 15))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Polygon,
                                               source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        pts = []
        ptDict = {}
        ptNdx = -1
        c = voronoi.Context()
        features = source.getFeatures()
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break

            geom = QgsGeometry(inFeat.geometry())
            if geom.isNull():
                continue
            if geom.isMultipart():
                points = geom.asMultiPoint()
            else:
                points = [geom.asPoint()]
            for n, point in enumerate(points):
                x = point.x()
                y = point.y()
                pts.append((x, y))
                ptNdx += 1
                ptDict[ptNdx] = (inFeat.id(), n)
            feedback.setProgress(int(current * total))

        if len(pts) < 3:
            raise QgsProcessingException(
                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) for i in uniqueSet])
        c.triangulate = True
        voronoi.voronoi(sl, c)
        triangles = c.triangles
        feat = QgsFeature()

        total = 100.0 / len(triangles) if triangles else 1
        for current, triangle in enumerate(triangles):
            if feedback.isCanceled():
                break

            indices = list(triangle)
            indices.append(indices[0])
            polygon = []
            attrs = []
            step = 0
            for index in indices:
                fid, n = ptDict[ids[index]]
                request = QgsFeatureRequest().setFilterFid(fid)
                inFeat = next(source.getFeatures(request))
                geom = QgsGeometry(inFeat.geometry())
                if geom.isMultipart():
                    point = QgsPointXY(geom.asMultiPoint()[n])
                else:
                    point = QgsPointXY(geom.asPoint())
                polygon.append(point)
                if step <= 3:
                    attrs.append(ids[index])
                step += 1
            feat.setAttributes(attrs)
            geometry = QgsGeometry().fromPolygonXY([polygon])
            feat.setGeometry(geometry)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 48
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], 1)
        self.assertEqual(f1.attributes()[1], 'foo')
        self.assertEqual(f1.attributes()[2], 'blah')
        self.assertEqual(f1.attributes()[3], QVariant())

        # 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')
Ejemplo n.º 49
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.VECTOR))
        pointCount = float(self.getParameterValue(self.POINT_NUMBER))
        minDistance = float(self.getParameterValue(self.MIN_DISTANCE))

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QGis.WKBPoint,
            layer.dataProvider().crs())

        nPoints = 0
        nIterations = 0
        maxIterations = pointCount * 200
        featureCount = layer.featureCount()
        total = 100.0 / pointCount

        index = QgsSpatialIndex()
        points = dict()

        da = QgsDistanceArea()
        request = QgsFeatureRequest()

        random.seed()

        while nIterations < maxIterations and nPoints < pointCount:
            # pick random feature
            fid = random.randint(0, featureCount - 1)
            f = layer.getFeatures(request.setFilterFid(fid)).next()
            fGeom = QgsGeometry(f.geometry())

            if fGeom.isMultipart():
                lines = fGeom.asMultiPolyline()
                # pick random line
                lineId = random.randint(0, len(lines) - 1)
                vertices = lines[lineId]
            else:
                vertices = fGeom.asPolyline()

            # pick random segment
            if len(vertices) == 2:
                vid = 0
            else:
                vid = random.randint(0, len(vertices) - 2)
            startPoint = vertices[vid]
            endPoint = vertices[vid + 1]
            length = da.measureLine(startPoint, endPoint)
            dist = length * random.random()

            if dist > minDistance:
                d = dist / (length - dist)
                rx = (startPoint.x() + d * endPoint.x()) / (1 + d)
                ry = (startPoint.y() + d * endPoint.y()) / (1 + d)

                # generate random point
                pnt = QgsPoint(rx, ry)
                geom = QgsGeometry.fromPoint(pnt)
                if vector.checkMinDistance(pnt, index, minDistance, points):
                    f = QgsFeature(nPoints)
                    f.initAttributes(1)
                    f.setFields(fields)
                    f.setAttribute('id', nPoints)
                    f.setGeometry(geom)
                    writer.addFeature(f)
                    index.insertFeature(f)
                    points[nPoints] = pnt
                    nPoints += 1
                    progress.setPercentage(int(nPoints * total))
            nIterations += 1

        if nPoints < pointCount:
            ProcessingLog.addToLog(
                ProcessingLog.LOG_INFO,
                self.tr('Can not generate requested number of random points. '
                        'Maximum number of attempts exceeded.'))

        del writer
Ejemplo n.º 50
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))

        pointCount = self.parameterAsDouble(parameters, self.POINTS_NUMBER, context)
        minDistance = self.parameterAsDouble(parameters, self.MIN_DISTANCE, context)

        bbox = source.sourceExtent()
        sourceIndex = QgsSpatialIndex(source, feedback)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.Point, source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        nPoints = 0
        nIterations = 0
        maxIterations = pointCount * 200
        total = 100.0 / pointCount if pointCount else 1

        index = QgsSpatialIndex()
        points = dict()

        random.seed()

        while nIterations < maxIterations and nPoints < pointCount:
            if feedback.isCanceled():
                break

            rx = bbox.xMinimum() + bbox.width() * random.random()
            ry = bbox.yMinimum() + bbox.height() * random.random()

            p = QgsPointXY(rx, ry)
            geom = QgsGeometry.fromPointXY(p)
            ids = sourceIndex.intersects(geom.buffer(5, 5).boundingBox())
            if len(ids) > 0 and \
                    vector.checkMinDistance(p, index, minDistance, points):
                request = QgsFeatureRequest().setFilterFids(ids).setSubsetOfAttributes([])
                for f in source.getFeatures(request):
                    if feedback.isCanceled():
                        break

                    tmpGeom = f.geometry()
                    if geom.within(tmpGeom):
                        f = QgsFeature(nPoints)
                        f.initAttributes(1)
                        f.setFields(fields)
                        f.setAttribute('id', nPoints)
                        f.setGeometry(geom)
                        sink.addFeature(f, QgsFeatureSink.FastInsert)
                        index.addFeature(f)
                        points[nPoints] = p
                        nPoints += 1
                        feedback.setProgress(int(nPoints * total))
            nIterations += 1

        if nPoints < pointCount:
            feedback.pushInfo(self.tr('Could not generate requested number of random points. '
                                      'Maximum number of attempts exceeded.'))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 51
0
    def processAlgorithm(self, progress):
        target = dataobjects.getObjectFromUri(
            self.getParameterValue(self.TARGET))
        join = dataobjects.getObjectFromUri(
            self.getParameterValue(self.JOIN))
        predicates = self.getParameterValue(self.PREDICATE)
        precision = self.getParameterValue(self.PRECISION)

        summary = self.getParameterValue(self.SUMMARY) == 1
        keep = self.getParameterValue(self.KEEP) == 1

        sumList = self.getParameterValue(self.STATS).lower().split(',')

        targetFields = target.fields()
        joinFields = join.fields()

        fieldList = QgsFields()

        if not summary:
            joinFields = vector.testForUniqueness(targetFields, joinFields)
            seq = range(len(targetFields) + len(joinFields))
            targetFields.extend(joinFields)
            targetFields = dict(zip(seq, targetFields))
        else:
            numFields = {}
            for j in xrange(len(joinFields)):
                if joinFields[j].type() in [QVariant.Int, QVariant.Double, QVariant.LongLong, QVariant.UInt, QVariant.ULongLong]:
                    numFields[j] = []
                    for i in sumList:
                        field = QgsField(i + unicode(joinFields[j].name()), QVariant.Double, '', 24, 16)
                        fieldList.append(field)
            field = QgsField('count', QVariant.Double, '', 24, 16)
            fieldList.append(field)
            joinFields = vector.testForUniqueness(targetFields, fieldList)
            targetFields.extend(fieldList)
            seq = range(len(targetFields))
            targetFields = dict(zip(seq, targetFields))

        fields = QgsFields()
        for f in targetFields.values():
            fields.append(f)

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, target.wkbType(), target.crs())

        outFeat = QgsFeature()
        inFeatB = QgsFeature()
        inGeom = QgsGeometry()

        index = vector.spatialindex(join)

        mapP2 = dict()
        features = vector.features(join)
        for f in features:
            mapP2[f.id()] = QgsFeature(f)

        features = vector.features(target)
        total = 100.0 / len(features)
        for c, f in enumerate(features):
            atMap1 = f.attributes()
            outFeat.setGeometry(f.geometry())
            inGeom = vector.snapToPrecision(f.geometry(), precision)
            none = True
            joinList = []
            if inGeom.type() == QgsWkbTypes.PointGeometry:
                bbox = inGeom.buffer(10, 2).boundingBox()
            else:
                bbox = inGeom.boundingBox()
            bufferedBox = vector.bufferedBoundingBox(bbox, 0.51 * precision)
            joinList = index.intersects(bufferedBox)
            if len(joinList) > 0:
                count = 0
                for i in joinList:
                    inFeatB = mapP2[i]
                    inGeomB = vector.snapToPrecision(inFeatB.geometry(), precision)

                    res = False
                    for predicate in predicates:
                        if predicate == 'intersects':
                            res = inGeom.intersects(inGeomB)
                        elif predicate == 'contains':
                            res = inGeom.contains(inGeomB)
                        elif predicate == 'equals':
                            res = inGeom.equals(inGeomB)
                        elif predicate == 'touches':
                            res = inGeom.touches(inGeomB)
                        elif predicate == 'overlaps':
                            res = inGeom.overlaps(inGeomB)
                        elif predicate == 'within':
                            res = inGeom.within(inGeomB)
                        elif predicate == 'crosses':
                            res = inGeom.crosses(inGeomB)
                        if res:
                            break

                    if res:
                        count = count + 1
                        none = False
                        atMap2 = inFeatB.attributes()
                        if not summary:
                            atMap = atMap1
                            atMap2 = atMap2
                            atMap.extend(atMap2)
                            atMap = dict(zip(seq, atMap))
                            break
                        else:
                            for j in numFields.keys():
                                numFields[j].append(atMap2[j])

                if summary and not none:
                    atMap = atMap1
                    for j in numFields.keys():
                        for k in sumList:
                            if k == 'sum':
                                atMap.append(sum(self._filterNull(numFields[j])))
                            elif k == 'mean':
                                try:
                                    nn_count = sum(1 for _ in self._filterNull(numFields[j]))
                                    atMap.append(sum(self._filterNull(numFields[j])) / nn_count)
                                except ZeroDivisionError:
                                    atMap.append(NULL)
                            elif k == 'min':
                                try:
                                    atMap.append(min(self._filterNull(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)
                            elif k == 'median':
                                atMap.append(self._median(numFields[j]))
                            else:
                                try:
                                    atMap.append(max(self._filterNull(numFields[j])))
                                except ValueError:
                                    atMap.append(NULL)

                        numFields[j] = []
                    atMap.append(count)
                    atMap = dict(zip(seq, atMap))
            if none:
                outFeat.setAttributes(atMap1)
            else:
                outFeat.setAttributes(atMap.values())

            if keep:
                writer.addFeature(outFeat)
            else:
                if not none:
                    writer.addFeature(outFeat)

            progress.setPercentage(int(c * total))
        del writer
Ejemplo n.º 52
0
    def processAlgorithm(self, parameters, context, feedback):
        spacing = self.parameterAsDouble(parameters, self.SPACING, context)
        inset = self.parameterAsDouble(parameters, self.INSET, context)
        randomize = self.parameterAsBool(parameters, self.RANDOMIZE, context)
        isSpacing = self.parameterAsBool(parameters, self.IS_SPACING, context)
        crs = self.parameterAsCrs(parameters, self.CRS, context)
        extent = self.parameterAsExtent(parameters, self.EXTENT, context, crs)

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 10, 0))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.Point, crs)
        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        if randomize:
            seed()

        area = extent.width() * extent.height()
        if isSpacing:
            pSpacing = spacing
        else:
            pSpacing = sqrt(area / spacing)

        f = QgsFeature()
        f.initAttributes(1)
        f.setFields(fields)

        count = 0
        id = 0
        total = 100.0 / (area / pSpacing)
        y = extent.yMaximum() - inset

        extent_geom = QgsGeometry.fromRect(extent)
        extent_engine = QgsGeometry.createGeometryEngine(extent_geom.constGet())
        extent_engine.prepareGeometry()

        while y >= extent.yMinimum():
            x = extent.xMinimum() + inset
            while x <= extent.xMaximum():
                if feedback.isCanceled():
                    break

                if randomize:
                    geom = QgsGeometry(QgsPoint(
                        uniform(x - (pSpacing / 2.0), x + (pSpacing / 2.0)),
                        uniform(y - (pSpacing / 2.0), y + (pSpacing / 2.0))))
                else:
                    geom = QgsGeometry(QgsPoint(x, y))

                if extent_engine.intersects(geom.constGet()):
                    f.setAttributes([id])
                    f.setGeometry(geom)
                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    x += pSpacing
                    id += 1

                count += 1
                feedback.setProgress(int(count * total))

            y = y - pSpacing

        return {self.OUTPUT: dest_id}
Ejemplo n.º 53
0
    def processAlgorithm(self, parameters, context, feedback):

        source = self.parameterAsSource(
            parameters,
            self.INPUT,
            context
        )

        sampled_raster = self.parameterAsRasterLayer(
            parameters,
            self.RASTERCOPY,
            context
        )

        columnPrefix = self.parameterAsString(
            parameters,
            self.COLUMN_PREFIX,
            context
        )

        if source is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

        source_fields = source.fields()
        raster_fields = QgsFields()

        # append field to vector as columnPrefix_bandCount
        for b in range(sampled_raster.bandCount()):
            raster_fields.append(QgsField(
                columnPrefix + str('_{}'.format(b + 1)), QVariant.Double
            )
            )

        # combine all the vector fields
        out_fields = QgsProcessingUtils.combineFields(source_fields, raster_fields)

        (sink, dest_id) = self.parameterAsSink(
            parameters,
            self.OUTPUT,
            context,
            out_fields,
            source.wkbType(),
            source.sourceCrs()
        )

        if sink is None:
            raise QgsProcessingException(self.invalidSinkError(parameters, self.OUTPUT))

        total = 100.0 / source.featureCount() if source.featureCount() else 0
        features = source.getFeatures()

        # create the coordinates transformation context
        ct = QgsCoordinateTransform(source.sourceCrs(), sampled_raster.crs(), context.transformContext())

        for n, i in enumerate(source.getFeatures()):

            attrs = i.attributes()

            if i.geometry().isMultipart() and i.geometry().constGet().partCount() > 1:
                sink.addFeature(i, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(n * total))
                feedback.reportError(self.tr('Impossible to sample data of multipart feature {}.').format(i.id()))
                continue

            # get the feature geometry as point
            point = QgsPointXY()
            if i.geometry().isMultipart():
                point = i.geometry().asMultiPoint()[0]
            else:
                point = i.geometry().asPoint()

            # reproject to raster crs
            try:
                point = ct.transform(point)
            except QgsCsException:
                for b in range(sampled_raster.bandCount()):
                    attrs.append(None)
                i.setAttributes(attrs)
                sink.addFeature(i, QgsFeatureSink.FastInsert)
                feedback.setProgress(int(n * total))
                feedback.reportError(self.tr('Could not reproject feature {} to raster CRS').format(i.id()))
                continue

            for b in range(sampled_raster.bandCount()):
                value, ok = sampled_raster.dataProvider().sample(point, b + 1)
                if ok:
                    attrs.append(value)
                else:
                    attrs.append(NULL)

            i.setAttributes(attrs)

            sink.addFeature(i, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(n * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 54
0
class PyProvider(QgsVectorDataProvider):

    next_feature_id = 1

    @classmethod
    def providerKey(cls):
        """Returns the memory provider key"""
        return 'pythonprovider'

    @classmethod
    def description(cls):
        """Returns the memory provider description"""
        return 'Python Test Provider'

    @classmethod
    def createProvider(cls, uri, providerOptions):
        return PyProvider(uri, providerOptions)

    # Implementation of functions from QgsVectorDataProvider

    def __init__(self,
                 uri='',
                 providerOptions=QgsDataProvider.ProviderOptions()):
        super().__init__(uri)
        # Use the memory layer to parse the uri
        mlayer = QgsVectorLayer(uri, 'ml', 'memory')
        self.setNativeTypes(mlayer.dataProvider().nativeTypes())
        self._uri = uri
        self._fields = mlayer.fields()
        self._wkbType = mlayer.wkbType()
        self._features = {}
        self._extent = QgsRectangle()
        self._extent.setMinimal()
        self._subset_string = ''
        self._crs = mlayer.crs()
        self._spatialindex = None
        self._provider_options = providerOptions
        if 'index=yes' in self._uri:
            self.createSpatialIndex()

    def featureSource(self):
        return PyFeatureSource(self)

    def dataSourceUri(self, expandAuthConfig=True):
        return self._uri

    def storageType(self):
        return "Python test memory storage"

    def getFeatures(self, request=QgsFeatureRequest()):
        return QgsFeatureIterator(
            PyFeatureIterator(PyFeatureSource(self), request))

    def uniqueValues(self, fieldIndex, limit=1):
        results = set()
        if fieldIndex >= 0 and fieldIndex < self.fields().count():
            req = QgsFeatureRequest()
            req.setFlags(QgsFeatureRequest.NoGeometry)
            req.setSubsetOfAttributes([fieldIndex])
            for f in self.getFeatures(req):
                results.add(f.attributes()[fieldIndex])
        return results

    def wkbType(self):
        return self._wkbType

    def featureCount(self):
        if not self.subsetString():
            return len(self._features)
        else:
            req = QgsFeatureRequest()
            req.setFlags(QgsFeatureRequest.NoGeometry)
            req.setSubsetOfAttributes([])
            return len([f for f in self.getFeatures(req)])

    def fields(self):
        return self._fields

    def addFeatures(self, flist, flags=None):
        added = False
        f_added = []
        for f in flist:
            if f.hasGeometry() and (f.geometry().wkbType() != self.wkbType()):
                return added, f_added

        for f in flist:
            _f = QgsFeature(self.fields())
            _f.setGeometry(f.geometry())
            attrs = [None for i in range(_f.fields().count())]
            for i in range(min(len(attrs), len(f.attributes()))):
                attrs[i] = f.attributes()[i]
            _f.setAttributes(attrs)
            _f.setId(self.next_feature_id)
            self._features[self.next_feature_id] = _f
            self.next_feature_id += 1
            added = True
            f_added.append(_f)

            if self._spatialindex is not None:
                self._spatialindex.insertFeature(_f)

        if len(f_added):
            self.clearMinMaxCache()
            self.updateExtents()

        return added, f_added

    def deleteFeatures(self, ids):
        if not ids:
            return True
        removed = False
        for id in ids:
            if id in self._features:
                if self._spatialindex is not None:
                    self._spatialindex.deleteFeature(self._features[id])
                del self._features[id]
                removed = True
        if removed:
            self.clearMinMaxCache()
            self.updateExtents()
        return removed

    def addAttributes(self, attrs):
        try:
            for new_f in attrs:
                if new_f.type() not in (QVariant.Int, QVariant.Double,
                                        QVariant.String, QVariant.Date,
                                        QVariant.Time, QVariant.DateTime,
                                        QVariant.LongLong, QVariant.StringList,
                                        QVariant.List):
                    continue
                self._fields.append(new_f)
                for f in self._features.values():
                    old_attrs = f.attributes()
                    old_attrs.append(None)
                    f.setAttributes(old_attrs)
            self.clearMinMaxCache()
            return True
        except Exception:
            return False

    def renameAttributes(self, renamedAttributes):
        result = True
        # We need to replace all fields because python bindings return a copy from [] and at()
        new_fields = [self._fields.at(i) for i in range(self._fields.count())]
        for fieldIndex, new_name in renamedAttributes.items():
            if fieldIndex < 0 or fieldIndex >= self._fields.count():
                result = False
                continue
            if self._fields.indexFromName(new_name) >= 0:
                #field name already in use
                result = False
                continue
            new_fields[fieldIndex].setName(new_name)
        if result:
            self._fields = QgsFields()
            for i in range(len(new_fields)):
                self._fields.append(new_fields[i])
        return result

    def deleteAttributes(self, attributes):
        attrIdx = sorted(attributes, reverse=True)

        # delete attributes one-by-one with decreasing index
        for idx in attrIdx:
            self._fields.remove(idx)
            for f in self._features.values():
                attr = f.attributes()
                del (attr[idx])
                f.setAttributes(attr)
        self.clearMinMaxCache()
        return True

    def changeAttributeValues(self, attr_map):
        for feature_id, attrs in attr_map.items():
            try:
                f = self._features[feature_id]
            except KeyError:
                continue
            for k, v in attrs.items():
                f.setAttribute(k, v)
        self.clearMinMaxCache()
        return True

    def changeGeometryValues(self, geometry_map):
        for feature_id, geometry in geometry_map.items():
            try:
                f = self._features[feature_id]
                f.setGeometry(geometry)
            except KeyError:
                continue
        self.updateExtents()
        return True

    def allFeatureIds(self):
        return list(self._features.keys())

    def subsetString(self):
        return self._subset_string

    def setSubsetString(self, subsetString):
        if subsetString == self._subset_string:
            return True
        self._subset_string = subsetString
        self.updateExtents()
        self.clearMinMaxCache()
        self.dataChanged.emit()
        return True

    def supportsSubsetString(self):
        return True

    def createSpatialIndex(self):
        if self._spatialindex is None:
            self._spatialindex = QgsSpatialIndex()
            for f in self._features:
                self._spatialindex.insertFeature(f)
        return True

    def capabilities(self):
        return QgsVectorDataProvider.AddFeatures | QgsVectorDataProvider.DeleteFeatures | QgsVectorDataProvider.CreateSpatialIndex | QgsVectorDataProvider.ChangeGeometries | QgsVectorDataProvider.ChangeAttributeValues | QgsVectorDataProvider.AddAttributes | QgsVectorDataProvider.DeleteAttributes | QgsVectorDataProvider.RenameAttributes | QgsVectorDataProvider.SelectAtId | QgsVectorDataProvider.CircularGeometries

    #/* Implementation of functions from QgsDataProvider */

    def name(self):
        return self.providerKey()

    def extent(self):
        if self._extent.isEmpty() and self._features:
            self._extent.setMinimal()
            if not self._subset_string:
                # fast way - iterate through all features
                for feat in self._features.values():
                    if feat.hasGeometry():
                        self._extent.combineExtentWith(
                            feat.geometry().boundingBox())
            else:
                for f in self.getFeatures(
                        QgsFeatureRequest().setSubsetOfAttributes([])):
                    if f.hasGeometry():
                        self._extent.combineExtentWith(
                            f.geometry().boundingBox())

        elif not self._features:
            self._extent.setMinimal()
        return QgsRectangle(self._extent)

    def updateExtents(self):
        self._extent.setMinimal()

    def isValid(self):
        return True

    def crs(self):
        return self._crs
Ejemplo n.º 55
0
    def processAlgorithm(self, parameters, context, feedback):
        # Get variables from dialog
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        field_name = self.parameterAsString(parameters, self.FIELD, context)
        kneighbors = self.parameterAsInt(parameters, self.KNEIGHBORS, context)
        use_field = bool(field_name)

        field_index = -1

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))

        current = 0

        # Get properties of the field the grouping is based on
        if use_field:
            field_index = source.fields().lookupField(field_name)
            if field_index >= 0:
                fields.append(
                    source.fields()[field_index]
                )  # Add a field with the name of the grouping field

                # Initialize writer
                (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                                       context, fields,
                                                       QgsWkbTypes.Polygon,
                                                       source.sourceCrs())
                if sink is None:
                    raise QgsProcessingException(
                        self.invalidSinkError(parameters, self.OUTPUT))

                success = False
                fid = 0

                # Get unique values of grouping field
                unique_values = source.uniqueValues(field_index)
                total = 100.0 / float(
                    source.featureCount() * len(unique_values))

                for unique in unique_values:
                    points = []
                    filter = QgsExpression.createFieldEqualityExpression(
                        field_name, unique)
                    request = QgsFeatureRequest().setFilterExpression(filter)
                    request.setSubsetOfAttributes([])
                    # Get features with the grouping attribute equal to the current grouping value
                    features = source.getFeatures(request)
                    for in_feature in features:
                        if feedback.isCanceled():
                            break
                        # Add points or vertices of more complex geometry
                        points.extend(extract_points(in_feature.geometry()))
                        current += 1
                        feedback.setProgress(int(current * total))
                    # A minimum of 3 points is necessary to proceed
                    if len(points) >= 3:
                        out_feature = QgsFeature()
                        the_hull = concave_hull(points, kneighbors)
                        if the_hull:
                            vertex = [
                                QgsPointXY(point[0], point[1])
                                for point in the_hull
                            ]
                            poly = QgsGeometry().fromPolygonXY([vertex])

                            out_feature.setGeometry(poly)
                            # Give the polygon the same attribute as the point grouping attribute
                            out_feature.setAttributes([fid, unique])
                            sink.addFeature(out_feature,
                                            QgsFeatureSink.FastInsert)
                            success = True  # at least one polygon created
                    fid += 1
                if not success:
                    raise QgsProcessingException(
                        'No hulls could be created. Most likely there were not at least three unique points in any of the groups.'
                    )
            else:
                # Field parameter provided but can't read from it
                raise QgsProcessingException('Unable to find grouping field')

        else:
            # Not grouped by field
            # Initialize writer
            (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                                   context, fields,
                                                   QgsWkbTypes.Polygon,
                                                   source.sourceCrs())
            if sink is None:
                raise QgsProcessingException(
                    self.invalidSinkError(parameters, self.OUTPUT))

            points = []
            request = QgsFeatureRequest()
            request.setSubsetOfAttributes([])
            features = source.getFeatures(request)  # Get all features
            total = 100.0 / source.featureCount() if source.featureCount(
            ) else 0
            for in_feature in features:
                if feedback.isCanceled():
                    break
                # Add points or vertices of more complex geometry
                points.extend(extract_points(in_feature.geometry()))
                current += 1
                feedback.setProgress(int(current * total))

            # A minimum of 3 points is necessary to proceed
            if len(points) >= 3:
                out_feature = QgsFeature()
                the_hull = concave_hull(points, kneighbors)
                if the_hull:
                    vertex = [
                        QgsPointXY(point[0], point[1]) for point in the_hull
                    ]
                    poly = QgsGeometry().fromPolygonXY([vertex])

                    out_feature.setGeometry(poly)
                    out_feature.setAttributes([0])
                    sink.addFeature(out_feature, QgsFeatureSink.FastInsert)
                else:
                    # the_hull returns None only when there are less than three points after cleaning
                    raise QgsProcessingException(
                        'At least three unique points are required to create a concave hull.'
                    )
            else:
                raise QgsProcessingException(
                    'At least three points are required to create a concave hull.'
                )

        return {self.OUTPUT: dest_id}
Ejemplo n.º 56
0
    def doCheck(self, method, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT_LAYER, context)

        (valid_output_sink,
         valid_output_dest_id) = self.parameterAsSink(parameters,
                                                      self.VALID_OUTPUT,
                                                      context, source.fields(),
                                                      source.wkbType(),
                                                      source.sourceCrs())
        valid_count = 0

        invalid_fields = source.fields()
        invalid_fields.append(
            QgsField('_errors', QVariant.String, 'string', 255))
        (invalid_output_sink, invalid_output_dest_id) = self.parameterAsSink(
            parameters, self.INVALID_OUTPUT, context, invalid_fields,
            source.wkbType(), source.sourceCrs())
        invalid_count = 0

        error_fields = QgsFields()
        error_fields.append(QgsField('message', QVariant.String, 'string',
                                     255))
        (error_output_sink, error_output_dest_id) = self.parameterAsSink(
            parameters, self.ERROR_OUTPUT, context, error_fields,
            QgsWkbTypes.Point, source.sourceCrs())
        error_count = 0

        features = source.getFeatures(
            QgsFeatureRequest(),
            QgsProcessingFeatureSource.FlagSkipGeometryValidityChecks)
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break
            geom = inFeat.geometry()
            attrs = inFeat.attributes()

            valid = True
            if not geom.isNull() and not geom.isEmpty():
                errors = list(geom.validateGeometry(method))
                if errors:
                    # QGIS method return a summary at the end
                    if method == 1:
                        errors.pop()
                    valid = False
                    reasons = []
                    for error in errors:
                        errFeat = QgsFeature()
                        error_geom = QgsGeometry.fromPointXY(error.where())
                        errFeat.setGeometry(error_geom)
                        errFeat.setAttributes([error.what()])
                        if error_output_sink:
                            error_output_sink.addFeature(
                                errFeat, QgsFeatureSink.FastInsert)
                        error_count += 1

                        reasons.append(error.what())

                    reason = "\n".join(reasons)
                    if len(reason) > 255:
                        reason = reason[:252] + '…'
                    attrs.append(reason)

            outFeat = QgsFeature()
            outFeat.setGeometry(geom)
            outFeat.setAttributes(attrs)

            if valid:
                if valid_output_sink:
                    valid_output_sink.addFeature(outFeat,
                                                 QgsFeatureSink.FastInsert)
                valid_count += 1

            else:
                if invalid_output_sink:
                    invalid_output_sink.addFeature(outFeat,
                                                   QgsFeatureSink.FastInsert)
                invalid_count += 1

            feedback.setProgress(int(current * total))

        results = {
            self.VALID_COUNT: valid_count,
            self.INVALID_COUNT: invalid_count,
            self.ERROR_COUNT: error_count
        }
        if valid_output_sink:
            results[self.VALID_OUTPUT] = valid_output_dest_id
        if invalid_output_sink:
            results[self.INVALID_OUTPUT] = invalid_output_dest_id
        if error_output_sink:
            results[self.ERROR_OUTPUT] = error_output_dest_id
        return results
Ejemplo n.º 57
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))

        field_name = self.parameterAsString(parameters, self.FIELD, context)
        type = self.parameterAsEnum(parameters, self.TYPE, context)
        use_field = bool(field_name)

        field_index = -1

        fields = QgsFields()
        fields.append(QgsField('id', QVariant.Int, '', 20))

        if use_field:
            # keep original field type, name and parameters
            field_index = source.fields().lookupField(field_name)
            if field_index >= 0:
                fields.append(source.fields()[field_index])
        if type == 0:
            # envelope
            fields.append(QgsField('width', QVariant.Double, '', 20, 6))
            fields.append(QgsField('height', QVariant.Double, '', 20, 6))
            fields.append(QgsField('area', QVariant.Double, '', 20, 6))
            fields.append(QgsField('perimeter', QVariant.Double, '', 20, 6))
        elif type == 1:
            # oriented rect
            fields.append(QgsField('width', QVariant.Double, '', 20, 6))
            fields.append(QgsField('height', QVariant.Double, '', 20, 6))
            fields.append(QgsField('angle', QVariant.Double, '', 20, 6))
            fields.append(QgsField('area', QVariant.Double, '', 20, 6))
            fields.append(QgsField('perimeter', QVariant.Double, '', 20, 6))
        elif type == 2:
            # circle
            fields.append(QgsField('radius', QVariant.Double, '', 20, 6))
            fields.append(QgsField('area', QVariant.Double, '', 20, 6))
        elif type == 3:
            # convex hull
            fields.append(QgsField('area', QVariant.Double, '', 20, 6))
            fields.append(QgsField('perimeter', QVariant.Double, '', 20, 6))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.Polygon,
                                               source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        if field_index >= 0:
            geometry_dict = {}
            bounds_dict = {}
            total = 50.0 / source.featureCount() if source.featureCount(
            ) else 1
            features = source.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes([field_index]))
            for current, f in enumerate(features):
                if feedback.isCanceled():
                    break

                if not f.hasGeometry():
                    continue

                if type == 0:
                    # bounding boxes - calculate on the fly for efficiency
                    if not f.attributes()[field_index] in bounds_dict:
                        bounds_dict[f.attributes()[field_index]] = f.geometry(
                        ).boundingBox()
                    else:
                        bounds_dict[f.attributes()
                                    [field_index]].combineExtentWith(
                                        f.geometry().boundingBox())
                else:
                    if not f.attributes()[field_index] in geometry_dict:
                        geometry_dict[f.attributes()[field_index]] = [
                            f.geometry()
                        ]
                    else:
                        geometry_dict[f.attributes()[field_index]].append(
                            f.geometry())

                feedback.setProgress(int(current * total))

            if type == 0:
                # bounding boxes
                current = 0
                total = 50.0 / len(bounds_dict) if bounds_dict else 1
                for group, rect in bounds_dict.items():
                    if feedback.isCanceled():
                        break

                    # envelope
                    feature = QgsFeature()
                    feature.setGeometry(QgsGeometry.fromRect(rect))
                    feature.setAttributes([
                        current, group,
                        rect.width(),
                        rect.height(),
                        rect.area(),
                        rect.perimeter()
                    ])
                    sink.addFeature(feature, QgsFeatureSink.FastInsert)
                    geometry_dict[group] = None

                    feedback.setProgress(50 + int(current * total))
                    current += 1
            else:
                current = 0
                total = 50.0 / len(geometry_dict) if geometry_dict else 1

                for group, geometries in geometry_dict.items():
                    if feedback.isCanceled():
                        break

                    feature = self.createFeature(feedback, current, type,
                                                 geometries, group)
                    sink.addFeature(feature, QgsFeatureSink.FastInsert)
                    geometry_dict[group] = None

                    feedback.setProgress(50 + int(current * total))
                    current += 1
        else:
            total = 80.0 / source.featureCount() if source.featureCount(
            ) else 1
            features = source.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes([]))
            geometry_queue = []
            bounds = QgsRectangle()
            for current, f in enumerate(features):
                if feedback.isCanceled():
                    break

                if not f.hasGeometry():
                    continue

                if type == 0:
                    # bounding boxes, calculate on the fly for efficiency
                    bounds.combineExtentWith(f.geometry().boundingBox())
                else:
                    geometry_queue.append(f.geometry())
                feedback.setProgress(int(current * total))

            if not feedback.isCanceled():
                if type == 0:
                    feature = QgsFeature()
                    feature.setGeometry(QgsGeometry.fromRect(bounds))
                    feature.setAttributes([
                        0,
                        bounds.width(),
                        bounds.height(),
                        bounds.area(),
                        bounds.perimeter()
                    ])
                else:
                    feature = self.createFeature(feedback, 0, type,
                                                 geometry_queue)
                sink.addFeature(feature, QgsFeatureSink.FastInsert)

        return {self.OUTPUT: dest_id}
Ejemplo n.º 58
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        value_field_name = self.parameterAsString(parameters,
                                                  self.VALUES_FIELD_NAME,
                                                  context)
        category_field_names = self.parameterAsFields(
            parameters, self.CATEGORIES_FIELD_NAME, context)

        value_field_index = source.fields().lookupField(value_field_name)
        if value_field_index >= 0:
            value_field = source.fields().at(value_field_index)
        else:
            value_field = None
        category_field_indexes = [
            source.fields().lookupField(n) for n in category_field_names
        ]

        # generate output fields
        fields = QgsFields()
        for c in category_field_indexes:
            fields.append(source.fields().at(c))

        def addField(name):
            """
            Adds a field to the output, keeping the same data type as the value_field
            """
            field = QgsField(value_field)
            field.setName(name)
            fields.append(field)

        if value_field is None:
            field_type = 'none'
            fields.append(QgsField('count', QVariant.Int))
        elif value_field.isNumeric():
            field_type = 'numeric'
            fields.append(QgsField('count', QVariant.Int))
            fields.append(QgsField('unique', QVariant.Int))
            fields.append(QgsField('min', QVariant.Double))
            fields.append(QgsField('max', QVariant.Double))
            fields.append(QgsField('range', QVariant.Double))
            fields.append(QgsField('sum', QVariant.Double))
            fields.append(QgsField('mean', QVariant.Double))
            fields.append(QgsField('median', QVariant.Double))
            fields.append(QgsField('stddev', QVariant.Double))
            fields.append(QgsField('minority', QVariant.Double))
            fields.append(QgsField('majority', QVariant.Double))
            fields.append(QgsField('q1', QVariant.Double))
            fields.append(QgsField('q3', QVariant.Double))
            fields.append(QgsField('iqr', QVariant.Double))
        elif value_field.type() in (QVariant.Date, QVariant.Time,
                                    QVariant.DateTime):
            field_type = 'datetime'
            fields.append(QgsField('count', QVariant.Int))
            fields.append(QgsField('unique', QVariant.Int))
            fields.append(QgsField('empty', QVariant.Int))
            fields.append(QgsField('filled', QVariant.Int))
            # keep same data type for these fields
            addField('min')
            addField('max')
        else:
            field_type = 'string'
            fields.append(QgsField('count', QVariant.Int))
            fields.append(QgsField('unique', QVariant.Int))
            fields.append(QgsField('empty', QVariant.Int))
            fields.append(QgsField('filled', QVariant.Int))
            # keep same data type for these fields
            addField('min')
            addField('max')
            fields.append(QgsField('min_length', QVariant.Int))
            fields.append(QgsField('max_length', QVariant.Int))
            fields.append(QgsField('mean_length', QVariant.Double))

        request = QgsFeatureRequest().setFlags(QgsFeatureRequest.NoGeometry)
        if value_field is not None:
            attrs = [value_field_index]
        else:
            attrs = []
        attrs.extend(category_field_indexes)
        request.setSubsetOfAttributes(attrs)
        features = source.getFeatures(request)
        total = 50.0 / source.featureCount() if source.featureCount() else 0
        if field_type == 'none':
            values = defaultdict(lambda: 0)
        else:
            values = defaultdict(list)
        for current, feat in enumerate(features):
            if feedback.isCanceled():
                break

            feedback.setProgress(int(current * total))
            attrs = feat.attributes()
            cat = tuple([attrs[c] for c in category_field_indexes])
            if field_type == 'none':
                values[cat] += 1
                continue
            if field_type == 'numeric':
                if attrs[value_field_index] == NULL:
                    continue
                else:
                    value = float(attrs[value_field_index])
            elif field_type == 'string':
                if attrs[value_field_index] == NULL:
                    value = ''
                else:
                    value = str(attrs[value_field_index])
            elif attrs[value_field_index] == NULL:
                value = NULL
            else:
                value = attrs[value_field_index]
            values[cat].append(value)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.NoGeometry,
                                               QgsCoordinateReferenceSystem())

        if field_type == 'none':
            self.saveCounts(values, sink, feedback)
        elif field_type == 'numeric':
            self.calcNumericStats(values, sink, feedback)
        elif field_type == 'datetime':
            self.calcDateTimeStats(values, sink, feedback)
        else:
            self.calcStringStats(values, sink, feedback)

        return {self.OUTPUT: dest_id}
Ejemplo n.º 59
0
    def processAlgorithm(self, parameters, context, feedback):
        sourceA = self.parameterAsSource(parameters, self.INPUT, context)
        sourceB = self.parameterAsSource(parameters, self.INTERSECT, context)

        fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS,
                                         context)
        fieldsB = self.parameterAsFields(parameters, self.INTERSECT_FIELDS,
                                         context)

        fieldListA = QgsFields()
        field_indices_a = []
        if len(fieldsA) > 0:
            for f in fieldsA:
                idxA = sourceA.fields().lookupField(f)
                if idxA >= 0:
                    field_indices_a.append(idxA)
                    fieldListA.append(sourceA.fields()[idxA])
        else:
            fieldListA = sourceA.fields()
            field_indices_a = [i for i in range(0, fieldListA.count())]

        fieldListB = QgsFields()
        field_indices_b = []
        if len(fieldsB) > 0:
            for f in fieldsB:
                idxB = sourceB.fields().lookupField(f)
                if idxB >= 0:
                    field_indices_b.append(idxB)
                    fieldListB.append(sourceB.fields()[idxB])
        else:
            fieldListB = sourceB.fields()
            field_indices_b = [i for i in range(0, fieldListB.count())]

        fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
        for b in fieldListB:
            fieldListA.append(b)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fieldListA,
                                               QgsWkbTypes.Point,
                                               sourceA.sourceCrs())

        spatialIndex = QgsSpatialIndex(
            sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(
                []).setDestinationCrs(sourceA.sourceCrs())), feedback)

        outFeat = QgsFeature()
        features = sourceA.getFeatures(
            QgsFeatureRequest().setSubsetOfAttributes(field_indices_a))
        total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 0
        for current, inFeatA in enumerate(features):
            if feedback.isCanceled():
                break

            if not inFeatA.hasGeometry():
                continue

            inGeom = inFeatA.geometry()
            has_intersections = False
            lines = spatialIndex.intersects(inGeom.boundingBox())

            engine = None
            if len(lines) > 0:
                has_intersections = True
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(inGeom.geometry())
                engine.prepareGeometry()

            if has_intersections:
                request = QgsFeatureRequest().setFilterFids(lines)
                request.setDestinationCrs(sourceA.sourceCrs())
                request.setSubsetOfAttributes(field_indices_b)

                for inFeatB in sourceB.getFeatures(request):
                    if feedback.isCanceled():
                        break

                    tmpGeom = inFeatB.geometry()

                    points = []
                    if engine.intersects(tmpGeom.geometry()):
                        tempGeom = inGeom.intersection(tmpGeom)
                        out_attributes = [
                            inFeatA.attributes()[i] for i in field_indices_a
                        ]
                        out_attributes.extend(
                            [inFeatB.attributes()[i] for i in field_indices_b])
                        if tempGeom.type() == QgsWkbTypes.PointGeometry:
                            if tempGeom.isMultipart():
                                points = tempGeom.asMultiPoint()
                            else:
                                points.append(tempGeom.asPoint())

                            for j in points:
                                outFeat.setGeometry(tempGeom.fromPoint(j))
                                outFeat.setAttributes(out_attributes)
                                sink.addFeature(outFeat,
                                                QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Ejemplo n.º 60
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())

        fieldsA = self.parameterAsFields(parameters, self.INPUT_FIELDS,
                                         context)
        fieldsB = self.parameterAsFields(parameters, self.OVERLAY_FIELDS,
                                         context)

        fieldListA = QgsFields()
        field_indices_a = []
        if len(fieldsA) > 0:
            for f in fieldsA:
                idxA = sourceA.fields().lookupField(f)
                if idxA >= 0:
                    field_indices_a.append(idxA)
                    fieldListA.append(sourceA.fields()[idxA])
        else:
            fieldListA = sourceA.fields()
            field_indices_a = [i for i in range(0, fieldListA.count())]

        fieldListB = QgsFields()
        field_indices_b = []
        if len(fieldsB) > 0:
            for f in fieldsB:
                idxB = sourceB.fields().lookupField(f)
                if idxB >= 0:
                    field_indices_b.append(idxB)
                    fieldListB.append(sourceB.fields()[idxB])
        else:
            fieldListB = sourceB.fields()
            field_indices_b = [i for i in range(0, fieldListB.count())]

        fieldListB = vector.testForUniqueness(fieldListA, fieldListB)
        for b in fieldListB:
            fieldListA.append(b)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fieldListA, geomType,
                                               sourceA.sourceCrs())

        outFeat = QgsFeature()
        indexB = QgsSpatialIndex(
            sourceB.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(
                []).setDestinationCrs(sourceA.sourceCrs())), feedback)

        total = 100.0 / sourceA.featureCount() if sourceA.featureCount() else 1
        count = 0

        for featA in sourceA.getFeatures(
                QgsFeatureRequest().setSubsetOfAttributes(field_indices_a)):
            if feedback.isCanceled():
                break

            if not featA.hasGeometry():
                continue

            geom = featA.geometry()
            atMapA = featA.attributes()
            intersects = indexB.intersects(geom.boundingBox())

            request = QgsFeatureRequest().setFilterFids(intersects)
            request.setDestinationCrs(sourceA.sourceCrs())
            request.setSubsetOfAttributes(field_indices_b)

            engine = None
            if len(intersects) > 0:
                # use prepared geometries for faster intersection tests
                engine = QgsGeometry.createGeometryEngine(geom.geometry())
                engine.prepareGeometry()

            for featB in sourceB.getFeatures(request):
                if feedback.isCanceled():
                    break

                tmpGeom = featB.geometry()
                if engine.intersects(tmpGeom.geometry()):
                    out_attributes = [
                        featA.attributes()[i] for i in field_indices_a
                    ]
                    out_attributes.extend(
                        [featB.attributes()[i] for i in field_indices_b])
                    int_geom = QgsGeometry(geom.intersection(tmpGeom))
                    if int_geom.wkbType(
                    ) == QgsWkbTypes.Unknown or QgsWkbTypes.flatType(
                            int_geom.geometry().wkbType(
                            )) == QgsWkbTypes.GeometryCollection:
                        int_com = geom.combine(tmpGeom)
                        int_geom = QgsGeometry()
                        if int_com:
                            int_sym = geom.symDifference(tmpGeom)
                            int_geom = QgsGeometry(int_com.difference(int_sym))
                    if int_geom.isEmpty() or not int_geom.isGeosValid():
                        raise QgsProcessingException(
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                    try:
                        if QgsWkbTypes.geometryType(int_geom.wkbType(
                        )) == QgsWkbTypes.geometryType(geomType):
                            int_geom.convertToMultiType()
                            outFeat.setGeometry(int_geom)
                            outFeat.setAttributes(out_attributes)
                            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
                    except:
                        raise QgsProcessingException(
                            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}