Example #1
0
    def testGetFeatures(self):
        """ Test that expected results are returned when fetching all features """

        # IMPORTANT - we do not use `for f in provider.getFeatures()` as we are also
        # testing that existing attributes & geometry in f are overwritten correctly
        # (for f in ... uses a new QgsFeature for every iteration)

        it = self.provider.getFeatures()
        f = QgsFeature()
        attributes = {}
        geometries = {}
        while it.nextFeature(f):
            # expect feature to be valid
            self.assertTrue(f.isValid())
            # split off the first 5 attributes only - some provider test datasets will include
            # additional attributes which we ignore
            attrs = f.attributes()[0:5]
            # force the num_char attribute to be text - some providers (eg delimited text) will
            # automatically detect that this attribute contains numbers and set it as a numeric
            # field
            attrs[4] = str(attrs[4])
            attributes[f['pk']] = attrs
            geometries[f['pk']] = f.constGeometry() and f.constGeometry(
            ).exportToWkt()

        expected_attributes = {
            5: [5, -200, NULL, 'NuLl', '5'],
            3: [3, 300, 'Pear', 'PEaR', '3'],
            1: [1, 100, 'Orange', 'oranGe', '1'],
            2: [2, 200, 'Apple', 'Apple', '2'],
            4: [4, 400, 'Honey', 'Honey', '4']
        }
        self.assertEqual(
            attributes, expected_attributes,
            'Expected {}, got {}'.format(expected_attributes, attributes))

        expected_geometries = {
            1: 'Point (-70.332 66.33)',
            2: 'Point (-68.2 70.8)',
            3: None,
            4: 'Point(-65.32 78.3)',
            5: 'Point(-71.123 78.23)'
        }
        for pk, geom in expected_geometries.items():
            if geom:
                assert compareWkt(
                    geom, geometries[pk]
                ), "Geometry {} mismatch Expected:\n{}\nGot:\n{}\n".format(
                    pk, geom, geometries[pk].exportToWkt())
            else:
                self.assertFalse(geometries[pk],
                                 'Expected null geometry for {}'.format(pk))
Example #2
0
    def poly2nb(self):
        lst = []

        index = QgsSpatialIndex()
        featsA = self.lyr.getFeatures()
        featsB = self.lyr.getFeatures()
        for ft in featsA:
            index.insertFeature(ft)

        featB = QgsFeature()
        prv = self.lyr.dataProvider()
        while featsB.nextFeature(featB):
            geomB = featB.constGeometry()
            idb = featB.id()
            idxs = index.intersects(geomB.boundingBox())
            sor = []
            for idx in idxs:
                rqst = QgsFeatureRequest().setFilterFid(idx)
                featA = prv.getFeatures(rqst).next()
                ida = featA.id()
                geomA = QgsGeometry(featA.geometry())
                if idb!=ida:
                    if geomB.touches(geomA)==True:
                        sor.append(ida)

            lst.append(sor)

        return lst
Example #3
0
    def nbCalc(self):
        lsta = []
        lstb = []

        index = QgsSpatialIndex()
        featsA = self.lyr.getFeatures()
        featsB = self.lyr.getFeatures()
        for ft in featsA:
            index.insertFeature(ft)

        featB = QgsFeature()
        prv = self.lyr.dataProvider()
        while featsB.nextFeature(featB):
            geomB = featB.constGeometry()
            idb = featB.id()
            idxs = index.intersects(geomB.boundingBox())
            for idx in idxs:
                rqst = QgsFeatureRequest().setFilterFid(idx)
                featA = prv.getFeatures(rqst).next()
                ida = featA.id()
                geomA = QgsGeometry(featA.geometry())
                if idb>ida:
                    if geomB.touches(geomA)==True:
                        lsta.append(idb)
                        lstb.append(ida)
                        # self.plainTextEdit.insertPlainText('%s - %s\n' % (idb, ida))

        lstc = [lsta, lstb]
        return lstc
