Example #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
Example #2
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}
Example #3
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
    def testFilter(self):
        """ test calculating aggregate with filter """

        layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory")
        pr = layer.dataProvider()

        int_values = [4, 2, 3, 2, 5, None, 8]

        features = []
        for v in int_values:
            f = QgsFeature()
            f.setFields(layer.fields())
            f.setAttributes([v])
            features.append(f)
        assert pr.addFeatures(features)

        agg = QgsAggregateCalculator(layer)

        filter_string = "fldint > 2"
        agg.setFilter(filter_string)
        self.assertEqual(agg.filter(), filter_string)

        val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint')
        self.assertTrue(ok)
        self.assertEqual(val, 20)

        # remove filter and retest
        agg.setFilter(None)
        val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint')
        self.assertTrue(ok)
        self.assertEqual(val, 24)
Example #5
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT_VECTOR))

        rasterPath = unicode(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.toList(), QgsWkbTypes.Point, layer.crs())

        outFeature = QgsFeature()
        outFeature.setFields(fields)

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

        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            geom = f.geometry()
            if geom.isMultipart():
                lines = geom.asMultiPolyline()
                for line in lines:
                    for i in xrange(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 xrange(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

            progress.setPercentage(int(current * total))

        del writer
Example #6
0
    def outattrPrep(self, dlg, lyr):
        feat = QgsFeature()

        species = ''
        production = ''
        most = QDateTime.currentDateTimeUtc()

        rn = dlg.tableWidget.rowCount()
        for i in range(rn):
            if i==0:
                species = dlg.tableWidget.item(i, 0).text()
                production = dlg.tableWidget.item(i, 1).text()
            else:
                species = species + ' | ' + dlg.tableWidget.item(i, 0).text()
                production = production + ' | ' + dlg.tableWidget.item(i, 1).text()

        flds = lyr.dataProvider().fields()
        feat.setFields(flds, True)
        feat.setAttribute(feat.fieldNameIndex('localid'), dlg.lineEdit_3.text())
        feat.setAttribute(feat.fieldNameIndex('code'), dlg.lineEdit_5.text())
        feat.setAttribute(feat.fieldNameIndex('largescale'), dlg.comboBox_4.currentText())
        feat.setAttribute(feat.fieldNameIndex('disease'), dlg.comboBox_2.currentText())
        feat.setAttribute(feat.fieldNameIndex('animalno'), dlg.lineEdit_6.text())
        feat.setAttribute(feat.fieldNameIndex('species'), species)
        feat.setAttribute(feat.fieldNameIndex('production'), production)
        feat.setAttribute(feat.fieldNameIndex('year'), dlg.lineEdit_4.text())
        feat.setAttribute(feat.fieldNameIndex('status'), dlg.comboBox_3.currentText())
        feat.setAttribute(feat.fieldNameIndex('suspect'), self.dateCheck(dlg.dateEdit.date()))
        feat.setAttribute(feat.fieldNameIndex('confirmation'), self.dateCheck(dlg.dateEdit_2.date()))
        feat.setAttribute(feat.fieldNameIndex('expiration'), self.dateCheck(dlg.dateEdit_3.date()))
        feat.setAttribute(feat.fieldNameIndex('notes'), dlg.textEdit.toPlainText())
        feat.setAttribute(feat.fieldNameIndex('hrid'), self.hashIDer(most))
        feat.setAttribute(feat.fieldNameIndex('timestamp'), most.toString('dd/MM/yyyy hh:mm:ss'))
        return feat
Example #7
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
Example #8
0
 def __createMemoryLayer(self, layer_name, gtype, geometries, attributes, fNames, fTypes):
     """
     Create a memory layer from parameters
     :param layer_name: name for the layer
     :param gtype: geometry type of the layer
     :param geometries: objects geometries
     :param attributes: objects attributes
     :param fNames: fields names
     :param fTypes: fields types
     """
     layerList = QgsMapLayerRegistry.instance().mapLayersByName(layer_name)
     if layerList:
         QgsMapLayerRegistry.instance().removeMapLayers([layerList[0].id()])
     epsg = self.canvas().mapRenderer().destinationCrs().authid()
     fieldsParam = ""
     for i in range(len(fNames)):
         fieldsParam += "&field=" + fNames[i] + ":" + fTypes[i]
     layer = QgsVectorLayer(gtype + "?crs=" + epsg + fieldsParam + "&index=yes", layer_name, "memory")
     QgsMapLayerRegistry.instance().addMapLayer(layer)
     layer.startEditing()
     for i in range(len(geometries)):
         feature = QgsFeature()
         feature.setGeometry(QgsGeometry().fromWkt(geometries[i]))
         fields = layer.pendingFields()
         feature.setFields(fields)
         for j in range(len(fNames)):
             feature.setAttribute(fNames[j], attributes[i][j])
         layer.addFeature(feature)
     layer.commitChanges()
Example #9
0
def add_gbif_occ_to_layer(occurrences, layer):
    features = []
    dp = layer.dataProvider()

    for o in occurrences:
        attrs = []
        for k in o.keys():
            field_index = dp.fieldNameIndex(k)
            # Add a layer attribute for each JSON fields(if not already encountered)
            if field_index == -1:
                dp.addAttributes([QgsField(k, QtCore.QVariant.String)])
            
            attrs.append({'attr': k, 'val': _get_field_value(o, k)})

        feat = QgsFeature()

        # We should tell the feature which will be its fields
        # !! We need a variable !! Don't merge the next two lines !!
        myFields = dp.fields()
        feat.setFields(myFields)

        for d in attrs:
            feat.setAttribute(d['attr'], d['val'])

        feat.setGeometry(QgsGeometry.fromPoint(QgsPoint(o['decimalLongitude'], o['decimalLatitude'])))
        
        features.append(feat)

    add_features_to_layer(layer, features)
    def canvasPressEvent(self, mouseEvent):
        self.rubber.reset()
        pos = mouseEvent.pos()
        features = self.getFeatures(pos)
        nFeat = len(features)
        if nFeat < 2:
            layerNames = " , ".join([feature.layer.name() for feature in features])
            self.iface.messageBar().pushMessage("Intersect It", "You need 2 features to proceed a simple intersection."
                                                " %u given (%s)" % (nFeat, layerNames), QgsMessageBar.WARNING, 3)
            return
        intersectionP = self.intersection(features, pos)
        if intersectionP == QgsPoint(0,0):
            self.iface.messageBar().pushMessage("Intersect It", "Objects do not intersect.", QgsMessageBar.WARNING, 2)
            return

        layer = self.checkLayer()
        if layer is None:
            return
        f = QgsFeature()
        initFields = layer.dataProvider().fields()
        f.setFields(initFields)
        f.initAttributes(initFields.size())
        f.setGeometry(QgsGeometry().fromPoint(intersectionP))
        layer.editBuffer().addFeature(f)
        layer.triggerRepaint()
    def postionupdated(self, position, info):
        if not self.logging or not self.layer or not self.layerprovider:
            return

        feature = QgsFeature()
        feature.setFields(self.fields)

        for field in self.fields:
            name = field.name()
            if name == 'time':
                value = self.gps.gpsinfo('utcDateTime').toString(Qt.ISODate)
            elif name == 'localtime':
                value = QDateTime.currentDateTime().toString(Qt.ISODate)
            elif name == 'user':
                value = getpass.getuser()
            else:
                try:
                    value = self.gps.gpsinfo(name)
                except AttributeError:
                    continue

            feature[name] = value

        geom = QgsGeometry.fromPoint(position)
        feature.setGeometry(geom)
        self.featurecache.append(feature)
        if len(self.featurecache) > 5:
            self.layerprovider.addFeatures(self.featurecache)
            self.featurecache = []
Example #12
0
    def testExportFeatureFieldFormatter(self):
        """ Test exporting a feature with formatting fields """

        # source layer
        source = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
                                "parent", "memory")
        pr = source.dataProvider()
        pf1 = QgsFeature()
        pf1.setFields(source.fields())
        pf1.setAttributes(["test1", 1])
        pf2 = QgsFeature()
        pf2.setFields(source.fields())
        pf2.setAttributes(["test2", 2])
        assert pr.addFeatures([pf1, pf2])

        setup = QgsEditorWidgetSetup('ValueMap', {"map": {"one": 1, "two": 2, "three": 3}})
        source.setEditorWidgetSetup(1, setup)

        exporter = QgsJsonExporter()
        exporter.setVectorLayer(source)

        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test1",
      "fldint":"one"
   }
}"""
        self.assertEqual(exporter.exportFeature(pf1), expected)
Example #13
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}
Example #14
0
    def testExportFieldAlias(self):
        """ Test exporting a feature with fields' alias """

        # source layer
        source = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer",
                                "parent", "memory")
        pr = source.dataProvider()
        pf1 = QgsFeature()
        pf1.setFields(source.fields())
        pf1.setAttributes(["test1", 1])
        pf2 = QgsFeature()
        pf2.setFields(source.fields())
        pf2.setAttributes(["test2", 2])
        assert pr.addFeatures([pf1, pf2])

        source.setFieldAlias(0, "alias_fldtxt")
        source.setFieldAlias(1, "alias_fldint")

        exporter = QgsJsonExporter()
        exporter.setAttributeDisplayName(True)
        exporter.setVectorLayer(source)

        expected = """{
  "geometry": null,
  "id": 0,
  "properties": {
    "alias_fldint": 1,
    "alias_fldtxt": "test1"
  },
  "type": "Feature"
}"""
        self.assertEqual(exporter.exportFeature(pf1, indent=2), expected)
Example #15
0
    def save(self):
        # observation
        f = QgsFeature()
        fields = self.lineLayer.dataProvider().fields()
        f.setFields(fields)
        f["id"] = self.id
        f["type"] = self.obsType
        f["x"] = self.point.x()
        f["y"] = self.point.y()
        f["observation"] = self.observation
        f["precision"] = self.precision
        f.setGeometry(self.geometry())
        ok, l = self.lineLayer.dataProvider().addFeatures([f])
        self.lineLayer.updateExtents()
        self.lineLayer.setCacheImage(None)
        self.lineLayer.triggerRepaint()
        self.lineLayer.featureAdded.emit(l[0].id())  # emit signal so feature is added to snapping index

        # center
        f = QgsFeature()
        fields = self.pointLayer.dataProvider().fields()
        f.setFields(fields)
        f["id"] = self.id
        f.setGeometry(QgsGeometry().fromPoint(self.point))
        ok, l = self.pointLayer.dataProvider().addFeatures([f])
        self.pointLayer.updateExtents()
        self.pointLayer.setCacheImage(None)
        self.pointLayer.triggerRepaint()
        self.pointLayer.featureAdded.emit(l[0].id())  # emit signal so feature is added to snapping index
Example #16
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()
Example #17
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 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)
Example #19
0
    def accept(self):
        def updatefeautrefields(feature):
            for key, value in values.iteritems():
                try:
                    feature[key] = value
                except KeyError:
                    continue
            return feature

        if not self.featureform.allpassing:
            self.bar.pushMessage("Missing fields", "Some fields are still required.",
                                 QgsMessageBar.WARNING, duration=2)
            return

        if not self.featureform:
            return

        if not self.featureform.accept():
            return

        layer = self.featureform.form.QGISLayer
        before = QgsFeature(self.feature)
        before.setFields(self.fields, initAttributes=False)

        values, savedvalues = self.featureform.getvalues()

        after = QgsFeature(self.feature)
        after.setFields(self.fields, initAttributes=False)
        after = updatefeautrefields(after)

        layer.startEditing()
        if after.id() > 0:
            if self.project.historyenabled(layer):
                # Mark the old one as history
                before['status'] = 'H'
                after['status'] = 'C'
                after['dateedited'] = QDateTime.currentDateTime()
                after['editedby'] = getpass.getuser()
                layer.addFeature(after)
                layer.updateFeature(before)
            else:
                layer.updateFeature(after)
        else:
            layer.addFeature(after)
            featureform.savevalues(layer, savedvalues)

        saved = layer.commitChanges()

        if not saved:
            self.failedsave.emit(layer.commitErrors())
            map(error, layer.commitErrors())
        else:
            self.featureform.featuresaved(after, values)
            self.featuresaved.emit()

        self.accepted.emit()
        self.featureform = None
Example #20
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
 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)
