def testPartNum(self):
        # test geometry_part_num variable
        s = QgsLineSymbol()
        s.deleteSymbolLayer(0)

        sym_layer = QgsGeometryGeneratorSymbolLayer.create({'geometryModifier': 'segments_to_lines($geometry)'})
        sym_layer.setSymbolType(QgsSymbol.Line)
        s.appendSymbolLayer(sym_layer)

        marker_line = QgsMarkerLineSymbolLayer(False)
        marker_line.setPlacement(QgsMarkerLineSymbolLayer.FirstVertex)
        f = QgsFontUtils.getStandardTestFont('Bold', 24)
        marker = QgsFontMarkerSymbolLayer(f.family(), 'x', 24, QColor(255, 255, 0))
        marker.setDataDefinedProperty(QgsSymbolLayer.PropertyCharacter, QgsProperty.fromExpression('@geometry_part_num'))
        marker_symbol = QgsMarkerSymbol()
        marker_symbol.changeSymbolLayer(0, marker)
        marker_line.setSubSymbol(marker_symbol)
        marker_line.setAverageAngleLength(0)
        line_symbol = QgsLineSymbol()
        line_symbol.changeSymbolLayer(0, marker_line)
        sym_layer.setSubSymbol(line_symbol)

        # rendering test
        g = QgsGeometry.fromWkt('LineString(0 0, 10 0, 10 10, 0 10)')
        rendered_image = self.renderGeometry(s, g, buffer=4)
        assert self.imageCheck('part_num_variable', 'part_num_variable', rendered_image)

        marker.setDataDefinedProperty(QgsSymbolLayer.PropertyCharacter,
                                      QgsProperty.fromExpression('@geometry_part_count'))

        # rendering test
        g = QgsGeometry.fromWkt('LineString(0 0, 10 0, 10 10, 0 10)')
        rendered_image = self.renderGeometry(s, g, buffer=4)
        assert self.imageCheck('part_count_variable', 'part_count_variable', rendered_image)
Exemplo n.º 2
1
    def testCreateLayerMultiPoint(self):
        layer = QgsVectorLayer("MultiPoint?crs=epsg:3111&field=id:integer&field=fldtxt:string&field=fldint:integer",
                               "addfeat", "memory")
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes([1, "test", 1])
        f.setGeometry(QgsGeometry.fromWkt('MultiPoint(1 2, 3 4)'))
        f2 = QgsFeature()
        f2.setAttributes([2, "test2", 3])
        f3 = QgsFeature()
        f3.setAttributes([3, "test2", NULL])
        f3.setGeometry(QgsGeometry.fromWkt('MultiPoint(7 8)'))
        pr.addFeatures([f, f2, f3])

        uri = '{} table="qgis_test"."new_table_multipoint" sql='.format(self.dbconn)
        error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:3111'))
        self.assertEqual(error, QgsVectorLayerExporter.NoError)

        new_layer = QgsVectorLayer(uri, 'new', 'mssql')
        self.assertTrue(new_layer.isValid())
        self.assertEqual(new_layer.wkbType(), QgsWkbTypes.MultiPoint)
        self.assertEqual(new_layer.crs().authid(), 'EPSG:3111')
        self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint'])

        features = [f.attributes() for f in new_layer.getFeatures()]
        self.assertEqual(features, [[1, 1, 'test', 1],
                                    [2, 2, 'test2', 3],
                                    [3, 3, 'test2', NULL]])
        geom = [f.geometry().asWkt() for f in new_layer.getFeatures()]
        self.assertEqual(geom, ['MultiPoint ((1 2),(3 4))', '', 'MultiPoint ((7 8))'])
Exemplo n.º 3
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_LAYER))

        writer = self.getOutputFromName(
            self.OUTPUT_LAYER).getVectorWriter(
                layer.fields().toList(),
                QGis.WKBPoint,
                layer.crs())

        features = vector.features(layer)
        total = 100.0 / len(features)

        for current, input_feature in enumerate(features):
            output_feature = input_feature
            if input_feature.constGeometry():
                input_geometry = QgsGeometry(input_feature.geometry())
                output_geometry = input_geometry.pointOnSurface()
                if not output_geometry:
                    raise GeoAlgorithmExecutionException(
                        self.tr('Error calculating point on surface'))

                output_feature.setGeometry(output_geometry)

            writer.addFeature(output_feature)
            progress.setPercentage(int(current * total))

        del writer
Exemplo n.º 4
0
 def testWFSPointsMultipleEdits(self):
     """
     Adds some points, then check.
     Modify 2 points, then checks and clear all
     """
     layer_name = 'test_point'
     layer = self._getLayer(layer_name)
     wfs_layer = self._getWFSLayer(layer_name)
     feat1 = QgsFeature(wfs_layer.pendingFields())
     feat1['id'] = 11
     feat1['name'] = 'name 11'
     feat1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(9, 45)))
     feat2 = QgsFeature(wfs_layer.pendingFields())
     feat2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(9.5, 45.5)))
     feat2['id'] = 12
     feat2['name'] = 'name 12'
     old_features = [feat1, feat2]
     # Change feat1 and feat2
     new_feat1 = QgsFeature(wfs_layer.pendingFields())
     new_feat1['id'] = 121
     new_feat1['name'] = 'name 121'
     new_feat1.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10, 46)))
     new_feat2 = QgsFeature(wfs_layer.pendingFields())
     new_feat2['id'] = 122
     new_feat2['name'] = 'name 122'
     new_feat2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(10.5, 47)))
     new_features = [new_feat1, new_feat2]
     self._testLayer(wfs_layer, layer, old_features, new_features)
Exemplo n.º 5
0
    def setUpClass(cls):
        """Run before all tests"""
        # Register the provider
        r = QgsProviderRegistry.instance()
        metadata = QgsProviderMetadata(PyProvider.providerKey(), PyProvider.description(), PyProvider.createProvider)
        assert r.registerProvider(metadata)
        assert r.providerMetadata(PyProvider.providerKey()) == metadata

        # Create test layer
        cls.vl = cls.createLayer()
        assert (cls.vl.isValid())
        cls.source = cls.vl.dataProvider()

        # poly layer
        cls.poly_vl = QgsVectorLayer('Polygon?crs=epsg:4326&field=pk:integer&key=pk',
                                     'test', 'pythonprovider')
        assert (cls.poly_vl.isValid())
        cls.poly_provider = cls.poly_vl.dataProvider()

        f1 = QgsFeature()
        f1.setAttributes([1])
        f1.setGeometry(QgsGeometry.fromWkt('Polygon ((-69.03664108 81.35818902, -69.09237722 80.24346619, -73.718477 80.1319939, -73.718477 76.28620011, -74.88893598 76.34193625, -74.83319983 81.35818902, -69.03664108 81.35818902))'))

        f2 = QgsFeature()
        f2.setAttributes([2])
        f2.setGeometry(QgsGeometry.fromWkt('Polygon ((-67.58750139 81.1909806, -66.30557012 81.24671674, -66.30557012 76.89929767, -67.58750139 76.89929767, -67.58750139 81.1909806))'))

        f3 = QgsFeature()
        f3.setAttributes([3])
        f3.setGeometry(QgsGeometry.fromWkt('Polygon ((-68.36780737 75.78457483, -67.53176524 72.60761475, -68.64648808 73.66660144, -70.20710006 72.9420316, -68.36780737 75.78457483))'))

        f4 = QgsFeature()
        f4.setAttributes([4])

        cls.poly_provider.addFeatures([f1, f2, f3, f4])
Exemplo n.º 6
0
 def linearMatrix(self, writer, provider1, provider2, index1, index2, nearest, distArea, matType, sindex, progressBar):
     inFeat = QgsFeature()
     outFeat = QgsFeature()
     inGeom = QgsGeometry()
     outGeom = QgsGeometry()
     start = 15.00
     add = 85.00 / provider1.featureCount()
     fit1 = provider1.getFeatures()
     while fit1.nextFeature(inFeat):
         inGeom = inFeat.geometry()
         inID = inFeat.attributes()[index1]
         featList = sindex.nearestNeighbor(inGeom.asPoint(), nearest)
         distList = []
         vari = 0.00
         for i in featList:
             provider2.getFeatures(QgsFeatureRequest().setFilterFid(int(i)).setSubsetOfAttributes([index2])).nextFeature(outFeat)
             outID = outFeat.attributes()[index2]
             outGeom = outFeat.geometry()
             dist = distArea.measureLine(inGeom.asPoint(), outGeom.asPoint())
             if dist > 0:
                 if matType == "Linear":
                     writer.writerow([unicode(inID), unicode(outID), unicode(dist)])
                 else:
                     distList.append(float(dist))
         if matType == "Summary":
             mean = sum(distList) / len(distList)
             for i in distList:
                 vari = vari + ((i - mean) * (i - mean))
             vari = sqrt(vari / len(distList))
             writer.writerow([unicode(inID), unicode(mean), unicode(vari), unicode(min(distList)), unicode(max(distList))])
         start = start + add
         progressBar.setValue(start)
     del writer
Exemplo n.º 7
0
    def createLayer(cls):
        vl = QgsVectorLayer(
            'Point?crs=epsg:4326&field=pk:integer&field=cnt:integer&field=name:string(0)&field=name2:string(0)&field=num_char:string&key=pk',
            'test', 'pythonprovider')
        assert (vl.isValid())

        f1 = QgsFeature()
        f1.setAttributes([5, -200, NULL, 'NuLl', '5'])
        f1.setGeometry(QgsGeometry.fromWkt('Point (-71.123 78.23)'))

        f2 = QgsFeature()
        f2.setAttributes([3, 300, 'Pear', 'PEaR', '3'])

        f3 = QgsFeature()
        f3.setAttributes([1, 100, 'Orange', 'oranGe', '1'])
        f3.setGeometry(QgsGeometry.fromWkt('Point (-70.332 66.33)'))

        f4 = QgsFeature()
        f4.setAttributes([2, 200, 'Apple', 'Apple', '2'])
        f4.setGeometry(QgsGeometry.fromWkt('Point (-68.2 70.8)'))

        f5 = QgsFeature()
        f5.setAttributes([4, 400, 'Honey', 'Honey', '4'])
        f5.setGeometry(QgsGeometry.fromWkt('Point (-65.32 78.3)'))

        vl.dataProvider().addFeatures([f1, f2, f3, f4, f5])
        return vl
Exemplo n.º 8
0
    def testDeleteMultipleFeatures(self):
        # test deleting multiple features from an edit buffer

        # make a layer with two features
        layer = createEmptyLayer()
        self.assertTrue(layer.startEditing())

        # add two features
        f1 = QgsFeature(layer.fields(), 1)
        f1.setGeometry(QgsGeometry.fromPoint(QgsPointXY(1, 2)))
        f1.setAttributes(["test", 123])
        self.assertTrue(layer.addFeature(f1))

        f2 = QgsFeature(layer.fields(), 2)
        f2.setGeometry(QgsGeometry.fromPoint(QgsPointXY(2, 4)))
        f2.setAttributes(["test2", 246])
        self.assertTrue(layer.addFeature(f2))

        layer.commitChanges()
        layer.startEditing()

        self.assertEqual(layer.editBuffer().deletedFeatureIds(), [])
        self.assertFalse(layer.editBuffer().isFeatureDeleted(1))
        self.assertFalse(layer.editBuffer().isFeatureDeleted(2))

        # delete features
        layer.deleteFeatures([1, 2])

        # test contents of buffer
        self.assertEqual(set(layer.editBuffer().deletedFeatureIds()), set([1, 2]))
        self.assertTrue(layer.editBuffer().isFeatureDeleted(1))
        self.assertTrue(layer.editBuffer().isFeatureDeleted(2))
Exemplo n.º 9
0
 def loopThruPolygons(self, inLayer, numRand, design):
     sProvider = inLayer.dataProvider()
     sFeat = QgsFeature()
     sGeom = QgsGeometry()
     sPoints = []
     if design == self.tr("field"):
       index = sProvider.fieldNameIndex(numRand)
     count = 10.00
     add = 60.00 / sProvider.featureCount()
     sFit = sProvider.getFeatures()
     featureErrors = []
     while sFit.nextFeature(sFeat):
         sGeom = sFeat.geometry()
         if design == self.tr("density"):
             sDistArea = QgsDistanceArea()
             value = int(round(numRand * sDistArea.measure(sGeom)))
         elif design == self.tr("field"):
             sAtMap = sFeat.attributes()
             try:
               value = int(sAtMap[index])
             except (ValueError,TypeError):
               featureErrors.append(sFeat)
               continue
         else:
             value = numRand
         sExt = sGeom.boundingBox()
         sPoints.extend(self.simpleRandom(value, sGeom, sExt.xMinimum(), sExt.xMaximum(), sExt.yMinimum(), sExt.yMaximum()))
         count = count + add
         self.progressBar.setValue(count)
     return sPoints, featureErrors
Exemplo n.º 10
0
    def testProxyFeatureSink(self):
        fields = QgsFields()
        fields.append(QgsField('fldtxt', QVariant.String))
        fields.append(QgsField('fldint', QVariant.Int))

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

        self.assertEqual(len(store), 0)

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

        f2 = QgsFeature()
        f2.setAttributes(["test2", 457])
        f2.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(200, 200)))
        f3 = QgsFeature()
        f3.setAttributes(["test3", 888])
        f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(300, 200)))
        proxy.addFeatures([f2, f3])
        self.assertEqual(len(store), 3)
        self.assertEqual(store.features()[1]['fldtxt'], 'test2')
        self.assertEqual(store.features()[2]['fldtxt'], 'test3')
Exemplo n.º 11
0
    def testAddMultipleFeatures(self):
        # test adding multiple features to an edit buffer
        layer = createEmptyLayer()
        self.assertTrue(layer.startEditing())

        self.assertEqual(layer.editBuffer().addedFeatures(), {})
        self.assertFalse(layer.editBuffer().isFeatureAdded(1))
        self.assertFalse(layer.editBuffer().isFeatureAdded(3))

        # add two features
        f1 = QgsFeature(layer.fields(), 1)
        f1.setGeometry(QgsGeometry.fromPoint(QgsPointXY(1, 2)))
        f1.setAttributes(["test", 123])
        f2 = QgsFeature(layer.fields(), 2)
        f2.setGeometry(QgsGeometry.fromPoint(QgsPointXY(2, 4)))
        f2.setAttributes(["test2", 246])

        self.assertTrue(layer.addFeatures([f1, f2]))

        # test contents of buffer
        added = layer.editBuffer().addedFeatures()
        new_feature_ids = list(added.keys())
        self.assertEqual(added[new_feature_ids[0]]['fldtxt'], 'test2')
        self.assertEqual(added[new_feature_ids[0]]['fldint'], 246)
        self.assertEqual(added[new_feature_ids[1]]['fldtxt'], 'test')
        self.assertEqual(added[new_feature_ids[1]]['fldint'], 123)

        self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[0]))
        self.assertTrue(layer.editBuffer().isFeatureAdded(new_feature_ids[1]))
Exemplo n.º 12
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}
Exemplo n.º 13
0
    def testChangeGeometries(self):
        if not getattr(self, 'getEditableLayer', None):
            return

        l = self.getEditableLayer()
        self.assertTrue(l.isValid())

        # find 2 features to change
        features = [f for f in l.dataProvider().getFeatures()]
        to_change = [f for f in features if f.attributes()[0] == 1]
        to_change.extend([f for f in features if f.attributes()[0] == 3])
        # changes by feature id, for changeGeometryValues call
        changes = {to_change[0].id(): QgsGeometry.fromWkt('Point (10 20)'), to_change[1].id(): QgsGeometry()}
        # changes by pk, for testing after retrieving changed features
        new_geom_map = {1: QgsGeometry.fromWkt('Point ( 10 20 )'), 3: QgsGeometry()}

        if l.dataProvider().capabilities() & QgsVectorDataProvider.ChangeGeometries:
            # expect success
            result = l.dataProvider().changeGeometryValues(changes)
            self.assertTrue(result,
                            'Provider reported ChangeGeometries capability, but returned False to changeGeometryValues')

            # check result
            self.testGetFeatures(l.dataProvider(), changed_geometries=new_geom_map)

            # change empty list, should return true for consistency
            self.assertTrue(l.dataProvider().changeGeometryValues({}))

        else:
            # expect fail
            self.assertFalse(l.dataProvider().changeGeometryValues(changes),
                             'Provider reported no ChangeGeometries capability, but returned true to changeGeometryValues')
