Skip to content

Commit

Permalink
Prepare for removal of QgsCoordinateTransformCache
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Dec 15, 2017
1 parent 018bfb4 commit 439ef20
Show file tree
Hide file tree
Showing 15 changed files with 87 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/analysis/vector/geometry_checker/qgsgeometrycheck.cpp
Expand Up @@ -18,7 +18,7 @@
#include "qgsgeometrycheck.h"
#include "qgsfeaturepool.h"

QgsGeometryCheckerContext::QgsGeometryCheckerContext( int _precision, const QString &_mapCrs, const QMap<QString, QgsFeaturePool *> &_featurePools )
QgsGeometryCheckerContext::QgsGeometryCheckerContext( int _precision, const QgsCoordinateReferenceSystem &_mapCrs, const QMap<QString, QgsFeaturePool *> &_featurePools )
: tolerance( std::pow( 10, -_precision ) )
, reducedTolerance( std::pow( 10, -_precision / 2 ) )
, mapCrs( _mapCrs )
Expand Down
4 changes: 2 additions & 2 deletions src/analysis/vector/geometry_checker/qgsgeometrycheck.h
Expand Up @@ -35,10 +35,10 @@ class QgsFeaturePool;

struct ANALYSIS_EXPORT QgsGeometryCheckerContext
{
QgsGeometryCheckerContext( int _precision, const QString &_mapCrs, const QMap<QString, QgsFeaturePool *> &_featurePools );
QgsGeometryCheckerContext( int _precision, const QgsCoordinateReferenceSystem &_mapCrs, const QMap<QString, QgsFeaturePool *> &_featurePools );
const double tolerance;
const double reducedTolerance;
const QString mapCrs;
const QgsCoordinateReferenceSystem mapCrs;
const QMap<QString, QgsFeaturePool *> featurePools;
};

Expand Down
5 changes: 3 additions & 2 deletions src/analysis/vector/geometry_checker/qgsgeometrychecker.cpp
Expand Up @@ -18,6 +18,7 @@
#include "qgsgeometrychecker.h"
#include "qgsgeometrycheck.h"
#include "qgsfeaturepool.h"
#include "qgsproject.h"

