Skip to content
Permalink
Browse files

Add mechanism to defer updates of rubber bands when adding multiple

geometries

GREATLY speeds up rubber band creation for many geometries, resulting
in consequent speed ups to the move features tool, rotate features tool,
....
  • Loading branch information
nyalldawson committed Feb 22, 2021
1 parent 67c2263 commit 7b37f32b4f83d4c6e1a7c689a34ce660e074b4dc
@@ -273,26 +273,33 @@ Sets this rubber band to a map canvas rectangle
:param rect: rectangle in canvas coordinates
%End

void addGeometry( const QgsGeometry &geometry, QgsVectorLayer *layer );
void addGeometry( const QgsGeometry &geometry, QgsVectorLayer *layer, bool doUpdate = true );
%Docstring
Adds the geometry of an existing feature to a rubberband
This is useful for multi feature highlighting.
As of 2.0, this method does not change the GeometryType any more. You need to set the GeometryType
of the rubberband explicitly by calling :py:func:`~QgsRubberBand.reset` or :py:func:`~QgsRubberBand.setToGeometry` with appropriate arguments.
:py:func:`~QgsRubberBand.setToGeometry` is also to be preferred for backwards-compatibility.

If additional geometries are to be added then set ``doUpdate`` to ``False`` to defer costly repaint and bounding rectangle calculations for better performance.
After adding the final geometry :py:func:`~QgsRubberBand.updatePosition` should be called.

:param geometry: the geometry object. Will be treated as a collection of vertices.
:param layer: the layer containing the feature, used for coord transformation to map
crs. If ``layer`` is ``None``, the coordinates are not going to be transformed.
:param doUpdate: set to ``False`` to defer updates of the rubber band.
%End

void addGeometry( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
void addGeometry( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem(), bool doUpdate = true );
%Docstring
Adds a ``geometry`` to the rubberband.

If ``crs`` is specified, the geometry will be automatically reprojected from ``crs``
to the canvas CRS.

If additional geometries are to be added then set ``doUpdate`` to ``False`` to defer costly repaint and bounding rectangle calculations for better performance.
After adding the final geometry :py:func:`~QgsRubberBand.updatePosition` should be called.

.. versionadded:: 3.0
%End

@@ -138,11 +138,13 @@ void QgsMapToolMoveFeature::cadCanvasReleaseEvent( QgsMapMouseEvent *e )

while ( it.nextFeature( feat ) )
{
mRubberBand->addGeometry( feat.geometry(), vlayer );
mRubberBand->addGeometry( feat.geometry(), vlayer, false );

if ( allFeaturesInView && !viewRect.intersects( feat.geometry().boundingBox() ) )
allFeaturesInView = false;
}
mRubberBand->updatePosition();
mRubberBand->update();

if ( !allFeaturesInView )
{
@@ -304,8 +304,10 @@ void QgsMapToolRotateFeature::canvasReleaseEvent( QgsMapMouseEvent *e )
QgsFeatureIterator it = vlayer->getSelectedFeatures();
while ( it.nextFeature( feat ) )
{
mRubberBand->addGeometry( feat.geometry(), vlayer );
mRubberBand->addGeometry( feat.geometry(), vlayer, false );
}
mRubberBand->updatePosition();
mRubberBand->update();
}

mRubberBand->show();
@@ -266,9 +266,11 @@ void QgsMapToolScaleFeature::canvasReleaseEvent( QgsMapMouseEvent *e )
QgsFeatureIterator it = vlayer->getSelectedFeatures();
while ( it.nextFeature( feat ) )
{
mRubberBand->addGeometry( feat.geometry(), vlayer );
mRubberBand->addGeometry( feat.geometry(), vlayer, false );
mOriginalGeometries << feat.geometry();
}
mRubberBand->updatePosition();
mRubberBand->update();
}

mScalingActive = true;
@@ -1624,7 +1624,9 @@ void QgsMapCanvas::flashGeometries( const QList<QgsGeometry> &geometries, const
QgsWkbTypes::GeometryType geomType = QgsWkbTypes::geometryType( geometries.at( 0 ).wkbType() );
QgsRubberBand *rb = new QgsRubberBand( this, geomType );
for ( const QgsGeometry &geom : geometries )
rb->addGeometry( geom, crs );
rb->addGeometry( geom, crs, false );
rb->updatePosition();
rb->update();

if ( geomType == QgsWkbTypes::LineGeometry || geomType == QgsWkbTypes::PointGeometry )
{
@@ -276,7 +276,7 @@ void QgsRubberBand::setToGeometry( const QgsGeometry &geom, const QgsCoordinateR
addGeometry( geom, crs );
}

void QgsRubberBand::addGeometry( const QgsGeometry &geometry, QgsVectorLayer *layer )
void QgsRubberBand::addGeometry( const QgsGeometry &geometry, QgsVectorLayer *layer, bool doUpdate )
{
QgsGeometry geom = geometry;
if ( layer )
@@ -292,10 +292,10 @@ void QgsRubberBand::addGeometry( const QgsGeometry &geometry, QgsVectorLayer *la
}
}

addGeometry( geom );
addGeometry( geom, QgsCoordinateReferenceSystem(), doUpdate );
}

void QgsRubberBand::addGeometry( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &crs )
void QgsRubberBand::addGeometry( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &crs, bool doUpdate )
{
if ( geometry.isEmpty() )
{
@@ -394,8 +394,11 @@ void QgsRubberBand::addGeometry( const QgsGeometry &geometry, const QgsCoordinat
}

setVisible( true );
updateRect();
update();
if ( doUpdate )
{
updateRect();
update();
}
}

void QgsRubberBand::setToCanvasRectangle( QRect rect )
@@ -324,21 +324,28 @@ class GUI_EXPORT QgsRubberBand : public QgsMapCanvasItem
* of the rubberband explicitly by calling reset() or setToGeometry() with appropriate arguments.
* setToGeometry() is also to be preferred for backwards-compatibility.
*
* If additional geometries are to be added then set \a doUpdate to FALSE to defer costly repaint and bounding rectangle calculations for better performance.
* After adding the final geometry updatePosition() should be called.
*
* \param geometry the geometry object. Will be treated as a collection of vertices.
* \param layer the layer containing the feature, used for coord transformation to map
* crs. If \a layer is NULLPTR, the coordinates are not going to be transformed.
* \param doUpdate set to FALSE to defer updates of the rubber band.
*/
void addGeometry( const QgsGeometry &geometry, QgsVectorLayer *layer );
void addGeometry( const QgsGeometry &geometry, QgsVectorLayer *layer, bool doUpdate = true );

/**
* Adds a \a geometry to the rubberband.
*
* If \a crs is specified, the geometry will be automatically reprojected from \a crs
* to the canvas CRS.
*
* If additional geometries are to be added then set \a doUpdate to FALSE to defer costly repaint and bounding rectangle calculations for better performance.
* After adding the final geometry updatePosition() should be called.
*
* \since QGIS 3.0
*/
void addGeometry( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() );
void addGeometry( const QgsGeometry &geometry, const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem(), bool doUpdate = true );

/**
* Adds translation to original coordinates (all in map coordinates)

0 comments on commit 7b37f32

Please sign in to comment.