Exemplo n.º 14
0
 def regularMatrix(self, writer, provider1, provider2, index1, index2, nearest, distArea, sindex, progressBar):
     inFeat = QgsFeature()
     outFeat = QgsFeature()
     inGeom = QgsGeometry()
     outGeom = QgsGeometry()
     first = True
     start = 15.00
     add = 85.00 / provider1.featureCount()
     fit1 = provider1.getFeatures()
     while fit1.nextFeature(inFeat):
         inGeom = inFeat.geometry()
         inID = inFeat.attributes()[index1]
         if first:
             featList = sindex.nearestNeighbor(inGeom.asPoint(), nearest)
             first = False
             data = ["ID"]
             for i in featList:
                 provider2.getFeatures(QgsFeatureRequest().setFilterFid(int(i)).setSubsetOfAttributes([index2])).nextFeature(outFeat)
                 data.append(unicode(outFeat.attributes()[index2]))
             writer.writerow(data)
         data = [unicode(inID)]
         for j in featList:
             provider2.getFeatures(QgsFeatureRequest().setFilterFid(int(j))).nextFeature(outFeat)
             outGeom = outFeat.geometry()
             dist = distArea.measureLine(inGeom.asPoint(), outGeom.asPoint())
             data.append(unicode(float(dist)))
         writer.writerow(data)
         start = start + add
         progressBar.setValue(start)
     del writer
Exemplo n.º 15
0
    def layerOmmb(self, layer, writer, progress):
        current = 0

        fit = layer.getFeatures()
        inFeat = QgsFeature()
        total = 100.0 / layer.featureCount()
        newgeometry = QgsGeometry()
        first = True
        while fit.nextFeature(inFeat):
            if first:
                newgeometry = inFeat.geometry()
                first = False
            else:
                newgeometry = newgeometry.combine(inFeat.geometry())
            current += 1
            progress.setPercentage(int(current * total))

        geometry, area, perim, angle, width, height = self.OMBBox(newgeometry)

        if geometry:
            outFeat = QgsFeature()

            outFeat.setGeometry(geometry)
            outFeat.setAttributes([area,
                                   perim,
                                   angle,
                                   width,
                                   height])
            writer.addFeature(outFeat)
Exemplo n.º 16
0
 def densifyGeometry(self, geometry, pointsNumber, isPolygon):
     output = []
     if isPolygon:
         if geometry.isMultipart():
             polygons = geometry.asMultiPolygon()
             for poly in polygons:
                 p = []
                 for ring in poly:
                     p.append(self.densify(ring, pointsNumber))
                 output.append(p)
             return QgsGeometry.fromMultiPolygon(output)
         else:
             rings = geometry.asPolygon()
             for ring in rings:
                 output.append(self.densify(ring, pointsNumber))
             return QgsGeometry.fromPolygon(output)
     else:
         if geometry.isMultipart():
             lines = geometry.asMultiPolyline()
             for points in lines:
                 output.append(self.densify(points, pointsNumber))
             return QgsGeometry.fromMultiPolyline(output)
         else:
             points = geometry.asPolyline()
             output = self.densify(points, pointsNumber)
             return QgsGeometry.fromPolyline(output)
Exemplo n.º 17
0
def union_geometry(vector, request=QgsFeatureRequest()):
    """Return union of the vector geometries regardless of the attributes.
    (If request is specified, filter the objects before union).
    If all geometries in the vector are invalid, return None.

    The boundaries will be dissolved during the operation.

    :param vector:  Vector layer
    :type vector:   QgsVectorLayer

    :param request: Filter for vector objects
    :type request:  QgsFeatureRequest

    :return:        Union of the geometry
    :rtype:         QgsGeometry or None
    """

    result_geometry = None
    for feature in vector.getFeatures(request):
        if result_geometry is None:
            result_geometry = QgsGeometry(feature.geometry())
        else:
            # But some feature.geometry() may be invalid, skip them
            tmp_geometry = result_geometry.combine(feature.geometry())
            try:
                if tmp_geometry.isGeosValid():
                    result_geometry = tmp_geometry
            except AttributeError:
                pass
    return result_geometry
Exemplo n.º 18
0
    def testNoSliverPolygons(self):

        # create a layer with some polygons that will be used as a source for "avoid intersections"
        l = QgsVectorLayer('MultiPolygon', 'test_layer', 'memory')
        assert l.isValid()
        QgsProject.instance().addMapLayer(l)
        QgsProject.instance().writeEntry("Digitizing", "/AvoidIntersectionsList", [l.id()])

        features = []
        for i, wkt in enumerate(feat_wkt):
            f = QgsFeature(i + 1)
            f.setGeometry(QgsGeometry.fromWkt(wkt))
            features.append(f)

        l.dataProvider().addFeatures(features)
        assert l.pendingFeatureCount() == 7

        # create a geometry and remove its intersections with other geometries

        g = QgsGeometry.fromWkt(newg_wkt)
        assert g.avoidIntersections() == 0

        # the resulting multi-polygon must have exactly three parts
        # (in QGIS 2.0 it has one more tiny part that appears at the border between two of the original polygons)
        mpg = g.asMultiPolygon()
        assert len(mpg) == 3
Exemplo n.º 19
0
    def getSource(self):
        # create temporary table for edit tests
        self.execSQLCommand('DROP TABLE IF EXISTS qgis_test.edit_data')
        self.execSQLCommand(
            """CREATE TABLE qgis_test.edit_data (pk INTEGER PRIMARY KEY,cnt integer, name nvarchar(max), name2 nvarchar(max), num_char nvarchar(max), geom geometry)""")

        vl = QgsVectorLayer(
            self.dbconn + ' sslmode=disable key=\'pk\' srid=4326 type=POINT table="qgis_test"."edit_data" (geom) sql=',
            'test', 'mssql')

        self.assertTrue(vl.isValid(), vl.dataProvider().error().message())

        f1 = QgsFeature()
        f1.setAttributes([5, -200, NULL, 'NuLl', '5'])
        f1.setGeometry(QgsGeometry.fromWkt('Point (-71.123 78.23)'))

        f2 = QgsFeature()
        f2.setAttributes([3, 300, 'Pear', 'PEaR', '3'])

        f3 = QgsFeature()
        f3.setAttributes([1, 100, 'Orange', 'oranGe', '1'])
        f3.setGeometry(QgsGeometry.fromWkt('Point (-70.332 66.33)'))

        f4 = QgsFeature()
        f4.setAttributes([2, 200, 'Apple', 'Apple', '2'])
        f4.setGeometry(QgsGeometry.fromWkt('Point (-68.2 70.8)'))

        f5 = QgsFeature()
        f5.setAttributes([4, 400, 'Honey', 'Honey', '4'])
        f5.setGeometry(QgsGeometry.fromWkt('Point (-65.32 78.3)'))

        self.assertTrue(vl.dataProvider().addFeatures([f1, f2, f3, f4, f5]))

        return vl
Exemplo n.º 20
0
    def testCreateLayer(self):
        layer = QgsVectorLayer("Point?field=id:integer&field=fldtxt:string&field=fldint:integer",
                               "addfeat", "memory")
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes([1, "test", 1])
        f.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(1, 2)))
        f2 = QgsFeature()
        f2.setAttributes([2, "test2", 3])
        f3 = QgsFeature()
        f3.setAttributes([3, "test2", NULL])
        f3.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(3, 2)))
        f4 = QgsFeature()
        f4.setAttributes([4, NULL, 3])
        f4.setGeometry(QgsGeometry.fromPointXY(QgsPointXY(4, 3)))
        pr.addFeatures([f, f2, f3, f4])

        uri = '{} table="qgis_test"."new_table" sql='.format(self.dbconn)
        error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326'))
        self.assertEqual(error, QgsVectorLayerExporter.NoError)

        new_layer = QgsVectorLayer(uri, 'new', 'mssql')
        self.assertTrue(new_layer.isValid())
        self.assertEqual(new_layer.wkbType(), QgsWkbTypes.Point)
        self.assertEqual([f.name() for f in new_layer.fields()], ['qgs_fid', 'id', 'fldtxt', 'fldint'])

        features = [f.attributes() for f in new_layer.getFeatures()]
        self.assertEqual(features, [[1, 1, 'test', 1],
                                    [2, 2, 'test2', 3],
                                    [3, 3, 'test2', NULL],
                                    [4, 4, NULL, 3]])
        geom = [f.geometry().asWkt() for f in new_layer.getFeatures()]
        self.assertEqual(geom, ['Point (1 2)', '', 'Point (3 2)', 'Point (4 3)'])
Exemplo n.º 21
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(self.getParameterValue(self.INPUT))
        tolerance = self.getParameterValue(self.TOLERANCE)

        pointsBefore = 0
        pointsAfter = 0

        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            layer.pendingFields().toList(), layer.wkbType(), layer.crs())

        features = vector.features(layer)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            featGeometry = QgsGeometry(f.geometry())
            attrs = f.attributes()
            pointsBefore += self.geomVertexCount(featGeometry)
            newGeometry = featGeometry.simplify(tolerance)
            pointsAfter += self.geomVertexCount(newGeometry)
            feature = QgsFeature()
            feature.setGeometry(newGeometry)
            feature.setAttributes(attrs)
            writer.addFeature(feature)
            progress.setPercentage(int(current * total))

        del writer

        ProcessingLog.addToLog(ProcessingLog.LOG_INFO,
                               self.tr('Simplify: Input geometries have been simplified from %s to %s points' % (pointsBefore, pointsAfter)))
Exemplo n.º 22
0
    def test_check_validity(self):
        """Test that the output invalid contains the error reason"""

        polygon_layer = self._make_layer('Polygon')
        self.assertTrue(polygon_layer.startEditing())
        f = QgsFeature(polygon_layer.fields())
        f.setAttributes([1])
        # Flake!
        f.setGeometry(QgsGeometry.fromWkt(
            'POLYGON ((0 0, 2 2, 0 2, 2 0, 0 0))'))
        self.assertTrue(f.isValid())
        f2 = QgsFeature(polygon_layer.fields())
        f2.setAttributes([1])
        f2.setGeometry(QgsGeometry.fromWkt(
            'POLYGON((1.1 1.1, 1.1 2.1, 2.1 2.1, 2.1 1.1, 1.1 1.1))'))
        self.assertTrue(f2.isValid())
        self.assertTrue(polygon_layer.addFeatures([f, f2]))
        polygon_layer.commitChanges()
        polygon_layer.rollBack()
        self.assertEqual(polygon_layer.featureCount(), 2)

        QgsProject.instance().addMapLayers([polygon_layer])

        alg = self.registry.createAlgorithmById('qgis:checkvalidity')

        context = QgsProcessingContext()
        context.setProject(QgsProject.instance())
        feedback = ConsoleFeedBack()

        self.assertIsNotNone(alg)
        parameters = {}
        parameters['INPUT_LAYER'] = polygon_layer.id()
        parameters['VALID_OUTPUT'] = 'memory:'
        parameters['INVALID_OUTPUT'] = 'memory:'
        parameters['ERROR_OUTPUT'] = 'memory:'

        # QGIS method
        parameters['METHOD'] = 1
        ok, results = execute(
            alg, parameters, context=context, feedback=feedback)
        self.assertTrue(ok)
        invalid_layer = QgsProcessingUtils.mapLayerFromString(
            results['INVALID_OUTPUT'], context)
        self.assertEqual(invalid_layer.fields().names()[-1], '_errors')
        self.assertEqual(invalid_layer.featureCount(), 1)
        f = next(invalid_layer.getFeatures())
        self.assertEqual(f.attributes(), [
                         1, 'segments 0 and 2 of line 0 intersect at 1, 1'])

        # GEOS method
        parameters['METHOD'] = 2
        ok, results = execute(
            alg, parameters, context=context, feedback=feedback)
        self.assertTrue(ok)
        invalid_layer = QgsProcessingUtils.mapLayerFromString(
            results['INVALID_OUTPUT'], context)
        self.assertEqual(invalid_layer.fields().names()[-1], '_errors')
        self.assertEqual(invalid_layer.featureCount(), 1)
        f = next(invalid_layer.getFeatures())
        self.assertEqual(f.attributes(), [1, 'Self-intersection'])
Exemplo n.º 23
0
    def diamonds(self, writer, features, width, height, rotation):
        ft = QgsFeature()

        xOffset = width / 2.0
        yOffset = height / 2.0

        if rotation is not None:
            phi = rotation * math.pi / 180
            for current, feat in enumerate(features):
                point = feat.geometry().asPoint()
                x = point.x()
                y = point.y()
                points = [(0.0, -yOffset), (-xOffset, 0.0), (0.0, yOffset), (xOffset, 0.0)]
                polygon = [[QgsPoint(i[0] * math.cos(phi) + i[1] * math.sin(phi) + x,
                                     -i[0] * math.sin(phi) + i[1] * math.cos(phi) + y) for i in points]]

                ft.setGeometry(QgsGeometry.fromPolygon(polygon))
                ft.setAttributes(feat.attributes())
                writer.addFeature(ft)
        else:
            for current, feat in enumerate(features):
                point = feat.geometry().asPoint()
                x = point.x()
                y = point.y()
                points = [(0.0, -yOffset), (-xOffset, 0.0), (0.0, yOffset), (xOffset, 0.0)]
                polygon = [[QgsPoint(i[0] + x, i[1] + y) for i in points]]

                ft.setGeometry(QgsGeometry.fromPolygon(polygon))
                ft.setAttributes(feat.attributes())
                writer.addFeature(ft)
Exemplo n.º 24
0
    def ovals(self, writer, features, width, height, rotation, segments):
        ft = QgsFeature()

        xOffset = width / 2.0
        yOffset = height / 2.0

        if rotation is not None:
            phi = rotation * math.pi / 180
            for current, feat in enumerate(features):
                point = feat.geometry().asPoint()
                x = point.x()
                y = point.y()
                points = []
                for t in [(2 * math.pi) / segments * i for i in range(segments)]:
                    points.append((xOffset * math.cos(t), yOffset * math.sin(t)))
                polygon = [[QgsPoint(i[0] * math.cos(phi) + i[1] * math.sin(phi) + x,
                                     -i[0] * math.sin(phi) + i[1] * math.cos(phi) + y) for i in points]]

                ft.setGeometry(QgsGeometry.fromPolygon(polygon))
                ft.setAttributes(feat.attributes())
                writer.addFeature(ft)
        else:
            for current, feat in enumerate(features):
                point = feat.geometry().asPoint()
                x = point.x()
                y = point.y()
                points = []
                for t in [(2 * math.pi) / segments * i for i in range(segments)]:
                    points.append((xOffset * math.cos(t), yOffset * math.sin(t)))
                polygon = [[QgsPoint(i[0] + x, i[1] + y) for i in points]]

                ft.setGeometry(QgsGeometry.fromPolygon(polygon))
                ft.setAttributes(feat.attributes())
                writer.addFeature(ft)
Exemplo n.º 25
0
    def test_snappointstogrid(self):
        """Check that this runs correctly"""

        polygon_layer = self._make_layer('Polygon')
        f1 = QgsFeature(polygon_layer.fields())
        f1.setAttributes([1])
        f1.setGeometry(QgsGeometry.fromWkt('POLYGON((1.2 1.2, 1.2 2.2, 2.2 2.2, 2.2 1.2, 1.2 1.2))'))
        f2 = QgsFeature(polygon_layer.fields())
        f2.setAttributes([2])
        f2.setGeometry(QgsGeometry.fromWkt('POLYGON((1.1 1.1, 1.1 2.1, 2.1 2.1, 2.1 1.1, 1.1 1.1))'))
        self.assertTrue(f2.isValid())
        self.assertTrue(polygon_layer.startEditing())
        self.assertTrue(polygon_layer.addFeatures([f1, f2]))
        self.assertEqual(polygon_layer.featureCount(), 2)
        polygon_layer.commitChanges()
        self.assertEqual(polygon_layer.featureCount(), 2)
        QgsProject.instance().addMapLayers([polygon_layer])

        polygon_layer.selectByIds([next(polygon_layer.getFeatures()).id()])
        self.assertEqual(polygon_layer.selectedFeatureCount(), 1)

        old_features, new_features = self._alg_tester(
            'native:snappointstogrid',
            polygon_layer,
            {
                'HSPACING': 0.5,
                'VSPACING': 0.5,
            }
        )

        g = [f.geometry() for f in new_features][0]
        self.assertEqual(g.asWkt(), 'Polygon ((1 1, 1 2, 2 2, 2 1, 1 1))')
        # Check selected
        self.assertEqual(polygon_layer.selectedFeatureIds(), [1])
