Skip to content

Commit dfe633b

Browse files
authored
Merge pull request #7861 from m-kuhn/featurePoolContext
Make QgsFeaturePool free of reprojection code and other improvements
2 parents d844f0f + 532fb62 commit dfe633b

37 files changed

+380
-209
lines changed

src/analysis/vector/geometry_checker/qgsfeaturepool.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,12 @@
2626
#include <QMutexLocker>
2727

2828

29-
QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer, double layerToMapUnits, const QgsCoordinateTransform &layerToMapTransform )
29+
QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer )
3030
: mFeatureCache( CACHE_SIZE )
3131
, mLayer( layer )
32-
, mLayerToMapUnits( layerToMapUnits )
33-
, mLayerToMapTransform( layerToMapTransform )
3432
, mLayerId( layer->id() )
3533
, mGeometryType( layer->geometryType() )
34+
, mCrs( layer->crs() )
3635
{
3736

3837
}
@@ -82,6 +81,11 @@ QgsVectorLayer *QgsFeaturePool::layer() const
8281
return mLayer.data();
8382
}
8483

84+
QPointer<QgsVectorLayer> QgsFeaturePool::layerPtr() const
85+
{
86+
return mLayer;
87+
}
88+
8589
void QgsFeaturePool::insertFeature( const QgsFeature &feature )
8690
{
8791
QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Write );
@@ -118,6 +122,11 @@ void QgsFeaturePool::setFeatureIds( const QgsFeatureIds &ids )
118122
mFeatureIds = ids;
119123
}
120124