Example #22
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'
Example #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
Example #24
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
Example #25
0
    def processAlgorithm(self, progress):
        extent = self.getParameterValue(self.EXTENT).split(',')
        xSpace = self.getParameterValue(self.STEP_X)
        ySpace = self.getParameterValue(self.STEP_Y)

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

        mapCRS = iface.mapCanvas().mapSettings().destinationCrs()

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

        fields.append(QgsField('xmin', QVariant.Double, '', 24, 15))
        fields.append(QgsField('xmax', QVariant.Double, '', 24, 15))
        fields.append(QgsField('ymin', QVariant.Double, '', 24, 15))
        fields.append(QgsField('ymax', QVariant.Double, '', 24, 15))
        fieldCount = 5
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, QgsWkbTypes.Polygon, mapCRS)

        feat = QgsFeature()
        feat.initAttributes(fieldCount)
        feat.setFields(fields)
        geom = QgsGeometry()
        idVar = 0

        # counters for progressbar - update every 5%
        count = 0
        count_max = (bbox.yMaximum() - bbox.yMinimum()) / ySpace
        count_update = count_max * 0.05
        y = bbox.yMaximum()
        while y >= bbox.yMinimum():
            x = bbox.xMinimum()
            while x <= bbox.xMaximum():
                pt1 = QgsPoint(x, y)
                pt2 = QgsPoint(x + xSpace, y)
                pt3 = QgsPoint(x + xSpace, y - ySpace)
                pt4 = QgsPoint(x, y - ySpace)
                pt5 = QgsPoint(x, y)
                polygon = [[pt1, pt2, pt3, pt4, pt5]]
                feat.setGeometry(geom.fromPolygon(polygon))
                feat.setAttribute(0, idVar)
                feat.setAttribute(1, x)
                feat.setAttribute(2, x + xSpace)
                feat.setAttribute(3, y - ySpace)
                feat.setAttribute(4, y)
                writer.addFeature(feat)
                idVar += 1
                x = x + xSpace
            y = y - ySpace
            count += 1
            if int(math.fmod(count, count_update)) == 0:
                progress.setPercentage(int(count / count_max * 100))

        del writer
    def testString(self):
        """ Test calculation of aggregates on string fields"""

        layer = QgsVectorLayer("Point?field=fldstring:string", "layer", "memory")
        pr = layer.dataProvider()

        values = ['cc', 'aaaa', 'bbbbbbbb', 'aaaa', 'eeee', '', 'eeee', '', 'dddd']
        features = []
        for v in values:
            f = QgsFeature()
            f.setFields(layer.fields())
            f.setAttributes([v])
            features.append(f)
        assert pr.addFeatures(features)

        tests = [[QgsAggregateCalculator.Count, 'fldstring', 9],
                 [QgsAggregateCalculator.CountDistinct, 'fldstring', 6],
                 [QgsAggregateCalculator.CountMissing, 'fldstring', 2],
                 [QgsAggregateCalculator.Min, 'fldstring', 'aaaa'],
                 [QgsAggregateCalculator.Max, 'fldstring', 'eeee'],
                 [QgsAggregateCalculator.StringMinimumLength, 'fldstring', 0],
                 [QgsAggregateCalculator.StringMaximumLength, 'fldstring', 8],
                 [QgsAggregateCalculator.ArrayAggregate, 'fldstring', values],
                 ]

        agg = QgsAggregateCalculator(layer)
        for t in tests:
            val, ok = agg.calculate(t[0], t[1])
            self.assertTrue(ok)
            self.assertEqual(val, t[2])

        # test string concatenation
        agg.setDelimiter(',')
        self.assertEqual(agg.delimiter(), ',')
        val, ok = agg.calculate(QgsAggregateCalculator.StringConcatenate, 'fldstring')
        self.assertTrue(ok)
        self.assertEqual(val, 'cc,aaaa,bbbbbbbb,aaaa,eeee,,eeee,,dddd')
        val, ok = agg.calculate(QgsAggregateCalculator.StringConcatenateUnique, 'fldstring')
        self.assertTrue(ok)
        self.assertEqual(val, 'cc,aaaa,bbbbbbbb,eeee,,dddd')

        # bad tests - the following stats should not be calculatable for string fields
        for t in [QgsAggregateCalculator.Sum,
                  QgsAggregateCalculator.Mean,
                  QgsAggregateCalculator.Median,
                  QgsAggregateCalculator.StDev,
                  QgsAggregateCalculator.StDevSample,
                  QgsAggregateCalculator.Range,
                  QgsAggregateCalculator.Minority,
                  QgsAggregateCalculator.Majority,
                  QgsAggregateCalculator.FirstQuartile,
                  QgsAggregateCalculator.ThirdQuartile,
                  QgsAggregateCalculator.InterQuartileRange
                  ]:
            val, ok = agg.calculate(t, 'fldstring')
            self.assertFalse(ok)
Example #27
0
    def create_layer(self, parameters, name, is_memory, dest_crs, layer_style=None):
        save_as = parameters.file_path
        file_format = parameters.file_format
        # save paramaters
        serialized = base64.b64encode(parameters.serialize(with_style=False, with_geometry=False))

        # save geometry
        layer = QgsVectorLayer("MultiPolygon?crs=%s" % dest_crs.authid(), name, "memory")
        pr = layer.dataProvider()
        layer.startEditing()
        layer.addAttribute(QgsField("params", QVariant.String))
        fet1 = QgsFeature(0)
        fet1.setFields(layer.fields())
        fet1.setAttribute("params", str(serialized)[2:-1])
        fet1.setGeometry(parameters.geometry)
        pr.addFeatures([fet1])
        layer.commitChanges()

        # copy layer style
        if layer_style is not None:
            self.set_layer_style(layer, layer_style)

        if is_memory:
            return layer

        if os.path.isfile(save_as):
            # delete first if already exists
            if save_as.endswith(".shp"):
                QgsVectorFileWriter.deleteShapeFile(save_as)
            else:
                os.unlink(save_as)

        # create the disk layer
        QgsMessageLog.logMessage("Mask saving '{}' as {}".format(save_as, file_format),
                                 'Extensions')
        error = QgsVectorFileWriter.writeAsVectorFormat(layer, save_as, "System", dest_crs,
                                                        file_format)

        if error == 0:
            nlayer = QgsVectorLayer(save_as, name, "ogr")
            if not nlayer.dataProvider().isValid():
                return None
            if not nlayer.hasGeometryType():
                return None
            # force CRS
            nlayer.setCrs(dest_crs)

            # copy layer style
            layer_style = self.get_layer_style(layer)
            self.set_layer_style(nlayer, layer_style)
            return nlayer
        else:
            raise RuntimeError(error)

        return None
Example #28
0
    def testAggregate(self):
        """ Test aggregate calculation """
        layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory")
        pr = layer.dataProvider()

        int_values = [4, 2, 3, 2, 5, None, 8]
        features = []
        for i in int_values:
            f = QgsFeature()
            f.setFields(layer.fields())
            f.setAttributes([i])
            features.append(f)
        assert pr.addFeatures(features)

        tests = [[QgsAggregateCalculator.Count, 6],
                 [QgsAggregateCalculator.Sum, 24],
                 [QgsAggregateCalculator.Mean, 4],
                 [QgsAggregateCalculator.StDev, 2.0816],
                 [QgsAggregateCalculator.StDevSample, 2.2803],
                 [QgsAggregateCalculator.Min, 2],
                 [QgsAggregateCalculator.Max, 8],
                 [QgsAggregateCalculator.Range, 6],
                 [QgsAggregateCalculator.Median, 3.5],
                 [QgsAggregateCalculator.CountDistinct, 5],
                 [QgsAggregateCalculator.CountMissing, 1],
                 [QgsAggregateCalculator.FirstQuartile, 2],
                 [QgsAggregateCalculator.ThirdQuartile, 5.0],
                 [QgsAggregateCalculator.InterQuartileRange, 3.0]
                 ]

        for t in tests:
            val, ok = layer.aggregate(t[0], 'fldint')
            self.assertTrue(ok)
            if isinstance(t[1], int):
                self.assertEqual(val, t[1])
            else:
                self.assertAlmostEqual(val, t[1], 3)

        # test with parameters
        layer = QgsVectorLayer("Point?field=fldstring:string", "layer", "memory")
        pr = layer.dataProvider()

        string_values = ['this', 'is', 'a', 'test']
        features = []
        for s in string_values:
            f = QgsFeature()
            f.setFields(layer.fields())
            f.setAttributes([s])
            features.append(f)
        assert pr.addFeatures(features)
        params = QgsAggregateCalculator.AggregateParameters()
        params.delimiter = ' '
        val, ok = layer.aggregate(QgsAggregateCalculator.StringConcatenate, 'fldstring', params)
        self.assertTrue(ok)
        self.assertEqual(val, 'this is a test')
Example #29
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}
    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
Example #31
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_LAYER), context)
        fieldName = self.getParameterValue(self.FIELD_NAME)
        fieldType = self.TYPES[self.getParameterValue(self.FIELD_TYPE)]
        width = self.getParameterValue(self.FIELD_LENGTH)
        precision = self.getParameterValue(self.FIELD_PRECISION)
        newField = self.getParameterValue(self.NEW_FIELD)
        formula = self.getParameterValue(self.FORMULA)

        output = self.getOutputFromName(self.OUTPUT_LAYER)

        fields = layer.fields()
        if newField:
            fields.append(QgsField(fieldName, fieldType, '', width, precision))

        writer = output.getVectorWriter(fields, layer.wkbType(), layer.crs(),
                                        context)

        exp = QgsExpression(formula)

        da = QgsDistanceArea()
        da.setSourceCrs(layer.crs())
        da.setEllipsoid(QgsProject.instance().ellipsoid())
        exp.setGeomCalculator(da)
        exp.setDistanceUnits(QgsProject.instance().distanceUnits())
        exp.setAreaUnits(QgsProject.instance().areaUnits())

        exp_context = QgsExpressionContext(
            QgsExpressionContextUtils.globalProjectLayerScopes(layer))

        if not exp.prepare(exp_context):
            raise GeoAlgorithmExecutionException(
                self.tr('Evaluation error: {0}').format(exp.evalErrorString()))

        outFeature = QgsFeature()
        outFeature.initAttributes(len(fields))
        outFeature.setFields(fields)

        error = ''
        calculationSuccess = True

        features = QgsProcessingUtils.getFeatures(layer, context)
        total = 100.0 / layer.featureCount() if layer.featureCount() else 0

        rownum = 1
        for current, f in enumerate(features):
            rownum = current + 1
            exp_context.setFeature(f)
            exp_context.lastScope().setVariable("row_number", rownum)
            value = exp.evaluate(exp_context)
            if exp.hasEvalError():
                calculationSuccess = False
                error = exp.evalErrorString()
                break
            else:
                outFeature.setGeometry(f.geometry())
                for fld in f.fields():
                    outFeature[fld.name()] = f[fld.name()]
                outFeature[fieldName] = value
                writer.addFeature(outFeature, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(current * total))
        del writer

        if not calculationSuccess:
            raise GeoAlgorithmExecutionException(
                self.tr('An error occurred while evaluating the calculation '
                        'string:\n{0}').format(error))