Exemplo n.º 26
0
    def processAlgorithm(self, parameters, context, feedback):
        layerA = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Difference.INPUT), context)
        layerB = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(Difference.OVERLAY), context)

        geomType = QgsWkbTypes.multiType(layerA.wkbType())
        writer = self.getOutputFromName(
            Difference.OUTPUT).getVectorWriter(layerA.fields(), geomType, layerA.crs(), context)

        outFeat = QgsFeature()
        index = QgsProcessingUtils.createSpatialIndex(layerB, context)
        selectionA = QgsProcessingUtils.getFeatures(layerA, context)
        total = 100.0 / layerA.featureCount() if layerA.featureCount() else 0
        for current, inFeatA in enumerate(selectionA):
            geom = inFeatA.geometry()
            diff_geom = QgsGeometry(geom)
            attrs = inFeatA.attributes()
            intersections = index.intersects(geom.boundingBox())

            request = QgsFeatureRequest().setFilterFids(intersections).setSubsetOfAttributes([])
            for inFeatB in layerB.getFeatures(request):
                tmpGeom = inFeatB.geometry()
                if diff_geom.intersects(tmpGeom):
                    diff_geom = QgsGeometry(diff_geom.difference(tmpGeom))

            try:
                outFeat.setGeometry(diff_geom)
                outFeat.setAttributes(attrs)
                writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
            except:
                QgsMessageLog.logMessage(self.tr('Feature geometry error: One or more output features ignored due to invalid geometry.'), self.tr('Processing'), QgsMessageLog.WARNING)
                continue

            feedback.setProgress(int(current * total))

        del writer
Exemplo n.º 27
0
    def layerOmmb(self, layer, writer, feedback):
        req = QgsFeatureRequest().setSubsetOfAttributes([])
        features = vector.features(layer, req)
        total = 100.0 / len(features)
        newgeometry = QgsGeometry()
        first = True
        for current, inFeat in enumerate(features):
            if first:
                newgeometry = inFeat.geometry()
                first = False
            else:
                newgeometry = newgeometry.combine(inFeat.geometry())
            feedback.setProgress(int(current * total))

        geometry, area, angle, width, height = newgeometry.orientedMinimumBoundingBox()

        if geometry:
            outFeat = QgsFeature()

            outFeat.setGeometry(geometry)
            outFeat.setAttributes([area,
                                   width * 2 + height * 2,
                                   angle,
                                   width,
                                   height])
            writer.addFeature(outFeat)
Exemplo n.º 28
0
    def _rectangleGridLine(self, writer, width, height, originX, originY,
                           hSpacing, vSpacing):
        ft = QgsFeature()

        columns = int(math.floor(float(width) / hSpacing))
        rows = int(math.floor(float(height) / vSpacing))

        # Longitude lines
        for col in xrange(0, columns + 1):
            polyline = []
            x = originX + (col * hSpacing)
            for row in xrange(0, rows + 1):
                y = originY + (row * vSpacing)
                polyline.append(QgsPoint(x, y))

            ft.setGeometry(QgsGeometry.fromPolyline(polyline))
            ft.setAttributes([x, originY, x, originY + (rows * vSpacing)])
            writer.addFeature(ft)

        # Latitude lines
        for row in xrange(0, rows + 1):
            polyline = []
            y = originY + (row * vSpacing)
            for col in xrange(0, columns + 1):
                x = originX + (col * hSpacing)
                polyline.append(QgsPoint(x, y))

            ft.setGeometry(QgsGeometry.fromPolyline(polyline))
            ft.setAttributes([originX, y, originX + (col * hSpacing), y])
            writer.addFeature(ft)
Exemplo n.º 29
0
  def __init__(self, xmin, ymin, xmax, ymax, x_segments, y_segments):
    self.vbands = []
    self.hbands = []
    self.vidx = QgsSpatialIndex()
    self.hidx = QgsSpatialIndex()

    xres = (xmax - xmin) / x_segments
    yres = (ymax - ymin) / y_segments
    self.xmin, self.ymax, self.xres, self.yres = xmin, ymax, xres, yres

    def addVBand(idx, geom):
      f = QgsFeature(idx)
      f.setGeometry(geom)
      self.vbands.append(f)
      self.vidx.insertFeature(f)

    def addHBand(idx, geom):
      f = QgsFeature(idx)
      f.setGeometry(geom)
      self.hbands.append(f)
      self.hidx.insertFeature(f)

    for x in range(x_segments):
      addVBand(x, QgsGeometry.fromRect(QgsRectangle(xmin + x * xres, ymin, xmin + (x + 1) * xres, ymax)))

    for y in range(y_segments):
      addHBand(y, QgsGeometry.fromRect(QgsRectangle(xmin, ymax - (y + 1) * yres, xmax, ymax - y * yres)))
Exemplo n.º 30
0
    def processAlgorithm(self, parameters, context, feedback):
        if parameters[self.INPUT] == parameters[self.HUBS]:
            raise QgsProcessingException(
                self.tr('Same layer given for both hubs and spokes'))

        point_source = self.parameterAsSource(parameters, self.INPUT, context)
        hub_source = self.parameterAsSource(parameters, self.HUBS, context)
        fieldName = self.parameterAsString(parameters, self.FIELD, context)

        units = self.UNITS[self.parameterAsEnum(parameters, self.UNIT,
                                                context)]

        fields = point_source.fields()
        fields.append(QgsField('HubName', QVariant.String))
        fields.append(QgsField('HubDist', QVariant.Double))

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

        index = QgsSpatialIndex(
            hub_source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(
                []).setDestinationCrs(point_source.sourceCrs(),
                                      context.transformContext())))

        distance = QgsDistanceArea()
        distance.setSourceCrs(point_source.sourceCrs(),
                              context.transformContext())
        distance.setEllipsoid(context.project().ellipsoid())

        # Scan source points, find nearest hub, and write to output file
        features = point_source.getFeatures()
        total = 100.0 / point_source.featureCount(
        ) if point_source.featureCount() else 0
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                sink.addFeature(f, QgsFeatureSink.FastInsert)
                continue

            src = f.geometry().boundingBox().center()

            neighbors = index.nearestNeighbor(src, 1)
            ft = next(
                hub_source.getFeatures(QgsFeatureRequest().setFilterFid(
                    neighbors[0]).setSubsetOfAttributes(
                        [fieldName], hub_source.fields()).setDestinationCrs(
                            point_source.sourceCrs(),
                            context.transformContext())))
            closest = ft.geometry().boundingBox().center()
            hubDist = distance.measureLine(src, closest)

            if units != self.LAYER_UNITS:
                hub_dist_in_desired_units = distance.convertLengthMeasurement(
                    hubDist, units)
            else:
                hub_dist_in_desired_units = hubDist

            attributes = f.attributes()
            attributes.append(ft[fieldName])
            attributes.append(hub_dist_in_desired_units)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            feat.setGeometry(QgsGeometry.fromPointXY(src))

            sink.addFeature(feat, QgsFeatureSink.FastInsert)
            feedback.setProgress(int(current * total))

        return {self.OUTPUT: dest_id}
