[Geometry checker] Adapt for API changes

This commit is contained in:
Sandro Mani 2017-06-15 23:09:09 +02:00
parent b52b2c51e4
commit 1642eb1601
27 changed files with 102 additions and 81 deletions

View File

@ -51,11 +51,13 @@ void QgsGeometryAngleCheck::collectErrors( QList<QgsGeometryCheckError *> &error
continue;
}
double angle = std::acos( v21 * v23 ) / M_PI * 180.0;
double angle = qAcos( v21 * v23 ) / M_PI * 180.0;
if ( angle < mMinAngle )
{
QgsAbstractGeometry *part = QgsGeometryCheckerUtils::getGeomPart( geom, iPart )->clone();
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), part, p2, QgsVertexId( iPart, iRing, iVert ), angle ) );
part->transform( layerFeature.mapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsPointXY pos = layerFeature.mapToLayerTransform().transform( p2, QgsCoordinateTransform::ReverseTransform );
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), part, pos, QgsVertexId( iPart, iRing, iVert ), angle ) );
}
}
}

View File

@ -44,7 +44,10 @@ void QgsGeometryAreaCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
double value;
if ( checkThreshold( mapToLayerUnits, geom, value ) )
{
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), geom->clone(), geom->centroid(), QgsVertexId( 0 ), value / ( mapToLayerUnits * mapToLayerUnits ), QgsGeometryCheckError::ValueArea ) );
QgsAbstractGeometry *g = geom->clone();
g->transform( layerFeature.mapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsPoint pos = g->centroid();
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), g, pos, QgsVertexId( 0 ), value / ( mapToLayerUnits * mapToLayerUnits ), QgsGeometryCheckError::ValueArea ) );
}
}
}

View File