Example #32
0
    def processAlgorithm(self, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR), context)
        startPoint = self.getParameterValue(self.START_POINT)
        strategy = self.getParameterValue(self.STRATEGY)
        travelCost = self.getParameterValue(self.TRAVEL_COST)

        directionFieldName = self.getParameterValue(self.DIRECTION_FIELD)
        forwardValue = self.getParameterValue(self.VALUE_FORWARD)
        backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        speedFieldName = self.getParameterValue(self.SPEED_FIELD)
        defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED)
        tolerance = self.getParameterValue(self.TOLERANCE)

        tmp = startPoint.split(',')
        startPoint = QgsPoint(float(tmp[0]), float(tmp[1]))

        directionField = -1
        if directionFieldName is not None:
            directionField = layer.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName is not None:
            speedField = layer.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(layer, directionField, forwardValue,
                                          backwardValue, bothValue,
                                          defaultDirection)

        distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(
            iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance)
        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, [startPoint])

        feedback.pushInfo(self.tr('Calculating service area...'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])

        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        vertices = []
        for i, v in enumerate(cost):
            if v > travelCost and tree[i] != -1:
                vertexId = graph.edge(tree[i]).outVertex()
                if cost[vertexId] <= travelCost:
                    vertices.append(i)

        upperBoundary = []
        lowerBoundary = []
        for i in vertices:
            upperBoundary.append(
                graph.vertex(graph.edge(tree[i]).inVertex()).point())
            lowerBoundary.append(
                graph.vertex(graph.edge(tree[i]).outVertex()).point())

        feedback.pushInfo(self.tr('Writing results...'))

        fields = QgsFields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        geomUpper = QgsGeometry.fromMultiPoint(upperBoundary)
        geomLower = QgsGeometry.fromMultiPoint(lowerBoundary)

        writer = self.getOutputFromName(self.OUTPUT_POINTS).getVectorWriter(
            fields, QgsWkbTypes.MultiPoint, layer.crs(), context)

        feat.setGeometry(geomUpper)
        feat['type'] = 'upper'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat)

        feat.setGeometry(geomLower)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat)

        del writer

        upperBoundary.append(startPoint)
        lowerBoundary.append(startPoint)
        geomUpper = QgsGeometry.fromMultiPoint(upperBoundary)
        geomLower = QgsGeometry.fromMultiPoint(lowerBoundary)

        writer = self.getOutputFromName(self.OUTPUT_POLYGON).getVectorWriter(
            fields, QgsWkbTypes.Polygon, layer.crs(), context)

        geom = geomUpper.convexHull()
        feat.setGeometry(geom)
        feat['type'] = 'upper'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat)

        geom = geomLower.convexHull()
        feat.setGeometry(geom)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat)
        del writer
    def testFidSupport(self):

        # We do not use @unittest.expectedFailure since the test might actually succeed
        # on Linux 64bit with GDAL 1.11, where "long" is 64 bit...
        # GDAL 2.0 is guaranteed to properly support it on all platforms
        version_num = int(gdal.VersionInfo('VERSION_NUM'))
        if version_num < GDAL_COMPUTE_VERSION(2, 0, 0):
            return

        tmpfile = os.path.join(self.basetestpath, 'testFidSupport.sqlite')
        ds = ogr.GetDriverByName('SQLite').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('test', geom_type=ogr.wkbPoint, options=['FID=fid'])
        lyr.CreateField(ogr.FieldDefn('strfield', ogr.OFTString))
        lyr.CreateField(ogr.FieldDefn('intfield', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetFID(12)
        f.SetField(0, 'foo')
        f.SetField(1, 123)
        lyr.CreateFeature(f)
        f = None
        ds = None

        vl = QgsVectorLayer('{}'.format(tmpfile), 'test', 'ogr')
        self.assertEqual(len(vl.fields()), 3)
        got = [(f.attribute('fid'), f.attribute('strfield'), f.attribute('intfield')) for f in vl.getFeatures()]
        self.assertEqual(got, [(12, 'foo', 123)])

        got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("strfield = 'foo'"))]
        self.assertEqual(got, [(12, 'foo')])

        got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 12"))]
        self.assertEqual(got, [(12, 'foo')])

        result = [f['strfield'] for f in vl.dataProvider().getFeatures(QgsFeatureRequest().setSubsetOfAttributes(['strfield'], vl.dataProvider().fields()))]
        self.assertEqual(result, ['foo'])

        result = [f['fid'] for f in vl.dataProvider().getFeatures(QgsFeatureRequest().setSubsetOfAttributes(['fid'], vl.dataProvider().fields()))]
        self.assertEqual(result, [12])

        # Test that when the 'fid' field is not set, regular insertion is done
        f = QgsFeature()
        f.setFields(vl.fields())
        f.setAttributes([None, 'automatic_id'])
        (res, out_f) = vl.dataProvider().addFeatures([f])
        self.assertEqual(out_f[0].id(), 13)
        self.assertEqual(out_f[0].attribute('fid'), 13)
        self.assertEqual(out_f[0].attribute('strfield'), 'automatic_id')

        # Test that when the 'fid' field is set, it is really used to set the id
        f = QgsFeature()
        f.setFields(vl.fields())
        f.setAttributes([9876543210, 'bar'])
        (res, out_f) = vl.dataProvider().addFeatures([f])
        self.assertEqual(out_f[0].id(), 9876543210)
        self.assertEqual(out_f[0].attribute('fid'), 9876543210)
        self.assertEqual(out_f[0].attribute('strfield'), 'bar')

        got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))]
        self.assertEqual(got, [(9876543210, 'bar')])

        self.assertTrue(vl.dataProvider().changeAttributeValues({9876543210: {1: 'baz'}}))

        got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))]
        self.assertEqual(got, [(9876543210, 'baz')])

        self.assertTrue(vl.dataProvider().changeAttributeValues({9876543210: {0: 9876543210, 1: 'baw'}}))

        got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))]
        self.assertEqual(got, [(9876543210, 'baw')])

        # Not allowed: changing the fid regular field
        self.assertTrue(vl.dataProvider().changeAttributeValues({9876543210: {0: 12, 1: 'baw'}}))

        got = [(f.attribute('fid'), f.attribute('strfield')) for f in vl.getFeatures(QgsFeatureRequest().setFilterExpression("fid = 9876543210"))]
        self.assertEqual(got, [(9876543210, 'baw')])

        # Cannot delete fid
        self.assertFalse(vl.dataProvider().deleteAttributes([0]))

        # Delete first "genuine" attribute
        self.assertTrue(vl.dataProvider().deleteAttributes([1]))

        got = [(f.attribute('fid'), f.attribute('intfield')) for f in vl.dataProvider().getFeatures(QgsFeatureRequest().setFilterExpression("fid = 12"))]
        self.assertEqual(got, [(12, 123)])
Example #34
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs())
        endPoints = self.parameterAsSource(parameters, self.END_POINTS, context)
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

        directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context)
        defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        fields = endPoints.fields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

        feat = QgsFeature()
        feat.setFields(fields)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.LineString, network.sourceCrs())

        directionField = -1
        if directionFieldName:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network,
                                          directionField,
                                          forwardValue,
                                          backwardValue,
                                          bothValue,
                                          defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField,
                                               defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(),
                                  True,
                                  tolerance)

        feedback.pushInfo(self.tr('Loading end points...'))
        request = QgsFeatureRequest()
        request.setDestinationCrs(network.sourceCrs())
        features = endPoints.getFeatures(request)
        total = 100.0 / endPoints.featureCount() if endPoints.featureCount() else 0

        points = [startPoint]
        source_attributes = {}
        i = 1
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            for p in f.geometry().vertices():
                points.append(QgsPointXY(p))
                source_attributes[i] = f.attributes()
                i += 1

            feedback.setProgress(int(current * total))

        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, points, feedback)

        feedback.pushInfo(self.tr('Calculating shortest paths...'))
        graph = builder.graph()

        idxStart = graph.findVertex(snappedPoints[0])
        tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)

        nPoints = len(snappedPoints)
        total = 100.0 / nPoints if nPoints else 1
        for i in range(1, nPoints):
            if feedback.isCanceled():
                break

            idxEnd = graph.findVertex(snappedPoints[i])

            if tree[idxEnd] == -1:
                msg = self.tr('There is no route from start point ({}) to end point ({}).'.format(startPoint.toString(), points[i].toString()))
                feedback.reportError(msg)
                # add feature with no geometry
                feat.clearGeometry()
                attrs = source_attributes[i]
                attrs.extend([NULL, points[i].toString()])
                feat.setAttributes(attrs)
                sink.addFeature(feat, QgsFeatureSink.FastInsert)
                continue

            route = [graph.vertex(idxEnd).point()]
            cost = costs[idxEnd]
            current = idxEnd
            while current != idxStart:
                current = graph.edge(tree[current]).fromVertex()
                route.append(graph.vertex(current).point())

            route.reverse()

            geom = QgsGeometry.fromPolylineXY(route)
            attrs = source_attributes[i]
            attrs.extend([startPoint.toString(), points[i].toString(), cost / multiplier])
            feat.setAttributes(attrs)
            feat.setGeometry(geom)
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
    def simulation_step(self):
        # TODO: Remove print
        print("Step start", self._t_now)
        future_time: datetime.datetime = self._t_now + datetime.timedelta(seconds=self._time_step)
        # Create the ignition points list and sort it by ignition date
        ignition_points: List[SpreadSimulator.IgnitionPoint]
        ignition_points = [SpreadSimulator.IgnitionPoint(feature=feature, x=feature.geometry().asPoint().x(),
                                                         y=feature.geometry().asPoint().y(),
                                                         ignition_date=parser.parse(feature.attributes()[1])) for feature
                           in self._ignition_layer.getFeatures()]
        print(self._ignition_layer, ignition_points[0].ignition_date)
        ignition_points.sort()
        # Delete ignition points that ignited prior to the starting date of the simulation
        while (len(ignition_points) > 0) and (ignition_points[0].ignition_date < self._t_now):
            print("delete", ignition_points[0].ignition_date)
            ignition_points.pop(0)
        ignition_points = [point for point in ignition_points if self._t_now <= point.ignition_date < future_time]
        if len(ignition_points) > 0:
            # Compute the perimeter of the ignition point if it has to burn
            ignition_perimeters: List[List[SpreadSimulator.Point]] = list()
            for ignition_point in ignition_points:
                print(ignition_point.ignition_date)
                ignition_point.fuel_model = self._get_fire_model(ignition_point.x, ignition_point.y)
                perimeter = self.__ignite_point(ignition_point)
                if perimeter is not None:
                    ignition_perimeters.append(perimeter)
            # Move perimeters to a QGIS layer
            fields = self._perimeter_layer.fields()
            raw_perimeters_layer: QgsVectorLayer = SpreadSimulator.__create_memory_layer('Polygon', 'raw_perimeters')
            for perimeter in ignition_perimeters:
                qgis_points: List[QgsPointXY] = [QgsPointXY(point.x, point.y) for point in perimeter]
                qgis_feature: QgsFeature = QgsFeature()
                qgis_geometry: QgsGeometry = QgsGeometry.fromPolygonXY([qgis_points]) # NOQA
                qgis_feature.setGeometry(qgis_geometry)
                qgis_data_provider: QgsVectorLayer = raw_perimeters_layer.dataProvider()
                qgis_data_provider.addFeature(qgis_feature) # NOQA
            # Fix geometries
            params = {'INPUT': raw_perimeters_layer, 'OUTPUT': 'memory:'}
            feedback = QgsProcessingFeedback()
            result = processing.run('native:fixgeometries', params, feedback=feedback, is_child_algorithm=False)
            fixed_layer = result['OUTPUT']
            print(result)
            params = {'INPUT': fixed_layer, 'OUTPUT': 'memory:', 'FIELD': None}
            feedback = QgsProcessingFeedback()
            result = processing.run('native:dissolve', params, feedback=feedback, is_child_algorithm=False)
            dissolved_layer = result['OUTPUT']
            print(result)
            params = {'INPUT': dissolved_layer, 'OUTPUT': 'memory:'}
            feedback = QgsProcessingFeedback()
            result = processing.run('native:multiparttosingleparts', params, feedback=feedback, is_child_algorithm=False)
            single_part_layer = result['OUTPUT']
            params = {'INPUT': single_part_layer, 'OUTPUT': 'memory:'}
            feedback = QgsProcessingFeedback()
            result = processing.run('native:forcerhr', params, feedback=feedback, is_child_algorithm=False)
            del fixed_layer
            del dissolved_layer
            del single_part_layer
            with edit(self._perimeter_layer):
                features = list()
                for feature in result['OUTPUT'].getFeatures():
                    feat = QgsFeature()
                    feat.setGeometry(QgsGeometry.fromPolygonXY(feature.geometry().asPolygon()))
                    feat.setFields(fields)
                    feat['datetime'] = future_time.strftime("%Y-%m-%dT%H:%M:%S%Z")
                    features.append(feat)
                (_, _) = self._perimeter_layer.dataProvider().addFeatures(features)
            del result['OUTPUT']
            del raw_perimeters_layer

        # Calculate the propagation perimeters
        propagation_perimeters: List[List[Any]] = list()
        # Filter the perimeters needed to propagate and convert to simple points
        features_of_perimeters_to_propagate = [feature for feature in self._perimeter_layer.getFeatures() if parser.parse(feature.attributes()[1]) == self._t_now]
        for feature in features_of_perimeters_to_propagate:
            # Get the geometries, if a polygon is a list its points define the polygon, if it is a list of lists the
            # first defines the polygon and the other lists the islands. The islands can have polygons inside and so on.
            # So a recursive function is implemented
            propagation_perimeter: List[Any] = list()
            geometry = feature.geometry().asPolygon()
            points: List[SpreadSimulator.Point] = [SpreadSimulator.Point(x=point.x(), y=point.y()) for point in geometry[0]]
            for point in points:
                point.fuel_model = self._get_fire_model(point.x, point.y)
            propagation_perimeter.append(points)
            if len(geometry) > 1: # Has islands
                # TODO: Recursion
                pass
            propagation_perimeters.append(propagation_perimeter)
        if len(propagation_perimeters) > 0:
            # Propagate the perimeters as points
            propagated_perimeters: List[List[Any]] = list()
            for perimeter in propagation_perimeters:
                propagated_perimeter: List[Any] = list()
                new_perimeter = self._propagate_perimeter(perimeter[0][-2::-1])
                propagated_perimeter.append(new_perimeter)
                if len(perimeter) > 1: # Has islands
                    # TODO: Recursion
                    pass
                propagated_perimeters.append(propagated_perimeter)
            # Move perimeters to a QGIS layer
            fields = self._perimeter_layer.fields()
            raw_perimeters_layer: QgsVectorLayer = SpreadSimulator.__create_memory_layer('Polygon', 'raw_perimeters')
            for perimeter in propagated_perimeters:
                qgis_perimeter: List[List[Any]] = list()
                qgis_points: List[QgsPointXY] = [QgsPointXY(point.x, point.y) for point in perimeter[0]]
                qgis_feature: QgsFeature = QgsFeature()
                qgis_perimeter.append(qgis_points)
                if len(perimeter) > 1:
                    # TODO: Recursion
                    pass
                qgis_geometry: QgsGeometry = QgsGeometry.fromPolygonXY(qgis_perimeter) # NOQA
                qgis_feature.setGeometry(qgis_geometry)
                qgis_data_provider: QgsVectorLayer = raw_perimeters_layer.dataProvider()
                qgis_data_provider.addFeature(qgis_feature) # NOQA
            # Fix geometries
            params = {'INPUT': raw_perimeters_layer, 'OUTPUT': 'memory:'}
            feedback = QgsProcessingFeedback()
            result = processing.run('native:fixgeometries', params, feedback=feedback, is_child_algorithm=False)
            fixed_layer = result['OUTPUT']
            print(result)
            params = {'INPUT': fixed_layer, 'OUTPUT': 'memory:', 'FIELD': None}
            feedback = QgsProcessingFeedback()
            result = processing.run('native:dissolve', params, feedback=feedback, is_child_algorithm=False)
            dissolved_layer = result['OUTPUT']
            print(result)
            params = {'INPUT': dissolved_layer, 'OUTPUT': 'memory:'}
            feedback = QgsProcessingFeedback()
            result = processing.run('native:multiparttosingleparts', params, feedback=feedback, is_child_algorithm=False)
            single_part_layer = result['OUTPUT']
            params = {'INPUT': single_part_layer, 'OUTPUT': 'memory:'}
            feedback = QgsProcessingFeedback()
            result = processing.run('native:forcerhr', params, feedback=feedback, is_child_algorithm=False)
            del fixed_layer
            del dissolved_layer
            del single_part_layer
            with edit(self._perimeter_layer):
                features = list()
                for feature in result['OUTPUT'].getFeatures():
                    feat = QgsFeature()
                    feat.setGeometry(QgsGeometry.fromPolygonXY(feature.geometry().asPolygon()))
                    feat.setFields(fields)
                    feat['datetime'] = future_time.strftime("%Y-%m-%dT%H:%M:%S%Z")
                    features.append(feat)
                (_, _) = self._perimeter_layer.dataProvider().addFeatures(features)
            del result['OUTPUT']
            del raw_perimeters_layer

        # Update time
        self._t_now = future_time
        # TODO: Remove print
        print(self._t_now.strftime("%Y-%m-%dT%H:%M:%S%Z"))