Exemplo n.º 31
0
    def testReprojectionErrorsWhileRendering(self):
        # WKT of a polygon which causes reprojection errors while rendering
        # (apologies for the ridiculously complex wkt, but I can't find a way to reproduce with simplifiction)
        wkt = 'MultiPolygon (((16.93392988400009358 42.77094147300012139, 16.88493899800005238 42.72939687700012712, ' \
              '16.80298912900011032 42.76349518400014915, 16.85816491000014139 42.78400299700011544, ' \
              '16.93392988400009358 42.77094147300012139)),((17.38200931100010393 42.79783763200002511, ' \
              '17.65894616000011297 42.74298737200008702, 17.74887129000009622 42.69456614800010641, ' \
              '17.32374108200008322 42.79083893400003547, 17.38200931100010393 42.79783763200002511)),' \
              '((16.768565300000148 42.97223541900014254, 17.03207441500009622 42.98261139500014849, ' \
              '17.13184655000009116 42.96954987200014386, 17.20020592500009116 42.92177969000012183, ' \
              '16.85141035200010151 42.90070221600008438, 16.65544681100004709 42.92625560099999404, ' \
              '16.70679772200014668 42.96954987200014386, 16.63168379000003938 42.98261139500014849, ' \
              '16.768565300000148 42.97223541900014254)),((17.05567467500011958 43.02895742400001211, ' \
              '17.24024498800011429 43.02277252800014651, 17.74146569100011561 42.83926015800001608, ' \
              '17.70736738400009358 42.88703034100014122, 17.65334906206413734 42.8909283361407887, ' \
              '17.70158573400010482 42.91950022500007833, 17.81175988700005064 42.909862570000044, ' \
              '17.85847538200005147 42.81697418200012351, 18.22413781700009849 42.62807098500009317, ' \
              '18.43735477700010961 42.55921213800017711, 18.4371480710000526 42.4934022020000981, ' \
              '18.49642988400009358 42.41632721600008438, 18.23894290500010129 42.55906810100005089, ' \
              '18.21753991000014139 42.6201032570001388, 18.07601972700010151 42.65131256700003348, ' \
              '18.0432235040000819 42.70205312700007028, 17.90162194100014403 42.75189850500014188, ' \
              '17.8928328790000819 42.79083893400003547, 17.72095787900005348 42.8262393250000315, ' \
              '17.7618921230000808 42.77871328300012976, 17.74870853000004445 42.77204010600017625, ' \
              '17.21387780000011958 42.98261139500014849, 17.04615319100011561 42.9950625670000619, ' \
              '17.00163821700004974 43.05149974200010377, 17.05567467500011958 43.02895742400001211)),' \
              '((16.19467207100007045 43.07440827000000638, 16.254893425000148 43.06854889500006323, ' \
              '16.08716881600014403 43.01146067900008063, 16.04883873800011429 43.06517161700004692, ' \
              '16.19467207100007045 43.07440827000000638)),((16.56275475400011032 43.22898997600010773, ' \
              '16.65951582100009887 43.21596914300012315, 16.72771243600001867 43.16461823100003414, ' \
              '17.19336998800014271 43.12726471600016964, 16.67017662900013875 43.12547435099999404, ' \
              '16.37159264400014536 43.19550202000006323, 16.49642988400006516 43.21808502800014651, ' \
              '16.58326256600014403 43.18866608300005794, 16.52051842500006273 43.22898997600010773, ' \
              '16.56275475400011032 43.22898997600010773)),((16.80681399800010922 43.34247467700005529, ' \
              '16.89234459700011826 43.31220123900006058, 16.84620201900008851 43.27338288000005662, ' \
              '16.62826582100012729 43.26373932500008834, 16.50074303500014139 43.28424713700003679, ' \
              '16.42188561300008587 43.31757233300011478, 16.40577233200011165 43.33270905200011214, ' \
              '16.45346113400009358 43.35317617400009738, 16.42628014400008851 43.39411041900011412, ' \
              '16.44703209700008983 43.39484284100014122, 16.80681399800010922 43.34247467700005529)),' \
              '((16.29818769600012729 43.40363190300011809, 16.30274498800008587 43.38727448100009099, ' \
              '16.39144941500012465 43.34638092700005529, 16.348643425000148 43.33869049700003018, ' \
              '16.20045006600014403 43.40704987200003018, 16.29818769600012729 43.40363190300011809)),' \
              '((16.33415774800010922 43.50153229400014254, 16.3752547540000819 43.49017975500008504, ' \
              '16.21143639400008851 43.49005768400009231, 16.26441491000014139 43.51288483300011478, ' \
              '16.33415774800010922 43.50153229400014254)),((15.67888431100004709 43.64801666900014254, ' \
              '15.74040774800010922 43.62750885600009099, 15.67204837300002396 43.63743724200010377, ' \
              '15.60377037900013875 43.67470937700007028, 15.67888431100004709 43.64801666900014254)),' \
              '((15.36736087300005238 43.79010651200015047, 15.39568118600007551 43.7724063170000619, ' \
              '15.22779381600014403 43.87445709800014981, 15.24073326900014536 43.88076406500009341, ' \
              '15.36736087300005238 43.79010651200015047)),((15.44271894600009887 43.89907461100013109, ' \
              '15.35865319100014403 43.91937897300014981, 15.26124108200011165 44.01105377800003282, ' \
              '15.38404381600008719 43.9701602230000077, 15.44271894600009887 43.89907461100013109)),' \
              '((15.22575931100010393 44.06622955900014915, 15.25440514400008851 44.01788971600014122, ' \
              '15.12183678500014139 44.09223053600005926, 15.06251061300008587 44.16193268400012073, ' \
              '15.22575931100010393 44.06622955900014915)),((14.83545983200014007 44.15102773600013109, ' \
              '14.85726972700010151 44.15204498900000374, 14.86915123800014271 44.14052969000006499, ' \
              '14.83521569100008719 44.14166901200009363, 14.81983483200014007 44.15302155199999845, ' \
              '14.82243899800005238 44.16868724200004692, 14.83545983200014007 44.15102773600013109)),' \
              '((14.98511803500011297 44.09096914300012315, 15.21680748800008587 43.91278717700008372, ' \
              '15.13331139400011693 43.92121002800003282, 15.19450931100004709 43.87262604400017096, ' \
              '15.10661868600007551 43.92544179900015422, 14.84961998800014271 44.17560455900014915, ' \
              '14.98511803500011297 44.09096914300012315)),((14.765961134000122 44.26504140800015819, ' \
              '14.74854576900014536 44.26166413000014188, 14.73959394600012729 44.28017812700015554, ' \
              '14.79167728000007287 44.27252838700003679, 14.765961134000122 44.26504140800015819)),' \
              '((14.66138756600011561 44.30866120000014519, 14.6407983730000808 44.31183502800003282, ' \
              '14.59506269600007045 44.34711334800006455, 14.643565300000148 44.32575104400011412, ' \
              '14.66138756600011561 44.30866120000014519)),((14.81120853000004445 44.35004303600000242, ' \
              '14.75619550900009358 44.36399974200004692, 14.76343834700008983 44.41535065300017493, ' \
              '14.80323326900008851 44.40550364800004957, 14.81120853000004445 44.35004303600000242)),' \
              '((14.27116946700002131 44.61253489800004957, 14.23259524800005238 44.62604401200012205, ' \
              '14.2657983730000808 44.67951080900003547, 14.28044681100007551 44.67755768400009231, ' \
              '14.27116946700002131 44.61253489800004957)),((14.84522545700008322 44.60053131700011875, ' \
              '14.93824303500014139 44.59414297100001079, 15.07553144600007045 44.48407623900006058, ' \
              '14.91114342500011958 44.54547760600014783, 15.04802493600004709 44.43943919500001982, ' \
              '15.09669030000009116 44.41518789300000947, 15.04151451900014536 44.47662995000008834, ' \
              '15.25440514400008851 44.34003327000000638, 15.165049675000148 44.36737702000006323, ' \
              '15.22022545700008322 44.3127302100001117, 15.13086998800008587 44.33258698100003414, ' \
              '15.17237389400014536 44.29913971600016964, 15.12875410200007309 44.31199778900018771, ' \
              '15.08920332100009887 44.37421295800000109, 15.11719811300014271 44.38719310099999404, ' \
              '15.04900149800010922 44.39468008000015686, 14.89747155000009116 44.49091217699999845, ' \
              '14.91863040500010129 44.50454336100013109, 14.87696373800011429 44.55975983300005794, ' \
              '14.73365319100008719 44.70319245000014519, 14.84522545700008322 44.60053131700011875)),' \
              '((14.41000410200010151 44.60097890800001608, 14.52662194100011561 44.50372955900012073, ' \
              '14.53435306100010393 44.48407623900006058, 14.42261803500008455 44.57387929900009738, ' \
              '14.36304772200014668 44.57343170800000109, 14.38257897200014668 44.60325755399999537, ' \
              '14.33578535200007309 44.71678294500010509, 14.39747155000009116 44.6856143250000315, ' \
              '14.41000410200010151 44.60097890800001608)),((14.75326582100007045 44.84585195500012844, ' \
              '14.74048912900011032 44.82050202000000638, 14.82243899800005238 44.77142975500005662, ' \
              '14.84961998800014271 44.70319245000014519, 14.65788821700004974 44.79877350500014188, ' \
              '14.7268172540000819 44.79877350500014188, 14.6858016290000819 44.8471540390000456, ' \
              '14.75326582100007045 44.84585195500012844)),((14.47103925900006516 44.95392487200003018, ' \
              '14.45191491000008455 44.79877350500014188, 14.47217858200011165 44.7079531920000619, ' \
              '14.53435306100010393 44.63426341400010244, 14.51335696700007816 44.618841864000089, ' \
              '14.42790774800005238 44.65656159100014122, 14.29420006600008719 44.9086367860001161, ' \
              '14.30152428500011297 44.94342682500014519, 14.38738040500004445 44.90900299700003018, ' \
              '14.39031009200004974 44.96039459800012139, 14.41138756600008719 44.95636627800014651, ' \
              '14.27849368600004709 45.1133487000000315, 14.29957116000014139 45.16233958499999801, ' \
              '14.35621178500014139 45.16925690300008966, 14.387705925000148 45.03904857000013351, ' \
              '14.47103925900006516 44.95392487200003018)),((14.56332441500012465 45.24974192900008063, ' \
              '14.62378991000011297 45.17548248900006058, 14.59742272200011826 45.16644928600005926, ' \
              '14.66529381600011561 45.16181061400011743, 14.66529381600011561 45.08734772300006455, ' \
              '14.74048912900011032 45.07306549700014386, 14.81495201900008851 44.97748444200009033, ' \
              '14.70639082100009887 44.9467227230000077, 14.62891686300014271 44.97817617400004053, ' \
              '14.62086022200008983 45.04559967700011214, 14.61695397200008983 45.02464427300007799, ' \
              '14.51050866000014139 45.03217194200011875, 14.43873131600014403 45.07050202000006323, ' \
              '14.4670516290000819 45.12409088700015047, 14.53012129000009622 45.13483307500014519, ' \
              '14.53435306100010393 45.23753489800002114, 14.56332441500012465 45.24974192900008063)),' \
              '((16.36947066200013978 46.54057118800012915, 16.63767134600004738 46.47447703100009164, ' \
              '16.75508020000012266 46.38187286400001597, 16.83765913900006694 46.38187286400001597, ' \
              '16.88923221800007468 46.29216257800014489, 17.05294315600005461 46.15346303300005104, ' \
              '17.20859257000006437 46.11656606000003933, 17.27587528500004055 46.01202463800002818, ' \
              '17.31680301900004793 45.99765859000002877, 17.29013798000011093 45.98463612900009423, ' \
              '17.40620324700006449 45.94365671800015605, 17.59110152100009827 45.93621531200012953, ' \
              '17.65652388500006964 45.84541982000014571, 17.80917606600013414 45.81441396100005647, ' \
              '17.85806197100004056 45.77172922800004073, 18.21121870900006456 45.78537180600012846, ' \
              '18.40438521300006869 45.74180857400001798, 18.57347049900010916 45.81668772400014689, ' \
              '18.6556360270001278 45.90758656800015558, 18.7755253500000947 45.88283355700004051, ' \
              '18.90130578600007993 45.93120269800006383, 18.87288374800004931 45.89523590100002082, ' \
              '18.90699019400011593 45.86795074500018643, 18.85531376100007606 45.85735707600009903, ' \
              '18.84497847500006174 45.8157058720000947, 18.96848514800012708 45.66873809800016204, ' \
              '18.90357954900008508 45.57308502200005762, 18.94171675700005153 45.53892689999999277, ' \
              '19.01809452300011571 45.56740061400002162, 19.10625451700005328 45.51164174500017623, ' \
              '19.00961958800010621 45.49867095900005154, 19.00300500400010151 45.45536611000007099, ' \
              '19.03742150900006891 45.42229319300010104, 18.97592655400006834 45.39495636000008005, ' \
              '19.09199182100007874 45.34999786400005917, 19.12475467900009107 45.29811472600006539, ' \
              '19.36308638500014467 45.24824696900010679, 19.40783817500010855 45.20313344400013023, ' \
              '19.39068160000005037 45.16933705700016333, 19.22593713300008744 45.16194732700016345, ' \
              '19.12186079900010327 45.195795390000157, 19.13767378700009658 45.14603098600004216, ' \
              '19.04486291500009543 45.13724599300006446, 19.08227665200013234 45.08494944300004192, ' \
              '19.0872375890000967 44.97710072800013847, 19.13167932100006396 44.95317454000003465, ' \
              '19.06667036900009293 44.90568389900012392, 18.99142948400006503 44.9149339800001286, ' \
              '19.01582076000008215 44.86563466400004074, 18.88962691200009658 44.86119049100013001, ' \
              '18.78338016700013213 44.91374542300012251, 18.79175174900009893 45.00154368100008639, ' \
              '18.73831831900008638 45.0159097290000858, 18.68405806500004473 45.08479441400000098, ' \
              '18.64871138500012648 45.06267689999999959, 18.61667199700013953 45.09766184500010411, ' \
              '18.54959598800010667 45.09476796500011631, 18.51703983500007666 45.05585561200003042, ' \
              '18.23788374800011525 45.15745147700012296, 18.15365116400005263 45.0975584930001645, ' \
              '18.00347945100011771 45.1493382780000303, 17.83573775200005684 45.0644338990000648, ' \
              '17.68473921700012852 45.1639627080000281, 17.48185754400009273 45.11440500900012296, ' \
              '17.49622359200009214 45.1416901650001563, 17.44775109900012922 45.13430043600014585, ' \
              '17.44330692500011537 45.16205068000009248, 17.38243208800008688 45.1396231090000839, ' \
              '17.26895064300006766 45.18954254200015441, 17.24548954300007608 45.15538442000017483, ' \
              '17.18709517400012032 45.14856313100001728, 17.0363033440001459 45.23047027600007652, ' \
              '17.00829471800011561 45.21615590500009318, 17.00829471800011561 45.24416453100009505, ' \
              '16.94731652900014751 45.23568959600000028, 16.9243721930001243 45.28452382500016427, ' \
              '16.81171757000004163 45.18122263700009, 16.52894413300009546 45.22225372400005483, ' \
              '16.38921106000003647 45.11683380099999852, 16.31624393700010955 45.00123362300008978, ' \
              '16.12152714000009723 45.09616322900008356, 16.02044803900011516 45.213933818000001, ' \
              '15.79234826700013627 45.18980092400012438, 15.76361617000014803 44.97555043600003444, ' \
              '15.7308533120001357 44.92723297200008403, 15.77343469200010873 44.84501576800015243, ' \
              '15.71607385200013596 44.80320953400008932, 15.72847619600008784 44.76910308800002269, ' \
              '15.80568078600006743 44.69665273000013883, 15.88877648900006534 44.72424794500012979, ' \
              '15.96897831200004703 44.63924021400013942, 16.02830285600006732 44.62471913700009907, ' \
              '16.04473596200011798 44.58937245700018082, 16.00608199000004106 44.54100331600012908, ' \
              '16.11646285000011858 44.52146962500013672, 16.15966434700004584 44.41610138000002905, ' \
              '16.13827030500004867 44.37760243800015303, 16.20286584400008678 44.35977406800010669, ' \
              '16.18756962000011868 44.28241444999999032, 16.21578495300011014 44.20815541600011045, ' \
              '16.32688928200008149 44.08237498000012522, 16.50103885900011846 43.99271637000008184, ' \
              '16.67859908100004418 43.8406843060001421, 16.71260217300007866 43.77151540100005889, ' \
              '17.03051558500007445 43.54847991900005866, 17.27050093600007585 43.46321380700000248, ' \
              '17.28993127500007176 43.3034302780000786, 17.44206669100009321 43.15243174300015028, ' \
              '17.6284119050001209 43.04657257100008394, 17.66272505700004558 42.96569895500012137, ' \
              '17.63450972400008254 42.950402731000068, 17.51563561300008587 42.95888906500012183, ' \
              '17.47087649800005238 43.01341380400010905, 17.50196373800014271 43.03099192900005221, ' \
              '17.43360436300014271 43.01740143400009231, 17.46021569100011561 43.03099192900005221, ' \
              '17.42611738400009358 43.06517161700004692, 17.4045516290000819 43.05149974200010377, ' \
              '17.31625410200012993 43.12726471600016964, 17.11394290500004445 43.21320221600008438, ' \
              '16.88062584700011826 43.40595123900006058, 16.62582441500009622 43.44904205900009231, ' \
              '16.52466881600011561 43.51080963700009363, 16.39144941500012465 43.51080963700009363, ' \
              '16.47339928500008455 43.5381533870001789, 16.43384850400013875 43.54975006700000506, ' \
              '16.11768639400008851 43.52448151200003679, 16.17237389400014536 43.4896914730000077, ' \
              '16.11312910200004467 43.47890859600009605, 15.95948326900011693 43.50397370000008834, ' \
              '15.987315300000148 43.54490794500010509, 15.92530358200011165 43.55857982000004824, ' \
              '15.91895592500009116 43.62872955900012073, 15.96631920700011165 43.64118073100003414, ' \
              '15.90479576900014536 43.64801666900014254, 15.95297285200010151 43.65086497599999404, ' \
              '15.95045006600008719 43.68854401200015047, 15.70630944100008719 43.76341380400005221, ' \
              '15.6174422540000819 43.82550690300017493, 15.66309655000009116 43.81297435099999404, ' \
              '15.67888431100004709 43.81928131700011875, 15.45508873800014271 43.92804596600014122, ' \
              '15.14454186300011429 44.19546133000015686, 15.15219160200012993 44.23529694200014717, ' \
              '15.11036217500011958 44.26434967700011214, 15.14063561300011429 44.28245677300013483, ' \
              '15.17660566500009622 44.24994538000005662, 15.20777428500008455 44.27277252800014651, ' \
              '15.19809004000012465 44.30166250200007028, 15.295258009000122 44.25067780199999845, ' \
              '15.30274498800008587 44.29913971600016964, 15.26124108200011165 44.33258698100003414, ' \
              '15.42448978000001603 44.26797109600006763, 15.52865644600009887 44.27179596600008438, ' \
              '15.30795332100009887 44.35439687700007028, 15.00733483200014007 44.56972890800012976, ' \
              '14.883799675000148 44.7236188820001388, 14.883799675000148 44.86147695500012844, 14.92164147200008983 ' \
              '44.95880768400009231, 14.85279381600011561 45.09365469000000815, 14.65788821700004974 ' \
              '45.19660065300017493, 14.57081139400008851 45.29364655200011214, 14.31153405000009116 ' \
              '45.34398021000005485, 14.23259524800005238 45.14935944200000506, 14.17937259200007816 ' \
              '45.13450755400005221, 14.19312584700008983 45.10561758000012844, 14.14389082100007045 ' \
              '45.05939362200003018, 14.151377800000148 44.97748444200009033, 14.06885826900014536 ' \
              '44.94953034100014122, 14.08383222700007309 44.9863955750000315, 14.04029381600014403 ' \
              '45.03896719000015025, 14.0756942070000548 44.98371002800003282, 14.02051842500011958 ' \
              '44.90110911700004692, 13.97266686300011429 44.90110911700004692, 13.99301191500009622 ' \
              '44.88129303600014453, 13.97266686300011429 44.82664622599999404, 14.00001061300008587 ' \
              '44.81305573100003414, 13.89014733200011165 44.83348216400010244, 13.91797936300014271 ' \
              '44.77826569200009033, 13.90316816500009622 44.77240631700014717, 13.89698326900011693 ' \
              '44.81305573100003414, 13.78711998800014271 44.87506745000008834, 13.84229576900008851 ' \
              '44.88812897300006455, 13.79460696700010658 44.89496491100008768, 13.77409915500007287 ' \
              '44.96381256700014717, 13.6232202480000808 45.07306549700014386, 13.61255944100014403 ' \
              '45.11786530199999845, 13.72624759200004974 45.13450755400005221, 13.5959578790000819 ' \
              '45.14541250200001343, 13.57545006600011561 45.26487864800007799, 13.60271243600001867 ' \
              '45.28534577000012007, 13.57545006600011561 45.30646393400006389, 13.60954837300005238 ' \
              '45.32013580900017757, 13.54127037900013875 45.34613678600005926, 13.50709069100014403 ' \
              '45.51190827000000638, 13.62901778100007277 45.45898346000016943, 13.75929406800014476 ' \
              '45.46316925100011019, 13.88900191200011136 45.42363678000005223, 13.98263960800005634 ' \
              '45.47531321200001742, 13.97189091000012695 45.5142255660000643, 14.09291711400010172 ' \
              '45.47391794800002174, 14.21869755100007637 45.49717234400004884, 14.37279667100006009 ' \
              '45.47784535800009564, 14.4689148350000778 45.52559438100014688, 14.49857710800012001 ' \
              '45.59618438800005435, 14.58094934100009255 45.66780792200010808, 14.66848921700008646 ' \
              '45.53396596300005683, 14.79716353300005949 45.46518463200006011, 14.88160282300009385 ' \
              '45.46978383400001178, 14.9226339110000481 45.51494903600017494, 15.13926151500010064 ' \
              '45.43004465799999991, 15.32519331800011742 45.45283396399999276, 15.36136682100004691 ' \
              '45.48203114900003641, 15.29666792800006192 45.52295888300012905, 15.2685559480001416 ' \
              '45.60166208900012919, 15.37376916500011248 45.64021270800010655, 15.25501672300006817 ' \
              '45.72346344000011698, 15.42906294700014769 45.77529490200011253, 15.45128381300008868 ' \
              '45.81513743100013869, 15.67607629400006886 45.84169911700014666, 15.65943648300003588 ' \
              '45.88882802400014782, 15.69798710100010908 46.0362092080000167, 15.58988000500005455 ' \
              '46.11351715100001059, 15.62284956800010605 46.19170359400006021, 16.01920780400010358 ' \
              '46.29882883700007312, 16.05961877400008575 46.33231516600015709, 16.0579651280001201 ' \
              '46.37753204400003426, 16.2756262620000598 46.37316538500006402, 16.23490523300009158 ' \
              '46.4933389280001137, 16.36947066200013978 46.54057118800012915))) '
        geom = QgsGeometry.fromWkt(wkt)
        f = QgsFeature()
        f.setGeometry(geom)

        image = QImage(200, 200, QImage.Format_RGB32)

        painter = QPainter()
        ms = QgsMapSettings()
        crs = QgsCoordinateReferenceSystem.fromProj4(
            '+proj=ortho +lat_0=36.5 +lon_0=-118.8 +x_0=0 +y_0=0 +a=6371000 +b=6371000 +units=m +no_defs'
        )
        self.assertTrue(crs.isValid())
        ms.setDestinationCrs(crs)
        ms.setExtent(QgsRectangle(1374999.8, 3912610.7, 4724462.5, 6505499.6))
        ms.setOutputSize(image.size())
        context = QgsRenderContext.fromMapSettings(ms)
        context.setPainter(painter)
        context.setScaleFactor(96 / 25.4)  # 96 DPI
        ct = QgsCoordinateTransform(QgsCoordinateReferenceSystem('epsg:4326'),
                                    crs, QgsProject.instance())
        self.assertTrue(ct.isValid())
        context.setCoordinateTransform(ct)
        context.setExtent(
            ct.transformBoundingBox(ms.extent(),
                                    QgsCoordinateTransform.ReverseTransform))

        fill_symbol = QgsFillSymbol.createSimple({
            'color': '#ffffff',
            'outline_color': '#ffffff',
            'outline_width': '10'
        })

        painter.begin(image)
        try:
            image.fill(QColor(0, 0, 0))
            fill_symbol.startRender(context)
            fill_symbol.renderFeature(f, context)
            fill_symbol.stopRender(context)
        finally:
            painter.end()

        assert self.imageCheck('Reprojection errors polygon',
                               'reprojection_errors_polygon', image)

        #also test linestring
        linestring = QgsGeometry(geom.constGet().boundary())
        f.setGeometry(linestring)
        line_symbol = QgsLineSymbol.createSimple({
            'color': '#ffffff',
            'outline_width': '10'
        })

        image = QImage(200, 200, QImage.Format_RGB32)
        painter.begin(image)
        try:
            image.fill(QColor(0, 0, 0))
            line_symbol.startRender(context)
            line_symbol.renderFeature(f, context)
            line_symbol.stopRender(context)
        finally:
            painter.end()

        assert self.imageCheck('Reprojection errors linestring',
                               'reprojection_errors_linestring', image)