Example #4
0
    def testGetFeatures(self):
        """ Test that expected results are returned when fetching all features """

        # IMPORTANT - we do not use `for f in provider.getFeatures()` as we are also
        # testing that existing attributes & geometry in f are overwritten correctly
        # (for f in ... uses a new QgsFeature for every iteration)

        it = self.provider.getFeatures()
        f = QgsFeature()
        attributes = {}
        geometries = {}
        while it.nextFeature(f):
            # expect feature to be valid
            self.assertTrue(f.isValid())
            # split off the first 5 attributes only - some provider test datasets will include
            # additional attributes which we ignore
            attrs = f.attributes()[0:5]
            # force the num_char attribute to be text - some providers (eg delimited text) will
            # automatically detect that this attribute contains numbers and set it as a numeric
            # field
            attrs[4] = str(attrs[4])
            attributes[f["pk"]] = attrs
            geometries[f["pk"]] = f.constGeometry() and f.constGeometry().exportToWkt()

        expected_attributes = {
            5: [5, -200, NULL, "NuLl", "5"],
            3: [3, 300, "Pear", "PEaR", "3"],
            1: [1, 100, "Orange", "oranGe", "1"],
            2: [2, 200, "Apple", "Apple", "2"],
            4: [4, 400, "Honey", "Honey", "4"],
        }
        self.assertEqual(attributes, expected_attributes, "Expected {}, got {}".format(expected_attributes, attributes))

        expected_geometries = {
            1: "Point (-70.332 66.33)",
            2: "Point (-68.2 70.8)",
            3: None,
            4: "Point(-65.32 78.3)",
            5: "Point(-71.123 78.23)",
        }
        for pk, geom in expected_geometries.items():
            if geom:
                assert compareWkt(geom, geometries[pk]), "Geometry {} mismatch Expected:\n{}\nGot:\n{}\n".format(
                    pk, geom, geometries[pk].exportToWkt()
                )
            else:
                self.assertFalse(geometries[pk], "Expected null geometry for {}".format(pk))
    def layerData(self, layer, request={}, offset=0):
        # Retrieve the data for a layer
        first = True
        data = {}
        fields = []
        fieldTypes = []
        fr = QgsFeatureRequest()
        if request:
            if 'exact' in request and request['exact']:
                fr.setFlags(QgsFeatureRequest.ExactIntersect)
            if 'nogeom' in request and request['nogeom']:
                fr.setFlags(QgsFeatureRequest.NoGeometry)
            if 'fid' in request:
                fr.setFilterFid(request['fid'])
            elif 'extents' in request:
                fr.setFilterRect(QgsRectangle(*request['extents']))
            if 'attributes' in request:
                fr.setSubsetOfAttributes(request['attributes'])

        # IMPORTANT - we do not use `for f in layer.getFeatures(fr):` as we need
        # to verify that existing attributes and geometry are correctly cleared
        # from the feature when calling nextFeature()
        it = layer.getFeatures(fr)
        f = QgsFeature()
        while it.nextFeature(f):
            if first:
                first = False
                for field in f.fields():
                    fields.append(str(field.name()))
                    fieldTypes.append(str(field.typeName()))
            if sys.version_info.major == 2:
                fielddata = dict((name, unicode(f[name])) for name in fields)
            else:
                fielddata = dict((name, str(f[name])) for name in fields)
            g = f.constGeometry()
            if g:
                fielddata[geomkey] = str(g.exportToWkt())
            else:
                fielddata[geomkey] = "None"

            fielddata[fidkey] = f.id()
            id = fielddata[fields[0]]
            description = fielddata[fields[1]]
            fielddata['id'] = id
            fielddata['description'] = description
            data[f.id() + offset] = fielddata

        if 'id' not in fields:
            fields.insert(0, 'id')
        if 'description' not in fields:
            fields.insert(1, 'description')
        fields.append(fidkey)
        fields.append(geomkey)
        return fields, fieldTypes, data