#include <QtConcurrentMap>
#include <QFutureWatcher>
Expand Down Expand Up @@ -144,7 +145,7 @@ bool QgsGeometryChecker::fixError( QgsGeometryCheckError *error, int method, boo
{
const QMap<QgsFeatureId, QList<QgsGeometryCheck::Change>> &layerChanges = changes[layerId];
QgsFeaturePool *featurePool = mContext->featurePools[layerId];
QgsCoordinateTransform t = QgsCoordinateTransformCache::instance()->transform( featurePool->getLayer()->crs().authid(), mContext->mapCrs );
QgsCoordinateTransform t( featurePool->getLayer()->crs(), mContext->mapCrs, QgsProject::instance() );
for ( QgsFeatureId id : layerChanges.keys() )
{
bool removed = false;
Expand Down Expand Up @@ -183,7 +184,7 @@ bool QgsGeometryChecker::fixError( QgsGeometryCheckError *error, int method, boo
for ( const QString &layerId : mContext->featurePools.keys() )
{
QgsFeaturePool *featurePool = mContext->featurePools[layerId];
QgsCoordinateTransform t = QgsCoordinateTransformCache::instance()->transform( mContext->mapCrs, featurePool->getLayer()->crs().authid() );
QgsCoordinateTransform t( mContext->mapCrs, featurePool->getLayer()->crs(), QgsProject::instance() );
recheckAreaFeatures[layerId] = featurePool->getIntersects( t.transform( recheckArea ) );
}

Expand Down
Expand Up @@ -16,8 +16,10 @@
#include "qgscrscache.h"
#include "qgsgeometryfollowboundariescheck.h"
#include "qgsgeometryengine.h"
#include "qgsproject.h"
#include "qgsspatialindex.h"


QgsGeometryFollowBoundariesCheck::QgsGeometryFollowBoundariesCheck( QgsGeometryCheckerContext *context, QgsVectorLayer *checkLayer )
: QgsGeometryCheck( FeatureNodeCheck, {QgsWkbTypes::PolygonGeometry}, context )
{
Expand Down Expand Up @@ -48,7 +50,7 @@ void QgsGeometryFollowBoundariesCheck::collectErrors( QList<QgsGeometryCheckErro
const QgsAbstractGeometry *geom = layerFeature.geometry();

// The geometry to crs of the check layer
QgsCoordinateTransform crst = QgsCoordinateTransformCache::instance()->transform( layerFeature.layer().crs().authid(), mCheckLayer->crs().authid() );
QgsCoordinateTransform crst( layerFeature.layer().crs(), mCheckLayer->crs(), QgsProject::instance() );
QgsGeometry geomt( geom->clone() );
geomt.transform( crst );

Expand Down
4 changes: 2 additions & 2 deletions src/app/qgscustomprojectiondialog.cpp
Expand Up @@ -169,7 +169,7 @@ bool QgsCustomProjectionDialog::deleteCrs( const QString &id )
}

QgsCoordinateReferenceSystem::invalidateCache();
QgsCoordinateTransformCache::instance()->invalidateCrs( QStringLiteral( "USER:%1" ).arg( id ) );
QgsCoordinateTransform::invalidateCache();

return result == SQLITE_OK;
}
Expand Down Expand Up @@ -279,7 +279,7 @@ bool QgsCustomProjectionDialog::saveCrs( QgsCoordinateReferenceSystem parameters
mExistingCRSnames[id] = name;

QgsCoordinateReferenceSystem::invalidateCache();
QgsCoordinateTransformCache::instance()->invalidateCrs( QStringLiteral( "USER:%1" ).arg( id ) );
QgsCoordinateTransform::invalidateCache();

// If we have a projection acronym not in the user db previously, add it.
// This is a must, or else we can't select it from the vw_srs table.
Expand Down
2 changes: 1 addition & 1 deletion src/core/composer/qgsatlascomposition.cpp
Expand Up @@ -815,7 +815,7 @@ QgsGeometry QgsAtlasComposition::currentGeometry( const QgsCoordinateReferenceSy
}

QgsGeometry transformed = mCurrentFeature.geometry();
transformed.transform( QgsCoordinateTransformCache::instance()->transform( mCoverageLayer->crs().authid(), crs.authid() ) );
transformed.transform( QgsCoordinateTransform( mCoverageLayer->crs(), crs, mComposition->project() ) );
mGeometryCache[crs.srsid()] = transformed;
return transformed;
}
18 changes: 18 additions & 0 deletions src/core/qgscoordinatetransform.cpp
Expand Up @@ -41,6 +41,9 @@ extern "C"
// if defined shows all information about transform to stdout
// #define COORDINATE_TRANSFORM_VERBOSE

QReadWriteLock QgsCoordinateTransform::sCacheLock;
QMultiHash< QPair< QString, QString >, QgsCoordinateTransform > QgsCoordinateTransform::sTransforms;

QgsCoordinateTransform::QgsCoordinateTransform()
{
d = new QgsCoordinateTransformPrivate();
Expand All @@ -67,6 +70,14 @@ QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSyst
#endif
}

QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, int sourceDatumTransform, int destinationDatumTransform )
{
d = new QgsCoordinateTransformPrivate( source, destination, sourceDatumTransform, destinationDatumTransform );
#ifdef QGISDEBUG
d->mHasContext = true; // not strictly true, but we don't need to worry if datums have been explicitly set
#endif
}

QgsCoordinateTransform::QgsCoordinateTransform( const QgsCoordinateTransform &o )
{
d = o.d;
Expand Down Expand Up @@ -788,3 +799,10 @@ void QgsCoordinateTransform::initialize()
d.detach();
d->initialize();
}

void QgsCoordinateTransform::invalidateCache()
{
sCacheLock.lockForWrite();
sTransforms.clear();
sCacheLock.unlock();
}
25 changes: 25 additions & 0 deletions src/core/qgscoordinatetransform.h
Expand Up @@ -101,6 +101,18 @@ class CORE_EXPORT QgsCoordinateTransform
const QgsCoordinateReferenceSystem &destination,
const QgsProject *project );

/**
* Constructs a QgsCoordinateTransform to transform from the \a source
* to \a destination coordinate reference system, with the specified
* datum transforms.
*
* \since QGIS 3.0
*/
explicit QgsCoordinateTransform( const QgsCoordinateReferenceSystem &source,
const QgsCoordinateReferenceSystem &destination,
int sourceDatumTransform,
int destinationDatumTransform );

/**
* Copy constructor
*/
Expand Down Expand Up @@ -364,11 +376,24 @@ class CORE_EXPORT QgsCoordinateTransform
//!initialize is used to actually create the Transformer instance
void initialize();

/**
* Clears the internal cache used to initialize QgsCoordinateTransform objects.
* This should be called whenever the srs database has
* been modified in order to ensure that outdated CRS transforms are not created.
* \since QGIS 3.0
*/
static void invalidateCache();

private:

static void searchDatumTransform( const QString &sql, QList< int > &transforms );

mutable QExplicitlySharedDataPointer<QgsCoordinateTransformPrivate> d;

// cache
static QReadWriteLock sCacheLock;
static QMultiHash< QPair< QString, QString >, QgsCoordinateTransform > sTransforms; //same auth_id pairs might have different datum transformations

};

//! Output stream operator
Expand Down
10 changes: 10 additions & 0 deletions src/core/qgscoordinatetransform_p.cpp
Expand Up @@ -62,6 +62,16 @@ QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate( const QgsCoordinat
initialize();
}

QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination, int sourceDatumTransform, int destDatumTransform )
: mSourceCRS( source )
, mDestCRS( destination )
, mSourceDatumTransform( sourceDatumTransform )
, mDestinationDatumTransform( destDatumTransform )
{
setFinder();
initialize();
}