Example #36
0
    def testExportFeatureRelations(self):
        """ Test exporting a feature with relations """

        #parent layer
        parent = QgsVectorLayer("Point?field=fldtxt:string&field=fldint:integer&field=foreignkey:integer",
                                "parent", "memory")
        pr = parent.dataProvider()
        pf1 = QgsFeature()
        pf1.setFields(parent.fields())
        pf1.setAttributes(["test1", 67, 123])
        pf2 = QgsFeature()
        pf2.setFields(parent.fields())
        pf2.setAttributes(["test2", 68, 124])
        assert pr.addFeatures([pf1, pf2])

        #child layer
        child = QgsVectorLayer(
            "Point?field=x:string&field=y:integer&field=z:integer",
            "referencedlayer", "memory")
        pr = child.dataProvider()
        f1 = QgsFeature()
        f1.setFields(child.fields())
        f1.setAttributes(["foo", 123, 321])
        f2 = QgsFeature()
        f2.setFields(child.fields())
        f2.setAttributes(["bar", 123, 654])
        f3 = QgsFeature()
        f3.setFields(child.fields())
        f3.setAttributes(["foobar", 124, 554])
        assert pr.addFeatures([f1, f2, f3])

        QgsProject.instance().addMapLayers([child, parent])

        rel = QgsRelation()
        rel.setId('rel1')
        rel.setName('relation one')
        rel.setReferencingLayer(child.id())
        rel.setReferencedLayer(parent.id())
        rel.addFieldPair('y', 'foreignkey')

        QgsProject.instance().relationManager().addRelation(rel)

        exporter = QgsJsonExporter()

        exporter.setVectorLayer(parent)
        self.assertEqual(exporter.vectorLayer(), parent)
        exporter.setIncludeRelated(True)
        self.assertEqual(exporter.includeRelated(), True)

        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test1",
      "fldint":67,
      "foreignkey":123,
      "relation one":[{"x":"foo",
"y":123,
"z":321},
{"x":"bar",
"y":123,
"z":654}]
   }
}"""
        self.assertEqual(exporter.exportFeature(pf1), expected)

        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test2",
      "fldint":68,
      "foreignkey":124,
      "relation one":[{"x":"foobar",
"y":124,
"z":554}]
   }
}"""
        self.assertEqual(exporter.exportFeature(pf2), expected)

        # with field formatter
        setup = QgsEditorWidgetSetup('ValueMap', {"map": {"apples": 123, "bananas": 124}})
        child.setEditorWidgetSetup(1, setup)
        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test1",
      "fldint":67,
      "foreignkey":123,
      "relation one":[{"x":"foo",
"y":"apples",
"z":321},
{"x":"bar",
"y":"apples",
"z":654}]
   }
}"""
        self.assertEqual(exporter.exportFeature(pf1), expected)

        # test excluding related attributes
        exporter.setIncludeRelated(False)
        self.assertEqual(exporter.includeRelated(), False)

        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test2",
      "fldint":68,
      "foreignkey":124
   }
}"""
        self.assertEqual(exporter.exportFeature(pf2), expected)

        # test without vector layer set
        exporter.setIncludeRelated(True)
        exporter.setVectorLayer(None)

        expected = """{
   "type":"Feature",
   "id":0,
   "geometry":null,
   "properties":{
      "fldtxt":"test2",
      "fldint":68,
      "foreignkey":124
   }
}"""
        self.assertEqual(exporter.exportFeature(pf2), expected)
Example #37
0
    def processAlgorithm(self, feedback):
        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, QgsWkbTypes.Point, layer.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 = next(
                layer.getFeatures(
                    request.setFilterFid(fid).setSubsetOfAttributes([])))
            fGeom = 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
                    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
Example #38
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.VECTOR))
        groupField = self.getParameterValue(self.GROUP_FIELD)
        orderField = self.getParameterValue(self.ORDER_FIELD)
        dateFormat = str(self.getParameterValue(self.DATE_FORMAT))
        #gap = int(self.getParameterValue(self.GAP_PERIOD))
        dirName = self.getOutputValue(self.OUTPUT_TEXT)

        fields = QgsFields()
        fields.append(QgsField('group', QVariant.String, '', 254, 0))
        fields.append(QgsField('begin', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        writer = self.getOutputFromName(self.OUTPUT_LINES).getVectorWriter(
            fields, QgsWkbTypes.LineString, layer.crs())

        points = dict()
        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            point = f.geometry().asPoint()
            group = f[groupField]
            order = f[orderField]
            if dateFormat != '':
                order = datetime.strptime(str(order), dateFormat)
            if group in points:
                points[group].append((order, point))
            else:
                points[group] = [(order, point)]

            feedback.setProgress(int(current * total))

        feedback.setProgress(0)

        da = QgsDistanceArea()

        current = 0
        total = 100.0 / len(points)
        for group, vertices in list(points.items()):
            vertices.sort()
            f = QgsFeature()
            f.initAttributes(len(fields))
            f.setFields(fields)
            f['group'] = group
            f['begin'] = vertices[0][0]
            f['end'] = vertices[-1][0]

            fileName = os.path.join(dirName, '%s.txt' % group)

            with open(fileName, 'w') as fl:
                fl.write('angle=Azimuth\n')
                fl.write('heading=Coordinate_System\n')
                fl.write('dist_units=Default\n')

                line = []
                i = 0
                for node in vertices:
                    line.append(node[1])

                    if i == 0:
                        fl.write('startAt=%f;%f;90\n' % (node[1].x(), node[1].y()))
                        fl.write('survey=Polygonal\n')
                        fl.write('[data]\n')
                    else:
                        angle = line[i - 1].azimuth(line[i])
                        distance = da.measureLine(line[i - 1], line[i])
                        fl.write('%f;%f;90\n' % (angle, distance))

                    i += 1

            f.setGeometry(QgsGeometry.fromPolyline(line))
            writer.addFeature(f)
            current += 1
            feedback.setProgress(int(current * total))

        del writer
    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}
Example #40
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())
        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.insertFeature(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}
Example #41
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT_VECTOR, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT_VECTOR))

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

        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())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))

        outFeature = QgsFeature()
        outFeature.setFields(fields)

        fid = 0
        polyId = 0
        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

            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.constGet())
            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}
Example #42
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 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}
Example #43
0
    def compute(self, bound, xOffset, yOffset, polygon):
        crs = None
        layer = ftools_utils.getMapLayerByName(
            unicode(self.inShape.currentText()))

        if self.angle.value() != 0.0:
            bound = self.initRotation(bound)

        if layer is None:
            crs = self.iface.mapCanvas().mapRenderer().destinationCrs()
        else:
            crs = layer.crs()
        if not crs.isValid():
            crs = None

        fields = QgsFields()
        fields.append(QgsField("ID", QVariant.Int))
        fieldCount = 1

        if polygon:
            fields.append(QgsField("X_MIN", QVariant.Double))
            fields.append(QgsField("X_MAX", QVariant.Double))
            fields.append(QgsField("Y_MIN", QVariant.Double))
            fields.append(QgsField("Y_MAX", QVariant.Double))
            fieldCount = 5
            check = QFile(self.shapefileName)
            if check.exists():
                if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName):
                    return
            writer = QgsVectorFileWriter(self.shapefileName, self.encoding,
                                         fields, QGis.WKBPolygon, crs)
        else:
            fields.append(QgsField("COORD", QVariant.Double))
            fieldCount = 2
            check = QFile(self.shapefileName)
            if check.exists():
                if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName):
                    return
            writer = QgsVectorFileWriter(self.shapefileName, self.encoding,
                                         fields, QGis.WKBLineString, crs)
        outFeat = QgsFeature()
        outFeat.initAttributes(fieldCount)
        outFeat.setFields(fields)
        outGeom = QgsGeometry()
        idVar = 0
        self.progressBar.setValue(0)
        if not polygon:
            # counters for progressbar - update every 5%
            count = 0
            count_max = (bound.yMaximum() - bound.yMinimum()) / yOffset
            count_update = count_max * 0.10
            y = bound.yMaximum()
            while y >= bound.yMinimum():
                pt1 = QgsPoint(bound.xMinimum(), y)
                pt2 = QgsPoint(bound.xMaximum(), y)

                if self.angle.value() != 0.0:
                    self.rotatePoint(pt1)
                    self.rotatePoint(pt2)

                line = [pt1, pt2]
                outFeat.setGeometry(outGeom.fromPolyline(line))
                outFeat.setAttribute(0, idVar)
                outFeat.setAttribute(1, y)
                writer.addFeature(outFeat)
                y = y - yOffset
                idVar = idVar + 1
                count += 1
                if int(math.fmod(count, count_update)) == 0:
                    prog = int(count / count_max * 50)
                    self.progressBar.setValue(prog)
            self.progressBar.setValue(50)
            # counters for progressbar - update every 5%
            count = 0
            count_max = (bound.xMaximum() - bound.xMinimum()) / xOffset
            count_update = count_max * 0.10
            x = bound.xMinimum()
            while x <= bound.xMaximum():
                pt1 = QgsPoint(x, bound.yMaximum())
                pt2 = QgsPoint(x, bound.yMinimum())

                if self.angle.value() != 0.0:
                    self.rotatePoint(pt1)
                    self.rotatePoint(pt2)

                line = [pt1, pt2]
                outFeat.setGeometry(outGeom.fromPolyline(line))
                outFeat.setAttribute(0, idVar)
                outFeat.setAttribute(1, x)
                writer.addFeature(outFeat)
                x = x + xOffset
                idVar = idVar + 1
                count += 1
                if int(math.fmod(count, count_update)) == 0:
                    prog = 50 + int(count / count_max * 50)
                    self.progressBar.setValue(prog)
        else:
            # counters for progressbar - update every 5%
            count = 0
            count_max = (bound.yMaximum() - bound.yMinimum()) / yOffset
            count_update = count_max * 0.05
            y = bound.yMaximum()
            while y >= bound.yMinimum():
                x = bound.xMinimum()
                while x <= bound.xMaximum():

                    pt1 = QgsPoint(x, y)
                    pt2 = QgsPoint(x + xOffset, y)
                    pt3 = QgsPoint(x + xOffset, y - yOffset)
                    pt4 = QgsPoint(x, y - yOffset)
                    pt5 = QgsPoint(x, y)

                    if self.angle.value() != 0.0:
                        self.rotatePoint(pt1)
                        self.rotatePoint(pt2)
                        self.rotatePoint(pt3)
                        self.rotatePoint(pt4)
                        self.rotatePoint(pt5)

                    polygon = [[pt1, pt2, pt3, pt4, pt5]]
                    outFeat.setGeometry(outGeom.fromPolygon(polygon))
                    outFeat.setAttribute(0, idVar)
                    outFeat.setAttribute(1, x)
                    outFeat.setAttribute(2, x + xOffset)
                    outFeat.setAttribute(3, y - yOffset)
                    outFeat.setAttribute(4, y)
                    writer.addFeature(outFeat)
                    idVar = idVar + 1
                    x = x + xOffset
                y = y - yOffset
                count += 1
                if int(math.fmod(count, count_update)) == 0:
                    prog = int(count / count_max * 100)

        self.progressBar.setValue(100)
        del writer
    def processAlgorithm(self, feedback):
        layer = dataobjects.getLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR))
        startPoint = self.getParameterValue(self.START_POINT)
        endPoint = self.getParameterValue(self.END_POINT)
        strategy = self.getParameterValue(self.STRATEGY)

        directionFieldName = self.getParameterValue(self.DIRECTION_FIELD)
        forwardValue = self.getParameterValue(self.VALUE_FORWARD)
        backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        speedFieldName = self.getParameterValue(self.SPEED_FIELD)
        defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED)
        tolerance = self.getParameterValue(self.TOLERANCE)

        fields = QgsFields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

        writer = self.getOutputFromName(self.OUTPUT_LAYER).getVectorWriter(
            fields.toList(), QgsWkbTypes.LineString, layer.crs())

        tmp = startPoint.split(',')
        startPoint = QgsPoint(float(tmp[0]), float(tmp[1]))
        tmp = endPoint.split(',')
        endPoint = QgsPoint(float(tmp[0]), float(tmp[1]))

        directionField = -1
        if directionFieldName is not None:
            directionField = layer.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName is not None:
            speedField = layer.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(layer, directionField, forwardValue,
                                          backwardValue, bothValue,
                                          defaultDirection)

        distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(
            iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance)
        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, [startPoint, endPoint])

        feedback.pushInfo(self.tr('Calculating shortest path...'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])
        idxEnd = graph.findVertex(snappedPoints[1])

        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        if tree[idxEnd] == -1:
            raise GeoAlgorithmExecutionException(
                self.tr('There is no route from start point to end point.'))

        route = []
        cost = 0.0
        current = idxEnd
        while current != idxStart:
            cost += graph.edge(tree[current]).cost(0)
            route.append(
                graph.vertex(graph.edge(tree[current]).inVertex()).point())
            current = graph.edge(tree[current]).outVertex()

        route.append(snappedPoints[0])
        route.reverse()

        self.setOutputValue(self.TRAVEL_COST, cost / multiplier)

        feedback.pushInfo(self.tr('Writing results...'))
        geom = QgsGeometry.fromPolyline(route)
        feat = QgsFeature()
        feat.setFields(fields)
        feat['start'] = startPoint.toString()
        feat['end'] = endPoint.toString()
        feat['cost'] = cost / multiplier
        feat.setGeometry(geom)
        writer.addFeature(feat)
        del writer
