Skip to content

Commit

Permalink
[layouts] Fix attribute table filtering to items within atlas feature
Browse files Browse the repository at this point in the history
when atlas feature has a different CRS to table layer

And greatly improve performance when using an attribute table
filtered to the atlas feature

(cherry picked from commit 3cad7ed)
  • Loading branch information
nyalldawson committed Jun 10, 2019
1 parent 2e6025f commit 2b75a27
Show file tree
Hide file tree
Showing 2 changed files with 88 additions and 7 deletions.
33 changes: 26 additions & 7 deletions src/core/layout/qgslayoutitemattributetable.cpp
Expand Up @@ -449,6 +449,27 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont
visibleMapEngine->prepareGeometry();
}

QgsGeometry atlasGeometry;
std::unique_ptr< QgsGeometryEngine > atlasGeometryEngine;
if ( mFilterToAtlasIntersection )
{
atlasGeometry = mLayout->reportContext().currentGeometry( layer->crs() );
if ( !atlasGeometry.isNull() )
{
if ( selectionRect.isNull() )
{
selectionRect = atlasGeometry.boundingBox();
}
else
{
selectionRect = selectionRect.intersect( atlasGeometry.boundingBox() );
}

atlasGeometryEngine.reset( QgsGeometry::createGeometryEngine( atlasGeometry.constGet() ) );
atlasGeometryEngine->prepareGeometry();
}
}

if ( mSource == QgsLayoutItemAttributeTable::RelationChildren )
{
QgsRelation relation = mLayout->project()->relationManager()->relation( mRelationId );
Expand Down Expand Up @@ -499,20 +520,17 @@ bool QgsLayoutItemAttributeTable::getTableContents( QgsLayoutTableContents &cont
//check against atlas feature intersection
if ( mFilterToAtlasIntersection )
{
if ( !f.hasGeometry() )
if ( !f.hasGeometry() || !atlasGeometryEngine )
{
continue;
}
QgsFeature atlasFeature = mLayout->reportContext().feature();
if ( !atlasFeature.hasGeometry() ||
!f.geometry().intersects( atlasFeature.geometry() ) )
{
//feature falls outside current atlas feature

if ( !atlasGeometryEngine->intersects( f.geometry().constGet() ) )
continue;
}
}

QgsLayoutTableRow currentRow;
currentRow.reserve( mColumns.count() );

for ( QgsLayoutTableColumn *column : qgis::as_const( mColumns ) )
{
Expand Down Expand Up @@ -673,6 +691,7 @@ QVector<QPair<int, bool> > QgsLayoutItemAttributeTable::sortAttributes() const

//generate list of column index, bool for sort direction (to match 2.0 api)
QVector<QPair<int, bool> > attributesBySortRank;
attributesBySortRank.reserve( sortedColumns.size() );
for ( auto &column : qgis::as_const( sortedColumns ) )
{
attributesBySortRank.append( qMakePair( column.first,
Expand Down
62 changes: 62 additions & 0 deletions tests/src/core/testqgslayouttable.cpp
Expand Up @@ -55,6 +55,7 @@ class TestQgsLayoutTable : public QObject
void attributeTableFilterFeatures(); //test filtering attribute table rows
void attributeTableSetAttributes(); //test subset of attributes in table
void attributeTableVisibleOnly(); //test displaying only visible attributes
void attributeTableInsideAtlasOnly();
void attributeTableRender(); //test rendering attribute table
void manualColumnWidth(); //test setting manual column widths
void attributeTableEmpty(); //test empty modes for attribute table
Expand Down Expand Up @@ -355,6 +356,67 @@ void TestQgsLayoutTable::attributeTableVisibleOnly()
compareTable( table, expectedRows );
}

void TestQgsLayoutTable::attributeTableInsideAtlasOnly()
{
//test displaying only visible attributes inside the atlas feature
QgsLayout l( QgsProject::instance() );
l.initializeDefaults();
QgsLayoutItemAttributeTable *table = new QgsLayoutItemAttributeTable( &l );
table->setVectorLayer( mVectorLayer );

QgsLayoutItemMap *map = new QgsLayoutItemMap( &l );
map->attemptSetSceneRect( QRectF( 20, 20, 200, 100 ) );
map->setFrameEnabled( true );
map->setExtent( QgsRectangle( -95.537, 32.736, -84.389, 42.2920 ) );
l.addLayoutItem( map );

table->setMap( map );
table->setFilterToAtlasFeature( true );

// no atlas feature
QVector<QStringList> expectedRows;
compareTable( table, expectedRows );

//setup atlas
std::unique_ptr< QgsVectorLayer > atlasLayer = qgis::make_unique< QgsVectorLayer >( QStringLiteral( "Polygon?crs=EPSG:3857" ), QStringLiteral( "atlas" ), QStringLiteral( "memory" ) );
QVERIFY( atlasLayer->isValid() );
QgsGeometry atlasGeom( QgsGeometry::fromWkt( QStringLiteral( "Polygon ((-8863916.31126776337623596 4621257.48816855065524578, -9664269.45078738406300545 5097056.938785120844841, -10049249.44194872118532658 3765399.75924854446202517, -8985488.94005555473268032 3458599.17133777122944593, -8863916.31126776337623596 4621257.48816855065524578))" ) ) );
QgsFeature f;
f.setGeometry( atlasGeom );
atlasLayer->dataProvider()->addFeature( f );
l.reportContext().setLayer( atlasLayer.get() );

QgsFeatureIterator it = atlasLayer->getFeatures();
it.nextFeature( f );
l.reportContext().setFeature( f );

QStringList row;
row << QStringLiteral( "Biplane" ) << QStringLiteral( "0" ) << QStringLiteral( "1" ) << QStringLiteral( "3" ) << QStringLiteral( "3" ) << QStringLiteral( "6" );
expectedRows.append( row );
row.clear();
row << QStringLiteral( "Jet" ) << QStringLiteral( "90" ) << QStringLiteral( "3" ) << QStringLiteral( "1" ) << QStringLiteral( "0" ) << QStringLiteral( "1" );
expectedRows.append( row );
row.clear();
row << QStringLiteral( "Biplane" ) << QStringLiteral( "340" ) << QStringLiteral( "1" ) << QStringLiteral( "3" ) << QStringLiteral( "3" ) << QStringLiteral( "6" );
expectedRows.append( row );

//retrieve rows and check
compareTable( table, expectedRows );

// combination of atlas and map extent visibility
table->setDisplayOnlyVisibleFeatures( true );
expectedRows.clear();
row.clear();
row << QStringLiteral( "Jet" ) << QStringLiteral( "90" ) << QStringLiteral( "3" ) << QStringLiteral( "1" ) << QStringLiteral( "0" ) << QStringLiteral( "1" );
expectedRows.append( row );
row.clear();
row << QStringLiteral( "Biplane" ) << QStringLiteral( "340" ) << QStringLiteral( "1" ) << QStringLiteral( "3" ) << QStringLiteral( "3" ) << QStringLiteral( "6" );
expectedRows.append( row );

//retrieve rows and check
compareTable( table, expectedRows );
}

void TestQgsLayoutTable::attributeTableRender()
{
QgsLayout l( QgsProject::instance() );
Expand Down

0 comments on commit 2b75a27

Please sign in to comment.