[QGIS-Developer] get all the features of a specific layer which are visible in the viewport
Jorge Gustavo Rocha
jgr at di.uminho.pt
Sun Jan 19 07:36:27 PST 2020
Hi Jo,
You can use setFilterRect (see
https://docs.qgis.org/3.4/en/docs/pyqgis_developer_cookbook/vector.html).
request = QgsFeatureRequest().setFilterRect(iface.mapCanvas().extent())
for feature in layer.getFeatures(request):
print(feature.id)
This way, you only iterate over the visible features.
Regards,
Jorge Gustavo
On 18/01/20 20:39, Jo wrote:
> 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
>
>
> _______________________________________________
> QGIS-Developer mailing list
> QGIS-Developer at lists.osgeo.org
> List info: https://lists.osgeo.org/mailman/listinfo/qgis-developer
> Unsubscribe: https://lists.osgeo.org/mailman/listinfo/qgis-developer
>
J. Gustavo
--
Jorge Gustavo Rocha
Departamento de Informática
Universidade do Minho
4710-057 Braga
Gabinete 3.29 (Piso 3)
Tel: +351 253604480
Fax: +351 253604471
Móvel: +351 910333888
skype: nabocudnosor
More information about the QGIS-Developer
mailing list