Example #6
0
    def layerData(self, layer, request={}, offset=0):
        # Retrieve the data for a layer
        first = True
        data = {}
        fields = []
        fieldTypes = []
        fr = QgsFeatureRequest()
        if request:
            if "exact" in request and request["exact"]:
                fr.setFlags(QgsFeatureRequest.ExactIntersect)
            if "nogeom" in request and request["nogeom"]:
                fr.setFlags(QgsFeatureRequest.NoGeometry)
            if "fid" in request:
                fr.setFilterFid(request["fid"])
            elif "extents" in request:
                fr.setFilterRect(QgsRectangle(*request["extents"]))
            if "attributes" in request:
                fr.setSubsetOfAttributes(request["attributes"])

        # IMPORTANT - we do not use `for f in layer.getFeatures(fr):` as we need
        # to verify that existing attributes and geometry are correctly cleared
        # from the feature when calling nextFeature()
        it = layer.getFeatures(fr)
        f = QgsFeature()
        while it.nextFeature(f):
            if first:
                first = False
                for field in f.fields():
                    fields.append(str(field.name()))
                    fieldTypes.append(str(field.typeName()))
            if sys.version_info.major == 2:
                fielddata = dict((name, unicode(f[name])) for name in fields)
            else:
                fielddata = dict((name, str(f[name])) for name in fields)
            g = f.constGeometry()
            if g:
                fielddata[geomkey] = str(g.exportToWkt())
            else:
                fielddata[geomkey] = "None"

            fielddata[fidkey] = f.id()
            id = fielddata[fields[0]]
            description = fielddata[fields[1]]
            fielddata["id"] = id
            fielddata["description"] = description
            data[f.id() + offset] = fielddata

        if "id" not in fields:
            fields.insert(0, "id")
        if "description" not in fields:
            fields.insert(1, "description")
        fields.append(fidkey)
        fields.append(geomkey)
        return fields, fieldTypes, data