Example #45
0
    def testDuplicateFeature(self):
        """ test duplicating a feature """

        project = QgsProject().instance()

        # LAYERS
        # - add first layer (parent)
        layer1 = QgsVectorLayer("Point?field=fldtxt:string&field=pkid:integer",
                                "parentlayer", "memory")
        # > check first layer (parent)
        self.assertTrue(layer1.isValid())
        # -  set the value for the copy
        layer1.setDefaultValueDefinition(1, QgsDefaultValue("rand(1000,2000)"))
        # > check first layer (parent)
        self.assertTrue(layer1.isValid())
        # - add second layer (child)
        layer2 = QgsVectorLayer("Point?field=fldtxt:string&field=id:integer&field=foreign_key:integer",
                                "childlayer", "memory")
        # > check second layer (child)
        self.assertTrue(layer2.isValid())
        # - add layers
        project.addMapLayers([layer1, layer2])

        # FEATURES
        # - add 2 features on layer1 (parent)
        l1f1orig = QgsFeature()
        l1f1orig.setFields(layer1.fields())
        l1f1orig.setAttributes(["F_l1f1", 100])
        l1f2orig = QgsFeature()
        l1f2orig.setFields(layer1.fields())
        l1f2orig.setAttributes(["F_l1f2", 101])
        # > check by adding features
        self.assertTrue(layer1.dataProvider().addFeatures([l1f1orig, l1f2orig]))
        # add 4 features on layer2 (child)
        l2f1orig = QgsFeature()
        l2f1orig.setFields(layer2.fields())
        l2f1orig.setAttributes(["F_l2f1", 201, 100])
        l2f2orig = QgsFeature()
        l2f2orig.setFields(layer2.fields())
        l2f2orig.setAttributes(["F_l2f2", 202, 100])
        l2f3orig = QgsFeature()
        l2f3orig.setFields(layer2.fields())
        l2f3orig.setAttributes(["F_l2f3", 203, 100])
        l2f4orig = QgsFeature()
        l2f4orig.setFields(layer2.fields())
        l2f4orig.setAttributes(["F_l2f4", 204, 101])
        # > check by adding features
        self.assertTrue(layer2.dataProvider().addFeatures([l2f1orig, l2f2orig, l2f3orig, l2f4orig]))

        # RELATION
        # - create the relationmanager
        relMgr = project.relationManager()
        # - create the relation
        rel = QgsRelation()
        rel.setId('rel1')
        rel.setName('childrel')
        rel.setReferencingLayer(layer2.id())
        rel.setReferencedLayer(layer1.id())
        rel.addFieldPair('foreign_key', 'pkid')
        rel.setStrength(QgsRelation.Composition)
        # > check relation
        self.assertTrue(rel.isValid())
        # - add relation
        relMgr.addRelation(rel)
        # > check if referencedLayer is layer1
        self.assertEqual(rel.referencedLayer(), layer1)
        # > check if referencingLayer is layer2
        self.assertEqual(rel.referencingLayer(), layer2)
        # > check if the layers are correct in relation when loading from relationManager
        relations = project.relationManager().relations()
        relation = relations[list(relations.keys())[0]]
        # > check if referencedLayer is layer1
        self.assertEqual(relation.referencedLayer(), layer1)
        # > check if referencingLayer is layer2
        self.assertEqual(relation.referencingLayer(), layer2)
        # > check the relatedfeatures

        '''
        # testoutput 1
        print( "\nAll Features and relations")
        featit=layer1.getFeatures()
        f=QgsFeature()
        while featit.nextFeature(f):
            print( f.attributes())
            childFeature = QgsFeature()
            relfeatit=rel.getRelatedFeatures(f)
            while relfeatit.nextFeature(childFeature):
                 print( childFeature.attributes() )
        print( "\n--------------------------")

        print( "\nFeatures on layer1")
        for f in layer1.getFeatures():
            print( f.attributes() )

        print( "\nFeatures on layer2")
        for f in layer2.getFeatures():
            print( f.attributes() )
        '''

        # DUPLICATION
        # - duplicate feature l1f1orig with children
        layer1.startEditing()
        results = QgsVectorLayerUtils.duplicateFeature(layer1, l1f1orig, project, 0)

        # > check if name is name of duplicated (pk is different)
        result_feature = results[0]
        self.assertEqual(result_feature.attribute('fldtxt'), l1f1orig.attribute('fldtxt'))
        # > check duplicated child layer
        result_layer = results[1].layers()[0]
        self.assertEqual(result_layer, layer2)
        #  > check duplicated child features
        self.assertTrue(results[1].duplicatedFeatures(result_layer))

        '''
        # testoutput 2
        print( "\nFeatures on layer1 (after duplication)")
        for f in layer1.getFeatures():
            print( f.attributes() )

        print( "\nFeatures on layer2 (after duplication)")
        for f in layer2.getFeatures():
            print( f.attributes() )
            
        print( "\nAll Features and relations")
        featit=layer1.getFeatures()
        f=QgsFeature()
        while featit.nextFeature(f):
            print( f.attributes())
            childFeature = QgsFeature()
            relfeatit=rel.getRelatedFeatures(f)
            while relfeatit.nextFeature(childFeature):
                 print( childFeature.attributes() )
        '''

        # > compare text of parent feature
        self.assertEqual(result_feature.attribute('fldtxt'), l1f1orig.attribute('fldtxt'))

        # - create copyValueList
        childFeature = QgsFeature()
        relfeatit = rel.getRelatedFeatures(result_feature)
        copyValueList = []
        while relfeatit.nextFeature(childFeature):
            copyValueList.append(childFeature.attribute('fldtxt'))
        # - create origValueList
        childFeature = QgsFeature()
        relfeatit = rel.getRelatedFeatures(l1f1orig)
        origValueList = []
        while relfeatit.nextFeature(childFeature):
            origValueList.append(childFeature.attribute('fldtxt'))

        # - check if the ids are still the same
        self.assertEqual(copyValueList, origValueList)
Example #46
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        if network is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.INPUT))

        startPoints = self.parameterAsSource(parameters, self.START_POINTS, context)
        if startPoints is None:
            raise QgsProcessingException(self.invalidSourceError(parameters, self.START_POINTS))

        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context)

        directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context)
        defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        include_bounds = True # default to true to maintain 3.0 API
        if self.INCLUDE_BOUNDS in parameters:
            include_bounds = self.parameterAsBool(parameters, self.INCLUDE_BOUNDS, context)

        fields = startPoints.fields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        directionField = -1
        if directionFieldName:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network,
                                          directionField,
                                          forwardValue,
                                          backwardValue,
                                          bothValue,
                                          defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField,
                                               defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(),
                                  True,
                                  tolerance)

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Loading start points…'))
        request = QgsFeatureRequest()
        request.setDestinationCrs(network.sourceCrs(), context.transformContext())
        features = startPoints.getFeatures(request)
        total = 100.0 / startPoints.featureCount() if startPoints.featureCount() else 0

        points = []
        source_attributes = {}
        i = 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            for p in f.geometry().vertices():
                points.append(QgsPointXY(p))
                source_attributes[i] = f.attributes()
                i += 1

            feedback.setProgress(int(current * total))

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Building graph…'))
        snappedPoints = director.makeGraph(builder, points, feedback)

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromLayer', 'Calculating service areas…'))
        graph = builder.graph()

        (point_sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                                     fields, QgsWkbTypes.MultiPoint, network.sourceCrs())
        (line_sink, line_dest_id) = self.parameterAsSink(parameters, self.OUTPUT_LINES, context,
                                                         fields, QgsWkbTypes.MultiLineString, network.sourceCrs())

        total = 100.0 / len(snappedPoints) if snappedPoints else 1
        for i, p in enumerate(snappedPoints):
            if feedback.isCanceled():
                break

            idxStart = graph.findVertex(snappedPoints[i])
            origPoint = points[i].toString()

            tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)

            vertices = set()
            area_points = []
            lines = []
            for vertex, start_vertex_cost in enumerate(cost):
                inbound_edge_index = tree[vertex]
                if inbound_edge_index == -1 and vertex != idxStart:
                    # unreachable vertex
                    continue

                if start_vertex_cost > travelCost:
                    # vertex is too expensive, discard
                    continue

                vertices.add(vertex)
                start_point = graph.vertex(vertex).point()

                # find all edges coming from this vertex
                for edge_id in graph.vertex(vertex).outgoingEdges():
                    edge = graph.edge(edge_id)
                    end_vertex_cost = start_vertex_cost + edge.cost(0)
                    end_point = graph.vertex(edge.toVertex()).point()
                    if end_vertex_cost <= travelCost:
                        # end vertex is cheap enough to include
                        vertices.add(edge.toVertex())
                        lines.append([start_point, end_point])
                    else:
                        # travelCost sits somewhere on this edge, interpolate position
                        interpolated_end_point = QgsGeometryUtils.interpolatePointOnLineByValue(start_point.x(), start_point.y(), start_vertex_cost,
                                                                                                end_point.x(), end_point.y(), end_vertex_cost, travelCost)
                        area_points.append(interpolated_end_point)
                        lines.append([start_point, interpolated_end_point])

            for v in vertices:
                area_points.append(graph.vertex(v).point())

            feat = QgsFeature()
            if point_sink is not None:
                geomPoints = QgsGeometry.fromMultiPointXY(area_points)
                feat.setGeometry(geomPoints)
                attrs = source_attributes[i]
                attrs.extend(['within', origPoint])
                feat.setAttributes(attrs)
                point_sink.addFeature(feat, QgsFeatureSink.FastInsert)

                if include_bounds:
                    upperBoundary = []
                    lowerBoundary = []

                    vertices = []
                    for vertex, c in enumerate(cost):
                        if c > travelCost and tree[vertex] != -1:
                            vertexId = graph.edge(tree[vertex]).fromVertex()
                            if cost[vertexId] <= travelCost:
                                vertices.append(vertex)

                    for v in vertices:
                        upperBoundary.append(graph.vertex(graph.edge(tree[v]).toVertex()).point())
                        lowerBoundary.append(graph.vertex(graph.edge(tree[v]).fromVertex()).point())

                    geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary)
                    geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary)

                    feat.setGeometry(geomUpper)
                    attrs[-2] = 'upper'
                    feat.setAttributes(attrs)
                    point_sink.addFeature(feat, QgsFeatureSink.FastInsert)

                    feat.setGeometry(geomLower)
                    attrs[-2] = 'lower'
                    feat.setAttributes(attrs)
                    point_sink.addFeature(feat, QgsFeatureSink.FastInsert)

            if line_sink is not None:
                geom_lines = QgsGeometry.fromMultiPolylineXY(lines)
                feat.setGeometry(geom_lines)
                attrs = source_attributes[i]
                attrs.extend(['lines', origPoint])
                feat.setAttributes(attrs)
                line_sink.addFeature(feat, QgsFeatureSink.FastInsert)

            feedback.setProgress(int(i * total))

        results = {}
        if point_sink is not None:
            results[self.OUTPUT] = dest_id
        if line_sink is not None:
            results[self.OUTPUT_LINES] = line_dest_id
        return results
