Skip to content

Commit 66b0e59

Browse files
committedApr 23, 2018
Fix snapping on invisible geometry
1 parent 5e33d7d commit 66b0e59

14 files changed

+273
-125
lines changed
 

‎python/core/qgspointlocator.sip.in

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,13 @@ Get extent of the area point locator covers - if null then it caches the whole l
7171
Configure extent - if not null, it will index only that area
7272

7373
.. versionadded:: 2.14
74+
%End
75+
76+
void setRenderContext( const QgsRenderContext &context );
77+
%Docstring
78+
Configure render context - if not null, it will use to index only visible feature
79+
80+
.. versionadded:: 3.2
7481
%End
7582

7683
enum Type
@@ -199,7 +206,6 @@ Override of edgesInRect that construct rectangle from a center point and toleran
199206
find out if the point is in any polygons
200207
%End
201208

202-
203209
int cachedGeometryCount() const;
204210
%Docstring
205211
Return how many geometries are cached in the index

‎python/core/qgssnappingutils.sip.in

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ which keeps the configuration in sync with map canvas (e.g. current view, active
3535
%End
3636
public:
3737

38-
QgsSnappingUtils( QObject *parent /TransferThis/ = 0 );
38+
QgsSnappingUtils( QObject *parent /TransferThis/ = 0, bool enableSnappingForInvisibleFeature = true );
3939
%Docstring
4040
Constructor for QgsSnappingUtils
4141
%End
@@ -139,6 +139,15 @@ Get extra information about the instance
139139
QgsSnappingConfig config() const;
140140
%Docstring
141141
The snapping configuration controls the behavior of this object
142+
%End
143+
144+
void setEnableSnappingForInvisibleFeature( bool enable );
145+
%Docstring
146+
Set if invisible features must be snapped or not.
147+
148+
:param enable: Enable or not this feature
149+
150+
.. versionadded:: 3.2
142151
%End
143152

144153
public slots:

‎python/gui/qgsmapcanvassnappingutils.sip.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010

1111

12+
1213
class QgsMapCanvasSnappingUtils : QgsSnappingUtils
1314
{
1415
%Docstring

‎resources/qgis_global_settings.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ digitizing\default_snap_type=1
2020
# 2 = Project units
2121
digitizing\default_snapping_tolerance_unit=1
2222

23+
# Snap on invisble feature
24+
digitizing\snap_invisible_feature=false
25+
2326
# Default XYZ tile servers to include
2427
connections-xyz\OpenStreetMap\authcfg=
2528
connections-xyz\OpenStreetMap\password=

‎src/app/qgsoptions.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,7 @@ QgsOptions::QgsOptions( QWidget *parent, Qt::WindowFlags fl, const QList<QgsOpti
971971

972972
mSnappingMarkerColorButton->setColor( mSettings->value( QStringLiteral( "/qgis/digitizing/snap_color" ), QColor( Qt::magenta ) ).value<QColor>() );
973973
mSnappingTooltipsCheckbox->setChecked( mSettings->value( QStringLiteral( "/qgis/digitizing/snap_tooltip" ), false ).toBool() );
974+
mEnableSnappingOnInvisibleFeatureCheckbox->setChecked( mSettings->value( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), false ).toBool() );
974975

975976
//vertex marker
976977
mMarkersOnlyForSelectedCheckBox->setChecked( mSettings->value( QStringLiteral( "/qgis/digitizing/marker_only_for_selected" ), true ).toBool() );
@@ -1483,6 +1484,7 @@ void QgsOptions::saveOptions()
14831484

14841485
mSettings->setValue( QStringLiteral( "/qgis/digitizing/snap_color" ), mSnappingMarkerColorButton->color() );
14851486
mSettings->setValue( QStringLiteral( "/qgis/digitizing/snap_tooltip" ), mSnappingTooltipsCheckbox->isChecked() );
1487+
mSettings->setValue( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), mEnableSnappingOnInvisibleFeatureCheckbox->isChecked() );
14861488

14871489
mSettings->setValue( QStringLiteral( "/qgis/digitizing/marker_only_for_selected" ), mMarkersOnlyForSelectedCheckBox->isChecked() );
14881490

‎src/core/layertree/qgslayertreemodellegendnode.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ bool QgsSymbolLegendNode::setData( const QVariant &value, int role )
331331
vlayer->renderer()->checkLegendSymbolItem( mItem.ruleKey(), value == Qt::Checked );
332332

333333
emit dataChanged();
334+
emit vlayer->styleChanged();
334335

335336
vlayer->triggerRepaint();
336337

‎src/core/qgspointlocator.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "qgswkbptr.h"
2222
#include "qgis.h"
2323
#include "qgslogger.h"
24+
#include "qgsrenderer.h"
2425

2526
#include <SpatialIndex.h>
2627

@@ -636,6 +637,9 @@ QgsPointLocator::QgsPointLocator( QgsVectorLayer *layer, const QgsCoordinateRefe
636637
connect( mLayer, &QgsVectorLayer::featureDeleted, this, &QgsPointLocator::onFeatureDeleted );
637638
connect( mLayer, &QgsVectorLayer::geometryChanged, this, &QgsPointLocator::onGeometryChanged );
638639
connect( mLayer, &QgsVectorLayer::dataChanged, this, &QgsPointLocator::destroyIndex );
640+
connect( mLayer, &QgsVectorLayer::rendererChanged, this, &QgsPointLocator::destroyIndex );
641+
connect( mLayer, &QgsVectorLayer::styleChanged, this, &QgsPointLocator::destroyIndex );
642+
connect( mLayer, &QgsVectorLayer::layerModified, this, &QgsPointLocator::destroyIndex );
639643
}
640644

641645

@@ -661,6 +665,12 @@ void QgsPointLocator::setExtent( const QgsRectangle *extent )
661665
destroyIndex();
662666
}
663667

