[QGIS-Developer] get all the features of a specific layer which are visible in the viewport

Jo winfixit at gmail.com
Sat Jan 18 12:39:04 PST 2020


Hi,

I created the following code:

class FBSegmentPoiComboBox(FBComboBox):
    def __init__(self, name, identifier=None, update_method=None, iface=None):
        super().__init__(name=name, identifier=identifier,
update_method=update_method)
        self.iface = iface
        self.items_list = []
        self.find_segments()
        self.rubber_band = QgsRubberBand(self.iface.mapCanvas(), False)
        self.rubber_band.setWidth(12)
        self.rubber_band.setStrokeColor(QColor.fromRgb(90, 0, 20))
        self.highlighted.connect(self.highlight_segment)
        self.currentIndexChanged.connect(self.clear_rubberband)

    def find_segments(self):
        self.clear()
        self.add_item(REFRESH_SEGMENTS_LIST, None)
        # put a dummy at position 0
        self.items_list = ['dummy']
        segment_layer_list = QgsProject.instance().mapLayersByName('segment')
        if segment_layer_list:
            segment_layer = segment_layer_list[0]
            layer =
QgsProject.instance().layerTreeRoot().findLayer(segment_layer)
            if layer:
                layer.setItemVisibilityChecked(True)
            if self.iface:
                segments = QgsSpatialIndex()
                for segment in segment_layer.getFeatures():
                    segments.insertFeature(segment)
                nearby =
segments.nearestNeighbor(self.iface.mapCanvas().center(),
neighbors=10) # , maxDistance=1000)
                for featureId in nearby:
                    fit2 =
segment_layer.getFeatures(QgsFeatureRequest().setFilterFid(featureId))
                    ftr = QgsFeature()
                    fit2.nextFeature(ftr)
                    self.add_item(ftr.attribute(0), ftr.attribute(0))
                    self.items_list.append(ftr)
        self.changed = False

    def highlight_segment(self, index):
        self.rubber_band.reset()
        if index == 0:
            self.find_segments()
        elif index < len(self.items_list):
            self.rubber_band.setToGeometry(self.items_list[index].geometry())

    def clear_rubberband(self, index):
        self.rubber_band.reset()


It populates a drop down with all the LineStrings near to the center
of the screen.

It's not very efficient though, as I need to first pass all the
LineStrings on that particular layer to it.

Is there a way to replace this code:

                for segment in segment_layer.getFeatures():
                    segments.insertFeature(segment)

So it only works on a smaller subset of features that are actually
visible to on the user's screen?

Jo
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osgeo.org/pipermail/qgis-developer/attachments/20200118/55190790/attachment.html>


More information about the QGIS-Developer mailing list