@ -13,7 +13,6 @@
* *
***************************************************************************/
#include "qgscrscache.h"
#include "qgsgeometrycollection.h"
#include "qgscurvepolygon.h"
#include "qgsgeometrycheck.h"
@ -30,7 +29,7 @@ QgsGeometryCheckerContext::QgsGeometryCheckerContext( int _precision, const QStr
QgsGeometryCheckError::QgsGeometryCheckError( const QgsGeometryCheck *check, const QString &layerId,
QgsFeatureId featureId, QgsAbstractGeometry *geometry,
const QgsPoint &errorLocation,
const QgsPointXY &errorLocation,
QgsVertexId vidx,
const QVariant &value, ValueType valueType )
: mCheck( check )
@ -47,9 +46,7 @@ QgsGeometryCheckError::QgsGeometryCheckError( const QgsGeometryCheck *check, con
QgsRectangle QgsGeometryCheckError::affectedAreaBBox() const
{
QString srcCrs = mCheck->getContext()->featurePools[ layerId() ]->getLayer()->crs().authid();
QgsCoordinateTransform t = QgsCoordinateTransformCache::instance()->transform( srcCrs, mCheck->getContext()->mapCrs );
return t.transformBoundingBox( mGeometry->boundingBox() );
return mGeometry->boundingBox();
}
bool QgsGeometryCheckError::handleChanges( const QgsGeometryCheck::Changes &changes )

View File

@ -99,7 +99,7 @@ class QgsGeometryCheckError
const QString &layerId,
QgsFeatureId featureId,
QgsAbstractGeometry *geometry,
const QgsPoint &errorLocation,
const QgsPointXY &errorLocation,
QgsVertexId vidx = QgsVertexId(),
const QVariant &value = QVariant(),
ValueType valueType = ValueOther );
@ -113,11 +113,13 @@ class QgsGeometryCheckError
const QgsGeometryCheck *check() const { return mCheck; }
const QString &layerId() const { return mLayerId; }
QgsFeatureId featureId() const { return mFeatureId; }
QgsAbstractGeometry *geometry() const { return mGeometry; }
// In map units
const QgsAbstractGeometry *geometry() const { return mGeometry; }
// In map units
virtual QgsRectangle affectedAreaBBox() const;
virtual QString description() const { return mCheck->errorDescription(); }
const QgsPoint &location() const { return mErrorLocation; }
// In map units
const QgsPointXY &location() const { return mErrorLocation; }
// Lengths, areas in map units
QVariant value() const { return mValue; }
ValueType valueType() const { return mValueType; }
@ -165,7 +167,7 @@ class QgsGeometryCheckError
QString mLayerId;
QgsFeatureId mFeatureId;
QgsAbstractGeometry *mGeometry;
QgsPoint mErrorLocation;
QgsPointXY mErrorLocation;
QgsVertexId mVidx;
QVariant mValue;
ValueType mValueType;

View File

@ -13,7 +13,6 @@
* *
***************************************************************************/
#include "qgscrscache.h"
#include "qgsgeometryengine.h"
#include "qgsgeometrycontainedcheck.h"
#include "../utils/qgsfeaturepool.h"
@ -32,7 +31,9 @@ void QgsGeometryContainedCheck::collectErrors( QList<QgsGeometryCheckError *> &e
QString errMsg;
if ( geomEngineA->within( *layerFeatureB.geometry(), &errMsg ) )
{
errors.append( new QgsGeometryContainedCheckError( this, layerFeatureA.layer().id(), layerFeatureA.feature().id(), layerFeatureA.geometry()->clone(), layerFeatureA.geometry()->centroid(), qMakePair( layerFeatureB.layer().id(), layerFeatureB.feature().id() ) ) );
QgsAbstractGeometry *g = layerFeatureA.geometry()->clone();
QgsPoint pos = g->centroid();
errors.append( new QgsGeometryContainedCheckError( this, layerFeatureA.layer().id(), layerFeatureA.feature().id(), g, pos, qMakePair( layerFeatureB.layer().id(), layerFeatureB.feature().id() ) ) );
}
else if ( !errMsg.isEmpty() )
{
@ -56,16 +57,14 @@ void QgsGeometryContainedCheck::fixError( QgsGeometryCheckError *error, int meth
error->setObsolete();
return;
}
QgsCoordinateTransform crstA = QgsCoordinateTransformCache::instance()->transform( featurePoolA->getLayer()->crs().authid(), mContext->mapCrs );
QgsCoordinateTransform crstB = QgsCoordinateTransformCache::instance()->transform( featurePoolB->getLayer()->crs().authid(), mContext->mapCrs );
// Check if error still applies
QgsAbstractGeometry *featureGeomA = featureA.geometry().geometry()->clone();
featureGeomA->transform( crstA );
featureGeomA->transform( featurePoolA->getMapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QSharedPointer<QgsGeometryEngine> geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( featureGeomA, mContext->tolerance );
QgsAbstractGeometry *featureGeomB = featureB.geometry().geometry()->clone();
featureGeomB->transform( crstB );
featureGeomB->transform( featurePoolB->getMapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
bool within = geomEngineA->within( *featureGeomB );
delete featureGeomA;

View File

@ -25,7 +25,7 @@ class QgsGeometryContainedCheckError : public QgsGeometryCheckError
const QString &layerId,
QgsFeatureId featureId,
QgsAbstractGeometry *geometry,
const QgsPoint &errorLocation,
const QgsPointXY &errorLocation,
const QPair<QString, QgsFeatureId> &containingFeature
)
: QgsGeometryCheckError( check, layerId, featureId, geometry, errorLocation, QgsVertexId(), QString( "%1:%2" ).arg( containingFeature.first ).arg( containingFeature.second ), ValueOther )

View File

@ -29,7 +29,10 @@ void QgsGeometryDegeneratePolygonCheck::collectErrors( QList<QgsGeometryCheckErr
{
if ( QgsGeometryCheckerUtils::polyLineSize( geom, iPart, iRing ) < 3 )
{
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), geom->clone(), geom->vertexAt( QgsVertexId( iPart, iRing, 0 ) ), QgsVertexId( iPart, iRing ) ) );
QgsAbstractGeometry *g = geom->clone();
g->transform( layerFeature.mapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsPointXY pos = layerFeature.mapToLayerTransform().transform( geom->vertexAt( QgsVertexId( iPart, iRing, 0 ) ), QgsCoordinateTransform::ReverseTransform );
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), g, pos, QgsVertexId( iPart, iRing ) ) );
}
}
}

View File