668+
void QgsPointLocator::setRenderContext( const QgsRenderContext &context )
669+
{
670+
mContext = std::unique_ptr<QgsRenderContext>( new QgsRenderContext( context ) );
671+
672+
destroyIndex();
673+
}
664674

665675
bool QgsPointLocator::init( int maxFeaturesToIndex )
666676
{
@@ -686,6 +696,7 @@ bool QgsPointLocator::rebuildIndex( int maxFeaturesToIndex )
686696

687697
QgsFeatureRequest request;
688698
request.setSubsetOfAttributes( QgsAttributeList() );
699+
689700
if ( mExtent )
690701
{
691702
QgsRectangle rect = *mExtent;
@@ -704,13 +715,40 @@ bool QgsPointLocator::rebuildIndex( int maxFeaturesToIndex )
704715
}
705716
request.setFilterRect( rect );
706717
}
718+
719+
bool filter = false;
720+
std::unique_ptr< QgsFeatureRenderer > renderer( mLayer->renderer() ? mLayer->renderer()->clone() : nullptr );
721+
QgsRenderContext *ctx = nullptr;
722+
if ( mContext )
723+
{
724+
mContext->expressionContext() << QgsExpressionContextUtils::layerScope( mLayer );
725+
ctx = mContext.get();
726+
if ( renderer )
727+
{
728+
// setup scale for scale dependent visibility (rule based)
729+
renderer->startRender( *ctx, mLayer->fields() );
730+
filter = renderer->capabilities() & QgsFeatureRenderer::Filter;
731+
request.setSubsetOfAttributes( renderer->usedAttributes( *ctx ), mLayer->fields() );
732+
}
733+
}
734+
707735
QgsFeatureIterator fi = mLayer->getFeatures( request );
708736
int indexedCount = 0;
737+
709738
while ( fi.nextFeature( f ) )
710739
{
711740
if ( !f.hasGeometry() )
712741
continue;
713742

743+
if ( ctx && renderer )
744+
{
745+
ctx->expressionContext().setFeature( f );
746+
if ( filter && !renderer->willRenderFeature( f, *ctx ) )
747+
{
748+
continue;
749+
}
750+
}
751+
714752
if ( mTransform.isValid() )
715753
{
716754
try
@@ -761,6 +799,12 @@ bool QgsPointLocator::rebuildIndex( int maxFeaturesToIndex )
761799
QgsPointLocator_Stream stream( dataList );
762800
mRTree = RTree::createAndBulkLoadNewRTree( RTree::BLM_STR, stream, *mStorage, fillFactor, indexCapacity,
763801
leafCapacity, dimension, variant, indexId );
802+
803+
if ( ctx && renderer )
804+
{
805+
renderer->stopRender( *ctx );
806+
renderer.release();
807+
}
764808
return true;
765809
}
766810

@@ -832,6 +876,7 @@ void QgsPointLocator::onFeatureDeleted( QgsFeatureId fid )
832876
mRTree->deleteData( rect2region( mGeoms[fid]->boundingBox() ), fid );
833877
delete mGeoms.take( fid );
834878
}
879+
835880
}
836881