125+
QgsCoordinateReferenceSystem QgsFeaturePool::crs() const
126+
{
127+
return mCrs;
128+
}
129+
121130
QgsWkbTypes::GeometryType QgsFeaturePool::geometryType() const
122131
{
123132
return mGeometryType;

src/analysis/vector/geometry_checker/qgsfeaturepool.h

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class ANALYSIS_EXPORT QgsFeaturePool : public QgsFeatureSink
3838
{
3939

4040
public:
41-
QgsFeaturePool( QgsVectorLayer *layer, double layerToMapUnits, const QgsCoordinateTransform &layerToMapTransform );
41+
QgsFeaturePool( QgsVectorLayer *layer );
4242
virtual ~QgsFeaturePool() = default;
4343

4444
/**
@@ -72,25 +72,22 @@ class ANALYSIS_EXPORT QgsFeaturePool : public QgsFeatureSink
7272
*/
7373
QgsFeatureIds getIntersects( const QgsRectangle &rect ) const;
7474

75-
/**
76-
* The factor of layer units to map units.
77-
* TODO: should this be removed and determined on runtime by checks that need it?
78-
*/
79-
double getLayerToMapUnits() const { return mLayerToMapUnits; }
80-
81-
/**
82-
* A coordinate transform from layer to map CRS.
83-
* TODO: should this be removed and determined on runtime by checks that need it?
84-
*/
85-
const QgsCoordinateTransform &getLayerToMapTransform() const { return mLayerToMapTransform; }
86-
8775
/**
8876
* Get a pointer to the underlying layer.
8977
* May return a ``nullptr`` if the layer has been deleted.
9078
* This must only be called from the main thread.
9179
*/
9280
QgsVectorLayer *layer() const;
9381

82+
/**
83+
* Get a QPointer to the underlying layer.
84+
* Note that access to any methods of the object
85+
* will need to be done on the main thread and
86+
* the pointer will need to be checked for validity
87+
* before usage.
88+
*/
89+
QPointer<QgsVectorLayer> layerPtr() const;
90+
9491
/**
9592
* The layer id of the layer.
9693
*/
@@ -101,6 +98,11 @@ class ANALYSIS_EXPORT QgsFeaturePool : public QgsFeatureSink
10198
*/
10299
QgsWkbTypes::GeometryType geometryType() const;
103100

101+
/**
102+
* The coordinate reference system of this layer.
103+
*/
104+
QgsCoordinateReferenceSystem crs() const;
105+
104106
protected:
105107

106108
/**
@@ -135,10 +137,9 @@ class ANALYSIS_EXPORT QgsFeaturePool : public QgsFeatureSink
135137
mutable QReadWriteLock mCacheLock;
136138
QgsFeatureIds mFeatureIds;
137139
QgsSpatialIndex mIndex;
138-
double mLayerToMapUnits = 1.0;
139-
QgsCoordinateTransform mLayerToMapTransform;
140140
QString mLayerId;
141141
QgsWkbTypes::GeometryType mGeometryType;
142+
QgsCoordinateReferenceSystem mCrs;
142143
};
143144

144145
#endif // QGS_FEATUREPOOL_H

src/analysis/vector/geometry_checker/qgsgeometryanglecheck.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
void QgsGeometryAngleCheck::collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &/*messages*/, QAtomicInt *progressCounter, const QMap<QString, QgsFeatureIds> &ids ) const
2121
{
2222
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
23-
QgsGeometryCheckerUtils::LayerFeatures layerFeatures( mContext->featurePools, featureIds, mCompatibleGeometryTypes, progressCounter );
23+
QgsGeometryCheckerUtils::LayerFeatures layerFeatures( mContext->featurePools, featureIds, mCompatibleGeometryTypes, progressCounter, context() );
2424
for ( const QgsGeometryCheckerUtils::LayerFeature &layerFeature : layerFeatures )
2525
{
26-
const QgsAbstractGeometry *geom = layerFeature.geometry();
26+
const QgsAbstractGeometry *geom = layerFeature.geometry().constGet();
2727
for ( int iPart = 0, nParts = geom->partCount(); iPart < nParts; ++iPart )
2828
{
2929
for ( int iRing = 0, nRings = geom->ringCount( iPart ); iRing < nRings; ++iRing )

src/analysis/vector/geometry_checker/qgsgeometryareacheck.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@
2121
void QgsGeometryAreaCheck::collectErrors( QList<QgsGeometryCheckError *> &errors, QStringList &/*messages*/, QAtomicInt *progressCounter, const QMap<QString, QgsFeatureIds> &ids ) const
2222
{
2323
QMap<QString, QgsFeatureIds> featureIds = ids.isEmpty() ? allLayerFeatureIds() : ids;
24-
QgsGeometryCheckerUtils::LayerFeatures layerFeatures( mContext->featurePools, featureIds, mCompatibleGeometryTypes, progressCounter );
24+
QgsGeometryCheckerUtils::LayerFeatures layerFeatures( mContext->featurePools, featureIds, mCompatibleGeometryTypes, progressCounter, mContext );
2525
for ( const QgsGeometryCheckerUtils::LayerFeature &layerFeature : layerFeatures )
2626
{
27-
double layerToMapUnits = layerFeature.layerToMapUnits();
28-
const QgsAbstractGeometry *geom = layerFeature.geometry();
27+
const QgsAbstractGeometry *geom = layerFeature.geometry().constGet();
28+
double layerToMapUnits = mContext->layerScaleFactor( layerFeature.layer() );
2929
for ( int iPart = 0, nParts = geom->partCount(); iPart < nParts; ++iPart )
3030
{
3131
double value;
@@ -47,11 +47,13 @@ void QgsGeometryAreaCheck::fixError( QgsGeometryCheckError *error, int method, c
4747
error->setObsolete();
4848
return;
4949
}
50-
double layerToMapUnits = featurePool->getLayerToMapUnits();
51-
QgsGeometry g = feature.geometry();
50+
51+
const QgsGeometry g = feature.geometry();
5252
const QgsAbstractGeometry *geom = g.constGet();
5353
QgsVertexId vidx = error->vidx();
5454

55+
double layerToMapUnits = mContext->layerScaleFactor( featurePool->layer() );
56+
5557
// Check if polygon still exists
5658
if ( !vidx.isValid( geom ) )
5759
{

src/analysis/vector/geometry_checker/qgsgeometrycheck.cpp

Lines changed: 54 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,61 @@
1818
#include "qgsgeometrycheck.h"
1919
#include "qgsfeaturepool.h"
2020
#include "qgsvectorlayer.h"
21+
#include "qgsreadwritelocker.h"
22+
#include "qgsthreadingutils.h"
2123

22-
QgsGeometryCheckerContext::QgsGeometryCheckerContext( int _precision, const QgsCoordinateReferenceSystem &_mapCrs, const QMap<QString, QgsFeaturePool *> &_featurePools )
24+
QgsGeometryCheckerContext::QgsGeometryCheckerContext( int _precision, const QgsCoordinateReferenceSystem &_mapCrs, const QMap<QString, QgsFeaturePool *> &_featurePools, const QgsCoordinateTransformContext &transformContext )
2325
: tolerance( std::pow( 10, -_precision ) )
2426
, reducedTolerance( std::pow( 10, -_precision / 2 ) )
2527
, mapCrs( _mapCrs )
2628
, featurePools( _featurePools )
29+
, transformContext( transformContext )
2730
{
31+
}
32+
33+
const QgsCoordinateTransform &QgsGeometryCheckerContext::layerTransform( const QPointer<QgsVectorLayer> &layer )
34+
{
35+
QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
36+
if ( !mTransformCache.contains( layer ) )
37+
{
38+
QgsCoordinateTransform transform;
39+
QgsThreadingUtils::runOnMainThread( [this, &transform, layer]()
40+
{
41+
QgsVectorLayer *lyr = layer.data();
42+
if ( lyr )
43+
transform = QgsCoordinateTransform( lyr->crs(), mapCrs, transformContext );
44+
} );
45+
locker.changeMode( QgsReadWriteLocker::Write );
46+
mTransformCache[layer] = transform;
47+
locker.changeMode( QgsReadWriteLocker::Read );
48+
}
49+
50+
return mTransformCache[layer];
51+
}
52+
53+
double QgsGeometryCheckerContext::layerScaleFactor( const QPointer<QgsVectorLayer> &layer )
54+
{
55+
QgsReadWriteLocker locker( mCacheLock, QgsReadWriteLocker::Read );
56+
if ( !mScaleFactorCache.contains( layer ) )
57+
{
58+
double scaleFactor = 1.0;
59+
QgsThreadingUtils::runOnMainThread( [this, layer, &scaleFactor]()
60+
{
61+
QgsVectorLayer *lyr = layer.data();
62+
if ( lyr )
63+
scaleFactor = layerTransform( layer ).scaleFactor( lyr->extent() );
64+
} );
65+
66+
locker.changeMode( QgsReadWriteLocker::Write );
67+
mScaleFactorCache[layer] = scaleFactor;
68+
locker.changeMode( QgsReadWriteLocker::Read );
69+
}
2870

71+
return mScaleFactorCache.value( layer );
2972
}
3073

3174
QgsGeometryCheckError::QgsGeometryCheckError( const QgsGeometryCheck *check, const QString &layerId,
32-
QgsFeatureId featureId, QgsAbstractGeometry *geometry,
75+
QgsFeatureId featureId, const QgsGeometry &geometry,
3376
const QgsPointXY &errorLocation,
3477
QgsVertexId vidx,
3578
const QVariant &value, ValueType valueType )
@@ -50,7 +93,7 @@ QgsGeometryCheckError::QgsGeometryCheckError( const QgsGeometryCheck *check,
5093
const QgsPointXY &errorLocation, QgsVertexId vidx,
5194
const QVariant &value, ValueType valueType )
5295
: mCheck( check )
53-
, mLayerId( layerFeature.layer()->id() )
96+
, mLayerId( layerFeature.layerId() )
5497
, mFeatureId( layerFeature.feature().id() )
5598
, mErrorLocation( errorLocation )
5699
, mVidx( vidx )
@@ -60,27 +103,28 @@ QgsGeometryCheckError::QgsGeometryCheckError( const QgsGeometryCheck *check,
60103
{
61104
if ( vidx.part != -1 )
62105
{
63-
mGeometry.reset( QgsGeometryCheckerUtils::getGeomPart( layerFeature.geometry(), vidx.part )->clone() );
106+
mGeometry = QgsGeometry( QgsGeometryCheckerUtils::getGeomPart( layerFeature.geometry().constGet(), vidx.part )->clone() );
64107
}
65108
else
66109
{
67-
mGeometry.reset( layerFeature.geometry()->clone() );
110+
mGeometry = layerFeature.geometry();
68111
}
69-
if ( layerFeature.geometryCrs() != layerFeature.layerToMapTransform().destinationCrs().authid() )
112+
if ( !layerFeature.useMapCrs() )
70113
{
71-
mGeometry->transform( layerFeature.layerToMapTransform() );
72-
mErrorLocation = layerFeature.layerToMapTransform().transform( mErrorLocation );
114+
const QgsCoordinateTransform &transform = check->context()->layerTransform( layerFeature.layer() );
115+
mGeometry.transform( transform );
116+
mErrorLocation = transform.transform( mErrorLocation );
73117
}
74118
}
75119

76120
const QgsAbstractGeometry *QgsGeometryCheckError::geometry() const
77121
{
78-
return mGeometry.get();
122+
return mGeometry.constGet();
79123
}
80124

81125
QgsRectangle QgsGeometryCheckError::affectedAreaBBox() const
82126
{
83-
return mGeometry->boundingBox();
127+
return mGeometry.boundingBox();
84128
}
85129

86130
bool QgsGeometryCheckError::handleChanges( const QgsGeometryCheck::Changes &changes )

src/analysis/vector/geometry_checker/qgsgeometrycheck.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,11 @@
2121
#include <QApplication>
2222
#include <limits>
2323
#include <QStringList>
24+
#include <QPointer>
25+
2426
#include "qgis_analysis.h"
2527
#include "qgsfeature.h"
28+
#include "qgsvectorlayer.h"
2629
#include "geometry/qgsgeometry.h"
2730
#include "qgsgeometrycheckerutils.h"
2831

@@ -33,11 +36,19 @@ class QgsFeaturePool;
3336

3437
struct ANALYSIS_EXPORT QgsGeometryCheckerContext
3538
{
36-
QgsGeometryCheckerContext( int _precision, const QgsCoordinateReferenceSystem &_mapCrs, const QMap<QString, QgsFeaturePool *> &_featurePools );
37-
const double tolerance;
38-
const double reducedTolerance;
39-
const QgsCoordinateReferenceSystem mapCrs;
40-
const QMap<QString, QgsFeaturePool *> featurePools;
39+
QgsGeometryCheckerContext( int _precision, const QgsCoordinateReferenceSystem &_mapCrs, const QMap<QString, QgsFeaturePool *> &_featurePools, const QgsCoordinateTransformContext &transformContext );
40+
const double tolerance;
41+
const double reducedTolerance;
42+
const QgsCoordinateReferenceSystem mapCrs;
43+
const QMap<QString, QgsFeaturePool *> featurePools;
44+
const QgsCoordinateTransformContext transformContext;
45+
const QgsCoordinateTransform &layerTransform( const QPointer<QgsVectorLayer> &layer );
46+
double layerScaleFactor( const QPointer<QgsVectorLayer> &layer );
47+
48+
private:
49+
QMap<QPointer<QgsVectorLayer>, QgsCoordinateTransform> mTransformCache;
50+
QMap<QPointer<QgsVectorLayer>, double> mScaleFactorCache;
51+
QReadWriteLock mCacheLock;
4152
};
4253

4354
class ANALYSIS_EXPORT QgsGeometryCheck
@@ -177,7 +188,7 @@ class ANALYSIS_EXPORT QgsGeometryCheckError
177188
mErrorLocation = other->mErrorLocation;
178189
mVidx = other->mVidx;
179190
mValue = other->mValue;
180-
mGeometry.reset( other->mGeometry->clone() );
191+
mGeometry = other->mGeometry;
181192
}
182193

183194
virtual bool handleChanges( const QgsGeometryCheck::Changes &changes );
@@ -187,7 +198,7 @@ class ANALYSIS_EXPORT QgsGeometryCheckError
187198
QgsGeometryCheckError( const QgsGeometryCheck *check,
188199
const QString &layerId,
189200
QgsFeatureId featureId,
190-
QgsAbstractGeometry *geometry,
201+
const QgsGeometry &geometry,
191202
const QgsPointXY &errorLocation,
192203
QgsVertexId vidx = QgsVertexId(),
193204
const QVariant &value = QVariant(),
@@ -196,7 +207,7 @@ class ANALYSIS_EXPORT QgsGeometryCheckError
196207
const QgsGeometryCheck *mCheck = nullptr;
197208
QString mLayerId;
198209
QgsFeatureId mFeatureId;
199-
std::unique_ptr<QgsAbstractGeometry> mGeometry;
210+
QgsGeometry mGeometry;
200211
QgsPointXY mErrorLocation;
201212
QgsVertexId mVidx;
202213
QVariant mValue;

src/analysis/vector/geometry_checker/qgsgeometrychecker.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,3 +291,13 @@ void QgsGeometryChecker::runCheck( const QgsGeometryCheck *check )
291291
emit errorAdded( error );
292292
}
293293
}
294+
295+
QgsGeometryChecker::RunCheckWrapper::RunCheckWrapper( QgsGeometryChecker *instance )
296+
: mInstance( instance )
297+
{
298+
}
299+
300+
void QgsGeometryChecker::RunCheckWrapper::operator()( const QgsGeometryCheck *check )
301+
{
302+
mInstance->runCheck( check );
303+
}

src/analysis/vector/geometry_checker/qgsgeometrychecker.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@
2424
#include <QMutex>
2525
#include <QStringList>
2626
#include "qgis_analysis.h"
27-
#include "qgsfeatureid.h"
2827

28+
typedef qint64 QgsFeatureId;
29+
typedef QSet<QgsFeatureId> QgsFeatureIds;
2930
struct QgsGeometryCheckerContext;
3031
class QgsGeometryCheck;
3132
class QgsGeometryCheckError;
@@ -55,8 +56,8 @@ class ANALYSIS_EXPORT QgsGeometryChecker : public QObject
5556
class RunCheckWrapper
5657
{
5758
public:
58-
explicit RunCheckWrapper( QgsGeometryChecker *instance ) : mInstance( instance ) {}
59-
void operator()( const QgsGeometryCheck *check ) { mInstance->runCheck( check ); }
59+
explicit RunCheckWrapper( QgsGeometryChecker *instance );
60+
void operator()( const QgsGeometryCheck *check );
6061
private:
6162
QgsGeometryChecker *mInstance = nullptr;
6263
};

0 commit comments

Comments
 (0)