@ -13,7 +13,6 @@
* *
***************************************************************************/
#include "qgscrscache.h"
#include "qgsgeometryengine.h"
#include "qgsgeometryduplicatecheck.h"
#include "qgsspatialindex.h"
@ -56,7 +55,9 @@ void QgsGeometryDuplicateCheck::collectErrors( QList<QgsGeometryCheckError *> &e
}
if ( !duplicates.isEmpty() )
{
errors.append( new QgsGeometryDuplicateCheckError( this, layerFeatureA.layer().id(), layerFeatureA.feature().id(), layerFeatureA.geometry()->clone(), layerFeatureA.geometry()->centroid(), duplicates ) );
QgsAbstractGeometry *g = layerFeatureA.geometry()->clone();
QgsPoint pos = g->centroid();
errors.append( new QgsGeometryDuplicateCheckError( this, layerFeatureA.layer().id(), layerFeatureA.feature().id(), g, pos, duplicates ) );
}
}
}
@ -77,16 +78,14 @@ void QgsGeometryDuplicateCheck::fixError( QgsGeometryCheckError *error, int meth
}
else if ( method == RemoveDuplicates )
{
QgsCoordinateTransform crstA = QgsCoordinateTransformCache::instance()->transform( featurePoolA->getLayer()->crs().authid(), mContext->mapCrs );
QgsAbstractGeometry *featureGeomA = featureA.geometry().geometry()->clone();
featureGeomA->transform( crstA );
featureGeomA->transform( featurePoolA->getMapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QSharedPointer<QgsGeometryEngine> geomEngine = QgsGeometryCheckerUtils::createGeomEngine( featureGeomA, mContext->tolerance );
QgsGeometryDuplicateCheckError *duplicateError = static_cast<QgsGeometryDuplicateCheckError *>( error );
for ( const QString &layerIdB : duplicateError->duplicates().keys() )
{
QgsFeaturePool *featurePoolB = mContext->featurePools[ layerIdB ];
QgsCoordinateTransform crstB = QgsCoordinateTransformCache::instance()->transform( featurePoolB->getLayer()->crs().authid(), mContext->mapCrs );
for ( QgsFeatureId idB : duplicateError->duplicates()[layerIdB] )
{
QgsFeature featureB;
@ -95,7 +94,7 @@ void QgsGeometryDuplicateCheck::fixError( QgsGeometryCheckError *error, int meth
continue;
}
QgsAbstractGeometry *featureGeomB = featureB.geometry().geometry()->clone();
featureGeomB->transform( crstB );
featureGeomB->transform( featurePoolB->getMapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsAbstractGeometry *diffGeom = geomEngine->symDifference( *featureGeomB );
if ( diffGeom && diffGeom->area() < mContext->tolerance )
{

View File

@ -25,7 +25,7 @@ class QgsGeometryDuplicateCheckError : public QgsGeometryCheckError
const QString &layerId,
QgsFeatureId featureId,
QgsAbstractGeometry *geometry,
const QgsPoint &errorLocation,
const QgsPointXY &errorLocation,
const QMap<QString, QList<QgsFeatureId>> &duplicates )
: QgsGeometryCheckError( check, layerId, featureId, geometry, errorLocation, QgsVertexId(), duplicatesString( duplicates ) )
, mDuplicates( duplicates )

View File

@ -33,11 +33,14 @@ void QgsGeometryDuplicateNodesCheck::collectErrors( QList<QgsGeometryCheckError
continue;
for ( int iVert = nVerts - 1, jVert = 0; jVert < nVerts; iVert = jVert++ )
{
QgsPointV2 pi = geom->vertexAt( QgsVertexId( iPart, iRing, iVert ) );
QgsPointV2 pj = geom->vertexAt( QgsVertexId( iPart, iRing, jVert ) );
QgsPoint pi = geom->vertexAt( QgsVertexId( iPart, iRing, iVert ) );
QgsPoint pj = geom->vertexAt( QgsVertexId( iPart, iRing, jVert ) );
if ( QgsGeometryUtils::sqrDistance2D( pi, pj ) < mContext->tolerance )
{
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), geom->clone(), pj, QgsVertexId( iPart, iRing, jVert ) ) );
QgsAbstractGeometry *g = geom->clone();
g->transform( layerFeature.mapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsPointXY pos = layerFeature.mapToLayerTransform().transform( pj, QgsCoordinateTransform::ReverseTransform );
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), g, pos, QgsVertexId( iPart, iRing, jVert ) ) );
}
}
}

View File