QgsCoordinateTransformPrivate::QgsCoordinateTransformPrivate( const QgsCoordinateTransformPrivate &other )
: QSharedData( other )
, mIsValid( other.mIsValid )
Expand Down
5 changes: 5 additions & 0 deletions src/core/qgscoordinatetransform_p.h
Expand Up @@ -72,6 +72,11 @@ class QgsCoordinateTransformPrivate : public QSharedData
const QgsCoordinateReferenceSystem &destination,
const QgsCoordinateTransformContext &context );

QgsCoordinateTransformPrivate( const QgsCoordinateReferenceSystem &source,
const QgsCoordinateReferenceSystem &destination,
int sourceDatumTransform,
int destDatumTransform );

QgsCoordinateTransformPrivate( const QgsCoordinateTransformPrivate &other );

~QgsCoordinateTransformPrivate();
Expand Down
2 changes: 1 addition & 1 deletion src/core/qgsmaphittest.cpp
Expand Up @@ -115,7 +115,7 @@ void QgsMapHitTest::runHitTestLayer( QgsVectorLayer *vl, SymbolSet &usedSymbols,
{
if ( mSettings.destinationCrs() != vl->crs() )
{
QgsCoordinateTransform ct = QgsCoordinateTransformCache::instance()->transform( mSettings.destinationCrs().authid(), vl->crs().authid() );
QgsCoordinateTransform ct( mSettings.destinationCrs(), vl->crs(), mSettings.transformContext() );
transformedPolygon.transform( ct );
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/core/raster/qgsrasterprojector.cpp
Expand Up @@ -754,7 +754,7 @@ QgsRasterBlock *QgsRasterProjector::block( int bandNo, QgsRectangle const &exte
return mInput->block( bandNo, extent, width, height, feedback );
}

QgsCoordinateTransform inverseCt = QgsCoordinateTransformCache::instance()->transform( mDestCRS.authid(), mSrcCRS.authid(), mDestDatumTransform, mSrcDatumTransform );
QgsCoordinateTransform inverseCt( mDestCRS, mSrcCRS, mDestDatumTransform, mSrcDatumTransform );

ProjectorData pd( extent, width, height, mInput, inverseCt, mPrecision );

Expand Down Expand Up @@ -852,7 +852,7 @@ bool QgsRasterProjector::destExtentSize( const QgsRectangle &srcExtent, int srcX
{
return false;
}
QgsCoordinateTransform ct = QgsCoordinateTransformCache::instance()->transform( mSrcCRS.authid(), mDestCRS.authid(), mSrcDatumTransform, mDestDatumTransform );
QgsCoordinateTransform ct( mSrcCRS, mDestCRS, mSrcDatumTransform, mDestDatumTransform );

return extentSize( ct, srcExtent, srcXSize, srcYSize, destExtent, destXSize, destYSize );
}
Expand Down
Expand Up @@ -256,7 +256,7 @@ bool QgsGeometryCheckerResultTab::exportErrorsDo( const QString &file )
{
return false;
}
if ( !createEmptyDataSource( file, QStringLiteral( "ESRI Shapefile" ), "UTF-8", QgsWkbTypes::Point, attributes, mIface->mapCanvas()->mapSettings().destinationCrs() ) )
if ( !createEmptyDataSource( file, QStringLiteral( "ESRI Shapefile" ), "UTF-8", QgsWkbTypes::Point, attributes, QgsProject::instance()->crs() ) )
{
return false;
}
Expand Down
8 changes: 4 additions & 4 deletions src/plugins/geometry_checker/qgsgeometrycheckersetuptab.cpp
Expand Up @@ -173,7 +173,7 @@ QList<QgsVectorLayer *> QgsGeometryCheckerSetupTab::getSelectedLayers()

void QgsGeometryCheckerSetupTab::validateInput()
{
QStringList layerCrs = QStringList() << mIface->mapCanvas()->mapSettings().destinationCrs().authid();
QStringList layerCrs = QStringList() << QgsProject::instance()->crs().authid();
QList<QgsVectorLayer *> layers = getSelectedLayers();
int nApplicable = 0;
int nPoint = 0;
Expand Down Expand Up @@ -416,7 +416,7 @@ void QgsGeometryCheckerSetupTab::runChecks()
for ( QgsVectorLayer *layer : processLayers )
{
double layerToMapUntis = mIface->mapCanvas()->mapSettings().layerToMapUnits( layer );
QgsCoordinateTransform layerToMapTransform = QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), mIface->mapCanvas()->mapSettings().destinationCrs().authid() );
QgsCoordinateTransform layerToMapTransform( layer->crs(), QgsProject::instance()->crs(), QgsProject::instance() );
featurePools.insert( layer->id(), new QgsFeaturePool( layer, layerToMapUntis, layerToMapTransform, selectedOnly ) );
}
// LineLayerIntersection check is enabled, make sure there is also a feature pool for that layer
Expand All @@ -425,11 +425,11 @@ void QgsGeometryCheckerSetupTab::runChecks()
QgsVectorLayer *layer = dynamic_cast<QgsVectorLayer *>( QgsProject::instance()->mapLayer( ui.comboLineLayerIntersection->currentData().toString() ) );
Q_ASSERT( layer );
double layerToMapUntis = mIface->mapCanvas()->mapSettings().layerToMapUnits( layer );
QgsCoordinateTransform layerToMapTransform = QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), mIface->mapCanvas()->mapSettings().destinationCrs().authid() );
QgsCoordinateTransform layerToMapTransform( layer->crs(), QgsProject::instance()->crs(), QgsProject::instance() );
featurePools.insert( layer->id(), new QgsFeaturePool( layer, layerToMapUntis, layerToMapTransform, selectedOnly ) );
}