837882
void QgsPointLocator::onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom )

‎src/core/qgspointlocator.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,15 @@
1818

1919
class QgsPointXY;
2020
class QgsVectorLayer;
21+
class QgsFeatureRenderer;
22+
class QgsRenderContext;
2123

2224
#include "qgis_core.h"
2325
#include "qgsfeature.h"
2426
#include "qgspointxy.h"
2527
#include "qgscoordinatereferencesystem.h"
2628
#include "qgscoordinatetransform.h"
29+
#include <memory>
2730

2831
class QgsPointLocator_VisitorNearestVertex;
2932
class QgsPointLocator_VisitorNearestEdge;
@@ -92,6 +95,12 @@ class CORE_EXPORT QgsPointLocator : public QObject
9295
*/
9396
void setExtent( const QgsRectangle *extent );
9497

98+
/**
99+
* Configure render context - if not null, it will use to index only visible feature
100+
* \since QGIS 3.2
101+
*/
102+
void setRenderContext( const QgsRenderContext &context );
103+
95104
/**
96105
* The type of a snap result or the filter type for a snap request.
97106
*/
@@ -251,8 +260,6 @@ class CORE_EXPORT QgsPointLocator : public QObject
251260
//! find out if the point is in any polygons
252261
MatchList pointInPolygon( const QgsPointXY &point );
253262