Example #7
0
class FeatureHighlightItem(QgsMapCanvasItem):
    # Code ported from QGIS QgsHighlight

    def __init__(self, mapCanvas, feature, layer):
        super(FeatureHighlightItem, self).__init__(mapCanvas)

        self._mapCanvas = None  # QgsMapCanvas
        self._brush = QBrush()
        self._pen = QPen()
        self._feature = None  # QgsFeature()
        self._layer = None  # QgsMapLayer()
        self._buffer = 0.0
        self._minWidth = 0.0

        self._mapCanvas = mapCanvas
        if (not layer or not feature or not isinstance(feature, QgsFeature)
                or not feature.geometry() or feature.geometry().isEmpty()
                or not feature.geometry().isGeosValid()):
            return
        self._feature = QgsFeature(feature)  # Force deep copy
        self._layer = layer
        self.setLineColor(Application.highlightLineColor())
        self.setFillColor(Application.highlightFillColor())
        self._minWidth = Application.highlightMinimumWidth()
        self._buffer = Application.highlightBuffer()
        if self._mapCanvas.mapSettings().hasCrsTransformEnabled():
            ct = self._mapCanvas.mapSettings().layerTransform(self._layer)
            if ct:
                self._feature.geometry().transform(ct)
        self.updateRect()
        self.update()

    def remove(self):
        self._mapCanvas.scene().removeItem(self)

    def setLineWidth(self, width):
        self._pen.setWidth(width)

    def setLineColor(self, color):
        self._pen.setColor(color)

    def setFillColor(self, fillColor):
        self._brush.setColor(fillColor)
        self._brush.setStyle(Qt.SolidPattern)

    def setBuffer(self, buff):
        self._buffer = buff

    def setMinWidth(self, width):
        self._minWidth = width

    def layer(self):
        return self._layer

    def updatePosition(self):
        pass

    # protected:
    def paint(self, painter, option=None, widget=None):  # Override
        if not self._feature:
            return

        mapSettings = self._mapCanvas.mapSettings()
        context = QgsRenderContext.fromMapSettings(mapSettings)
        renderer = self._getRenderer(context, self._pen.color(),
                                     self._brush.color())

        if renderer:
            context.setPainter(painter)
            renderer.startRender(context, self._layer.fields())
            renderer.renderFeature(self._feature, context)
            renderer.stopRender(context)

    def updateRect(self):
        if self._feature and self._feature.constGeometry():
            m2p = self._mapCanvas.mapSettings().mapToPixel()
            topLeft = m2p.toMapPoint(0, 0)
            res = m2p.mapUnitsPerPixel()
            imageSize = self._mapCanvas.mapSettings().outputSize()
            rect = QgsRectangle(topLeft.x(), topLeft.y(),
                                topLeft.x() + imageSize.width() * res,
                                topLeft.y() - imageSize.height() * res)
            self.setRect(rect)
            self.setVisible(True)
        else:
            self.setRect(QgsRectangle())

    # private:
    def _setSymbol(self, symbol, context, color, fillColor):
        if not symbol:
            return

        for symbolLayer in reversed(symbol.symbolLayers()):
            if symbolLayer:
                if symbolLayer.subSymbol():
                    self._setSymbol(symbolLayer.subSymbol(), context, color,
                                    fillColor)
                else:
                    symbolLayer.setColor(color)
                    symbolLayer.setOutlineColor(color)
                    symbolLayer.setFillColor(fillColor)
                    if isinstance(symbolLayer, QgsSimpleMarkerSymbolLayerV2):
                        symbolLayer.setOutlineWidth(
                            self._getSymbolWidth(
                                context, symbolLayer.outlineWidth(),
                                symbolLayer.outlineWidthUnit()))
                    if symbolLayer.type() == QgsSymbolV2.Line:
                        symbolLayer.setWidth(
                            self._getSymbolWidth(context, symbolLayer.width(),
                                                 symbolLayer.widthUnit()))
                    if symbolLayer.type() == QgsSymbolV2.Fill:
                        symbolLayer.setBorderWidth(
                            self._getSymbolWidth(context,
                                                 symbolLayer.borderWidth(),
                                                 symbolLayer.outputUnit()))
                    symbolLayer.removeDataDefinedProperty('color')
                    symbolLayer.removeDataDefinedProperty('color_border')

    def _getSymbolWidth(self, context, width, unit):
        scale = 1.0
        if unit == QgsSymbolV2.MapUnit:
            scale = QgsSymbolLayerV2Utils.lineWidthScaleFactor(
                context,
                QgsSymbolV2.MM) / QgsSymbolLayerV2Utils.lineWidthScaleFactor(
                    context, QgsSymbolV2.MapUnit)
        width = max(width + 2 * self._buffer * scale, self._minWidth * scale)
        return width

    def _getRenderer(self, context, color, fillColor):
        renderer = None
        if self._layer and self._layer.rendererV2():
            renderer = self._layer.rendererV2().clone()
        if renderer:
            for symbol in renderer.symbols2(context):
                self._setSymbol(symbol, context, color, fillColor)
        return renderer