QgsGeometryCheckerContext *context = new QgsGeometryCheckerContext( ui.spinBoxTolerance->value(), mIface->mapCanvas()->mapSettings().destinationCrs().authid(), featurePools );
QgsGeometryCheckerContext *context = new QgsGeometryCheckerContext( ui.spinBoxTolerance->value(), QgsProject::instance()->crs(), featurePools );

QList<QgsGeometryCheck *> checks;
for ( const QgsGeometryCheckFactory *factory : QgsGeometryCheckFactoryRegistry::getCheckFactories() )
Expand Down
17 changes: 9 additions & 8 deletions tests/src/geometry_checker/testqgsgeometrychecks.cpp
Expand Up @@ -39,6 +39,7 @@
#include "qgsgeometryselfcontactcheck.h"
#include "qgsgeometryselfintersectioncheck.h"
#include "qgsgeometrysliverpolygoncheck.h"
#include "qgsproject.h"

#include "qgsgeometrytypecheck.h"

Expand All @@ -55,9 +56,9 @@ class TestQgsGeometryChecks: public QObject
QgsGeometryCheck::ChangeType type;
QgsVertexId vidx;
};
double layerToMapUnits( const QgsMapLayer *layer, const QString &mapCrs ) const;
QgsFeaturePool *createFeaturePool( QgsVectorLayer *layer, const QString &mapCrs, bool selectedOnly = false ) const;
QgsGeometryCheckerContext *createTestContext( QTemporaryDir &tempDir, QMap<QString, QString> &layers, const QString &mapCrs = "EPSG:4326", double prec = 8 ) const;
double layerToMapUnits( const QgsMapLayer *layer, const QgsCoordinateReferenceSystem &mapCrs ) const;
QgsFeaturePool *createFeaturePool( QgsVectorLayer *layer, const QgsCoordinateReferenceSystem &mapCrs, bool selectedOnly = false ) const;
QgsGeometryCheckerContext *createTestContext( QTemporaryDir &tempDir, QMap<QString, QString> &layers, const QgsCoordinateReferenceSystem &mapCrs = QgsCoordinateReferenceSystem( "EPSG:4326" ), double prec = 8 ) const;
void cleanupTestContext( QgsGeometryCheckerContext *ctx ) const;
void listErrors( const QList<QgsGeometryCheckError *> &checkErrors, const QStringList &messages ) const;
QList<QgsGeometryCheckError *> searchCheckErrors( const QList<QgsGeometryCheckError *> &checkErrors, const QString &layerId, const QgsFeatureId &featureId = -1, const QgsPointXY &pos = QgsPointXY(), const QgsVertexId &vid = QgsVertexId(), const QVariant &value = QVariant(), double tol = 1E-4 ) const;
Expand Down Expand Up @@ -958,9 +959,9 @@ void TestQgsGeometryChecks::testSliverPolygonCheck()