Exemplo n.º 32
0
    def processAlgorithm(self, progress):
        layer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT_LAYER))

        fields = layer.fields()
        fields.append(QgsField('node_pos', QVariant.Int))
        fields.append(QgsField('node_index', QVariant.Int))
        fields.append(QgsField('distance', QVariant.Double))
        fields.append(QgsField('angle', QVariant.Double))

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

        node_indices_string = self.getParameterValue(self.NODES)
        indices = []
        for node in node_indices_string.split(','):
            try:
                indices.append(int(node))
            except:
                raise GeoAlgorithmExecutionException(
                    self.tr('\'{}\' is not a valid node index').format(node))

        features = vector.features(layer)
        total = 100.0 / len(features)

        for current, f in enumerate(features):

            input_geometry = f.geometry()
            if not input_geometry:
                writer.addFeature(f)
            else:
                total_nodes = input_geometry.geometry().nCoordinates()

                for node in indices:
                    if node < 0:
                        node_index = total_nodes + node
                    else:
                        node_index = node

                    if node_index < 0 or node_index >= total_nodes:
                        continue

                    distance = input_geometry.distanceToVertex(node_index)
                    angle = math.degrees(input_geometry.angleAtVertex(node_index))

                    output_feature = QgsFeature()
                    attrs = f.attributes()
                    attrs.append(node)
                    attrs.append(node_index)
                    attrs.append(distance)
                    attrs.append(angle)
                    output_feature.setAttributes(attrs)

                    point = input_geometry.vertexAt(node_index)
                    output_feature.setGeometry(QgsGeometry.fromPoint(point))

                    writer.addFeature(output_feature)

            progress.setPercentage(int(current * total))

        del writer
Exemplo n.º 33
0
def buffering(feedback,
              context,
              writer,
              distance,
              field,
              useField,
              layer,
              dissolve,
              segments,
              endCapStyle=1,
              joinStyle=1,
              mitreLimit=2):

    if useField:
        field = layer.fields().lookupField(field)

    outFeat = QgsFeature()

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

    # With dissolve
    if dissolve:
        buffered_geometries = []
        for inFeat in features:
            attrs = inFeat.attributes()
            if useField:
                value = attrs[field]
            else:
                value = distance

            inGeom = inFeat.geometry()

            buffered_geometries.append(
                inGeom.buffer(float(value), segments, endCapStyle, joinStyle,
                              mitreLimit))

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

        final_geometry = QgsGeometry.unaryUnion(buffered_geometries)
        outFeat.setGeometry(final_geometry)
        outFeat.setAttributes(attrs)
        writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
    else:
        # Without dissolve
        for inFeat in features:
            attrs = inFeat.attributes()
            if useField:
                value = attrs[field]
            else:
                value = distance
            inGeom = inFeat.geometry()
            outFeat = QgsFeature()
            outGeom = inGeom.buffer(float(value), segments, endCapStyle,
                                    joinStyle, mitreLimit)
            outFeat.setGeometry(outGeom)
            outFeat.setAttributes(attrs)
            writer.addFeature(outFeat, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))

    del writer
Exemplo n.º 34
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}
Exemplo n.º 35
0
    def processAlgorithm(self, progress):
        layerPoints = dataobjects.getObjectFromUri(
            self.getParameterValue(self.POINTS))
        layerHubs = dataobjects.getObjectFromUri(
            self.getParameterValue(self.HUBS))
        fieldName = self.getParameterValue(self.FIELD)

        addLines = self.getParameterValue(self.GEOMETRY)
        units = self.UNITS[self.getParameterValue(self.UNIT)]

        if layerPoints.source() == layerHubs.source():
            raise GeoAlgorithmExecutionException(
                self.tr('Same layer given for both hubs and spokes'))

        fields = layerPoints.fields()
        fields.append(QgsField('HubName', QVariant.String))
        fields.append(QgsField('HubDist', QVariant.Double))

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

        index = vector.spatialindex(layerHubs)

        distance = QgsDistanceArea()
        distance.setSourceCrs(layerPoints.crs().srsid())
        distance.setEllipsoidalMode(True)

        # Scan source points, find nearest hub, and write to output file
        features = vector.features(layerPoints)
        total = 100.0 / len(features)
        for current, f in enumerate(features):
            src = f.geometry().boundingBox().center()

            neighbors = index.nearestNeighbor(src, 1)
            ft = next(
                layerHubs.getFeatures(QgsFeatureRequest().setFilterFid(
                    neighbors[0]).setSubsetOfAttributes([fieldName],
                                                        layerHubs.fields())))
            closest = ft.geometry().boundingBox().center()
            hubDist = distance.measureLine(src, closest)

            attributes = f.attributes()
            attributes.append(ft[fieldName])
            if units == 'Feet':
                attributes.append(hubDist * 3.2808399)
            elif units == 'Miles':
                attributes.append(hubDist * 0.000621371192)
            elif units == 'Kilometers':
                attributes.append(hubDist / 1000.0)
            elif units != 'Meters':
                attributes.append(
                    sqrt(
                        pow(src.x() - closest.x(), 2.0) +
                        pow(src.y() - closest.y(), 2.0)))
            else:
                attributes.append(hubDist)

            feat = QgsFeature()
            feat.setAttributes(attributes)

            feat.setGeometry(QgsGeometry.fromPoint(src))

            writer.addFeature(feat)
            progress.setPercentage(int(current * total))

        del writer
Exemplo n.º 36
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,
                                         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))

        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 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, nPoints + 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.fromPolylineXY(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}
Exemplo n.º 37
0
    def setUpClass(cls):
        """Run before all tests"""
        # Create test layer
        cls.vl = QgsVectorLayer(
            'Point?crs=epsg:4326&index=yes&field=pk:integer&field=cnt:int8&field=name:string(0)&field=name2:string(0)&field=num_char:string&key=pk',
            'test', 'memory')
        assert (cls.vl.isValid())
        cls.source = cls.vl.dataProvider()

        f1 = QgsFeature()
        f1.setAttributes([5, -200, NULL, 'NuLl', '5'])
        f1.setGeometry(QgsGeometry.fromWkt('Point (-71.123 78.23)'))

        f2 = QgsFeature()
        f2.setAttributes([3, 300, 'Pear', 'PEaR', '3'])

        f3 = QgsFeature()
        f3.setAttributes([1, 100, 'Orange', 'oranGe', '1'])
        f3.setGeometry(QgsGeometry.fromWkt('Point (-70.332 66.33)'))

        f4 = QgsFeature()
        f4.setAttributes([2, 200, 'Apple', 'Apple', '2'])
        f4.setGeometry(QgsGeometry.fromWkt('Point (-68.2 70.8)'))

        f5 = QgsFeature()
        f5.setAttributes([4, 400, 'Honey', 'Honey', '4'])
        f5.setGeometry(QgsGeometry.fromWkt('Point (-65.32 78.3)'))

        cls.source.addFeatures([f1, f2, f3, f4, f5])

        # poly layer
        cls.poly_vl = QgsVectorLayer(
            'Polygon?crs=epsg:4326&index=yes&field=pk:integer&key=pk', 'test',
            'memory')
        assert (cls.poly_vl.isValid())
        cls.poly_provider = cls.poly_vl.dataProvider()

        f1 = QgsFeature()
        f1.setAttributes([1])
        f1.setGeometry(
            QgsGeometry.fromWkt(
                'Polygon ((-69.0 81.4, -69.0 80.2, -73.7 80.2, -73.7 76.3, -74.9 76.3, -74.9 81.4, -69.0 81.4))'
            ))

        f2 = QgsFeature()
        f2.setAttributes([2])
        f2.setGeometry(
            QgsGeometry.fromWkt(
                'Polygon ((-67.6 81.2, -66.3 81.2, -66.3 76.9, -67.6 76.9, -67.6 81.2))'
            ))

        f3 = QgsFeature()
        f3.setAttributes([3])
        f3.setGeometry(
            QgsGeometry.fromWkt(
                'Polygon ((-68.4 75.8, -67.5 72.6, -68.6 73.7, -70.2 72.9, -68.4 75.8))'
            ))

        f4 = QgsFeature()
        f4.setAttributes([4])

        cls.poly_provider.addFeatures([f1, f2, f3, f4])
Exemplo n.º 38
0
    def loadData(self, resultFile, chunkId):
        """ Load data to the map """

        if isMimeTypeVector(self.mimeType, True) != None:
            # Memory layer:
            geometryTypes = [
                "Point", "LineString", "Polygon", "Unknown", "NoGeometry"
            ]
            vlayer = QgsVectorLayer(resultFile, "chunk", "ogr")

            if self.__bFirstChunk:
                self.__bFirstChunk = False
                self.__geometryType = geometryTypes[vlayer.geometryType()]
                self.__bGeomMulti = vlayer.wkbType() in [4, 5, 6, 11, 12, 13]
                self.__memoryLayer = QgsVectorLayer(self.__geometryType,
                                                    "Streamed data", "memory")
                self.__memoryLayer.dataProvider().addAttributes(
                    list(vlayer.pendingFields().values()))
                self.__memoryLayer.updateFieldMap()

            provider = vlayer.dataProvider()
            allAttrs = provider.attributeIndexes()
            vlayer.select(allAttrs)

            # Visualize temporal geometries during the downloading process
            # Don't add temporal geometries if last chunk
            if self.DEBUG:  # fix_print_with_import
                # fix_print_with_import
                print("Loaded chunkId:", chunkId)
            res = self.__memoryLayer.dataProvider().addFeatures(
                [feat for feat in vlayer])
            self.__deliveredChunks += 1

            if not self.allChunksDelivered():
                inFeat = QgsFeature()
                inGeom = QgsGeometry()
                self.createTempGeometry(chunkId, self.__geometryType)
                while provider.nextFeature(inFeat):
                    inGeom = inFeat.geometry()
                    featList = self.extractAsSingle(
                        self.__geometryType,
                        inGeom) if self.__bGeomMulti else [inGeom]
                    for geom in featList:
                        self.addTempGeometry(chunkId, self.__geometryType,
                                             geom)
            else:
                self.finishLoading()

        # Raster data
        elif isMimeTypeRaster(self.mimeType, True) != None:
            # We can directly attach the new layer
            if self.__bFirstChunk:
                self.__bFirstChunk = False
                self.__groupIndex = self.__legend.addGroup("Streamed-raster")

            rLayer = QgsRasterLayer(resultFile, "raster_" + str(chunkId))
            bLoaded = QgsProject.instance().addMapLayer(rLayer)
            self.stretchRaster(rLayer)
            self.__legend.moveLayer(rLayer, self.__groupIndex + 1)

            self.__deliveredChunks += 1

            if self.allChunksDelivered():
                self.finishLoading()
Exemplo n.º 39
0
    def testGeometryRendering(self):
        '''Tests rendering a bunch of different geometries, including bad/odd geometries.'''

        empty_multipolygon = QgsMultiPolygon()
        empty_multipolygon.addGeometry(QgsPolygon())
        empty_polygon = QgsPolygon()
        empty_linestring = QgsLineString()

        tests = [
            {
                'name': 'Point',
                'wkt': 'Point (1 2)',
                'reference_image': 'point'
            },
            {
                'name': 'MultiPoint',
                'wkt': 'MultiPoint ((10 30),(40 20),(30 10),(20 10))',
                'reference_image': 'multipoint'
            },
            {
                'name': 'LineString',
                'wkt': 'LineString (0 0,3 4,4 3)',
                'reference_image': 'linestring'
            },
            {
                'name': 'Empty LineString',
                'geom': QgsGeometry(empty_linestring),
                'reference_image': 'empty'
            },
            {
                'name': 'MultiLineString',
                'wkt':
                'MultiLineString ((0 0, 1 0, 1 1, 2 1, 2 0), (3 1, 5 1, 5 0, 6 0))',
                'reference_image': 'multilinestring'
            },
            {
                'name': 'Polygon',
                'wkt':
                'Polygon ((0 0, 10 0, 10 10, 0 10, 0 0),(5 5, 7 5, 7 7 , 5 7, 5 5))',
                'reference_image': 'polygon'
            },
            {
                'name': 'Empty Polygon',
                'geom': QgsGeometry(empty_polygon),
                'reference_image': 'empty'
            },
            {
                'name': 'MultiPolygon',
                'wkt':
                'MultiPolygon (((0 0, 1 0, 1 1, 2 1, 2 2, 0 2, 0 0)),((4 0, 5 0, 5 2, 3 2, 3 1, 4 1, 4 0)))',
                'reference_image': 'multipolygon'
            },
            {
                'name': 'Empty MultiPolygon',
                'geom': QgsGeometry(empty_multipolygon),
                'reference_image': 'empty'
            },
            {
                'name': 'CircularString',
                'wkt': 'CIRCULARSTRING(268 415,227 505,227 406)',
                'reference_image': 'circular_string'
            },
            {
                'name': 'CompoundCurve',
                'wkt':
                'COMPOUNDCURVE((5 3, 5 13), CIRCULARSTRING(5 13, 7 15, 9 13), (9 13, 9 3), CIRCULARSTRING(9 3, 7 1, 5 3))',
                'reference_image': 'compound_curve'
            },
            {
                'name': 'CurvePolygon',
                'wkt': 'CURVEPOLYGON(CIRCULARSTRING(1 3, 3 5, 4 7, 7 3, 1 3))',
                'reference_image': 'curve_polygon'
            },
            {
                'name': 'MultiCurve',
                'wkt':
                'MultiCurve((5 5,3 5,3 3,0 3),CIRCULARSTRING(0 0, 2 1,2 2))',
                'reference_image': 'multicurve'
            },
            {
                'name': 'CurvePolygon_no_arc',  # refs #14028
                'wkt': 'CURVEPOLYGON(LINESTRING(1 3, 3 5, 4 7, 7 3, 1 3))',
                'reference_image': 'curve_polygon_no_arc'
            }
        ]

        for test in tests:

            def get_geom():
                if 'geom' not in test:
                    geom = QgsGeometry.fromWkt(test['wkt'])
                    assert geom and not geom.isNull(
                    ), 'Could not create geometry {}'.format(test['wkt'])
                else:
                    geom = test['geom']
                return geom

            geom = get_geom()
            rendered_image = self.renderGeometry(geom)
            assert self.imageCheck(test['name'], test['reference_image'],
                                   rendered_image)

            # Note - each test is repeated with the same geometry and reference image, but with added
            # z and m dimensions. This tests that presence of the dimensions does not affect rendering

            # test with Z
            geom_z = get_geom()
            geom_z.get().addZValue(5)
            rendered_image = self.renderGeometry(geom_z)
            assert self.imageCheck(test['name'] + 'Z', test['reference_image'],
                                   rendered_image)

            # test with ZM
            geom_z.get().addMValue(15)
            rendered_image = self.renderGeometry(geom_z)
            assert self.imageCheck(test['name'] + 'ZM',
                                   test['reference_image'], rendered_image)

            # test with M
            geom_m = get_geom()
            geom_m.get().addMValue(15)
            rendered_image = self.renderGeometry(geom_m)
            assert self.imageCheck(test['name'] + 'M', test['reference_image'],
                                   rendered_image)
Exemplo n.º 40
0
    def _test_operations(self, md, conn):
        """Common tests"""

        capabilities = conn.capabilities()

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

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

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

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

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

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

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

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

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

            elif capabilities & QgsAbstractDatabaseProviderConnection.Schemas:
                schema = self.getUniqueSchemaName(self.defaultSchema)

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

                for row in res:
                    rows.append(row)

                self.assertEqual(rows, old_rows)

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

                self.assertFalse(res.hasNextRow())

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # Remove connection
        spy_deleted = QSignalSpy(md.connectionDeleted)
        md.deleteConnection('qgis_test1')
        self.assertEqual(list(md.connections().values()), [])
        self.assertEqual(len(spy_deleted), 1)