254-
//
255-
256263
/**
257264
* Return how many geometries are cached in the index
258265
* \since QGIS 2.14
@@ -278,11 +285,15 @@ class CORE_EXPORT QgsPointLocator : public QObject
278285
//! flag whether the layer is currently empty (i.e. mRTree is null but it is not necessary to rebuild it)
279286
bool mIsEmptyLayer;
280287

288+
QgsFeatureIds mFeatureIds;
289+
281290
//! R-tree containing spatial index
282291
QgsCoordinateTransform mTransform;
283292
QgsVectorLayer *mLayer = nullptr;
284293
QgsRectangle *mExtent = nullptr;
285294

295+
std::unique_ptr<QgsRenderContext> mContext;
296+
286297
friend class QgsPointLocator_VisitorNearestVertex;
287298
friend class QgsPointLocator_VisitorNearestEdge;
288299
friend class QgsPointLocator_VisitorArea;

‎src/core/qgssnappingutils.cpp

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,12 @@
1919
#include "qgsproject.h"
2020
#include "qgsvectorlayer.h"
2121
#include "qgslogger.h"
22+
#include "qgsrenderer.h"
2223

23-
QgsSnappingUtils::QgsSnappingUtils( QObject *parent )
24+
QgsSnappingUtils::QgsSnappingUtils( QObject *parent, bool enableSnappingForInvisibleFeature )
2425
: QObject( parent )
2526
, mSnappingConfig( QgsProject::instance() )
27+
, mEnableSnappingForInvisibleFeature( enableSnappingForInvisibleFeature )
2628
{
2729
}
2830

@@ -92,7 +94,6 @@ bool QgsSnappingUtils::isIndexPrepared( QgsVectorLayer *vl, const QgsRectangle &
9294
return ( mStrategy == IndexHybrid || mStrategy == IndexExtent ) && loc->hasIndex() && ( !loc->extent() || loc->extent()->contains( aoi ) ); // the index - even if it exists - is not suitable
9395
}
9496

95-
9697
static QgsPointLocator::Match _findClosestSegmentIntersection( const QgsPointXY &pt, const QgsPointLocator::MatchList &segments )
9798
{
9899
if ( segments.isEmpty() )
@@ -156,9 +157,9 @@ static QgsPointLocator::Match _findClosestSegmentIntersection( const QgsPointXY
156157
return QgsPointLocator::Match( QgsPointLocator::Vertex, nullptr, 0, std::sqrt( minSqrDist ), minP );
157158
}
158159

159-
160160
static void _replaceIfBetter( QgsPointLocator::Match &bestMatch, const QgsPointLocator::Match &candidateMatch, double maxDistance )
161161
{
162+
162163
// is candidate match relevant?
163164
if ( !candidateMatch.isValid() || candidateMatch.distance() > maxDistance )
164165
return;
@@ -174,7 +175,6 @@ static void _replaceIfBetter( QgsPointLocator::Match &bestMatch, const QgsPointL
174175
bestMatch = candidateMatch; // the other match is better!
175176
}
176177

177-
178178
static void _updateBestMatch( QgsPointLocator::Match &bestMatch, const QgsPointXY &pointMap, QgsPointLocator *loc, QgsPointLocator::Types type, double tolerance, QgsPointLocator::MatchFilter *filter )
179179
{
180180
if ( type & QgsPointLocator::Vertex )
@@ -329,7 +329,6 @@ QgsPointLocator::Match QgsSnappingUtils::snapToMap( const QgsPointXY &pointMap,
329329
return QgsPointLocator::Match();
330330
}
331331

332-
333332
void QgsSnappingUtils::prepareIndex( const QList<LayerAndAreaOfInterest> &layers )
334333
{
335334
if ( mIsIndexing )
@@ -341,6 +340,7 @@ void QgsSnappingUtils::prepareIndex( const QList<LayerAndAreaOfInterest> &layers
341340
Q_FOREACH ( const LayerAndAreaOfInterest &entry, layers )
342341
{
343342
QgsVectorLayer *vl = entry.first;
343+
344344
if ( vl->geometryType() == QgsWkbTypes::NullGeometry || mStrategy == IndexNeverFull )
345345
continue;
346346

@@ -359,7 +359,12 @@ void QgsSnappingUtils::prepareIndex( const QList<LayerAndAreaOfInterest> &layers
359359
QgsVectorLayer *vl = entry.first;
360360
QTime tt;
361361
tt.start();
362+
362363
QgsPointLocator *loc = locatorForLayer( vl );
364+
365+
if ( !mEnableSnappingForInvisibleFeature )
366+
loc->setRenderContext( QgsRenderContext::fromMapSettings( mMapSettings ) );
367+
363368
if ( mStrategy == IndexExtent )
364369
{
365370
QgsRectangle rect( mMapSettings.extent() );
@@ -428,6 +433,11 @@ QgsSnappingConfig QgsSnappingUtils::config() const
428433
return mSnappingConfig;
429434
}
430435

436+
void QgsSnappingUtils::setEnableSnappingForInvisibleFeature( bool enable )
437+
{
438+
mEnableSnappingForInvisibleFeature = enable;
439+
}
440+
431441
void QgsSnappingUtils::setConfig( const QgsSnappingConfig &config )
432442
{
433443
if ( mSnappingConfig == config )

‎src/core/qgssnappingutils.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ class CORE_EXPORT QgsSnappingUtils : public QObject
5353
public:
5454

5555
//! Constructor for QgsSnappingUtils
56-
QgsSnappingUtils( QObject *parent SIP_TRANSFERTHIS = nullptr );
56+
QgsSnappingUtils( QObject *parent SIP_TRANSFERTHIS = nullptr, bool enableSnappingForInvisibleFeature = true );
5757
~QgsSnappingUtils() override;
5858

5959
// main actions
@@ -159,6 +159,15 @@ class CORE_EXPORT QgsSnappingUtils : public QObject
159159
*/
160160
QgsSnappingConfig config() const;
161161

162+
/**
163+
* Set if invisible features must be snapped or not.
164+
*
165+
* \param enable Enable or not this feature
166+
*
167+
* \since QGIS 3.2
168+
*/
169+
void setEnableSnappingForInvisibleFeature( bool enable );
170+
162171
public slots:
163172