///////////////////////////////////////////////////////////////////////////////

double TestQgsGeometryChecks::layerToMapUnits( const QgsMapLayer *layer, const QString &mapCrs ) const
double TestQgsGeometryChecks::layerToMapUnits( const QgsMapLayer *layer, const QgsCoordinateReferenceSystem &mapCrs ) const
{
QgsCoordinateTransform crst = QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), mapCrs );
QgsCoordinateTransform crst = QgsCoordinateTransform( layer->crs(), mapCrs, QgsProject::instance() );
QgsRectangle extent = layer->extent();
QgsPointXY l1( extent.xMinimum(), extent.yMinimum() );
QgsPointXY l2( extent.xMaximum(), extent.yMaximum() );
Expand All @@ -971,14 +972,14 @@ double TestQgsGeometryChecks::layerToMapUnits( const QgsMapLayer *layer, const Q
return distMapUnits / distLayerUnits;
}

QgsFeaturePool *TestQgsGeometryChecks::createFeaturePool( QgsVectorLayer *layer, const QString &mapCrs, bool selectedOnly ) const
QgsFeaturePool *TestQgsGeometryChecks::createFeaturePool( QgsVectorLayer *layer, const QgsCoordinateReferenceSystem &mapCrs, bool selectedOnly ) const
{
double layerToMapUntis = layerToMapUnits( layer, mapCrs );
QgsCoordinateTransform layerToMapTransform = QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), mapCrs );
QgsCoordinateTransform layerToMapTransform = QgsCoordinateTransform( layer->crs(), mapCrs, QgsProject::instance() );
return new QgsFeaturePool( layer, layerToMapUntis, layerToMapTransform, selectedOnly );
}

QgsGeometryCheckerContext *TestQgsGeometryChecks::createTestContext( QTemporaryDir &tempDir, QMap<QString, QString> &layers, const QString &mapCrs, double prec ) const
QgsGeometryCheckerContext *TestQgsGeometryChecks::createTestContext( QTemporaryDir &tempDir, QMap<QString, QString> &layers, const QgsCoordinateReferenceSystem &mapCrs, double prec ) const
{
QDir testDataDir( QDir( TEST_DATA_DIR ).absoluteFilePath( "geometry_checker" ) );
QDir tmpDir( tempDir.path() );
Expand Down

0 comments on commit 439ef20

Please sign in to comment.