Skip to content

Commit 0cd9b68

Browse files
committed
[tracer] update tracer when any of the input layers is changed
1 parent 12705b7 commit 0cd9b68

File tree

3 files changed

+128
-3
lines changed

3 files changed

+128
-3
lines changed

src/core/qgstracer.cpp

+34
Original file line numberDiff line numberDiff line change
@@ -542,7 +542,22 @@ void QgsTracer::setLayers( const QList<QgsVectorLayer*>& layers )
542542
if ( mLayers == layers )
543543
return;
544544

545+
foreach ( QgsVectorLayer* layer, mLayers )
546+
{
547+
disconnect( layer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SLOT( onFeatureAdded( QgsFeatureId ) ) );
548+
disconnect( layer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( onFeatureDeleted( QgsFeatureId ) ) );
549+
disconnect( layer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SLOT( onGeometryChanged( QgsFeatureId, QgsGeometry& ) ) );
550+
}
551+
545552
mLayers = layers;
553+
554+
foreach ( QgsVectorLayer* layer, mLayers )
555+
{
556+
connect( layer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SLOT( onFeatureAdded( QgsFeatureId ) ) );
557+
connect( layer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( onFeatureDeleted( QgsFeatureId ) ) );
558+
connect( layer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SLOT( onGeometryChanged( QgsFeatureId, QgsGeometry& ) ) );
559+
}
560+
546561
invalidateGraph();
547562
}
548563

@@ -570,6 +585,25 @@ void QgsTracer::invalidateGraph()
570585
mGraph = 0;
571586
}
572587

588+
void QgsTracer::onFeatureAdded( QgsFeatureId fid )
589+
{
590+
Q_UNUSED( fid );
591+
invalidateGraph();
592+
}
593+
594+
void QgsTracer::onFeatureDeleted( QgsFeatureId fid )
595+
{
596+
Q_UNUSED( fid );
597+
invalidateGraph();
598+
}
599+
600+
void QgsTracer::onGeometryChanged( QgsFeatureId fid, QgsGeometry& geom )
601+
{
602+
Q_UNUSED( fid );
603+
Q_UNUSED( geom );
604+
invalidateGraph();
605+
}
606+
573607
QVector<QgsPoint> QgsTracer::findShortestPath( const QgsPoint& p1, const QgsPoint& p2 )
574608
{
575609
init(); // does nothing if the graph exists already

src/core/qgstracer.h

+7-1
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,9 @@ class QgsVectorLayer;
2121
#include <QSet>
2222
#include <QVector>
2323

24-
#include "qgspoint.h"
2524
#include "qgscoordinatereferencesystem.h"
25+
#include "qgsfeature.h"
26+
#include "qgspoint.h"
2627

2728
struct QgsTracerGraph;
2829

@@ -66,6 +67,11 @@ class CORE_EXPORT QgsTracer : public QObject
6667
void initGraph();
6768
void invalidateGraph();
6869

70+
private slots:
71+
void onFeatureAdded( QgsFeatureId fid );
72+
void onFeatureDeleted( QgsFeatureId fid );
73+
void onGeometryChanged( QgsFeatureId fid, QgsGeometry& geom );
74+
6975
private:
7076
//! Graph data structure for path searching
7177
QgsTracerGraph* mGraph;

tests/src/core/testqgstracer.cpp

+87-2
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,30 @@ class TestQgsTracer : public QObject
3131
void testSimple();
3232
void testPolygon();
3333
void testButterfly();
34+
void testLayerUpdates();
3435

3536
private:
3637

3738
};
3839

40+
namespace QTest
41+
{
42+
template<>
43+
char* toString( const QgsPoint& point )
44+
{
45+
QByteArray ba = "QgsPoint(" + QByteArray::number( point.x() ) +
46+
", " + QByteArray::number( point.y() ) + ")";
47+
return qstrdup( ba.data() );
48+
}
49+
}
50+
51+
static QgsFeature make_feature( const QString& wkt )
52+
{
53+
QgsFeature f;
54+
f.setGeometry( QgsGeometry::fromWkt( wkt ) );
55+
return f;
56+
}
57+
3958
static QgsVectorLayer* make_layer( const QStringList& wkts )
4059
{
4160
QgsVectorLayer* vl = new QgsVectorLayer( "LineString", "x", "memory" );
@@ -44,8 +63,7 @@ static QgsVectorLayer* make_layer( const QStringList& wkts )
4463
vl->startEditing();
4564
foreach ( const QString& wkt, wkts )
4665
{
47-
QgsFeature f;
48-
f.setGeometry( QgsGeometry::fromWkt( wkt ) );
66+
QgsFeature f( make_feature( wkt ) );
4967
vl->addFeature( f, false );
5068
}
5169
vl->commitChanges();
@@ -151,6 +169,8 @@ void TestQgsTracer::testPolygon()
151169
QCOMPARE( points[0], QgsPoint( 1, 0 ) );
152170
QCOMPARE( points[1], QgsPoint( 0, 0 ) );
153171
QCOMPARE( points[2], QgsPoint( 0, 1 ) );
172+
173+
delete vl;
154174
}
155175