@ -13,7 +13,6 @@
* *
***************************************************************************/
#include "qgscrscache.h"
#include "qgsgeometryengine.h"
#include "qgsgeometrygapcheck.h"
#include "qgsgeometrycollection.h"
@ -100,12 +99,11 @@ void QgsGeometryGapCheck::collectErrors( QList<QgsGeometryCheckError *> &errors,
for ( const QString &layerId : featureIds.keys() )
{
QgsFeaturePool *featurePool = mContext->featurePools[ layerId ];
QgsCoordinateTransform t = QgsCoordinateTransformCache::instance()->transform( mContext->mapCrs, featurePool->getLayer()->crs().authid() );
QgsRectangle gapAreaLayerBBox = t.transform( gapGeom->boundingBox() ); // Don't use gapAreaBBox since it is updated below
QgsRectangle gapAreaLayerBBox = featurePool->getMapToLayerTransform().transform( gapGeom->boundingBox() ); // Don't use gapAreaBBox since it is updated below
QgsFeatureIds intersectIds = featurePool->getIntersects( gapAreaLayerBBox );
QgsAbstractGeometry *gapLayerGeom = gapGeom->clone();
gapLayerGeom->transform( t );
gapLayerGeom->transform( featurePool->getMapToLayerTransform() );
for ( QgsFeatureId id : intersectIds )
{
@ -118,9 +116,9 @@ void QgsGeometryGapCheck::collectErrors( QList<QgsGeometryCheckError *> &errors,
if ( QgsGeometryCheckerUtils::sharedEdgeLength( gapLayerGeom, featureGeom, mContext->reducedTolerance ) > 0 )
{
neighboringIds[layerId].insert( feature.id() );
gapAreaLayerBBox.unionRect( featureGeom->boundingBox() );
gapAreaLayerBBox.combineExtentWith( featureGeom->boundingBox() );
}
gapAreaBBox.unionRect( t.transform( gapAreaLayerBBox, QgsCoordinateTransform::ReverseTransform ) );
gapAreaBBox.combineExtentWith( featurePool->getMapToLayerTransform().transform( gapAreaLayerBBox, QgsCoordinateTransform::ReverseTransform ) );
}
delete gapLayerGeom;
}
@ -170,15 +168,14 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( QgsGeometryGapCheckError *err, Chan
QgsFeature mergeFeature;
int mergePartIdx = -1;
QgsAbstractGeometry *errGeometry = QgsGeometryCheckerUtils::getGeomPart( err->geometry(), 0 );
const QgsAbstractGeometry *errGeometry = QgsGeometryCheckerUtils::getGeomPart( err->geometry(), 0 );
// Search for touching neighboring geometries
for ( const QString &layerId : err->neighbors().keys() )
{
QgsFeaturePool *featurePool = mContext->featurePools[ err->layerId() ];
QgsCoordinateTransform t = QgsCoordinateTransformCache::instance()->transform( mContext->mapCrs, featurePool->getLayer()->crs().authid() );
QgsAbstractGeometry *errLayerGeom = errGeometry->clone();
errLayerGeom->transform( t );
errLayerGeom->transform( featurePool->getMapToLayerTransform() );
for ( QgsFeatureId testId : err->neighbors()[layerId] )
{
@ -211,9 +208,8 @@ bool QgsGeometryGapCheck::mergeWithNeighbor( QgsGeometryGapCheckError *err, Chan
// Merge geometries
QgsFeaturePool *featurePool = mContext->featurePools[ mergeLayerId ];
QgsCoordinateTransform t = QgsCoordinateTransformCache::instance()->transform( mContext->mapCrs, featurePool->getLayer()->crs().authid() );
QgsAbstractGeometry *errLayerGeom = errGeometry->clone();
errLayerGeom->transform( t );
errLayerGeom->transform( featurePool->getMapToLayerTransform() );
QgsGeometry mergeFeatureGeom = mergeFeature.geometry();
QgsAbstractGeometry *mergeGeom = mergeFeatureGeom.geometry();
QSharedPointer<QgsGeometryEngine> geomEngine = QgsGeometryCheckerUtils::createGeomEngine( errLayerGeom, mContext->tolerance );

View File

@ -28,7 +28,10 @@ void QgsGeometryHoleCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
// Rings after the first one are interiors
for ( int iRing = 1, nRings = geom->ringCount( iPart ); iRing < nRings; ++iRing )
{
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), geom->clone(), QgsGeometryCheckerUtils::getGeomPart( geom, iPart )->centroid(), QgsVertexId( iPart, iRing ) ) );
QgsAbstractGeometry *g = geom->clone();
g->transform( layerFeature.mapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsPointXY pos = layerFeature.mapToLayerTransform().transform( QgsGeometryCheckerUtils::getGeomPart( geom, iPart )->centroid(), QgsCoordinateTransform::ReverseTransform );
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), g, pos, QgsVertexId( iPart, iRing ) ) );
}
}
}

View File

@ -26,7 +26,10 @@ void QgsGeometryMultipartCheck::collectErrors( QList<QgsGeometryCheckError *> &e
QgsWkbTypes::Type type = geom->wkbType();
if ( geom->partCount() == 1 && QgsWkbTypes::isMultiType( type ) )
{
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), geom->clone(), geom->centroid() ) );
QgsAbstractGeometry *g = geom->clone();
g->transform( layerFeature.mapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsPoint pos = g->centroid();
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), g, pos ) );
}
}
}

View File