Example #8
0
class FeatureHighlight(QgsMapCanvasItem):

    _mapCanvas = None  # QgsMapCanvas
    _brush = QBrush()
    _pen = QPen()
    _feature = None  # QgsFeature()
    _layer = None  # QgsMapLayer()
    _buffer = 0.0
    _minWidth = 0.0

    def __init__(self, mapCanvas, feature, layer):
        super(FeatureHighlight, self).__init__(mapCanvas)
        self._mapCanvas = mapCanvas
        if not layer or not feature or not isinstance(feature, QgsFeature) or not feature.geometry() or feature.geometry().isEmpty() or not feature.geometry().isGeosValid():
            return
        self._feature = QgsFeature(feature) # Force deep copy
        self._layer = layer
        self.setLineColor(Project.highlightLineColor())
        self.setFillColor(Project.highlightFillColor())
        self._minWidth = Project.highlightMinimumWidth()
        self._buffer = Project.highlightBuffer()
        if self._mapCanvas.mapSettings().hasCrsTransformEnabled():
            ct = self._mapCanvas.mapSettings().layerTransform(self._layer)
            if ct:
                self._feature.geometry().transform(ct)
        self.updateRect()
        self.update()

    def remove(self):
        self._mapCanvas.scene().removeItem(self)

    def setLineWidth(self, width):
        self._pen.setWidth(width)

    def setLineColor(self, color):
        self._pen.setColor(color)

    def setFillColor(self, fillColor):
        self._brush.setColor(fillColor)
        self._brush.setStyle(Qt.SolidPattern)

    def setBuffer(self, buff):
        self._buffer = buff

    def setMinWidth(self, width):
        self._minWidth = width

    def layer(self):
        return self._layer

    def updatePosition(self):
        pass

    # protected:
    def paint(self, painter, option=None, widget=None): # Override
        if not self._feature:
            return

        mapSettings = self._mapCanvas.mapSettings()
        context = QgsRenderContext.fromMapSettings(mapSettings)
        renderer = self._getRenderer(context, self._pen.color(), self._brush.color())

        if renderer:
            context.setPainter(painter)
            renderer.startRender(context, self._layer.fields())
            renderer.renderFeature(self._feature, context)
            renderer.stopRender(context)

    def updateRect(self):
        if self._feature and self._feature.constGeometry():
            m2p = self._mapCanvas.mapSettings().mapToPixel()
            topLeft = m2p.toMapPoint(0, 0)
            res = m2p.mapUnitsPerPixel()
            imageSize = self._mapCanvas.mapSettings().outputSize()
            rect = QgsRectangle(topLeft.x(), topLeft.y(),topLeft.x() + imageSize.width()*res, topLeft.y() - imageSize.height()*res)
            self.setRect(rect)
            self.setVisible(True)
        else:
            self.setRect(QgsRectangle())

    # private:
    def _setSymbol(self, symbol, context, color, fillColor):
        if  not symbol:
            return

        for symbolLayer in reversed(symbol.symbolLayers()):
            if symbolLayer:
                if symbolLayer.subSymbol():
                    self._setSymbol(symbolLayer.subSymbol(), context, color, fillColor)
                else:
                    symbolLayer.setColor(color)
                    symbolLayer.setOutlineColor(color)
                    symbolLayer.setFillColor(fillColor)
                    if isinstance(symbolLayer, QgsSimpleMarkerSymbolLayerV2):
                        symbolLayer.setOutlineWidth(self._getSymbolWidth(context, symbolLayer.outlineWidth(), symbolLayer.outlineWidthUnit()))
                    if symbolLayer.type() == QgsSymbolV2.Line:
                        symbolLayer.setWidth(self._getSymbolWidth(context, symbolLayer.width(), symbolLayer.widthUnit()))
                    if symbolLayer.type() == QgsSymbolV2.Fill:
                        symbolLayer.setBorderWidth(self._getSymbolWidth(context, symbolLayer.borderWidth(), symbolLayer.outputUnit()))
                    symbolLayer.removeDataDefinedProperty('color')
                    symbolLayer.removeDataDefinedProperty('color_border')

    def _getSymbolWidth(self, context, width, unit):
        scale = 1.0
        if unit == QgsSymbolV2.MapUnit:
            scale = QgsSymbolLayerV2Utils.lineWidthScaleFactor(context, QgsSymbolV2.MM) / QgsSymbolLayerV2Utils.lineWidthScaleFactor(context, QgsSymbolV2.MapUnit)
        width =  max(width + 2 * self._buffer * scale, self._minWidth * scale)
        return width

    def _getRenderer(self, context, color, fillColor):
        renderer = None
        if self._layer and self._layer.rendererV2():
            renderer = self._layer.rendererV2().clone()
        if renderer:
            for symbol in renderer.symbols2(context):
                self._setSymbol(symbol, context, color, fillColor)
        return renderer