156176
void TestQgsTracer::testButterfly()
@@ -183,6 +203,71 @@ void TestQgsTracer::testButterfly()
183203
delete vl;
184204
}
185205

206+
void TestQgsTracer::testLayerUpdates()
207+
{
208+
// check whether the tracer is updated on added/removed/changed features
209+
210+
// same shape as in testSimple()
211+
QStringList wkts;
212+
wkts << "LINESTRING(0 0, 0 10)"
213+
<< "LINESTRING(0 0, 10 0)"
214+
<< "LINESTRING(0 10, 20 10)"
215+
<< "LINESTRING(10 0, 20 10)";
216+
217+
QgsVectorLayer* vl = make_layer( wkts );
218+
219+
QgsTracer tracer;
220+
tracer.setLayers( QList<QgsVectorLayer*>() << vl );
221+
tracer.init();
222+
223+
QgsPolyline points1 = tracer.findShortestPath( QgsPoint( 10, 0 ), QgsPoint( 10, 10 ) );
224+
QCOMPARE( points1.count(), 3 );
225+
QCOMPARE( points1[0], QgsPoint( 10, 0 ) );
226+
QCOMPARE( points1[1], QgsPoint( 20, 10 ) );
227+
QCOMPARE( points1[2], QgsPoint( 10, 10 ) );
228+
229+
vl->startEditing();
230+
231+
// add a shortcut
232+
QgsFeature f( make_feature( "LINESTRING(10 0, 10 10)" ) );
233+
vl->addFeature( f );
234+
235+
QgsPolyline points2 = tracer.findShortestPath( QgsPoint( 10, 0 ), QgsPoint( 10, 10 ) );
236+
QCOMPARE( points2.count(), 2 );
237+
QCOMPARE( points2[0], QgsPoint( 10, 0 ) );
238+
QCOMPARE( points2[1], QgsPoint( 10, 10 ) );
239+
240+
// delete the shortcut
241+
vl->deleteFeature( f.id() );
242+
243+
QgsPolyline points3 = tracer.findShortestPath( QgsPoint( 10, 0 ), QgsPoint( 10, 10 ) );
244+
QCOMPARE( points3.count(), 3 );
245+
QCOMPARE( points3[0], QgsPoint( 10, 0 ) );
246+
QCOMPARE( points3[1], QgsPoint( 20, 10 ) );
247+
QCOMPARE( points3[2], QgsPoint( 10, 10 ) );
248+
249+
// make the shortcut again from a different feature
250+
QgsGeometry* g = QgsGeometry::fromWkt( "LINESTRING(10 0, 10 10)" );
251+
vl->changeGeometry( 2, g ); // change bottom line (second item in wkts)
252+
delete g;
253+
254+
QgsPolyline points4 = tracer.findShortestPath( QgsPoint( 10, 0 ), QgsPoint( 10, 10 ) );
255+
QCOMPARE( points4.count(), 2 );
256+
QCOMPARE( points4[0], QgsPoint( 10, 0 ) );
257+
QCOMPARE( points4[1], QgsPoint( 10, 10 ) );
258+
259+
QgsPolyline points5 = tracer.findShortestPath( QgsPoint( 0, 0 ), QgsPoint( 10, 0 ) );
260+
QCOMPARE( points5.count(), 4 );
261+
QCOMPARE( points5[0], QgsPoint( 0, 0 ) );
262+
QCOMPARE( points5[1], QgsPoint( 0, 10 ) );
263+
QCOMPARE( points5[2], QgsPoint( 10, 10 ) );
264+
QCOMPARE( points5[3], QgsPoint( 10, 0 ) );
265+
266+
vl->rollBack();
267+
268+
delete vl;
269+
}
270+
186271

187272
QTEST_MAIN( TestQgsTracer )
188273
#include "testqgstracer.moc"

0 commit comments

Comments
 (0)