@ -13,7 +13,6 @@
* *
***************************************************************************/
#include "qgscrscache.h"
#include "qgsgeometryengine.h"
#include "qgsgeometryoverlapcheck.h"
#include "../utils/qgsfeaturepool.h"
@ -81,16 +80,14 @@ void QgsGeometryOverlapCheck::fixError( QgsGeometryCheckError *error, int method
error->setObsolete();
return;
}
QgsCoordinateTransform crstA = QgsCoordinateTransformCache::instance()->transform( featurePoolA->getLayer()->crs().authid(), mContext->mapCrs );
QgsCoordinateTransform crstB = QgsCoordinateTransformCache::instance()->transform( featurePoolB->getLayer()->crs().authid(), mContext->mapCrs );
// Check if error still applies
QgsAbstractGeometry *featureGeomA = featureA.geometry().geometry()->clone();
featureGeomA->transform( crstA );
featureGeomA->transform( featurePoolA->getMapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QSharedPointer<QgsGeometryEngine> geomEngineA = QgsGeometryCheckerUtils::createGeomEngine( featureGeomA, mContext->reducedTolerance );
QgsAbstractGeometry *featureGeomB = featureB.geometry().geometry()->clone();
featureGeomB->transform( crstB );
featureGeomB->transform( featurePoolB->getMapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
if ( !geomEngineA->overlaps( *featureGeomB ) )
{

View File

@ -25,7 +25,7 @@ class QgsGeometryOverlapCheckError : public QgsGeometryCheckError
const QString &layerId,
QgsFeatureId featureId,
QgsAbstractGeometry *geometry,
const QgsPoint &errorLocation,
const QgsPointXY &errorLocation,
const QVariant &value,
const QPair<QString, QgsFeatureId> &overlappedFeature )
: QgsGeometryCheckError( check, layerId, featureId, geometry, errorLocation, QgsVertexId(), value, ValueArea )

View File

@ -43,7 +43,10 @@ void QgsGeometrySegmentLengthCheck::collectErrors( QList<QgsGeometryCheckError *
double dist = qSqrt( QgsGeometryUtils::sqrDistance2D( pi, pj ) );
if ( dist < minLength )
{
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), layerFeature.geometry()->clone(), QgsPoint( 0.5 * ( pi.x() + pj.x() ), 0.5 * ( pi.y() + pj.y() ) ), QgsVertexId( iPart, iRing, iVert ), dist / mapToLayerUnits, QgsGeometryCheckError::ValueLength ) );
QgsAbstractGeometry *g = layerFeature.geometry()->clone();
g->transform( layerFeature.mapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsPointXY pos = layerFeature.mapToLayerTransform().transform( QgsPoint( 0.5 * ( pi.x() + pj.x() ), 0.5 * ( pi.y() + pj.y() ) ), QgsCoordinateTransform::ReverseTransform );
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), g, pos, QgsVertexId( iPart, iRing, iVert ), dist / mapToLayerUnits, QgsGeometryCheckError::ValueLength ) );
}
}
}

View File

@ -26,7 +26,7 @@ void QgsGeometrySelfContactCheck::collectErrors( QList<QgsGeometryCheckError *>
// Geometry ring without duplicate nodes
QVector<int> vtxMap;
QVector<QgsPointV2> ring;
QVector<QgsPoint> ring;
vtxMap.append( 0 );
ring.append( geom->vertexAt( QgsVertexId( iPart, iRing, 0 ) ) );
for ( int i = 1; i < n; ++i )
@ -53,7 +53,7 @@ void QgsGeometrySelfContactCheck::collectErrors( QList<QgsGeometryCheckError *>
// For each vertex, check whether it lies on a segment
for ( int iVert = 0, nVerts = n - isClosed; iVert < nVerts; ++iVert )
{
const QgsPointV2 &p = ring[iVert];
const QgsPoint &p = ring[iVert];
for ( int i = 0, j = 1; j < n; i = j++ )
{
if ( iVert == i || iVert == j || ( isClosed && iVert == 0 && j == n - 1 ) )
@ -65,7 +65,10 @@ void QgsGeometrySelfContactCheck::collectErrors( QList<QgsGeometryCheckError *>
QgsPoint q = QgsGeometryUtils::projPointOnSegment( p, si, sj );
if ( QgsGeometryUtils::sqrDistance2D( p, q ) < mContext->tolerance * mContext->tolerance )
{
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), geom->clone(), p, QgsVertexId( iPart, iRing, vtxMap[iVert] ) ) );
QgsAbstractGeometry *g = geom->clone();
g->transform( layerFeature.mapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsPointXY pos = layerFeature.mapToLayerTransform().transform( p, QgsCoordinateTransform::ReverseTransform );
errors.append( new QgsGeometryCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), g, pos, QgsVertexId( iPart, iRing, vtxMap[iVert] ) ) );
break; // No need to report same contact on different segments multiple times
}
}

View File

@ -73,7 +73,10 @@ void QgsGeometrySelfIntersectionCheck::collectErrors( QList<QgsGeometryCheckErro
{
for ( const QgsGeometryUtils::SelfIntersection &inter : QgsGeometryUtils::getSelfIntersections( geom, iPart, iRing, mContext->tolerance ) )
{
errors.append( new QgsGeometrySelfIntersectionCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), geom->clone(), inter.point, QgsVertexId( iPart, iRing ), inter ) );
QgsAbstractGeometry *g = geom->clone();
g->transform( layerFeature.mapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsPointXY pos = layerFeature.mapToLayerTransform().transform( inter.point, QgsCoordinateTransform::ReverseTransform );
errors.append( new QgsGeometrySelfIntersectionCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), geom->clone(), pos, QgsVertexId( iPart, iRing ), inter ) );
}
}
}