Exemplo n.º 41
0
    def processAlgorithm(self, progress):
        layerA = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        layerB = dataobjects.getObjectFromUri(
            self.getParameterValue(self.OVERLAY))

        geomType = layerA.wkbType()
        fields = vector.combineVectorFields(layerA, layerB)
        writer = self.getOutputFromName(self.OUTPUT).getVectorWriter(
            fields, geomType, layerA.crs())

        featB = QgsFeature()
        outFeat = QgsFeature()

        indexA = vector.spatialindex(layerB)
        indexB = vector.spatialindex(layerA)

        featuresA = vector.features(layerA)
        featuresB = vector.features(layerB)

        total = 100.0 / (len(featuresA) * len(featuresB))
        count = 0

        for featA in featuresA:
            add = True
            geom = featA.geometry()
            diffGeom = QgsGeometry(geom)
            attrs = featA.attributes()
            intersects = indexA.intersects(geom.boundingBox())
            for i in intersects:
                layerB.getFeatures(
                    QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
                tmpGeom = featB.geometry()
                if diffGeom.intersects(tmpGeom):
                    diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
                    if not diffGeom.isGeosValid():
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                        add = False
                        break

            if add:
                try:
                    outFeat.setGeometry(diffGeom)
                    outFeat.setAttributes(attrs)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_WARNING,
                        self.
                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                           ))
                    continue

            count += 1
            progress.setPercentage(int(count * total))

        length = len(layerA.fields())

        for featA in featuresB:
            add = True
            geom = featA.geometry()
            diffGeom = QgsGeometry(geom)
            attrs = featA.attributes()
            attrs = [NULL] * length + attrs
            intersects = indexB.intersects(geom.boundingBox())
            for i in intersects:
                layerA.getFeatures(
                    QgsFeatureRequest().setFilterFid(i)).nextFeature(featB)
                tmpGeom = featB.geometry()
                if diffGeom.intersects(tmpGeom):
                    diffGeom = QgsGeometry(diffGeom.difference(tmpGeom))
                    if not diffGeom.isGeosValid():
                        ProcessingLog.addToLog(
                            ProcessingLog.LOG_ERROR,
                            self.tr('GEOS geoprocessing error: One or '
                                    'more input features have invalid '
                                    'geometry.'))
                        add = False
                        break

            if add:
                try:
                    outFeat.setGeometry(diffGeom)
                    outFeat.setAttributes(attrs)
                    writer.addFeature(outFeat)
                except:
                    ProcessingLog.addToLog(
                        ProcessingLog.LOG_WARNING,
                        self.
                        tr('Feature geometry error: One or more output features ignored due to invalid geometry.'
                           ))
                    continue

            count += 1
            progress.setPercentage(int(count * total))

        del writer
Exemplo n.º 42
0
    def processAlgorithm(self, parameters, context, feedback):
        inLayer = self.parameterAsVectorLayer(parameters, self.INPUT, context)
        boundary = self.parameterAsEnum(parameters, self.MODE,
                                        context) == self.MODE_BOUNDARY
        smallestArea = self.parameterAsEnum(parameters, self.MODE,
                                            context) == self.MODE_SMALLEST_AREA

        if inLayer.selectedFeatureCount() == 0:
            feedback.reportError(
                self.tr('{0}: (No selection in input layer "{1}")').format(
                    self.displayName(), parameters[self.INPUT]))

        featToEliminate = []
        selFeatIds = inLayer.selectedFeatureIds()

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

        for aFeat in inLayer.getFeatures():
            if feedback.isCanceled():
                break

            if aFeat.id() in selFeatIds:
                # Keep references to the features to eliminate
                featToEliminate.append(aFeat)
            else:
                # write the others to output
                sink.addFeature(aFeat, QgsFeatureSink.FastInsert)

        # Delete all features to eliminate in processLayer
        processLayer = QgsProcessingUtils.mapLayerFromString(dest_id, context)
        processLayer.startEditing()

        # ANALYZE
        if len(featToEliminate) > 0:  # Prevent zero division
            start = 20.00
            add = 80.00 / len(featToEliminate)
        else:
            start = 100

        feedback.setProgress(start)
        madeProgress = True

        # We go through the list and see if we find any polygons we can
        # merge the selected with. If we have no success with some we
        # merge and then restart the whole story.
        while madeProgress:  # Check if we made any progress
            madeProgress = False
            featNotEliminated = []

            # Iterate over the polygons to eliminate
            for i in range(len(featToEliminate)):
                if feedback.isCanceled():
                    break

                feat = featToEliminate.pop()
                geom2Eliminate = feat.geometry()
                bbox = geom2Eliminate.boundingBox()
                fit = processLayer.getFeatures(
                    QgsFeatureRequest().setFilterRect(
                        bbox).setSubsetOfAttributes([]))
                mergeWithFid = None
                mergeWithGeom = None
                max = 0
                min = -1
                selFeat = QgsFeature()

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

                while fit.nextFeature(selFeat):
                    if feedback.isCanceled():
                        break

                    selGeom = selFeat.geometry()

                    if engine.intersects(selGeom.constGet()):
                        # We have a candidate
                        iGeom = geom2Eliminate.intersection(selGeom)

                        if not iGeom:
                            continue

                        if boundary:
                            selValue = iGeom.length()
                        else:
                            # area. We need a common boundary in
                            # order to merge
                            if 0 < iGeom.length():
                                selValue = selGeom.area()
                            else:
                                selValue = -1

                        if -1 != selValue:
                            useThis = True

                            if smallestArea:
                                if -1 == min:
                                    min = selValue
                                else:
                                    if selValue < min:
                                        min = selValue
                                    else:
                                        useThis = False
                            else:
                                if selValue > max:
                                    max = selValue
                                else:
                                    useThis = False

                            if useThis:
                                mergeWithFid = selFeat.id()
                                mergeWithGeom = QgsGeometry(selGeom)
                # End while fit

                if mergeWithFid is not None:
                    # A successful candidate
                    newGeom = mergeWithGeom.combine(geom2Eliminate)

                    if processLayer.changeGeometry(mergeWithFid, newGeom):
                        madeProgress = True
                    else:
                        raise QgsProcessingException(
                            self.
                            tr('Could not replace geometry of feature with id {0}'
                               ).format(mergeWithFid))

                    start = start + add
                    feedback.setProgress(start)
                else:
                    featNotEliminated.append(feat)

            # End for featToEliminate

            featToEliminate = featNotEliminated

        # End while
        if not processLayer.commitChanges():
            raise QgsProcessingException(self.tr('Could not commit changes'))

        for feature in featNotEliminated:
            if feedback.isCanceled():
                break

            sink.addFeature(feature, QgsFeatureSink.FastInsert)

        return {self.OUTPUT: dest_id}
Exemplo n.º 43
0
    def processAlgorithm(self, parameters, context, feedback):
        extent = self.parameterAsExtent(parameters, self.EXTENT, context)

        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)

        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.geometry())
        extent_engine.prepareGeometry()

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

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

                if extent_engine.intersects(geom.geometry()):
                    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}
Exemplo n.º 44
0
def _clip_vector_layer(layer,
                       extent,
                       extra_keywords=None,
                       explode_flag=True,
                       hard_clip_flag=False,
                       explode_attribute=None):
    """Clip a Hazard or Exposure layer to the extents provided.

    The layer must be a vector layer or an exception will be thrown.

    The output layer will always be in WGS84/Geographic.

    :param layer: A valid QGIS vector or raster layer
    :type layer:

    :param extent: Either an array representing the exposure layer extents
        in the form [xmin, ymin, xmax, ymax]. It is assumed that the
        coordinates are in EPSG:4326 although currently no checks are made to
        enforce this.
        or:
        A QgsGeometry of type polygon.
        **Polygon clipping is currently only supported for vector datasets.**
    :type extent: list(float, float, float, float)

    :param extra_keywords: Optional keywords dictionary to be added to
        output layer.
    :type extra_keywords: dict

    :param explode_flag: A bool specifying whether multipart features
        should be 'exploded' into singleparts.
        **This parameter is ignored for raster layer clipping.**
    :type explode_flag: bool

    :param hard_clip_flag: A bool specifying whether line and polygon
        features that extend beyond the extents should be clipped such that
        they are reduced in size to the part of the geometry that intersects
        the extent only. Default is False.
        **This parameter is ignored for raster layer clipping.**
    :type hard_clip_flag: bool

    :param explode_attribute: A str specifying to which attribute #1,
        #2 and so on will be added in case of explode_flag being true. The
        attribute is modified only if there are at least 2 parts.
    :type explode_attribute: str

    :returns: Clipped layer (placed in the system temp dir). The output layer
        will be reprojected to EPSG:4326 if needed.
    :rtype: QgsVectorLayer

    """
    if not layer or not extent:
        message = tr('Layer or Extent passed to clip is None.')
        raise InvalidParameterError(message)

    if layer.type() != QgsMapLayer.VectorLayer:
        message = tr('Expected a vector layer but received a %s.' %
                     str(layer.type()))
        raise InvalidParameterError(message)

    #handle, file_name = tempfile.mkstemp('.sqlite', 'clip_',
    #    temp_dir())
    handle, file_name = tempfile.mkstemp('.shp', 'clip_', temp_dir())

    # Ensure the file is deleted before we try to write to it
    # fixes windows specific issue where you get a message like this
    # ERROR 1: c:\temp\inasafe\clip_jpxjnt.shp is not a directory.
    # This is because mkstemp creates the file handle and leaves
    # the file open.
    os.close(handle)
    os.remove(file_name)

    # Get the clip extents in the layer's native CRS
    geo_crs = QgsCoordinateReferenceSystem()
    geo_crs.createFromSrid(4326)
    transform = QgsCoordinateTransform(geo_crs, layer.crs())
    allowed_clip_values = [QGis.WKBPolygon, QGis.WKBPolygon25D]
    if type(extent) is list:
        rectangle = QgsRectangle(extent[0], extent[1], extent[2], extent[3])
        # noinspection PyCallByClass
        #noinspection PyTypeChecker
        polygon = QgsGeometry.fromRect(rectangle)
    elif (type(extent) is QgsGeometry
          and extent.wkbType in allowed_clip_values):
        rectangle = extent.boundingBox().toRectF()
        polygon = extent
    else:
        raise InvalidClipGeometryError(
            tr('Clip geometry must be an extent or a single part'
               'polygon based geometry.'))

    projected_extent = transform.transformBoundingBox(rectangle)

    # Get vector layer
    provider = layer.dataProvider()
    if provider is None:
        message = tr('Could not obtain data provider from '
                     'layer "%s"' % layer.source())
        raise Exception(message)

    # Get the layer field list, select by our extent then write to disk
    # .. todo:: FIXME - for different geometry types we should implement
    #    different clipping behaviour e.g. reject polygons that
    #    intersect the edge of the bbox. Tim
    request = QgsFeatureRequest()
    if not projected_extent.isEmpty():
        request.setFilterRect(projected_extent)
        request.setFlags(QgsFeatureRequest.ExactIntersect)

    field_list = provider.fields()

    writer = QgsVectorFileWriter(
        file_name,
        'UTF-8',
        field_list,
        layer.wkbType(),
        geo_crs,
        #'SQLite')  # FIXME (Ole): This works but is far too slow
        'ESRI Shapefile')
    if writer.hasError() != QgsVectorFileWriter.NoError:
        message = tr('Error when creating shapefile: <br>Filename:'
                     '%s<br>Error: %s' % (file_name, writer.hasError()))
        raise Exception(message)

    # Reverse the coordinate xform now so that we can convert
    # geometries from layer crs to geocrs.
    transform = QgsCoordinateTransform(layer.crs(), geo_crs)
    # Retrieve every feature with its geometry and attributes
    count = 0
    has_multipart = False

    for feature in provider.getFeatures(request):
        geometry = feature.geometry()

        # Loop through the parts adding them to the output file
        # we write out single part features unless explode_flag is False
        if explode_flag:
            geometry_list = explode_multipart_geometry(geometry)
        else:
            geometry_list = [geometry]

        for part_index, part in enumerate(geometry_list):
            part.transform(transform)
            if hard_clip_flag:
                # Remove any dangling bits so only intersecting area is
                # kept.
                part = clip_geometry(polygon, part)
            if part is None:
                continue

            feature.setGeometry(part)
            # There are multiple parts and we want to show it in the
            # explode_attribute
            if part_index > 0 and explode_attribute is not None:
                has_multipart = True

            writer.addFeature(feature)
        count += 1
    del writer  # Flush to disk

    if count < 1:
        message = tr(
            'No features fall within the clip extents. Try panning / zooming '
            'to an area containing data and then try to run your analysis '
            'again. If hazard and exposure data doesn\'t overlap at all, it '
            'is not possible to do an analysis. Another possibility is that '
            'the layers do overlap but because they may have different '
            'spatial references, they appear to be disjointed. If this is the '
            'case, try to turn on reproject on-the-fly in QGIS.')
        raise NoFeaturesInExtentError(message)

    keyword_io = KeywordIO()
    if extra_keywords is None:
        extra_keywords = {}
    extra_keywords['had multipart polygon'] = has_multipart
    keyword_io.copy_keywords(layer, file_name, extra_keywords=extra_keywords)
    base_name = '%s clipped' % layer.name()
    layer = QgsVectorLayer(file_name, base_name, 'ogr')

    return layer
    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
Exemplo n.º 46
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        if source is None:
            raise QgsProcessingException(
                self.invalidSourceError(parameters, self.INPUT))

        buf = self.parameterAsDouble(parameters, self.BUFFER, context)
        (sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT,
                                               context, source.fields(),
                                               QgsWkbTypes.Polygon,
                                               source.sourceCrs())
        if sink is None:
            raise QgsProcessingException(
                self.invalidSinkError(parameters, self.OUTPUT))
        outFeat = QgsFeature()
        extent = source.sourceExtent()
        extraX = extent.width() * (buf / 100.0)
        # Adjust the extent
        extent.setXMinimum(extent.xMinimum() - extraX)
        extent.setXMaximum(extent.xMaximum() + extraX)
        extraY = extent.height() * (buf / 100.0)
        extent.setYMinimum(extent.yMinimum() - extraY)
        extent.setYMaximum(extent.yMaximum() + extraY)
        height = extent.height()
        width = extent.width()
        c = voronoi.Context()
        pts = []
        ptDict = {}
        ptNdx = -1
        # Find the minimum and maximum x and y for the input points
        xmin = width
        xmax = 0
        ymin = height
        ymax = 0
        features = source.getFeatures()
        total = 100.0 / source.featureCount() if source.featureCount() else 0
        for current, inFeat in enumerate(features):
            if feedback.isCanceled():
                break
            geom = inFeat.geometry()
            point = geom.asPoint()
            x = point.x() - extent.xMinimum()
            y = point.y() - extent.yMinimum()
            pts.append((x, y))
            ptNdx += 1
            ptDict[ptNdx] = inFeat.id()
            if x < xmin:
                xmin = x
            if y < ymin:
                ymin = y
            if x > xmax:
                xmax = x
            if y > ymax:
                ymax = y
            feedback.setProgress(int(current * total))
        if xmin == xmax or ymin == ymax:
            raise QgsProcessingException('The extent of the input points is '
                                         'not a polygon (all the points are '
                                         'on a vertical or horizontal line) '
                                         '- cannot make a Voronoi diagram!')
        xyminmax = [xmin, ymin, xmax, ymax]
        if len(pts) < 3:
            raise QgsProcessingException(
                self.tr('Input file should contain at least 3 points. Choose '
                        'another file and try again.'))
        # Eliminate duplicate points
        uniqueSet = set(item for item in pts)
        ids = [pts.index(item) for item in uniqueSet]
        sl = voronoi.SiteList([
            voronoi.Site(i[0], i[1], sitenum=j)
            for (j, i) in enumerate(uniqueSet)
        ])
        voronoi.voronoi(sl, c)
        if len(c.polygons) == 0:
            raise QgsProcessingException(
                self.tr('There were no polygons created.'))

        inFeat = QgsFeature()
        current = 0
        total = 100.0 / len(c.polygons)
        # Clip each of the generated "polygons"
        for (site, edges) in list(c.polygons.items()):
            if feedback.isCanceled():
                break
            request = QgsFeatureRequest().setFilterFid(ptDict[ids[site]])
            inFeat = next(source.getFeatures(request))
            boundarypoints = self.clip_voronoi(edges, c, width, height, extent,
                                               inFeat.geometry().asPoint(),
                                               xyminmax)
            ptgeom = QgsGeometry.fromMultiPointXY(boundarypoints)
            geom = QgsGeometry(ptgeom.convexHull())
            outFeat.setGeometry(geom)
            outFeat.setAttributes(inFeat.attributes())
            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))
        return {self.OUTPUT: dest_id}
Exemplo n.º 47
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)

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

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

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

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

        if len(pts) < 3:
            raise QgsProcessingException(
                self.tr('Input file should contain at least 3 points. Choose '
                        'another file and try again.'))

        uniqueSet = set(item for item in pts)
        ids = [pts.index(item) for item in uniqueSet]
        sl = voronoi.SiteList([voronoi.Site(*i) for i in uniqueSet])
        c.triangulate = True
        voronoi.voronoi(sl, c)
        triangles = c.triangles
        feat = QgsFeature()

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

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

        return {self.OUTPUT: dest_id}