Example #47
0
    def compute(self, line1, line2, field1, field2, outPath, progressBar):

        layer1 = ftools_utils.getVectorLayerByName(line1)
        provider1 = layer1.dataProvider()
        fieldList = ftools_utils.getFieldList(layer1)
        index1 = provider1.fieldNameIndex(field1)
        field1 = fieldList[index1]
        field1.setName(unicode(field1.name()) + "_1")

        layer2 = ftools_utils.getVectorLayerByName(line2)
        provider2 = layer2.dataProvider()
        fieldList = ftools_utils.getFieldList(layer2)
        index2 = provider2.fieldNameIndex(field2)
        field2 = fieldList[index2]
        field2.setName(unicode(field2.name()) + "_2")

        fieldList = QgsFields()
        fieldList.append(field1)
        fieldList.append(field2)
        sRs = provider1.crs()
        check = QFile(self.shapefileName)
        if check.exists():
            if not QgsVectorFileWriter.deleteShapeFile(self.shapefileName):
                return

        writer = QgsVectorFileWriter(self.shapefileName, self.encoding,
                                     fieldList, QGis.WKBPoint, sRs)
        inFeat = QgsFeature()
        inFeatB = QgsFeature()
        outFeat = QgsFeature()
        outFields = QgsFields()
        outFields.append(field1)
        outFields.append(field2)
        outFeat.setFields(outFields)
        start = 15.00
        add = 85.00 / layer1.featureCount()

        index = ftools_utils.createIndex(provider2)

        singlelayer_tempList = []
        fit1 = provider1.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(
            [index1]))
        while fit1.nextFeature(inFeat):
            inGeom = inFeat.geometry()
            v1 = inFeat.attributes()[index1]

            lineList = index.intersects(inGeom.boundingBox())
            for i in lineList:
                provider2.getFeatures(QgsFeatureRequest().setFilterFid(
                    int(i)).setSubsetOfAttributes([index2
                                                   ])).nextFeature(inFeatB)
                tmpGeom = QgsGeometry(inFeatB.geometry())
                v2 = inFeatB.attributes()[index2]

                if inGeom.intersects(tmpGeom):
                    tempGeom = inGeom.intersection(tmpGeom)
                    if tempGeom.type() == QGis.Point:
                        tempList = []
                        if tempGeom.isMultipart():
                            tempList = tempGeom.asMultiPoint()
                        else:
                            tempList.append(tempGeom.asPoint())

                        for j in tempList:
                            # if same layer, avoid insert duplicated points
                            if line1 == line2:
                                if j not in singlelayer_tempList:
                                    singlelayer_tempList.append(j)
                                    outFeat.setGeometry(tempGeom.fromPoint(j))
                                    outFeat.setAttribute(0, v1)
                                    outFeat.setAttribute(1, v2)
                                    writer.addFeature(outFeat)
                            else:
                                outFeat.setGeometry(tempGeom.fromPoint(j))
                                outFeat.setAttribute(0, v1)
                                outFeat.setAttribute(1, v2)
                                writer.addFeature(outFeat)

            start = start + add
            progressBar.setValue(start)

        del writer
Example #48
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)
        travelCost = self.parameterAsDouble(parameters, self.TRAVEL_COST, context)

        directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context)
        defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        directionField = -1
        if directionFieldName:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network,
                                          directionField,
                                          forwardValue,
                                          backwardValue,
                                          bothValue,
                                          defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField,
                                               defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(),
                                  True,
                                  tolerance)
        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Building graph…'))
        snappedPoints = director.makeGraph(builder, [startPoint], feedback)

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Calculating service area…'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])

        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        vertices = []
        for i, v in enumerate(cost):
            if v > travelCost and tree[i] != -1:
                vertexId = graph.edge(tree[i]).fromVertex()
                if cost[vertexId] <= travelCost:
                    vertices.append(i)

        upperBoundary = []
        lowerBoundary = []
        for i in vertices:
            upperBoundary.append(graph.vertex(graph.edge(tree[i]).toVertex()).point())
            lowerBoundary.append(graph.vertex(graph.edge(tree[i]).fromVertex()).point())

        feedback.pushInfo(QCoreApplication.translate('ServiceAreaFromPoint', 'Writing results…'))

        fields = QgsFields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary)
        geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.MultiPoint, network.sourceCrs())

        feat.setGeometry(geomUpper)
        feat['type'] = 'upper'
        feat['start'] = startPoint.toString()
        sink.addFeature(feat, QgsFeatureSink.FastInsert)

        feat.setGeometry(geomLower)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        sink.addFeature(feat, QgsFeatureSink.FastInsert)

        upperBoundary.append(startPoint)
        lowerBoundary.append(startPoint)
        geomUpper = QgsGeometry.fromMultiPointXY(upperBoundary)
        geomLower = QgsGeometry.fromMultiPointXY(lowerBoundary)

        return {self.OUTPUT: dest_id}
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoint = self.parameterAsPoint(parameters, self.START_POINT, context, network.sourceCrs())
        endPoint = self.parameterAsPoint(parameters, self.END_POINT, context, network.sourceCrs())
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

        directionFieldName = self.parameterAsString(parameters, self.DIRECTION_FIELD, context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD, context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD, context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH, context)
        defaultDirection = self.parameterAsEnum(parameters, self.DEFAULT_DIRECTION, context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD, context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED, context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        fields = QgsFields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
                                               fields, QgsWkbTypes.LineString, network.sourceCrs())

        directionField = -1
        if directionField:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network,
                                          directionField,
                                          forwardValue,
                                          backwardValue,
                                          bothValue,
                                          defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField,
                                               defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(network.sourceCrs(),
                                  True,
                                  tolerance)
        feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Building graph…'))
        snappedPoints = director.makeGraph(builder, [startPoint, endPoint], feedback)

        feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Calculating shortest path…'))
        graph = builder.graph()
        idxStart = graph.findVertex(snappedPoints[0])
        idxEnd = graph.findVertex(snappedPoints[1])

        tree, costs = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        if tree[idxEnd] == -1:
            raise QgsProcessingException(
                self.tr('There is no route from start point to end point.'))

        route = [graph.vertex(idxEnd).point()]
        cost = costs[idxEnd]
        current = idxEnd
        while current != idxStart:
            current = graph.edge(tree[current]).fromVertex()
            route.append(graph.vertex(current).point())

        route.reverse()

        feedback.pushInfo(QCoreApplication.translate('ShortestPathPointToPoint', 'Writing results…'))
        geom = QgsGeometry.fromPolylineXY(route)
        feat = QgsFeature()
        feat.setFields(fields)
        feat['start'] = startPoint.toString()
        feat['end'] = endPoint.toString()
        feat['cost'] = cost / multiplier
        feat.setGeometry(geom)
        sink.addFeature(feat, QgsFeatureSink.FastInsert)

        results = {}
        results[self.TRAVEL_COST] = cost / multiplier
        results[self.OUTPUT] = dest_id
        return results
Example #50
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_VECTOR))

        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.toList(), QgsWkbTypes.Point, layer.crs())

        outFeature = QgsFeature()
        outFeature.setFields(fields)

        fid = 0
        polyId = 0
        pointId = 0

        features = vector.features(layer)
        total = 100.0 / len(features)
        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
Example #51
0
    def writeShapefile(self, filename, shape_type):

        if filename[-4:] != '.shp':
            filename += '.shp'

        proj = QgsProject.instance()
        crs = proj.crs()
        #Create new shapefile object, loop trough triangle edges and add each
        # edge as a line.
        if shape_type == 'points':
            shape = QgsWkbTypes.Point
            fields = QgsFields()
            fields.append(QgsField("Id", QVariant.Int, 'integer', 9, 0))
            fields.append(QgsField("Depth", QVariant.Double, 'double', 9, 3))
            fields.append(QgsField("Connect", QVariant.Int, 'integer', 2, 0))

        elif shape_type == 'edges':
            shape = QgsWkbTypes.LineString
            fields = QgsFields()
            fields.append(QgsField("Id", QVariant.Int, 'integer', 9, 0))
            fields.append(QgsField("Flag", QVariant.Int, 'integer', 2, 0))
            fields.append(QgsField("Name", QVariant.String, 'string', 10, 0))

        elif shape_type == 'faces':
            shape = QgsWkbTypes.Polygon
            fields = QgsFields()
            fields.append(QgsField("Id", QVariant.Int, 'integer', 9, 0))
            fields.append(QgsField("Node1", QVariant.Int, 'integer', 11, 0))
            fields.append(QgsField("Node2", QVariant.Int, 'integer', 11, 0))
            fields.append(QgsField("Node3", QVariant.Int, 'integer', 11, 0))
            fields.append(QgsField("Node4", QVariant.Int, 'integer', 11, 0))
            fields.append(QgsField("type", QVariant.Int, 'integer', 1, 0))
            fields.append(QgsField("area", QVariant.Int, 'integer', 9, 0))
            fields.append(QgsField("volume", QVariant.Int, 'integer', 9, 0))
            fields.append(QgsField("depth", QVariant.Double, 'double', 9, 2))
            fields.append(QgsField("resolution", QVariant.Int, 'integer', 9,
                                   0))
            fields.append(QgsField("ETA", QVariant.Double, 'double', 3, 2))
            fields.append(QgsField("NSR", QVariant.Double, 'double', 3, 2))
            fields.append(QgsField("Angle", QVariant.Double, 'double', 3, 2))

        fileWriter = QgsVectorFileWriter(filename, "system", fields, shape,
                                         crs, "ESRI Shapefile")

        if fileWriter.hasError() != QgsVectorFileWriter.NoError:
            raise Exception('Error when creating shapefile ' + filename +
                            ' : ' + str(fileWriter.hasError()))

        if shape_type == 'points':
            for node in range(0, len(self.x)):
                point = QgsPointXY()
                point.setX(self.x[node])
                point.setY(self.y[node])
                newFeature = QgsFeature()
                newFeature.setGeometry(QgsGeometry.fromPointXY(point))
                newFeature.setFields(fields)
                newFeature.setAttributes([
                    int(node + 1),
                    float('%9.3f' % self.z[node]),
                    int(self.conn[node])
                ])
                fileWriter.addFeature(newFeature)

        if shape_type == 'edges':

            for key in self.physical:
                edgID = np.nonzero(
                    np.logical_or(self.physicalID == self.physical[key][0],
                                  np.asarray(self.physicalID) == 0))[0]
                points = []
                edgeN = 0
                for i, edg in enumerate(edgID):
                    if self.physicalID[edg] > 0:
                        points.append(
                            QgsPointXY(self.x[self.edges[edg]],
                                       self.y[self.edges[edg]]))
                    elif len(points) > 0:
                        newFeature = QgsFeature()
                        newFeature.setGeometry(
                            QgsGeometry.fromPolylineXY(points))
                        newFeature.setFields(fields)
                        newFeature.setAttributes(
                            [int(edgeN + 1),
                             int(self.physical[key][0]), key])
                        fileWriter.addFeature(newFeature)
                        points = []
                        edgeN += 1

        if shape_type == 'faces':
            for ie in range(0, len(self.faces)):
                if self.faces[ie, -1] < 0:
                    nface = 3
                else:
                    nface = 4

                points = []
                for fc in range(0, nface):
                    i = self.faces[ie, fc]
                    points.append(QgsPointXY(self.x[i], self.y[i]))

                i = self.faces[ie, 0]
                points.append(QgsPointXY(self.x[i], self.y[i]))
                newFeature = QgsFeature()
                newFeature.setGeometry(QgsGeometry.fromPolygonXY([points]))
                newFeature.setFields(fields)
                newFeature.setAttributes([int(ie+1),\
                    int(self.faces[ie,0]+1),int(self.faces[ie,1]+1),int(self.faces[ie,2]+1),int(self.faces[ie,3]+1),\
                    int(nface),\
                    float('%9.f' % self.areas[ie]),float('%9.f' % self.volumes[ie]),float('%9.2f' % self.zctr[ie]),float('%9.f' % self.res[ie]),\
                    float('%3.2f' % self.eta[ie]),float('%3.2f' % self.nsr[ie]),float('%3.2f' % self.min_angle[ie])])
                fileWriter.addFeature(newFeature)

        del fileWriter
