Skip to content

Commit 2ef3a5f

Browse files
committed
Port current geometry from atlas to layouts
1 parent 92003c8 commit 2ef3a5f

File tree

4 files changed

+106
-0
lines changed

4 files changed

+106
-0
lines changed

python/core/layout/qgslayoutcontext.sip

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,21 @@ Returns the current feature for evaluating the layout. This feature may
104104
be used for altering an item's content and appearance for a report
105105
or atlas layout.
106106

107+
.. seealso:: :py:func:`currentGeometry()`
108+
107109
.. seealso:: :py:func:`setFeature()`
110+
%End
111+
112+
QgsGeometry currentGeometry( const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() ) const;
113+
%Docstring
114+
Returns the current feature() geometry in the given ``crs``.
115+
If no CRS is specified, the original feature geometry is returned.
116+
117+
Reprojection only works if a valid layer is set for layer().
118+
119+
.. seealso:: :py:func:`feature()`
120+
121+
.. seealso:: :py:func:`layer()`
108122
%End
109123

110124
QgsVectorLayer *layer() const;

src/core/layout/qgslayoutcontext.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,42 @@ QgsRenderContext::Flags QgsLayoutContext::renderContextFlags() const
7474
void QgsLayoutContext::setFeature( const QgsFeature &feature )
7575
{
7676
mFeature = feature;
77+
mGeometryCache.clear();
7778
emit changed();
7879
}
7980

81+
QgsGeometry QgsLayoutContext::currentGeometry( const QgsCoordinateReferenceSystem &crs ) const
82+
{
83+
if ( !crs.isValid() )
84+
{
85+
// no projection, return the native geometry
86+
return mFeature.geometry();
87+
}
88+
89+
if ( !mLayer || !mFeature.isValid() || !mFeature.hasGeometry() )
90+
{
91+
return QgsGeometry();
92+
}
93+
94+
if ( mLayer->crs() == crs )
95+
{
96+
// no projection, return the native geometry
97+
return mFeature.geometry();
98+
}
99+
100+
auto it = mGeometryCache.constFind( crs.srsid() );
101+
if ( it != mGeometryCache.constEnd() )
102+
{
103+
// we have it in cache, return it
104+
return it.value();
105+
}
106+
107+
QgsGeometry transformed = mFeature.geometry();
108+
transformed.transform( QgsCoordinateTransform( mLayer->crs(), crs, mLayout->project() ) );
109+
mGeometryCache[crs.srsid()] = transformed;
110+
return transformed;
111+
}
112+
80113
QgsVectorLayer *QgsLayoutContext::layer() const
81114
{
82115
return mLayer;

src/core/layout/qgslayoutcontext.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,22 @@ class CORE_EXPORT QgsLayoutContext : public QObject
107107
* Returns the current feature for evaluating the layout. This feature may
108108
* be used for altering an item's content and appearance for a report
109109
* or atlas layout.
110+
* \see currentGeometry()
110111
* \see setFeature()
111112
*/
112113
QgsFeature feature() const { return mFeature; }
113114

115+
/**
116+
* Returns the current feature() geometry in the given \a crs.
117+
* If no CRS is specified, the original feature geometry is returned.
118+
*
119+
* Reprojection only works if a valid layer is set for layer().
120+
*
121+
* \see feature()
122+
* \see layer()
123+
*/
124+
QgsGeometry currentGeometry( const QgsCoordinateReferenceSystem &crs = QgsCoordinateReferenceSystem() ) const;
125+
114126
/**
115127
* Returns the vector layer associated with the layout's context.
116128
* \see setLayer()
@@ -262,6 +274,9 @@ class CORE_EXPORT QgsLayoutContext : public QObject
262274
bool mBoundingBoxesVisible = true;
263275
bool mPagesVisible = true;
264276

277+
// projected geometry cache
278+
mutable QMap<long, QgsGeometry> mGeometryCache;
279+
265280
friend class QgsLayoutExporter;
266281
friend class TestQgsLayout;
267282
friend class LayoutContextPreviewSettingRestorer;

tests/src/core/testqgslayoutcontext.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@
1919
#include "qgis.h"
2020
#include "qgsfeature.h"
2121
#include "qgsvectorlayer.h"
22+
#include "qgsgeometry.h"
23+
#include "qgsproject.h"
24+
#include "qgslayout.h"
2225
#include <QObject>
2326
#include "qgstest.h"
2427
#include <QtTest/QSignalSpy>
@@ -40,6 +43,7 @@ class TestQgsLayoutContext: public QObject
4043
void renderContextFlags();
4144
void boundingBoxes();
4245
void exportLayer();
46+
void geometry();
4347

4448
private:
4549
QString mReport;
@@ -198,5 +202,45 @@ void TestQgsLayoutContext::exportLayer()
198202
QCOMPARE( context.currentExportLayer(), 1 );
199203
}
200204

205+
void TestQgsLayoutContext::geometry()
206+
{
207+
QgsProject p;
208+
QgsLayout l( &p );
209+
QgsLayoutContext context( &l );
210+
211+
// no feature set
212+
QVERIFY( context.currentGeometry().isNull() );
213+
QVERIFY( context.currentGeometry( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) ).isNull() );
214+
215+
// no layer set
216+
QgsFeature f;
217+
f.setGeometry( QgsGeometry::fromWkt( QStringLiteral( "LineString( 144 -38, 145 -39 )" ) ) );
218+
context.setFeature( f );
219+
QCOMPARE( context.currentGeometry().asWkt(), f.geometry().asWkt() );
220+
QVERIFY( context.currentGeometry( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) ).isNull() );
221+
222+
//with layer
223+
QgsVectorLayer *layer = new QgsVectorLayer( QStringLiteral( "Point?crs=EPSG:4326&field=id_a:integer" ), QStringLiteral( "A" ), QStringLiteral( "memory" ) );
224+
context.setLayer( layer );
225+
226+
QCOMPARE( context.currentGeometry().asWkt(), f.geometry().asWkt() );
227+
QVERIFY( !context.currentGeometry( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) ).isNull() );
228+
QCOMPARE( context.currentGeometry( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) ).asWkt( 0 ), QStringLiteral( "LineString (2412169 2388563, 2500000 2277996)" ) );
229+
230+
// should be cached
231+
QCOMPARE( context.currentGeometry( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) ).asWkt( 0 ), QStringLiteral( "LineString (2412169 2388563, 2500000 2277996)" ) );
232+
233+
// layer crs
234+
QCOMPARE( context.currentGeometry( layer->crs() ).asWkt(), f.geometry().asWkt() );
235+
236+
// clear cache
237+
QgsFeature f2;
238+
context.setFeature( f2 );
239+
QVERIFY( context.currentGeometry().isNull() );
240+
QVERIFY( context.currentGeometry( QgsCoordinateReferenceSystem( QStringLiteral( "EPSG:3111" ) ) ).isNull() );
241+
242+
delete layer;
243+
}
244+
201245
QGSTEST_MAIN( TestQgsLayoutContext )
202246
#include "testqgslayoutcontext.moc"

0 commit comments

Comments
 (0)