Exemplo n.º 48
0
    def processAlgorithm(self, parameters, context, feedback):
        raster_layer = self.parameterAsRasterLayer(parameters, self.INPUT_DEM,
                                                   context)
        target_crs = raster_layer.crs()
        rasterPath = raster_layer.source()

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

        step = self.parameterAsDouble(parameters, self.STEP, context)
        percentage = self.parameterAsBoolean(parameters, self.USE_PERCENTAGE,
                                             context)

        outputPath = self.parameterAsString(parameters, self.OUTPUT_DIRECTORY,
                                            context)

        rasterDS = gdal.Open(rasterPath, gdal.GA_ReadOnly)
        geoTransform = rasterDS.GetGeoTransform()
        rasterBand = rasterDS.GetRasterBand(1)
        noData = rasterBand.GetNoDataValue()

        cellXSize = abs(geoTransform[1])
        cellYSize = abs(geoTransform[5])
        rasterXSize = rasterDS.RasterXSize
        rasterYSize = rasterDS.RasterYSize

        rasterBBox = QgsRectangle(geoTransform[0],
                                  geoTransform[3] - cellYSize * rasterYSize,
                                  geoTransform[0] + cellXSize * rasterXSize,
                                  geoTransform[3])
        rasterGeom = QgsGeometry.fromRect(rasterBBox)

        crs = osr.SpatialReference()
        crs.ImportFromProj4(str(target_crs.toProj4()))

        memVectorDriver = ogr.GetDriverByName('Memory')
        memRasterDriver = gdal.GetDriverByName('MEM')

        features = source.getFeatures(QgsFeatureRequest().setDestinationCrs(
            target_crs, context.transformContext()))
        total = 100.0 / source.featureCount() if source.featureCount() else 0

        for current, f in enumerate(features):
            if not f.hasGeometry():
                continue

            if feedback.isCanceled():
                break

            geom = f.geometry()
            intersectedGeom = rasterGeom.intersection(geom)

            if intersectedGeom.isEmpty():
                feedback.pushInfo(
                    self.tr('Feature {0} does not intersect raster or '
                            'entirely located in NODATA area').format(f.id()))
                continue

            fName = os.path.join(
                outputPath,
                'hystogram_%s_%s.csv' % (source.sourceName(), f.id()))

            ogrGeom = ogr.CreateGeometryFromWkt(intersectedGeom.asWkt())
            bbox = intersectedGeom.boundingBox()
            xMin = bbox.xMinimum()
            xMax = bbox.xMaximum()
            yMin = bbox.yMinimum()
            yMax = bbox.yMaximum()

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

            width = endColumn - startColumn
            height = endRow - startRow

            srcOffset = (startColumn, startRow, width, height)
            srcArray = rasterBand.ReadAsArray(*srcOffset)

            if srcOffset[2] == 0 or srcOffset[3] == 0:
                feedback.pushInfo(
                    self.tr('Feature {0} is smaller than raster '
                            'cell size').format(f.id()))
                continue

            newGeoTransform = (geoTransform[0] +
                               srcOffset[0] * geoTransform[1], geoTransform[1],
                               0.0, geoTransform[3] +
                               srcOffset[1] * geoTransform[5], 0.0,
                               geoTransform[5])

            memVDS = memVectorDriver.CreateDataSource('out')
            memLayer = memVDS.CreateLayer('poly', crs, ogr.wkbPolygon)

            ft = ogr.Feature(memLayer.GetLayerDefn())
            ft.SetGeometry(ogrGeom)
            memLayer.CreateFeature(ft)
            ft.Destroy()

            rasterizedDS = memRasterDriver.Create('', srcOffset[2],
                                                  srcOffset[3], 1,
                                                  gdal.GDT_Byte)
            rasterizedDS.SetGeoTransform(newGeoTransform)
            gdal.RasterizeLayer(rasterizedDS, [1], memLayer, burn_values=[1])
            rasterizedArray = rasterizedDS.ReadAsArray()

            srcArray = numpy.nan_to_num(srcArray)
            masked = numpy.ma.MaskedArray(
                srcArray,
                mask=numpy.logical_or(srcArray == noData,
                                      numpy.logical_not(rasterizedArray)))

            self.calculateHypsometry(f.id(), fName, feedback, masked,
                                     cellXSize, cellYSize, percentage, step)

            memVDS = None
            rasterizedDS = None
            feedback.setProgress(int(current * total))

        rasterDS = None

        return {self.OUTPUT_DIRECTORY: outputPath}
Exemplo n.º 49
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}
Exemplo n.º 50
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        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 ProcessingException(expression.parserErrorString())

        expressionContext = self.createExpressionContext(parameters, context)
        if not expression.prepare(expressionContext):
            raise ProcessingException(
                self.tr('Evaluation error: {0}').format(
                    expression.evalErrorString()))

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

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

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

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

            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()
            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.")
                continue

            index = QgsSpatialIndex()
            points = dict()

            nPoints = 0
            nIterations = 0
            maxIterations = pointCount * 200
            total = 100.0 / 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 geom.within(fGeom) 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(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.'))

            feedback.setProgress(0)

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

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

        join_fields = self.parameterAsFields(parameters, self.JOIN_FIELDS,
                                             context)
        method = self.parameterAsEnum(parameters, self.METHOD, context)
        discard_nomatch = self.parameterAsBool(parameters,
                                               self.DISCARD_NONMATCHING,
                                               context)

        source_fields = source.fields()
        fields_to_join = QgsFields()
        join_field_indexes = []
        if not join_fields:
            fields_to_join = join_source.fields()
            join_field_indexes = [i for i in range(len(fields_to_join))]
        else:
            for f in join_fields:
                idx = join_source.fields().lookupField(f)
                join_field_indexes.append(idx)
                if idx >= 0:
                    fields_to_join.append(join_source.fields().at(idx))

        out_fields = QgsProcessingUtils.combineFields(source_fields,
                                                      fields_to_join)

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

        # do the join

        # build a list of 'reversed' predicates, because in this function
        # we actually test the reverse of what the user wants (allowing us
        # to prepare geometries and optimise the algorithm)
        predicates = [
            self.reversed_predicates[self.predicates[i][0]]
            for i in self.parameterAsEnums(parameters, self.PREDICATE, context)
        ]

        remaining = set()
        if not discard_nomatch:
            remaining = set(source.allFeatureIds())

        added_set = set()

        request = QgsFeatureRequest().setSubsetOfAttributes(
            join_field_indexes).setDestinationCrs(source.sourceCrs(),
                                                  context.transformContext())
        features = join_source.getFeatures(request)
        total = 100.0 / join_source.featureCount() if join_source.featureCount(
        ) else 0

        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            bbox = f.geometry().boundingBox()
            engine = None

            request = QgsFeatureRequest().setFilterRect(bbox)
            for test_feat in source.getFeatures(request):
                if feedback.isCanceled():
                    break
                if method == 1 and test_feat.id() in added_set:
                    # already added this feature, and user has opted to only output first match
                    continue

                join_attributes = []
                for a in join_field_indexes:
                    join_attributes.append(f.attributes()[a])

                if engine is None:
                    engine = QgsGeometry.createGeometryEngine(
                        f.geometry().constGet())
                    engine.prepareGeometry()

                for predicate in predicates:
                    if getattr(engine,
                               predicate)(test_feat.geometry().constGet()):
                        added_set.add(test_feat.id())

                        # join attributes and add
                        attributes = test_feat.attributes()
                        attributes.extend(join_attributes)
                        output_feature = test_feat
                        output_feature.setAttributes(attributes)
                        sink.addFeature(output_feature,
                                        QgsFeatureSink.FastInsert)
                        break

            feedback.setProgress(int(current * total))

        if not discard_nomatch:
            remaining = remaining.difference(added_set)
            for f in source.getFeatures(QgsFeatureRequest().setFilterFids(
                    list(remaining))):
                if feedback.isCanceled():
                    break
                sink.addFeature(f, QgsFeatureSink.FastInsert)

        return {self.OUTPUT: dest_id}
Exemplo n.º 52
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
Exemplo n.º 53
0
    def processAlgorithm(self, parameters, context, feedback):
        layer = QgsProcessingUtils.mapLayerFromString(
            self.getParameterValue(self.VECTOR), context)
        fieldName = self.getParameterValue(self.FIELD)
        minDistance = float(self.getParameterValue(self.MIN_DISTANCE))
        strategy = self.getParameterValue(self.STRATEGY)

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

        da = QgsDistanceArea()

        features = QgsProcessingUtils.getFeatures(layer, context)
        for current, f in enumerate(features):
            fGeom = f.geometry()
            bbox = fGeom.boundingBox()
            if strategy == 0:
                pointCount = int(f[fieldName])
            else:
                pointCount = int(round(f[fieldName] * da.measureArea(fGeom)))

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

            index = QgsSpatialIndex()
            points = dict()

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

            random.seed()

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

                pnt = QgsPointXY(rx, ry)
                geom = QgsGeometry.fromPoint(pnt)
                if geom.within(fGeom) 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, QgsFeatureSink.FastInsert)
                    index.insertFeature(f)
                    points[nPoints] = pnt
                    nPoints += 1
                    feedback.setProgress(int(nPoints * total))
                nIterations += 1

            if nPoints < pointCount:
                QgsMessageLog.logMessage(
                    self.tr('Can not generate requested number of random '
                            'points. Maximum number of attempts exceeded.'),
                    self.tr('Processing'), QgsMessageLog.INFO)

            feedback.setProgress(0)

        del writer
Exemplo n.º 54
0
    def processAlgorithm(self, feedback):
        inLayer = dataobjects.getObjectFromUri(
            self.getParameterValue(self.INPUT))
        boundary = self.getParameterValue(self.MODE) == self.MODE_BOUNDARY
        smallestArea = self.getParameterValue(
            self.MODE) == self.MODE_SMALLEST_AREA
        keepSelection = self.getParameterValue(self.KEEPSELECTION)
        processLayer = vector.duplicateInMemory(inLayer)

        if not keepSelection:
            # Make a selection with the values provided
            attribute = self.getParameterValue(self.ATTRIBUTE)
            comparison = self.comparisons[self.getParameterValue(
                self.COMPARISON)]
            comparisonvalue = self.getParameterValue(self.COMPARISONVALUE)

            selectindex = vector.resolveFieldIndex(processLayer, attribute)
            selectType = processLayer.fields()[selectindex].type()
            selectionError = False

            if selectType in [
                    QVariant.Int, QVariant.LongLong, QVariant.UInt,
                    QVariant.ULongLong
            ]:
                try:
                    y = int(comparisonvalue)
                except ValueError:
                    selectionError = True
                    msg = self.tr('Cannot convert "%s" to integer' %
                                  str(comparisonvalue))
            elif selectType == QVariant.Double:
                try:
                    y = float(comparisonvalue)
                except ValueError:
                    selectionError = True
                    msg = self.tr('Cannot convert "%s" to float' %
                                  str(comparisonvalue))
            elif selectType == QVariant.String:
                # 10: string, boolean
                try:
                    y = str(comparisonvalue)
                except ValueError:
                    selectionError = True
                    msg = self.tr('Cannot convert "%s" to Unicode' %
                                  str(comparisonvalue))
            elif selectType == QVariant.Date:
                # date
                dateAndFormat = comparisonvalue.split(' ')

                if len(dateAndFormat) == 1:
                    # QDate object
                    y = QLocale.system().toDate(dateAndFormat[0])

                    if y.isNull():
                        msg = self.tr(
                            'Cannot convert "%s" to date with system date format %s'
                            % (str(dateAndFormat),
                               QLocale.system().dateFormat()))
                elif len(dateAndFormat) == 2:
                    y = QDate.fromString(dateAndFormat[0], dateAndFormat[1])

                    if y.isNull():
                        msg = self.tr(
                            'Cannot convert "%s" to date with format string "%s"'
                            % (str(dateAndFormat[0]), dateAndFormat[1]))
                else:
                    y = QDate()
                    msg = ''

                if y.isNull():
                    # Conversion was unsuccessful
                    selectionError = True
                    msg += self.tr(
                        'Enter the date and the date format, e.g. "07.26.2011" "MM.dd.yyyy".'
                    )

            if (comparison == 'begins with' or comparison == 'contains') \
               and selectType != QVariant.String:
                selectionError = True
                msg = self.tr('"%s" can only be used with string fields' %
                              comparison)

            selected = []

            if selectionError:
                raise GeoAlgorithmExecutionException(
                    self.tr('Error in selection input: %s' % msg))
            else:
                for feature in processLayer.getFeatures():
                    aValue = feature.attributes()[selectindex]

                    if aValue is None:
                        continue

                    if selectType in [
                            QVariant.Int, QVariant.LongLong, QVariant.UInt,
                            QVariant.ULongLong
                    ]:
                        x = int(aValue)
                    elif selectType == QVariant.Double:
                        x = float(aValue)
                    elif selectType == QVariant.String:
                        # 10: string, boolean
                        x = str(aValue)
                    elif selectType == QVariant.Date:
                        # date
                        x = aValue  # should be date

                    match = False

                    if comparison == '==':
                        match = x == y
                    elif comparison == '!=':
                        match = x != y
                    elif comparison == '>':
                        match = x > y
                    elif comparison == '>=':
                        match = x >= y
                    elif comparison == '<':
                        match = x < y
                    elif comparison == '<=':
                        match = x <= y
                    elif comparison == 'begins with':
                        match = x.startswith(y)
                    elif comparison == 'contains':
                        match = x.find(y) >= 0

                    if match:
                        selected.append(feature.id())

            processLayer.selectByIds(selected)

        if processLayer.selectedFeatureCount() == 0:
            ProcessingLog.addToLog(
                ProcessingLog.LOG_WARNING,
                self.tr('%s: (No selection in input layer "%s")' %
                        (self.commandLineName(),
                         self.getParameterValue(self.INPUT))))

        # Keep references to the features to eliminate
        featToEliminate = []
        for aFeat in processLayer.selectedFeatures():
            featToEliminate.append(aFeat)

        # Delete all features to eliminate in processLayer (we won't save this)
        processLayer.startEditing()
        processLayer.deleteSelectedFeatures()

        # ANALYZE
        if len(featToEliminate) > 0:  # Prevent zero division
            start = 20.00
            add = 80.00 / len(featToEliminate)
        else:
            start = 100

        feedback.setProgress(start)
        madeProgress = True

        # We go through the list and see if we find any polygons we can
        # merge the selected with. If we have no success with some we
        # merge and then restart the whole story.
        while madeProgress:  # Check if we made any progress
            madeProgress = False
            featNotEliminated = []

            # Iterate over the polygons to eliminate
            for i in range(len(featToEliminate)):
                feat = featToEliminate.pop()
                geom2Eliminate = feat.geometry()
                bbox = geom2Eliminate.boundingBox()
                fit = processLayer.getFeatures(
                    QgsFeatureRequest().setFilterRect(
                        bbox).setSubsetOfAttributes([]))
                mergeWithFid = None
                mergeWithGeom = None
                max = 0
                min = -1
                selFeat = QgsFeature()

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

                while fit.nextFeature(selFeat):
                    selGeom = selFeat.geometry()

                    if engine.intersects(selGeom.geometry()):
                        # We have a candidate
                        iGeom = geom2Eliminate.intersection(selGeom)

                        if not iGeom:
                            continue

                        if boundary:
                            selValue = iGeom.length()
                        else:
                            # area. We need a common boundary in
                            # order to merge
                            if 0 < iGeom.length():
                                selValue = selGeom.area()
                            else:
                                selValue = -1

                        if -1 != selValue:
                            useThis = True

                            if smallestArea:
                                if -1 == min:
                                    min = selValue
                                else:
                                    if selValue < min:
                                        min = selValue
                                    else:
                                        useThis = False
                            else:
                                if selValue > max:
                                    max = selValue
                                else:
                                    useThis = False

                            if useThis:
                                mergeWithFid = selFeat.id()
                                mergeWithGeom = QgsGeometry(selGeom)
                # End while fit

                if mergeWithFid is not None:
                    # A successful candidate
                    newGeom = mergeWithGeom.combine(geom2Eliminate)

                    if processLayer.changeGeometry(mergeWithFid, newGeom):
                        madeProgress = True
                    else:
                        raise GeoAlgorithmExecutionException(
                            self.
                            tr('Could not replace geometry of feature with id %s'
                               % mergeWithFid))

                    start = start + add
                    feedback.setProgress(start)
                else:
                    featNotEliminated.append(feat)

            # End for featToEliminate

            featToEliminate = featNotEliminated

        # End while

        # Create output
        output = self.getOutputFromName(self.OUTPUT)
        writer = output.getVectorWriter(processLayer.fields(),
                                        processLayer.wkbType(),
                                        processLayer.crs())

        # Write all features that are left over to output layer
        iterator = processLayer.getFeatures()
        for feature in iterator:
            writer.addFeature(feature)

        # Leave processLayer untouched
        processLayer.rollBack()

        for feature in featNotEliminated:
            writer.addFeature(feature)