Example #52
0
    def processAlgorithm(self, feedback):
        layer = dataobjects.getLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR))
        startPoints = dataobjects.getLayerFromString(
            self.getParameterValue(self.START_POINTS))
        strategy = self.getParameterValue(self.STRATEGY)
        travelCost = self.getParameterValue(self.TRAVEL_COST)

        directionFieldName = self.getParameterValue(self.DIRECTION_FIELD)
        forwardValue = self.getParameterValue(self.VALUE_FORWARD)
        backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        speedFieldName = self.getParameterValue(self.SPEED_FIELD)
        defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED)
        tolerance = self.getParameterValue(self.TOLERANCE)

        fields = QgsFields()
        fields.append(QgsField('type', QVariant.String, '', 254, 0))
        fields.append(QgsField('start', QVariant.String, '', 254, 0))

        feat = QgsFeature()
        feat.setFields(fields)

        writerPoints = self.getOutputFromName(
            self.OUTPUT_POINTS).getVectorWriter(fields, QgsWkbTypes.MultiPoint,
                                                layer.crs())

        writerPolygons = self.getOutputFromName(
            self.OUTPUT_POLYGON).getVectorWriter(fields, QgsWkbTypes.Polygon,
                                                 layer.crs())

        directionField = -1
        if directionFieldName is not None:
            directionField = layer.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName is not None:
            speedField = layer.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(layer, directionField, forwardValue,
                                          backwardValue, bothValue,
                                          defaultDirection)

        distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(
            iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance)

        feedback.pushInfo(self.tr('Loading start points...'))
        request = QgsFeatureRequest()
        request.setFlags(request.flags()
                         ^ QgsFeatureRequest.SubsetOfAttributes)
        features = vector.features(startPoints, request)
        points = []
        for f in features:
            points.append(f.geometry().asPoint())

        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, points)

        feedback.pushInfo(self.tr('Calculating service areas...'))
        graph = builder.graph()

        vertices = []
        upperBoundary = []
        lowerBoundary = []
        total = 100.0 / len(snappedPoints)
        for i, p in enumerate(snappedPoints):
            idxStart = graph.findVertex(snappedPoints[i])
            origPoint = points[i].toString()

            tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
            for j, v in enumerate(cost):
                if v > travelCost and tree[j] != -1:
                    vertexId = graph.edge(tree[j]).outVertex()
                    if cost[vertexId] <= travelCost:
                        vertices.append(j)

            for j in vertices:
                upperBoundary.append(
                    graph.vertex(graph.edge(tree[j]).inVertex()).point())
                lowerBoundary.append(
                    graph.vertex(graph.edge(tree[j]).outVertex()).point())

            geomUpper = QgsGeometry.fromMultiPoint(upperBoundary)
            geomLower = QgsGeometry.fromMultiPoint(lowerBoundary)

            feat.setGeometry(geomUpper)
            feat['type'] = 'upper'
            feat['start'] = origPoint
            writerPoints.addFeature(feat)

            feat.setGeometry(geomLower)
            feat['type'] = 'lower'
            feat['start'] = origPoint
            writerPoints.addFeature(feat)

            upperBoundary.append(origPoint)
            lowerBoundary.append(origPoint)
            geomUpper = QgsGeometry.fromMultiPoint(upperBoundary)
            geomLower = QgsGeometry.fromMultiPoint(lowerBoundary)

            geom = geomUpper.convexHull()
            feat.setGeometry(geom)
            feat['type'] = 'upper'
            feat['start'] = origPoint
            writerPolygons.addFeature(feat)

            geom = geomLower.convexHull()
            feat.setGeometry(geom)
            feat['type'] = 'lower'
            feat['start'] = origPoint
            writerPolygons.addFeature(feat)

            vertices[:] = []
            upperBoundary[:] = []
            lowerBoundary[:] = []

            feedback.setProgress(int(i * total))

        del writerPoints
        del writerPolygons
Example #53
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT_VECTOR), context)
        startPoint = self.getParameterValue(self.START_POINT)
        endPoints = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.END_POINTS), context)
        strategy = self.getParameterValue(self.STRATEGY)

        directionFieldName = self.getParameterValue(self.DIRECTION_FIELD)
        forwardValue = self.getParameterValue(self.VALUE_FORWARD)
        backwardValue = self.getParameterValue(self.VALUE_BACKWARD)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        bothValue = self.getParameterValue(self.VALUE_BOTH)
        defaultDirection = self.getParameterValue(self.DEFAULT_DIRECTION)
        speedFieldName = self.getParameterValue(self.SPEED_FIELD)
        defaultSpeed = self.getParameterValue(self.DEFAULT_SPEED)
        tolerance = self.getParameterValue(self.TOLERANCE)

        fields = QgsFields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

        feat = QgsFeature()
        feat.setFields(fields)

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

        tmp = startPoint.split(',')
        startPoint = QgsPointXY(float(tmp[0]), float(tmp[1]))

        directionField = -1
        if directionFieldName is not None:
            directionField = layer.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName is not None:
            speedField = layer.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(layer, directionField, forwardValue,
                                          backwardValue, bothValue,
                                          defaultDirection)

        distUnit = iface.mapCanvas().mapSettings().destinationCrs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(
            iface.mapCanvas().mapSettings().destinationCrs(), True, tolerance)

        feedback.pushInfo(self.tr('Loading end points...'))
        request = QgsFeatureRequest()
        request.setFlags(request.flags()
                         ^ QgsFeatureRequest.SubsetOfAttributes)
        features = QgsProcessingUtils.getFeatures(endPoints, context, request)
        count = QgsProcessingUtils.featureCount(endPoints, context)

        points = [startPoint]
        for f in features:
            points.append(f.geometry().asPoint())

        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, points)

        feedback.pushInfo(self.tr('Calculating shortest paths...'))
        graph = builder.graph()

        idxStart = graph.findVertex(snappedPoints[0])
        tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)
        route = []

        total = 100.0 / count if count else 1
        for i in range(1, count + 1):
            idxEnd = graph.findVertex(snappedPoints[i])

            if tree[idxEnd] == -1:
                msg = self.tr(
                    'There is no route from start point ({}) to end point ({}).'
                    .format(startPoint.toString(), points[i].toString()))
                feedback.setProgressText(msg)
                QgsMessageLog.logMessage(msg, self.tr('Processing'),
                                         QgsMessageLog.WARNING)
                continue

            cost = 0.0
            current = idxEnd
            while current != idxStart:
                cost += graph.edge(tree[current]).cost(0)
                route.append(
                    graph.vertex(graph.edge(tree[current]).inVertex()).point())
                current = graph.edge(tree[current]).outVertex()

            route.append(snappedPoints[0])
            route.reverse()

            geom = QgsGeometry.fromPolyline(route)
            feat.setGeometry(geom)
            feat['start'] = startPoint.toString()
            feat['end'] = points[i].toString()
            feat['cost'] = cost / multiplier
            writer.addFeature(feat, QgsFeatureSink.FastInsert)

            route[:] = []

            feedback.setProgress(int(i * total))

        del writer
Example #54
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.fromPoint(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}
    def testNumeric(self):
        """ Test calculation of aggregates on numeric fields"""

        layer = QgsVectorLayer("Point?field=fldint:integer&field=flddbl:double",
                               "layer", "memory")
        pr = layer.dataProvider()

        # must be same length:
        int_values = [4, 2, 3, 2, 5, None, 8]
        dbl_values = [5.5, 3.5, 7.5, 5, 9, None, 7]
        self.assertEqual(len(int_values), len(dbl_values))

        features = []
        for i in range(len(int_values)):
            f = QgsFeature()
            f.setFields(layer.fields())
            f.setAttributes([int_values[i], dbl_values[i]])
            features.append(f)
        assert pr.addFeatures(features)

        tests = [[QgsAggregateCalculator.Count, 'fldint', 6],
                 [QgsAggregateCalculator.Count, 'flddbl', 6],
                 [QgsAggregateCalculator.Sum, 'fldint', 24],
                 [QgsAggregateCalculator.Sum, 'flddbl', 37.5],
                 [QgsAggregateCalculator.Mean, 'fldint', 4],
                 [QgsAggregateCalculator.Mean, 'flddbl', 6.25],
                 [QgsAggregateCalculator.StDev, 'fldint', 2.0816],
                 [QgsAggregateCalculator.StDev, 'flddbl', 1.7969],
                 [QgsAggregateCalculator.StDevSample, 'fldint', 2.2803],
                 [QgsAggregateCalculator.StDevSample, 'flddbl', 1.9685],
                 [QgsAggregateCalculator.Min, 'fldint', 2],
                 [QgsAggregateCalculator.Min, 'flddbl', 3.5],
                 [QgsAggregateCalculator.Max, 'fldint', 8],
                 [QgsAggregateCalculator.Max, 'flddbl', 9],
                 [QgsAggregateCalculator.Range, 'fldint', 6],
                 [QgsAggregateCalculator.Range, 'flddbl', 5.5],
                 [QgsAggregateCalculator.Median, 'fldint', 3.5],
                 [QgsAggregateCalculator.Median, 'flddbl', 6.25],
                 [QgsAggregateCalculator.CountDistinct, 'fldint', 5],
                 [QgsAggregateCalculator.CountDistinct, 'flddbl', 6],
                 [QgsAggregateCalculator.CountMissing, 'fldint', 1],
                 [QgsAggregateCalculator.CountMissing, 'flddbl', 1],
                 [QgsAggregateCalculator.FirstQuartile, 'fldint', 2],
                 [QgsAggregateCalculator.FirstQuartile, 'flddbl', 5.0],
                 [QgsAggregateCalculator.ThirdQuartile, 'fldint', 5.0],
                 [QgsAggregateCalculator.ThirdQuartile, 'flddbl', 7.5],
                 [QgsAggregateCalculator.InterQuartileRange, 'fldint', 3.0],
                 [QgsAggregateCalculator.InterQuartileRange, 'flddbl', 2.5],
                 [QgsAggregateCalculator.ArrayAggregate, 'fldint', int_values],
                 [QgsAggregateCalculator.ArrayAggregate, 'flddbl', dbl_values],
                 ]

        agg = QgsAggregateCalculator(layer)
        for t in tests:
            val, ok = agg.calculate(t[0], t[1])
            self.assertTrue(ok)
            if isinstance(t[2], (int, list)):
                self.assertEqual(val, t[2])
            else:
                self.assertAlmostEqual(val, t[2], 3)

        # bad tests - the following stats should not be calculatable for numeric fields
        for t in [QgsAggregateCalculator.StringMinimumLength,
                  QgsAggregateCalculator.StringMaximumLength]:
            val, ok = agg.calculate(t, 'fldint')
            self.assertFalse(ok)
            val, ok = agg.calculate(t, 'flddbl')
            self.assertFalse(ok)
Example #56
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.INPUT), context)
        method = self.getParameterValue(self.METHOD)

        geometryType = layer.geometryType()
        fields = layer.fields()

        export_z = False
        export_m = False
        if geometryType == QgsWkbTypes.PolygonGeometry:
            areaName = vector.createUniqueFieldName('area', fields)
            fields.append(QgsField(areaName, QVariant.Double))
            perimeterName = vector.createUniqueFieldName('perimeter', fields)
            fields.append(QgsField(perimeterName, QVariant.Double))
        elif geometryType == QgsWkbTypes.LineGeometry:
            lengthName = vector.createUniqueFieldName('length', fields)
            fields.append(QgsField(lengthName, QVariant.Double))
        else:
            xName = vector.createUniqueFieldName('xcoord', fields)
            fields.append(QgsField(xName, QVariant.Double))
            yName = vector.createUniqueFieldName('ycoord', fields)
            fields.append(QgsField(yName, QVariant.Double))
            if QgsWkbTypes.hasZ(layer.wkbType()):
                export_z = True
                zName = vector.createUniqueFieldName('zcoord', fields)
                fields.append(QgsField(zName, QVariant.Double))
            if QgsWkbTypes.hasM(layer.wkbType()):
                export_m = True
                zName = vector.createUniqueFieldName('mvalue', fields)
                fields.append(QgsField(zName, QVariant.Double))

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

        ellips = None
        crs = None
        coordTransform = None

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

        if method == 2:
            ellips = QgsProject.instance().ellipsoid()
            crs = layer.crs().srsid()
        elif method == 1:
            mapCRS = iface.mapCanvas().mapSettings().destinationCrs()
            layCRS = layer.crs()
            coordTransform = QgsCoordinateTransform(layCRS, mapCRS)

        outFeat = QgsFeature()

        outFeat.initAttributes(len(fields))
        outFeat.setFields(fields)

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

            if method == 1:
                inGeom.transform(coordTransform)

            (attr1, attr2) = vector.simpleMeasure(inGeom, method, ellips, crs)

            outFeat.setGeometry(inGeom)
            attrs = f.attributes()
            attrs.append(attr1)
            if attr2 is not None:
                attrs.append(attr2)

            # add point z/m
            if export_z:
                attrs.append(inGeom.geometry().z())
            if export_m:
                attrs.append(inGeom.geometry().m())

            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat)

            feedback.setProgress(int(current * total))

        del writer