164173
/**
@@ -242,6 +251,10 @@ class CORE_EXPORT QgsSnappingUtils : public QObject
242251

243252
//! internal flag that an indexing process is going on. Prevents starting two processes in parallel.
244253
bool mIsIndexing = false;
254+
255+
//! Disable or not the snapping on all features. By default is always true except for non visible features on map canvas.
256+
bool mEnableSnappingForInvisibleFeature = true;
257+
245258
};
246259

247260

‎src/gui/qgsmapcanvassnappingutils.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,13 @@
1616

1717
#include "qgsmapcanvas.h"
1818
#include "qgsvectorlayer.h"
19+
#include "qgssettings.h"
1920

2021
#include <QApplication>
2122
#include <QProgressDialog>
2223

2324
QgsMapCanvasSnappingUtils::QgsMapCanvasSnappingUtils( QgsMapCanvas *canvas, QObject *parent )
24-
: QgsSnappingUtils( parent )
25+
: QgsSnappingUtils( parent, QgsSettings().value( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), false ).toBool() )
2526
, mCanvas( canvas )
2627

2728
{
@@ -30,13 +31,15 @@ QgsMapCanvasSnappingUtils::QgsMapCanvasSnappingUtils( QgsMapCanvas *canvas, QObj
3031
connect( canvas, &QgsMapCanvas::layersChanged, this, &QgsMapCanvasSnappingUtils::canvasMapSettingsChanged );
3132
connect( canvas, &QgsMapCanvas::currentLayerChanged, this, &QgsMapCanvasSnappingUtils::canvasCurrentLayerChanged );
3233
connect( canvas, &QgsMapCanvas::transformContextChanged, this, &QgsMapCanvasSnappingUtils::canvasTransformContextChanged );
34+
connect( canvas, &QgsMapCanvas::mapToolSet, this, &QgsMapCanvasSnappingUtils::canvasMapToolChanged );
3335
canvasMapSettingsChanged();
3436
canvasCurrentLayerChanged();
3537
}
3638

3739
void QgsMapCanvasSnappingUtils::canvasMapSettingsChanged()
3840
{
3941
setMapSettings( mCanvas->mapSettings() );
42+
setEnableSnappingForInvisibleFeature( QgsSettings().value( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), false ).toBool() );
4043
}
4144

4245
void QgsMapCanvasSnappingUtils::canvasTransformContextChanged()
@@ -51,6 +54,11 @@ void QgsMapCanvasSnappingUtils::canvasCurrentLayerChanged()
5154
setCurrentLayer( qobject_cast<QgsVectorLayer *>( mCanvas->currentLayer() ) );
5255
}
5356

57+
void QgsMapCanvasSnappingUtils::canvasMapToolChanged()
58+
{
59+
setEnableSnappingForInvisibleFeature( QgsSettings().value( QStringLiteral( "/qgis/digitizing/snap_invisible_feature" ), false ).toBool() );
60+
}
61+
5462
void QgsMapCanvasSnappingUtils::prepareIndexStarting( int count )
5563
{
5664
QApplication::setOverrideCursor( Qt::WaitCursor );

‎src/gui/qgsmapcanvassnappingutils.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
#include "qgssnappingutils.h"
1919
#include "qgis_gui.h"
2020

21+
#include "qgsmaptool.h"
22+
2123
class QgsMapCanvas;
2224

2325
class QProgressDialog;
@@ -42,6 +44,7 @@ class GUI_EXPORT QgsMapCanvasSnappingUtils : public QgsSnappingUtils
4244
void canvasMapSettingsChanged();
4345
void canvasTransformContextChanged();
4446
void canvasCurrentLayerChanged();
47+
void canvasMapToolChanged();
4548

4649
private:
4750
QgsMapCanvas *mCanvas = nullptr;

‎src/ui/qgsoptionsbase.ui

Lines changed: 111 additions & 106 deletions
Large diffs are not rendered by default.

‎tests/src/core/testqgssnappingutils.cpp

Lines changed: 39 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
#include "qgsproject.h"
2525
#include "qgssnappingutils.h"
2626
#include "qgssnappingconfig.h"
27-
27+
#include "qgscategorizedsymbolrenderer.h"
28+
#include "qgssettings.h"
2829

2930
struct FilterExcludePoint : public QgsPointLocator::MatchFilter
3031
{
@@ -44,6 +45,7 @@ class TestQgsSnappingUtils : public QObject
4445

4546
private:
4647
QgsVectorLayer *mVL = nullptr;
48+
QgsFeature f1, f2;
4749
private slots:
4850

4951
void initTestCase()
@@ -60,16 +62,29 @@ class TestQgsSnappingUtils : public QObject
6062
// \ |
6163
// \|
6264
// + (1,0)
63-
mVL = new QgsVectorLayer( QStringLiteral( "Polygon" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
64-
QgsFeature ff( 0 );
65+
mVL = new QgsVectorLayer( QStringLiteral( "Polygon?field=fld:int" ), QStringLiteral( "x" ), QStringLiteral( "memory" ) );
66+
int idx = mVL->fields().indexFromName( QStringLiteral( "fld" ) );
67+
QVERIFY( idx != -1 );
68+
f1.initAttributes( 1 );
69+
f2.initAttributes( 1 );
70+
6571
QgsPolygonXY polygon;
6672
QgsPolylineXY polyline;
6773
polyline << QgsPointXY( 0, 1 ) << QgsPointXY( 1, 0 ) << QgsPointXY( 1, 1 ) << QgsPointXY( 0, 1 );
6874
polygon << polyline;
6975
QgsGeometry polygonGeom = QgsGeometry::fromPolygonXY( polygon );
70-
ff.setGeometry( polygonGeom );
76+
f1.setGeometry( polygonGeom );
77+
f1.setAttribute( idx, QVariant( 2 ) );
78+
79+
polyline << QgsPointXY( 10, 11 ) << QgsPointXY( 11, 10 ) << QgsPointXY( 11, 11 ) << QgsPointXY( 10, 11 );
80+
polygon << polyline;
81+
polygonGeom = QgsGeometry::fromPolygonXY( polygon );
82+
f2.setGeometry( polygonGeom );
83+
f2.setAttribute( idx, QVariant( 20 ) );
7184
QgsFeatureList flist;
72-
flist << ff;
85+
flist << f1 << f2;
86+
87+
7388
mVL->dataProvider()->addFeatures( flist );
7489

7590
QgsProject::instance()->addMapLayer( mVL );
@@ -82,13 +97,21 @@ class TestQgsSnappingUtils : public QObject
8297

8398
void testSnapModeCurrent()
8499
{
100+
QgsSymbol *s1 = QgsSymbol::defaultSymbol( QgsWkbTypes::PolygonGeometry );
101+
QgsSymbol *s2 = QgsSymbol::defaultSymbol( QgsWkbTypes::PolygonGeometry );
102+
QgsRendererCategory c1( 2, s1, "f1", true );
103+
QgsRendererCategory c2( 20, s2, "f2", false );
104+
QgsCategoryList cl;
105+
cl << c1 << c2;
106+
85107
QgsMapSettings mapSettings;
86108
mapSettings.setOutputSize( QSize( 100, 100 ) );
87109
mapSettings.setExtent( QgsRectangle( 0, 0, 1, 1 ) );
88110
QVERIFY( mapSettings.hasValidSettings() );
89111

90112
QgsSnappingUtils u;
91113
u.setMapSettings( mapSettings );
114+
u.setEnableSnappingForInvisibleFeature( false );
92115
u.setCurrentLayer( mVL );
93116

94117
// first try with no snapping enabled
@@ -99,7 +122,7 @@ class TestQgsSnappingUtils : public QObject
99122
snappingConfig.setMode( QgsSnappingConfig::ActiveLayer );
100123
u.setConfig( snappingConfig );
101124

102-
QgsPointLocator::Match m0 = u.snapToMap( QPoint( 100, 100 ) );
125+
QgsPointLocator::Match m0 = u.snapToMap( QPoint( 2, 2 ) );
103126
QVERIFY( !m0.isValid() );
104127
QVERIFY( !m0.hasVertex() );
105128

@@ -108,10 +131,16 @@ class TestQgsSnappingUtils : public QObject
108131
snappingConfig.setType( QgsSnappingConfig::Vertex );
109132
u.setConfig( snappingConfig );
110133

111-
QgsPointLocator::Match m = u.snapToMap( QPoint( 100, 100 ) );
134+
QgsPointLocator::Match m = u.snapToMap( QPoint( 11, 11 ) );
135+
QVERIFY( !m.isValid() );
136+
QVERIFY( !m.hasVertex() );
137+
138+
u.setEnableSnappingForInvisibleFeature( true );
139+
mVL->styleChanged();
140+
m = u.snapToMap( QPoint( 2, 2 ) );
112141
QVERIFY( m.isValid() );
113142
QVERIFY( m.hasVertex() );
114-
QCOMPARE( m.point(), QgsPointXY( 1, 0 ) );
143+
QCOMPARE( m.point(), QgsPointXY( 0, 1 ) );
115144

116145
QgsPointLocator::Match m2 = u.snapToMap( QPoint( 0, 100 ) );
117146
QVERIFY( !m2.isValid() );
@@ -127,6 +156,8 @@ class TestQgsSnappingUtils : public QObject
127156
FilterExcludePoint myFilter( QgsPointXY( 1, 0 ) );
128157
QgsPointLocator::Match m3 = u.snapToMap( QPoint( 100, 100 ), &myFilter );
129158
QVERIFY( !m3.isValid() );
159+
160+
130161
}
131162

132163
void testSnapModeAll()

0 commit comments

Comments
 (0)
Please sign in to comment.