Exemplo n.º 55
0
    def processAlgorithm(self, parameters, context, feedback):
        source = self.parameterAsSource(parameters, self.INPUT, context)
        proximity = self.parameterAsDouble(parameters, self.PROXIMITY, context)
        radius = self.parameterAsDouble(parameters, self.DISTANCE, context)
        horizontal = self.parameterAsBool(parameters, self.HORIZONTAL, context)

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

        features = source.getFeatures()

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

        def searchRect(p):
            return QgsRectangle(p.x() - proximity, p.y() - proximity, p.x() + proximity, p.y() + proximity)

        index = QgsSpatialIndex()

        # NOTE: this is a Python port of QgsPointDistanceRenderer::renderFeature. If refining this algorithm,
        # please port the changes to QgsPointDistanceRenderer::renderFeature also!

        clustered_groups = []
        group_index = {}
        group_locations = {}
        for current, f in enumerate(features):
            if feedback.isCanceled():
                break

            if not f.hasGeometry():
                continue

            point = f.geometry().asPoint()

            other_features_within_radius = index.intersects(searchRect(point))
            if not other_features_within_radius:
                index.insertFeature(f)
                group = [f]
                clustered_groups.append(group)
                group_index[f.id()] = len(clustered_groups) - 1
                group_locations[f.id()] = point
            else:
                # find group with closest location to this point (may be more than one within search tolerance)
                min_dist_feature_id = other_features_within_radius[0]
                min_dist = group_locations[min_dist_feature_id].distance(point)
                for i in range(1, len(other_features_within_radius)):
                    candidate_id = other_features_within_radius[i]
                    new_dist = group_locations[candidate_id].distance(point)
                    if new_dist < min_dist:
                        min_dist = new_dist
                        min_dist_feature_id = candidate_id

                group_index_pos = group_index[min_dist_feature_id]
                group = clustered_groups[group_index_pos]

                # calculate new centroid of group
                old_center = group_locations[min_dist_feature_id]
                group_locations[min_dist_feature_id] = QgsPointXY((old_center.x() * len(group) + point.x()) / (len(group) + 1.0),
                                                                  (old_center.y() * len(group) + point.y()) / (len(group) + 1.0))
                # add to a group
                clustered_groups[group_index_pos].append(f)
                group_index[f.id()] = group_index_pos

            feedback.setProgress(int(current * total))

        current = 0
        total = 100.0 / len(clustered_groups) if clustered_groups else 1
        feedback.setProgress(0)

        fullPerimeter = 2 * math.pi

        for group in clustered_groups:
            if feedback.isCanceled():
                break

            count = len(group)
            if count == 1:
                sink.addFeature(group[0], QgsFeatureSink.FastInsert)
            else:
                angleStep = fullPerimeter / count
                if count == 2 and horizontal:
                    currentAngle = math.pi / 2
                else:
                    currentAngle = 0

                old_point = group_locations[group[0].id()]

                for f in group:
                    if feedback.isCanceled():
                        break

                    sinusCurrentAngle = math.sin(currentAngle)
                    cosinusCurrentAngle = math.cos(currentAngle)
                    dx = radius * sinusCurrentAngle
                    dy = radius * cosinusCurrentAngle

                    # we want to keep any existing m/z values
                    point = f.geometry().geometry().clone()
                    point.setX(old_point.x() + dx)
                    point.setY(old_point.y() + dy)
                    f.setGeometry(QgsGeometry(point))

                    sink.addFeature(f, QgsFeatureSink.FastInsert)
                    currentAngle += angleStep

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

        return {self.OUTPUT: dest_id}
Exemplo n.º 56
0
    def processAlgorithm(self, parameters, 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 = 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)

        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, QgsFeatureSink.FastInsert)

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

        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, QgsFeatureSink.FastInsert)

        geom = geomLower.convexHull()
        feat.setGeometry(geom)
        feat['type'] = 'lower'
        feat['start'] = startPoint.toString()
        writer.addFeature(feat, QgsFeatureSink.FastInsert)
        del writer
Exemplo n.º 57
0
    def testGeopackageTwoLayerEdition(self):
        ''' test https://issues.qgis.org/issues/17034 '''
        tmpfile = os.path.join(self.basetestpath, 'testGeopackageTwoLayerEdition.gpkg')
        ds = ogr.GetDriverByName('GPKG').CreateDataSource(tmpfile)
        lyr = ds.CreateLayer('layer1', geom_type=ogr.wkbPoint)
        lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(0 0)'))
        lyr.CreateFeature(f)
        f = None
        lyr = ds.CreateLayer('layer2', geom_type=ogr.wkbPoint)
        lyr.CreateField(ogr.FieldDefn('attr', ogr.OFTInteger))
        f = ogr.Feature(lyr.GetLayerDefn())
        f.SetGeometry(ogr.CreateGeometryFromWkt('POINT(1 1)'))
        lyr.CreateFeature(f)
        f = None
        ds = None

        vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer1', u'ogr')
        vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer2", u'layer2', u'ogr')

        # Edit vl1, vl2 multiple times
        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl2.startEditing())
        self.assertTrue(vl1.changeGeometry(1, QgsGeometry.fromWkt('Point (2 2)')))
        self.assertTrue(vl2.changeGeometry(1, QgsGeometry.fromWkt('Point (3 3)')))
        self.assertTrue(vl1.commitChanges())
        self.assertTrue(vl2.commitChanges())

        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl2.startEditing())
        self.assertTrue(vl1.changeAttributeValue(1, 1, 100))
        self.assertTrue(vl2.changeAttributeValue(1, 1, 101))
        self.assertTrue(vl1.commitChanges())
        self.assertTrue(vl2.commitChanges())

        self.assertTrue(vl1.startEditing())
        self.assertTrue(vl2.startEditing())
        self.assertTrue(vl1.changeGeometry(1, QgsGeometry.fromWkt('Point (4 4)')))
        self.assertTrue(vl2.changeGeometry(1, QgsGeometry.fromWkt('Point (5 5)')))
        self.assertTrue(vl1.commitChanges())
        self.assertTrue(vl2.commitChanges())

        vl1 = None
        vl2 = None

        # Check everything is as expected after re-opening
        vl1 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer1", u'layer1', u'ogr')
        vl2 = QgsVectorLayer(u'{}'.format(tmpfile) + "|layername=layer2", u'layer2', u'ogr')

        got = [feat for feat in vl1.getFeatures()][0]
        got_geom = got.geometry()
        self.assertEqual(got['attr'], 100)
        reference = QgsGeometry.fromWkt('Point (4 4)')
        self.assertEqual(got_geom.asWkb(), reference.asWkb(), 'Expected {}, got {}'.format(reference.asWkt(), got_geom.asWkt()))

        got = [feat for feat in vl2.getFeatures()][0]
        got_geom = got.geometry()
        self.assertEqual(got['attr'], 101)
        reference = QgsGeometry.fromWkt('Point (5 5)')
        self.assertEqual(got_geom.asWkb(), reference.asWkb(), 'Expected {}, got {}'.format(reference.asWkt(), got_geom.asWkt()))
    def _get_compared_parcels_data(self, inverse=False):
        """
        inverse: By default False, which takes the collected db as base_db and the supplies_db as compare_db
                 Inverse True is useful to find missing parcels (from the supplies authority's perspective)

        :return: dict() --> {PARCEL_NUMBER: X,
                             PARCEL_ATTRIBUTES: {PARCEL_ID: [self._db.names.T_ID_F], PARCEL_STATUS: '', PARCEL_STATUS_DISPLAY: ''}]
        """
        base_db = self._supplies_db if inverse else self._db
        compare_db = self._db if inverse else self._supplies_db

        layer_modifiers = {
            LayerConfig.PREFIX_LAYER_MODIFIERS: LayerConfig.SUPPLIES_DB_PREFIX,
            LayerConfig.SUFFIX_LAYER_MODIFIERS: LayerConfig.SUPPLIES_DB_SUFFIX,
            LayerConfig.STYLE_GROUP_LAYER_MODIFIERS: Symbology().get_style_group_layer_modifiers(self._supplies_db.names)
        }

        if inverse:
            dict_collected_parcels = self.ladm_data.get_parcel_data_to_compare_changes_supplies(self._supplies_db, None)
            dict_supplies_parcels = self.ladm_data.get_parcel_data_to_compare_changes(self._db, None, layer_modifiers=layer_modifiers)
        else:
            dict_collected_parcels = self.ladm_data.get_parcel_data_to_compare_changes(self._db, None)
            dict_supplies_parcels = self.ladm_data.get_parcel_data_to_compare_changes_supplies(self._supplies_db, None, layer_modifiers=layer_modifiers)

        dict_compared_parcel_data = dict()
        for collected_parcel_number, collected_features in dict_collected_parcels.items():
            dict_attrs_comparison = dict()

            if not collected_parcel_number: # NULL parcel numbers
                dict_attrs_comparison[DICT_KEY_PARCEL_T_PARCEL_NUMBER_F] = NULL
                dict_attrs_comparison[base_db.names.T_ID_F] = [feature[base_db.names.T_ID_F] for feature in collected_features]
                dict_attrs_comparison[PARCEL_STATUS] = CHANGE_DETECTION_NULL_PARCEL
                dict_attrs_comparison[PARCEL_STATUS_DISPLAY] = "({})".format(len(collected_features))
            else:
                # A parcel number has at least one dict of attributes (i.e., one feature)
                dict_attrs_comparison[DICT_KEY_PARCEL_T_PARCEL_NUMBER_F] = collected_parcel_number
                dict_attrs_comparison[base_db.names.T_ID_F] = [feature[base_db.names.T_ID_F] for feature in collected_features]

                if len(collected_features) > 1:
                    dict_attrs_comparison[PARCEL_STATUS] = CHANGE_DETECTION_SEVERAL_PARCELS
                    dict_attrs_comparison[PARCEL_STATUS_DISPLAY] = "({})".format(len(collected_features))
                else:  # Only one feature, at this point is safe to call the first element ([0]) of the array
                    if not collected_parcel_number in dict_supplies_parcels:
                        dict_attrs_comparison[PARCEL_STATUS] = CHANGE_DETECTION_NEW_PARCEL
                        dict_attrs_comparison[PARCEL_STATUS_DISPLAY] = CHANGE_DETECTION_NEW_PARCEL
                    else:
                        supplies_features = dict_supplies_parcels[collected_parcel_number]

                        del collected_features[0][base_db.names.T_ID_F]  # We won't compare ID_FIELDS
                        del supplies_features[0][compare_db.names.T_ID_F]  # We won't compare ID_FIELDS

                        # Compare all attributes except geometry: a change in feature attrs is enough to mark it as
                        #   changed in the summary panel
                        if not self.compare_features_attrs(collected_features[0], supplies_features[0]):
                            dict_attrs_comparison[PARCEL_STATUS] = CHANGE_DETECTION_PARCEL_CHANGED
                            dict_attrs_comparison[PARCEL_STATUS_DISPLAY] = CHANGE_DETECTION_PARCEL_CHANGED
                        else:  # Attrs are equal, what about geometries?
                            collected_geometry = QgsGeometry()
                            supplies_geometry = QgsGeometry()
                            if PLOT_GEOMETRY_KEY in collected_features[0]:
                                collected_geometry = collected_features[0][PLOT_GEOMETRY_KEY]
                            if PLOT_GEOMETRY_KEY in supplies_features[0]:
                                supplies_geometry = supplies_features[0][PLOT_GEOMETRY_KEY]

                            if not self.compare_features_geometries(collected_geometry, supplies_geometry):
                                dict_attrs_comparison[PARCEL_STATUS] = CHANGE_DETECTION_PARCEL_ONLY_GEOMETRY_CHANGED
                                dict_attrs_comparison[PARCEL_STATUS_DISPLAY] = CHANGE_DETECTION_PARCEL_ONLY_GEOMETRY_CHANGED
                            else:  # Attrs and geometry are the same!
                                dict_attrs_comparison[PARCEL_STATUS] = CHANGE_DETECTION_PARCEL_REMAINS
                                dict_attrs_comparison[PARCEL_STATUS_DISPLAY] = CHANGE_DETECTION_PARCEL_REMAINS

            dict_compared_parcel_data[collected_parcel_number or NULL] = dict_attrs_comparison

        return dict_compared_parcel_data
Exemplo n.º 59
0
def buffering(feedback, context, sink, distance, field, useField, source, dissolve, segments, endCapStyle=1,
              joinStyle=1, miterLimit=2):

    if useField:
        field = source.fields().lookupField(field)

    outFeat = QgsFeature()

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

    # With dissolve
    if dissolve:
        attributes_to_fetch = []
        if useField:
            attributes_to_fetch.append(field)

        features = source.getFeatures(QgsFeatureRequest().setSubsetOfAttributes(attributes_to_fetch))
        buffered_geometries = []
        for inFeat in features:
            if feedback.isCanceled():
                break

            attrs = inFeat.attributes()
            if useField:
                value = attrs[field]
            else:
                value = distance

            inGeom = inFeat.geometry()

            buffered_geometries.append(inGeom.buffer(float(value), segments, endCapStyle, joinStyle, miterLimit))

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

        final_geometry = QgsGeometry.unaryUnion(buffered_geometries)
        outFeat.setGeometry(final_geometry)
        outFeat.setAttributes(attrs)
        sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
    else:

        features = source.getFeatures()

        # Without dissolve
        for inFeat in features:
            if feedback.isCanceled():
                break
            attrs = inFeat.attributes()
            if useField:
                value = attrs[field]
            else:
                value = distance
            inGeom = inFeat.geometry()
            outFeat = QgsFeature()
            outGeom = inGeom.buffer(float(value), segments, endCapStyle, joinStyle, miterLimit)
            outFeat.setGeometry(outGeom)
            outFeat.setAttributes(attrs)
            sink.addFeature(outFeat, QgsFeatureSink.FastInsert)
            current += 1
            feedback.setProgress(int(current * total))
Exemplo n.º 60
-1
    def testInsertPolygonInMultiPolygon(self):
        layer = QgsVectorLayer("MultiPolygon?crs=epsg:4326&field=id:integer", "addfeat", "memory")
        pr = layer.dataProvider()
        f = QgsFeature()
        f.setAttributes([1])
        f.setGeometry(QgsGeometry.fromWkt('MultiPolygon(((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))'))
        pr.addFeatures([f])

        uri = '{} table="qgis_test"."new_table_multipolygon" sql='.format(self.dbconn)
        error, message = QgsVectorLayerExporter.exportLayer(layer, uri, 'mssql', QgsCoordinateReferenceSystem('EPSG:4326'))
        self.assertEqual(error, QgsVectorLayerExporter.NoError)

        new_layer = QgsVectorLayer(uri, 'new', 'mssql')
        self.assertTrue(new_layer.isValid())
        self.assertEqual(new_layer.wkbType(), QgsWkbTypes.MultiPolygon)
        geom = [f.geometry().asWkt() for f in new_layer.getFeatures()]
        self.assertEqual(geom, ['MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))'])

        # add single part
        f2 = QgsFeature()
        f2.setAttributes([2])
        f2.setGeometry(QgsGeometry.fromWkt('Polygon((30 0, 31 0, 31 1, 30 1, 30 0))'))
        self.assertTrue(new_layer.dataProvider().addFeatures([f2]))

        # should become multipart
        geom = [f.geometry().asWkt() for f in new_layer.getFeatures()]
        self.assertEqual(geom, ['MultiPolygon (((0 0, 1 0, 1 1, 0 1, 0 0)),((10 0, 11 0, 11 1, 10 1, 10 0)))', 'MultiPolygon (((30 0, 31 0, 31 1, 30 1, 30 0)))'])