Example #57
0
    def processAlgorithm(self, parameters, context, feedback):
        network = self.parameterAsSource(parameters, self.INPUT, context)
        startPoints = self.parameterAsSource(parameters, self.START_POINTS,
                                             context)
        endPoint = self.parameterAsPoint(parameters, self.END_POINT, context)
        strategy = self.parameterAsEnum(parameters, self.STRATEGY, context)

        directionFieldName = self.parameterAsString(parameters,
                                                    self.DIRECTION_FIELD,
                                                    context)
        forwardValue = self.parameterAsString(parameters, self.VALUE_FORWARD,
                                              context)
        backwardValue = self.parameterAsString(parameters, self.VALUE_BACKWARD,
                                               context)
        bothValue = self.parameterAsString(parameters, self.VALUE_BOTH,
                                           context)
        defaultDirection = self.parameterAsEnum(parameters,
                                                self.DEFAULT_DIRECTION,
                                                context)
        speedFieldName = self.parameterAsString(parameters, self.SPEED_FIELD,
                                                context)
        defaultSpeed = self.parameterAsDouble(parameters, self.DEFAULT_SPEED,
                                              context)
        tolerance = self.parameterAsDouble(parameters, self.TOLERANCE, context)

        fields = QgsFields()
        fields.append(QgsField('start', QVariant.String, '', 254, 0))
        fields.append(QgsField('end', QVariant.String, '', 254, 0))
        fields.append(QgsField('cost', QVariant.Double, '', 20, 7))

        feat = QgsFeature()
        feat.setFields(fields)

        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, fields,
                                               QgsWkbTypes.LineString,
                                               network.sourceCrs())

        directionField = -1
        if directionFieldName:
            directionField = network.fields().lookupField(directionFieldName)
        speedField = -1
        if speedFieldName:
            speedField = network.fields().lookupField(speedFieldName)

        director = QgsVectorLayerDirector(network, directionField,
                                          forwardValue, backwardValue,
                                          bothValue, defaultDirection)

        distUnit = context.project().crs().mapUnits()
        multiplier = QgsUnitTypes.fromUnitToUnitFactor(
            distUnit, QgsUnitTypes.DistanceMeters)
        if strategy == 0:
            strategy = QgsNetworkDistanceStrategy()
        else:
            strategy = QgsNetworkSpeedStrategy(speedField, defaultSpeed,
                                               multiplier * 1000.0 / 3600.0)
            multiplier = 3600

        director.addStrategy(strategy)
        builder = QgsGraphBuilder(context.project().crs(), True, tolerance)

        feedback.pushInfo(self.tr('Loading start points...'))
        request = QgsFeatureRequest()
        request.setFlags(request.flags()
                         ^ QgsFeatureRequest.SubsetOfAttributes)
        request.setDestinationCrs(network.sourceCrs())
        features = startPoints.getFeatures(request)
        total = 100.0 / startPoints.featureCount() if startPoints.featureCount(
        ) else 0

        points = [endPoint]
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            points.append(f.geometry().asPoint())
            feedback.setProgress(int(current * total))

        feedback.pushInfo(self.tr('Building graph...'))
        snappedPoints = director.makeGraph(builder, points, feedback)

        feedback.pushInfo(self.tr('Calculating shortest paths...'))
        graph = builder.graph()

        idxEnd = graph.findVertex(snappedPoints[0])
        route = []

        nPoints = len(snappedPoints)
        total = 100.0 / nPoints if nPoints else 1
        for i in range(1, count + 1):
            if feedback.isCanceled():
                break

            idxStart = graph.findVertex(snappedPoints[i])
            tree, cost = QgsGraphAnalyzer.dijkstra(graph, idxStart, 0)

            if tree[idxEnd] == -1:
                msg = self.tr(
                    'There is no route from start point ({}) to end point ({}).'
                    .format(points[i].toString(), endPoint.toString()))
                feedback.setProgressText(msg)
                QgsMessageLog.logMessage(msg, self.tr('Processing'),
                                         QgsMessageLog.WARNING)
                continue

            cost = 0.0
            current = idxEnd
            while current != idxStart:
                cost += graph.edge(tree[current]).cost(0)
                route.append(
                    graph.vertex(graph.edge(tree[current]).inVertex()).point())
                current = graph.edge(tree[current]).outVertex()

            route.append(snappedPoints[i])
            route.reverse()

            geom = QgsGeometry.fromPolyline(route)
            feat.setGeometry(geom)
            feat['start'] = points[i].toString()
            feat['end'] = endPoint.toString()
            feat['cost'] = cost / multiplier
            sink.addFeature(feat, QgsFeatureSink.FastInsert)

            route[:] = []

            feedback.setProgress(int(i * total))

        return {self.OUTPUT: dest_id}
def create_preview_group(
        group_name: str,
        images: List[dict],
        footprints_filename = None,
        catalog_layer_name = None,
        tile_service: str = 'xyz',
        search_query: str = None,
        sort_order: Tuple[str, str] = None) -> None:

    if tile_service.lower() not in ['wmts', 'xyz']:
        log.debug(f'Incorrect tile service passed for preview group: '
                  f'{tile_service} (must be wmts or xyz)')
        return

    item_ids = [f"{img['properties'][ITEM_TYPE]}:{img[ID]}" for img in images]
    uri = tile_service_data_src_uri(
        item_ids, service=tile_service)

    if uri:
        log.debug(f'Tile datasource URI:\n{uri}')

        rlayer = QgsRasterLayer(uri, 'Image previews', 'wms')
        rlayer.setCustomProperty(PLANET_PREVIEW_ITEM_IDS, json.dumps(item_ids))

        if tile_service == 'xyz' and catalog_layer_name is not None:
            url = uri.split("url=")[-1]
            s = QSettings()
            s.setValue(f'qgis/connections-xyz/{catalog_layer_name}/username', "")
            s.setValue(f'qgis/connections-xyz/{catalog_layer_name}/password', "")
            s.setValue(f'qgis/connections-xyz/{catalog_layer_name}/authcfg', "")
            s.setValue(f'qgis/connections-xyz/{catalog_layer_name}/url',
                url.replace(PlanetClient.getInstance().api_key(), ""))
    else:
        log.debug('No tile URI for preview group')
        return

    vlayer = None
    if images:
        vlayer = create_preview_vector_layer(images[0])

        vlayer.startEditing()
        dp = vlayer.dataProvider()
        fields: List[QgsField] = vlayer.fields()

        for img in images:
            feat = QgsFeature()
            feat.setFields(fields)
            qgs_geom = qgsgeometry_from_geojson(img['geometry'])
            feat.setGeometry(qgs_geom)

            f_names = [f.name() for f in fields]

            if 'item_id' in f_names:
                feat['item_id'] = img[ID]

            if search_query and 'search_query' in f_names:
                feat['search_query'] = json.dumps(search_query)
            if (sort_order and 'sort_order' in f_names
                    and len(sort_order) > 1):
                feat['sort_order'] = ' '.join(sort_order)

            props: dict = img['properties']
            for k, v in props.items():
                if k in f_names:
                    feat[k] = v

            dp.addFeature(feat)

        vlayer.commitChanges()

        if footprints_filename:
            QgsVectorFileWriter.writeAsVectorFormat(vlayer, footprints_filename, "UTF-8")
            gpkglayer = QgsVectorLayer(footprints_filename, 'Footprints')
            gpkglayer.setRenderer(vlayer.renderer().clone())
            vlayer = gpkglayer
        QgsProject.instance().addMapLayer(vlayer, False)

    # noinspection PyArgumentList
    QgsProject.instance().addMapLayer(rlayer, False)

    # noinspection PyArgumentList
    root: QgsLayerTree = QgsProject.instance().layerTreeRoot()
    group = root.insertGroup(0, f'{group_name} {tile_service.upper()} preview')
    if vlayer:
        group.addLayer(vlayer)
    group.addLayer(rlayer)
    if vlayer:
        iface.setActiveLayer(vlayer)
    def testExpression(self):
        """ test aggregate calculation using an expression """

        # numeric
        layer = QgsVectorLayer("Point?field=fldint:integer", "layer", "memory")
        pr = layer.dataProvider()

        int_values = [4, 2, 3, 2, 5, None, 8]

        features = []
        for v in int_values:
            f = QgsFeature()
            f.setFields(layer.fields())
            f.setAttributes([v])
            features.append(f)
        assert pr.addFeatures(features)

        # int
        agg = QgsAggregateCalculator(layer)
        val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 2')
        self.assertTrue(ok)
        self.assertEqual(val, 48)

        # double
        val, ok = agg.calculate(QgsAggregateCalculator.Sum, 'fldint * 1.5')
        self.assertTrue(ok)
        self.assertEqual(val, 36)

        # datetime
        val, ok = agg.calculate(
            QgsAggregateCalculator.Max,
            "to_date('2012-05-04') + to_interval( fldint || ' day' )")
        self.assertTrue(ok)
        self.assertEqual(val, QDateTime(QDate(2012, 5, 12), QTime(0, 0, 0)))

        # date
        val, ok = agg.calculate(
            QgsAggregateCalculator.Min,
            "to_date(to_date('2012-05-04') + to_interval( fldint || ' day' ))")
        self.assertTrue(ok)
        self.assertEqual(val, QDateTime(QDate(2012, 5, 6), QTime(0, 0, 0)))

        # string
        val, ok = agg.calculate(QgsAggregateCalculator.Max,
                                "fldint || ' oranges'")
        self.assertTrue(ok)
        self.assertEqual(val, '8 oranges')

        # geometry
        val, ok = agg.calculate(QgsAggregateCalculator.GeometryCollect,
                                "make_point( coalesce(fldint,0), 2 )")
        self.assertTrue(ok)
        self.assertTrue(val.asWkt(),
                        'MultiPoint((4 2, 2 2, 3 2, 2 2,5 2, 0 2,8 2))')

        # try a bad expression
        val, ok = agg.calculate(QgsAggregateCalculator.Max,
                                "not_a_field || ' oranges'")
        self.assertFalse(ok)
        val, ok = agg.calculate(QgsAggregateCalculator.Max, "5+")
        self.assertFalse(ok)

        # test expression context

        # check default context first
        # should have layer variables:
        val, ok = agg.calculate(QgsAggregateCalculator.Min, "@layer_name")
        self.assertTrue(ok)
        self.assertEqual(val, 'layer')
        # but not custom variables:
        val, ok = agg.calculate(QgsAggregateCalculator.Min, "@my_var")
        self.assertTrue(ok)
        self.assertEqual(val, NULL)

        # test with manual expression context
        scope = QgsExpressionContextScope()
        scope.setVariable('my_var', 5)
        context = QgsExpressionContext()
        context.appendScope(scope)
        val, ok = agg.calculate(QgsAggregateCalculator.Min, "@my_var", context)
        self.assertTrue(ok)
        self.assertEqual(val, 5)
    def testDateTime(self):
        """ Test calculation of aggregates on date/datetime fields"""

        layer = QgsVectorLayer(
            "Point?field=flddate:date&field=flddatetime:datetime", "layer",
            "memory")
        pr = layer.dataProvider()

        # must be same length:
        datetime_values = [
            QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)),
            QDateTime(QDate(2011, 1, 5), QTime(15, 3, 1)),
            QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)),
            QDateTime(QDate(2015, 3, 4), QTime(11, 10, 54)),
            QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1)),
            QDateTime(),
            QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54)),
            QDateTime(),
            QDateTime(QDate(2011, 1, 5), QTime(11, 10, 54))
        ]
        date_values = [
            QDate(2015, 3, 4),
            QDate(2015, 3, 4),
            QDate(2019, 12, 28),
            QDate(),
            QDate(1998, 1, 2),
            QDate(),
            QDate(2011, 1, 5),
            QDate(2011, 1, 5),
            QDate(2011, 1, 5)
        ]
        self.assertEqual(len(datetime_values), len(date_values))

        features = []
        for i in range(len(datetime_values)):
            f = QgsFeature()
            f.setFields(layer.fields())
            f.setAttributes([date_values[i], datetime_values[i]])
            features.append(f)
        assert pr.addFeatures(features)

        tests = [
            [QgsAggregateCalculator.Count, 'flddatetime', 9],
            [QgsAggregateCalculator.Count, 'flddate', 9],
            [QgsAggregateCalculator.CountDistinct, 'flddatetime', 6],
            [QgsAggregateCalculator.CountDistinct, 'flddate', 5],
            [QgsAggregateCalculator.CountMissing, 'flddatetime', 2],
            [QgsAggregateCalculator.CountMissing, 'flddate', 2],
            [
                QgsAggregateCalculator.Min, 'flddatetime',
                QDateTime(QDate(1998, 1, 2), QTime(1, 10, 54))
            ],
            [
                QgsAggregateCalculator.Min, 'flddate',
                QDateTime(QDate(1998, 1, 2), QTime(0, 0, 0))
            ],
            [
                QgsAggregateCalculator.Max, 'flddatetime',
                QDateTime(QDate(2019, 12, 28), QTime(23, 10, 1))
            ],
            [
                QgsAggregateCalculator.Max, 'flddate',
                QDateTime(QDate(2019, 12, 28), QTime(0, 0, 0))
            ],
            [
                QgsAggregateCalculator.Range, 'flddatetime',
                QgsInterval(693871147)
            ],
            [QgsAggregateCalculator.Range, 'flddate',
             QgsInterval(693792000)],
            [
                QgsAggregateCalculator.ArrayAggregate, 'flddatetime',
                [None if v.isNull() else v for v in datetime_values]
            ],
            [
                QgsAggregateCalculator.ArrayAggregate, 'flddate',
                [None if v.isNull() else v for v in date_values]
            ],
        ]

        agg = QgsAggregateCalculator(layer)
        for t in tests:
            val, ok = agg.calculate(t[0], t[1])
            self.assertTrue(ok)
            self.assertEqual(val, t[2])

        # bad tests - the following stats should not be calculatable for string fields
        for t in [
                QgsAggregateCalculator.Sum,
                QgsAggregateCalculator.Mean,
                QgsAggregateCalculator.Median,
                QgsAggregateCalculator.StDev,
                QgsAggregateCalculator.StDevSample,
                QgsAggregateCalculator.Minority,
                QgsAggregateCalculator.Majority,
                QgsAggregateCalculator.FirstQuartile,
                QgsAggregateCalculator.ThirdQuartile,
                QgsAggregateCalculator.InterQuartileRange,
                QgsAggregateCalculator.StringMinimumLength,
                QgsAggregateCalculator.StringMaximumLength,
        ]:
            val, ok = agg.calculate(t, 'flddatetime')
            self.assertFalse(ok)