Skip to content
Permalink
Browse files

[tracer] update tracer when any of the input layers is changed

  • Loading branch information
wonder-sk committed Jan 8, 2016
1 parent 12705b7 commit 0cd9b68abfea4c09f44f28858016453e80b88ae1
Showing with 128 additions and 3 deletions.
  1. +34 −0 src/core/qgstracer.cpp
  2. +7 −1 src/core/qgstracer.h
  3. +87 −2 tests/src/core/testqgstracer.cpp
@@ -542,7 +542,22 @@ void QgsTracer::setLayers( const QList<QgsVectorLayer*>& layers )
if ( mLayers == layers )
return;

foreach ( QgsVectorLayer* layer, mLayers )
{
disconnect( layer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SLOT( onFeatureAdded( QgsFeatureId ) ) );
disconnect( layer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( onFeatureDeleted( QgsFeatureId ) ) );
disconnect( layer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SLOT( onGeometryChanged( QgsFeatureId, QgsGeometry& ) ) );
}

mLayers = layers;

foreach ( QgsVectorLayer* layer, mLayers )
{
connect( layer, SIGNAL( featureAdded( QgsFeatureId ) ), this, SLOT( onFeatureAdded( QgsFeatureId ) ) );
connect( layer, SIGNAL( featureDeleted( QgsFeatureId ) ), this, SLOT( onFeatureDeleted( QgsFeatureId ) ) );
connect( layer, SIGNAL( geometryChanged( QgsFeatureId, QgsGeometry& ) ), this, SLOT( onGeometryChanged( QgsFeatureId, QgsGeometry& ) ) );
}

invalidateGraph();
}

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

void QgsTracer::onFeatureAdded( QgsFeatureId fid )
{
Q_UNUSED( fid );
invalidateGraph();
}

void QgsTracer::onFeatureDeleted( QgsFeatureId fid )
{
Q_UNUSED( fid );
invalidateGraph();
}

void QgsTracer::onGeometryChanged( QgsFeatureId fid, QgsGeometry& geom )
{
Q_UNUSED( fid );
Q_UNUSED( geom );
invalidateGraph();
}

QVector<QgsPoint> QgsTracer::findShortestPath( const QgsPoint& p1, const QgsPoint& p2 )
{
init(); // does nothing if the graph exists already
@@ -21,8 +21,9 @@ class QgsVectorLayer;
#include <QSet>
#include <QVector>

#include "qgspoint.h"
#include "qgscoordinatereferencesystem.h"
#include "qgsfeature.h"
#include "qgspoint.h"

struct QgsTracerGraph;

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

private slots:
void onFeatureAdded( QgsFeatureId fid );
void onFeatureDeleted( QgsFeatureId fid );
void onGeometryChanged( QgsFeatureId fid, QgsGeometry& geom );

private:
//! Graph data structure for path searching
QgsTracerGraph* mGraph;
@@ -31,11 +31,30 @@ class TestQgsTracer : public QObject
void testSimple();
void testPolygon();
void testButterfly();
void testLayerUpdates();

private:

};

namespace QTest
{
template<>
char* toString( const QgsPoint& point )
{
QByteArray ba = "QgsPoint(" + QByteArray::number( point.x() ) +
", " + QByteArray::number( point.y() ) + ")";
return qstrdup( ba.data() );
}
}

static QgsFeature make_feature( const QString& wkt )
{
QgsFeature f;
f.setGeometry( QgsGeometry::fromWkt( wkt ) );
return f;
}

static QgsVectorLayer* make_layer( const QStringList& wkts )
{
QgsVectorLayer* vl = new QgsVectorLayer( "LineString", "x", "memory" );
@@ -44,8 +63,7 @@ static QgsVectorLayer* make_layer( const QStringList& wkts )
vl->startEditing();
foreach ( const QString& wkt, wkts )
{
QgsFeature f;
f.setGeometry( QgsGeometry::fromWkt( wkt ) );
QgsFeature f( make_feature( wkt ) );
vl->addFeature( f, false );
}
vl->commitChanges();
@@ -151,6 +169,8 @@ void TestQgsTracer::testPolygon()
QCOMPARE( points[0], QgsPoint( 1, 0 ) );
QCOMPARE( points[1], QgsPoint( 0, 0 ) );
QCOMPARE( points[2], QgsPoint( 0, 1 ) );

delete vl;
}

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

void TestQgsTracer::testLayerUpdates()
{
// check whether the tracer is updated on added/removed/changed features

// same shape as in testSimple()
QStringList wkts;
wkts << "LINESTRING(0 0, 0 10)"
<< "LINESTRING(0 0, 10 0)"
<< "LINESTRING(0 10, 20 10)"
<< "LINESTRING(10 0, 20 10)";

QgsVectorLayer* vl = make_layer( wkts );

QgsTracer tracer;
tracer.setLayers( QList<QgsVectorLayer*>() << vl );
tracer.init();

QgsPolyline points1 = tracer.findShortestPath( QgsPoint( 10, 0 ), QgsPoint( 10, 10 ) );
QCOMPARE( points1.count(), 3 );
QCOMPARE( points1[0], QgsPoint( 10, 0 ) );
QCOMPARE( points1[1], QgsPoint( 20, 10 ) );
QCOMPARE( points1[2], QgsPoint( 10, 10 ) );

vl->startEditing();

// add a shortcut
QgsFeature f( make_feature( "LINESTRING(10 0, 10 10)" ) );
vl->addFeature( f );

QgsPolyline points2 = tracer.findShortestPath( QgsPoint( 10, 0 ), QgsPoint( 10, 10 ) );
QCOMPARE( points2.count(), 2 );
QCOMPARE( points2[0], QgsPoint( 10, 0 ) );
QCOMPARE( points2[1], QgsPoint( 10, 10 ) );

// delete the shortcut
vl->deleteFeature( f.id() );

QgsPolyline points3 = tracer.findShortestPath( QgsPoint( 10, 0 ), QgsPoint( 10, 10 ) );
QCOMPARE( points3.count(), 3 );
QCOMPARE( points3[0], QgsPoint( 10, 0 ) );
QCOMPARE( points3[1], QgsPoint( 20, 10 ) );
QCOMPARE( points3[2], QgsPoint( 10, 10 ) );

// make the shortcut again from a different feature
QgsGeometry* g = QgsGeometry::fromWkt( "LINESTRING(10 0, 10 10)" );
vl->changeGeometry( 2, g ); // change bottom line (second item in wkts)
delete g;

QgsPolyline points4 = tracer.findShortestPath( QgsPoint( 10, 0 ), QgsPoint( 10, 10 ) );
QCOMPARE( points4.count(), 2 );
QCOMPARE( points4[0], QgsPoint( 10, 0 ) );
QCOMPARE( points4[1], QgsPoint( 10, 10 ) );

QgsPolyline points5 = tracer.findShortestPath( QgsPoint( 0, 0 ), QgsPoint( 10, 0 ) );
QCOMPARE( points5.count(), 4 );
QCOMPARE( points5[0], QgsPoint( 0, 0 ) );
QCOMPARE( points5[1], QgsPoint( 0, 10 ) );
QCOMPARE( points5[2], QgsPoint( 10, 10 ) );
QCOMPARE( points5[3], QgsPoint( 10, 0 ) );

vl->rollBack();

delete vl;
}


QTEST_MAIN( TestQgsTracer )
#include "testqgstracer.moc"

0 comments on commit 0cd9b68

Please sign in to comment.
You can’t perform that action at this time.