View File

@ -26,7 +26,7 @@ class QgsGeometrySelfIntersectionCheckError : public QgsGeometryCheckError
const QString &layerId,
QgsFeatureId featureId,
QgsAbstractGeometry *geometry,
const QgsPoint &errorLocation,
const QgsPointXY &errorLocation,
QgsVertexId vidx,
const QgsGeometryUtils::SelfIntersection &inter )
: QgsGeometryCheckError( check, layerId, featureId, geometry, errorLocation, vidx )

View File

@ -33,7 +33,10 @@ void QgsGeometryTypeCheck::collectErrors( QList<QgsGeometryCheckError *> &errors
QgsWkbTypes::Type type = QgsWkbTypes::flatType( geom->wkbType() );
if ( ( mAllowedTypes & ( 1 << type ) ) == 0 )
{
errors.append( new QgsGeometryTypeCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), geom->clone(), geom->centroid(), type ) );
QgsAbstractGeometry *g = geom->clone();
g->transform( layerFeature.mapToLayerTransform(), QgsCoordinateTransform::ReverseTransform );
QgsPoint pos = g->centroid();
errors.append( new QgsGeometryTypeCheckError( this, layerFeature.layer().id(), layerFeature.feature().id(), g, pos, type ) );
}
}
}

View File

@ -25,7 +25,7 @@ class QgsGeometryTypeCheckError : public QgsGeometryCheckError
const QString &layerId,
QgsFeatureId featureId,
QgsAbstractGeometry *geometry,
const QgsPoint &errorLocation,
const QgsPointXY &errorLocation,
QgsWkbTypes::Type flatType )
: QgsGeometryCheckError( check, layerId, featureId, geometry, errorLocation )
{

View File

@ -268,8 +268,7 @@ bool QgsGeometryCheckerResultTab::exportErrorsDo( const QString &file )
f.setAttribute( fieldLayer, srcLayer->name() );
f.setAttribute( fieldFeatureId, error->featureId() );
f.setAttribute( fieldErrDesc, error->description() );
QgsGeometry geom( error->location().clone() );
geom.transform( QgsCoordinateTransformCache::instance()->transform( srcLayer->crs().authid(), layer->crs().authid() ) );
QgsGeometry geom( new QgsPoint( error->location() ) );
f.setGeometry( geom );
layer->dataProvider()->addFeatures( QgsFeatureList() << f );
}
@ -324,14 +323,13 @@ void QgsGeometryCheckerResultTab::highlightErrors( bool current )
for ( QTableWidgetItem *item : items )
{
QgsGeometryCheckError *error = ui.tableWidgetErrors->item( item->row(), 0 )->data( Qt::UserRole ).value<QgsGeometryCheckError *>();
QgsVectorLayer *layer = !error->layerId().isEmpty() ? mChecker->getContext()->featurePools[error->layerId()]->getLayer() : nullptr;
QgsAbstractGeometry *geometry = error->geometry();
const QgsAbstractGeometry *geometry = error->geometry();
if ( ui.checkBoxHighlight->isChecked() && geometry )
{
QgsRubberBand *featureRubberBand = new QgsRubberBand( mIface->mapCanvas() );
QgsGeometry geom( geometry->clone() );
featureRubberBand->addGeometry( geom, layer );
featureRubberBand->addGeometry( geom, 0 );
featureRubberBand->setWidth( 5 );
featureRubberBand->setColor( Qt::yellow );
mCurrentRubberBands.append( featureRubberBand );
@ -340,12 +338,11 @@ void QgsGeometryCheckerResultTab::highlightErrors( bool current )
if ( ui.radioButtonError->isChecked() || current || error->status() == QgsGeometryCheckError::StatusFixed )
{
QgsRubberBand *pointRubberBand = new QgsRubberBand( mIface->mapCanvas(), QgsWkbTypes::PointGeometry );
QgsPoint pos = mIface->mapCanvas()->mapSettings().layerToMapCoordinates( layer, QgsPointXY( error->location().x(), error->location().y() ) );
pointRubberBand->addPoint( pos );
pointRubberBand->addPoint( error->location() );
pointRubberBand->setWidth( 20 );
pointRubberBand->setColor( Qt::red );
mCurrentRubberBands.append( pointRubberBand );
errorPositions.append( pos );
errorPositions.append( error->location() );
}
else if ( ui.radioButtonFeature->isChecked() )
{

View File

@ -24,6 +24,7 @@
#include "qgsfeatureiterator.h"
#include "qgisinterface.h"
#include "qgscrscache.h"
#include "qgsproject.h"
#include "qgsvectorlayer.h"
#include "qgsmapcanvas.h"
@ -64,7 +65,7 @@ QgsGeometryCheckerSetupTab::QgsGeometryCheckerSetupTab( QgisInterface *iface, QW
}
connect( mRunButton, &QAbstractButton::clicked, this, &QgsGeometryCheckerSetupTab::runChecks );
connect( ui.listWidgetInputLayers, &QListWidgetItem::itemChanged, this, &QgsGeometryCheckerSetupTab::validateInput() );
connect( ui.listWidgetInputLayers, &QListWidget::itemChanged, this, &QgsGeometryCheckerSetupTab::validateInput );
connect( QgsProject::instance(), &QgsProject::layersAdded, this, &QgsGeometryCheckerSetupTab::updateLayers );
connect( QgsProject::instance(), static_cast<void ( QgsProject::* )( const QStringList & )>( &QgsProject::layersWillBeRemoved ), this, &QgsGeometryCheckerSetupTab::updateLayers );
connect( ui.radioButtonOutputNew, &QAbstractButton::toggled, ui.frameOutput, &QWidget::setEnabled );
@ -397,7 +398,8 @@ void QgsGeometryCheckerSetupTab::runChecks()
for ( QgsVectorLayer *layer : processLayers )
{
double mapToLayerUnits = 1. / mIface->mapCanvas()->mapSettings().layerToMapUnits( layer );
featurePools.insert( layer->id(), new QgsFeaturePool( layer, mapToLayerUnits, selectedOnly ) );
QgsCoordinateTransform mapToLayerTransform = QgsCoordinateTransformCache::instance()->transform( mIface->mapCanvas()->mapSettings().destinationCrs().authid(), layer->crs().authid() );
featurePools.insert( layer->id(), new QgsFeaturePool( layer, mapToLayerUnits, mapToLayerTransform, selectedOnly ) );
}
QgsGeometryCheckerContext *context = new QgsGeometryCheckerContext( ui.spinBoxTolerance->value(), mIface->mapCanvas()->mapSettings().destinationCrs().authid(), featurePools );

View File

@ -25,10 +25,11 @@
#include <QMutexLocker>
#include <limits>
QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer, double mapToLayerUnits, bool selectedOnly )
QgsFeaturePool::QgsFeaturePool( QgsVectorLayer *layer, double mapToLayerUnits, const QgsCoordinateTransform &mapToLayerTransform, bool selectedOnly )
: mFeatureCache( CACHE_SIZE )
, mLayer( layer )
, mMapToLayerUnits( mapToLayerUnits )
, mMapToLayerTransform( mapToLayerTransform )
, mSelectedOnly( selectedOnly )
{
if ( selectedOnly )

View File

@ -30,7 +30,7 @@ class QgsVectorLayer;
class QgsFeaturePool
{
public:
QgsFeaturePool( QgsVectorLayer *layer, double mapToLayerUnits, bool selectedOnly = false );
QgsFeaturePool( QgsVectorLayer *layer, double mapToLayerUnits, const QgsCoordinateTransform &mapToLayerTransform, bool selectedOnly = false );
bool get( QgsFeatureId id, QgsFeature &feature );
void addFeature( QgsFeature &feature );
void updateFeature( QgsFeature &feature );
@ -38,7 +38,8 @@ class QgsFeaturePool
QgsFeatureIds getIntersects( const QgsRectangle &rect ) const;
QgsVectorLayer *getLayer() const { return mLayer; }
const QgsFeatureIds &getFeatureIds() const { return mFeatureIds; }
double getMapToLayerUnits() const { return mMapToLayerUnits;}
double getMapToLayerUnits() const { return mMapToLayerUnits; }
const QgsCoordinateTransform &getMapToLayerTransform() const { return mMapToLayerTransform; }
bool getSelectedOnly() const { return mSelectedOnly; }
void clearLayer() { mLayer = nullptr; }
@ -62,6 +63,7 @@ class QgsFeaturePool
mutable QMutex mIndexMutex;
QgsSpatialIndex mIndex;
double mMapToLayerUnits;
QgsCoordinateTransform mMapToLayerTransform;
bool mSelectedOnly;
bool getTouchingWithSharedEdge( QgsFeature &feature, QgsFeatureId &touchingId, const double & ( *comparator )( const double &, const double & ), double init );

View File

@ -25,19 +25,19 @@
namespace QgsGeometryCheckerUtils
{
LayerFeature::LayerFeature( const QgsVectorLayer *layer, const QgsFeature &feature, double mapToLayerUnits, const QString &targetCrs )
LayerFeature::LayerFeature( const QgsVectorLayer *layer, const QgsFeature &feature, double mapToLayerUnits, const QgsCoordinateTransform &mapToLayerTransform )
: mLayer( layer )
, mFeature( feature )
, mMapToLayerUnits( mapToLayerUnits )
, mMapToLayerTransform( mapToLayerTransform )
, mClonedGeometry( false )
{
mGeometry = feature.geometry().geometry();
if ( !targetCrs.isEmpty() && targetCrs != layer->crs().authid() )
if ( !mapToLayerTransform.isShortCircuited() )
{
mClonedGeometry = true;
mGeometry = mGeometry->clone();
QgsCoordinateTransform crst = QgsCoordinateTransformCache::instance()->transform( layer->crs().authid(), targetCrs );
mGeometry->transform( crst );
mGeometry->transform( mapToLayerTransform, QgsCoordinateTransform::ReverseTransform );
}
}
LayerFeature::~LayerFeature()
@ -55,7 +55,7 @@ namespace QgsGeometryCheckerUtils
, mFeatureIt( featureIt )
, mFeature( feature )
, mParent( parent )
, mCurrentFeature( LayerFeature( parent->mFeaturePools[ * layerIt]->getLayer(), feature, parent->mFeaturePools[ * layerIt]->getMapToLayerUnits(), parent->mTargetCrs ) )
, mCurrentFeature( LayerFeature( parent->mFeaturePools[ * layerIt]->getLayer(), feature, parent->mFeaturePools[ * layerIt]->getMapToLayerUnits(), parent->mFeaturePools[ * layerIt]->getMapToLayerTransform() ) )
{
}
@ -89,7 +89,7 @@ namespace QgsGeometryCheckerUtils
mParent->mProgressCounter->fetchAndAddRelaxed( 1 );
if ( featurePool->get( *mFeatureIt, mFeature ) )
{
mCurrentFeature = LayerFeature( mParent->mFeaturePools[*mLayerIt]->getLayer(), mFeature, mParent->mFeaturePools[*mLayerIt]->getMapToLayerUnits(), mParent->mTargetCrs );
mCurrentFeature = LayerFeature( mParent->mFeaturePools[*mLayerIt]->getLayer(), mFeature, mParent->mFeaturePools[*mLayerIt]->getMapToLayerUnits(), mParent->mFeaturePools[*mLayerIt]->getMapToLayerTransform() );
return true;
}
}
@ -125,8 +125,7 @@ namespace QgsGeometryCheckerUtils
const QgsFeaturePool *featurePool = featurePools[layerId];
if ( geometryTypes.contains( featurePool->getLayer()->geometryType() ) )
{
QgsCoordinateTransform crst = QgsCoordinateTransformCache::instance()->transform( targetCrs, featurePool->getLayer()->crs().authid() );
mFeatureIds.insert( layerId, featurePool->getIntersects( crst.transform( extent ) ) );
mFeatureIds.insert( layerId, featurePool->getIntersects( featurePool->getMapToLayerTransform().transform( extent ) ) );
}
else
{

View File

@ -17,7 +17,6 @@
#ifndef QGS_GEOMETRYCHECKERUTILS_H
#define QGS_GEOMETRYCHECKERUTILS_H
#include "qgscrscache.h"
#include "qgsfeature.h"
#include "qgsvectorlayer.h"
#include "geometry/qgsabstractgeometry.h"
@ -31,11 +30,12 @@ namespace QgsGeometryCheckerUtils
class LayerFeature
{
public:
LayerFeature( const QgsVectorLayer *layer, const QgsFeature &feature, double mapToLayerUnits, const QString &targetCrs );
LayerFeature( const QgsVectorLayer *layer, const QgsFeature &feature, double mapToLayerUnits, const QgsCoordinateTransform &mapToLayerTransform );
~LayerFeature();
const QgsVectorLayer &layer() const { return *mLayer; }
const QgsFeature &feature() const { return mFeature; }
double mapToLayerUnits() const { return mMapToLayerUnits; }
const QgsCoordinateTransform &mapToLayerTransform() const { return mMapToLayerTransform; }
const QgsAbstractGeometry *geometry() const { return mGeometry; }
QString id() const { return QString( "%1:%2" ).arg( mLayer->id() ).arg( mFeature.id() ); }
@ -43,6 +43,7 @@ namespace QgsGeometryCheckerUtils
const QgsVectorLayer *mLayer = nullptr;
QgsFeature mFeature;
double mMapToLayerUnits;
QgsCoordinateTransform mMapToLayerTransform;
QgsAbstractGeometry *mGeometry = nullptr;
bool mClonedGeometry = false;
};
@ -132,7 +133,7 @@ namespace QgsGeometryCheckerUtils
* \param tol The tolerance
* \returns Whether the points are equal
*/
inline bool pointsFuzzyEqual( const QgsPoint &p1, const QgsPoint &p2, double tol )
inline bool pointsFuzzyEqual( const QgsPointXY &p1, const QgsPointXY &p2, double tol )
{
double dx = p1.x() - p2.x(), dy = p1.y() - p2.y();
return ( dx * dx + dy * dy ) < tol * tol;