Skip to content

Commit 33ea60d

Browse files
committedJan 11, 2016
[tracer] Fix reprojection, limit tracing graph to visible extent
1 parent bf8571d commit 33ea60d

File tree

6 files changed

+105
-7
lines changed

6 files changed

+105
-7
lines changed
 

‎src/core/qgstracer.cpp

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -250,14 +250,14 @@ QVector<QgsPoint> shortest_path( const QgsTracerGraph& g, int v1, int v2 )
250250
}
251251

252252

253-
int point2vertex( const QgsTracerGraph& g, const QgsPoint& pt )
253+
int point2vertex( const QgsTracerGraph& g, const QgsPoint& pt, double epsilon = 1e-6 )
254254
{
255255
// TODO: use spatial index
256256

257257
for ( int i = 0; i < g.v.count(); ++i )
258258
{
259259
const QgsTracerGraph::V& v = g.v.at( i );
260-
if ( v.pt == pt )
260+
if ( v.pt == pt || ( fabs( v.pt.x() - pt.x() ) < epsilon && fabs( v.pt.y() - pt.y() ) < epsilon ) )
261261
return i;
262262
}
263263

@@ -472,7 +472,12 @@ void QgsTracer::initGraph()
472472
{
473473
QgsCoordinateTransform ct( vl->crs(), mCRS );
474474

475-
QgsFeatureIterator fi = vl->getFeatures( QgsFeatureRequest().setSubsetOfAttributes( QgsAttributeList() ) );
475+
QgsFeatureRequest request;
476+
request.setSubsetOfAttributes( QgsAttributeList() );
477+
if ( !mExtent.isEmpty() )
478+
request.setFilterRect( ct.transformBoundingBox( mExtent, QgsCoordinateTransform::ReverseTransform ) );
479+
480+
QgsFeatureIterator fi = vl->getFeatures( request );
476481
while ( fi.nextFeature( f ) )
477482
{
478483
if ( !f.geometry() )
@@ -567,6 +572,15 @@ void QgsTracer::setDestinationCrs( const QgsCoordinateReferenceSystem& crs )
567572
invalidateGraph();
568573
}
569574

575+
void QgsTracer::setExtent( const QgsRectangle& extent )
576+
{
577+
if ( mExtent == extent )
578+
return;
579+
580+
mExtent = extent;
581+
invalidateGraph();
582+
}
583+
570584
void QgsTracer::init()
571585
{
572586
if ( mGraph )

‎src/core/qgstracer.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ class QgsVectorLayer;
2424
#include "qgscoordinatereferencesystem.h"
2525
#include "qgsfeature.h"
2626
#include "qgspoint.h"
27+
#include "qgsrectangle.h"
2728

2829
struct QgsTracerGraph;
2930

@@ -51,6 +52,11 @@ class CORE_EXPORT QgsTracer : public QObject
5152
//! Set CRS used for tracing
5253
void setDestinationCrs( const QgsCoordinateReferenceSystem& crs );
5354

55+
//! Get extent to which graph's features will be limited (empty extent means no limit)
56+
QgsRectangle extent() const { return mExtent; }
57+
//! Set extent to which graph's features will be limited (empty extent means no limit)
58+
void setExtent( const QgsRectangle& extent );
59+
5460
//! Build the internal data structures. This may take some time
5561
//! depending on how big the input layers are. It is not necessary
5662
//! to call this method explicitly - it will be called by findShortestPath()
@@ -82,6 +88,8 @@ class CORE_EXPORT QgsTracer : public QObject
8288
QList<QgsVectorLayer*> mLayers;
8389
//! Destination CRS in which graph is built and tracing done
8490
QgsCoordinateReferenceSystem mCRS;
91+
//! Extent for graph building (empty extent means no limit)
92+
QgsRectangle mExtent;
8593
};
8694

8795

‎src/gui/qgsmapcanvastracer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ QgsMapCanvasTracer::QgsMapCanvasTracer( QgsMapCanvas* canvas )
1717

1818
connect( canvas, SIGNAL( destinationCrsChanged() ), this, SLOT( updateSettings() ) );
1919
connect( canvas, SIGNAL( layersChanged() ), this, SLOT( updateSettings() ) );
20+
connect( canvas, SIGNAL( extentsChanged() ), this, SLOT( updateSettings() ) );
2021
// TODO: watch for snapping changes
2122

2223
mActionEnableTracing = new QAction( QIcon( QgsApplication::getThemeIcon( "/mActionTracing.png" ) ), tr( "Enable Tracing" ), this );
@@ -48,4 +49,5 @@ void QgsMapCanvasTracer::updateSettings()
4849
setLayers( layers );
4950

5051
setDestinationCrs( mCanvas->mapSettings().destinationCrs() );
52+
setExtent( mCanvas->extent() );
5153
}

‎src/gui/qgsmaptoolcapture.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,20 +143,40 @@ bool QgsMapToolCapture::tracingEnabled()
143143
}
144144

145145

146+
QgsPoint QgsMapToolCapture::tracingStartPoint()
147+
{
148+
try
149+
{
150+
QgsMapLayer* layer = mCanvas->currentLayer();
151+
if ( !layer )
152+
return QgsPoint();
153+
QgsPointV2 v = mCaptureCurve.endPoint();
154+
return toMapCoordinates( layer, QgsPoint( v.x(), v.y() ) );
155+
}
156+
catch ( QgsCsException & )
157+
{
158+
QgsDebugMsg( "transformation to layer coordinate failed" );
159+
return QgsPoint();
160+
}
161+
}
162+
163+
146164
void QgsMapToolCapture::tracingMouseMove( QgsMapMouseEvent* e )
147165
{
148166
if ( !e->isSnapped() )
149167
return;
150168

151-
QgsPointV2 v = mCaptureCurve.endPoint();
169+
QgsPoint pt0 = tracingStartPoint();
170+
if ( pt0 == QgsPoint() )
171+
return;
152172

153173
QgsMapCanvasTracer* tracer = QgsMapCanvasTracer::tracerForCanvas( mCanvas );
154174
if ( !tracer )
155175
return; // this should not happen!
156176

157177
mTempRubberBand->reset( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line );
158178

159-
QVector<QgsPoint> points = tracer->findShortestPath( QgsPoint( v.x(), v.y() ), e->mapPoint() );
179+
QVector<QgsPoint> points = tracer->findShortestPath( pt0, e->mapPoint() );
160180
if ( points.isEmpty() )
161181
return;
162182

@@ -190,9 +210,11 @@ bool QgsMapToolCapture::tracingAddVertex( const QgsPoint& point )
190210
return res;
191211
}
192212

193-
QgsPointV2 v = mCaptureCurve.endPoint();
213+
QgsPoint pt0 = tracingStartPoint();
214+
if ( pt0 == QgsPoint() )
215+
return false;
194216

195-
QVector<QgsPoint> points = tracer->findShortestPath( QgsPoint( v.x(), v.y() ), point );
217+
QVector<QgsPoint> points = tracer->findShortestPath( pt0, point );
196218
if ( points.isEmpty() )
197219
return false; // ignore the vertex - can't find path to the end point!
198220

‎src/gui/qgsmaptoolcapture.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing
143143
private:
144144
//! whether tracing has been requested by the user
145145
bool tracingEnabled();
146+
//! first point that will be used as a start of the trace
147+
QgsPoint tracingStartPoint();
146148
//! handle of mouse movement when tracing enabled and capturing has started
147149
void tracingMouseMove( QgsMapMouseEvent* e );
148150
//! handle of addition of clicked point (with the rest of the trace) when tracing enabled

‎tests/src/core/testqgstracer.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ class TestQgsTracer : public QObject
3232
void testPolygon();
3333
void testButterfly();
3434
void testLayerUpdates();
35+
void testExtent();
36+
void testReprojection();
3537

3638
private:
3739

@@ -268,6 +270,54 @@ void TestQgsTracer::testLayerUpdates()
268270
delete vl;
269271
}
270272

273+
void TestQgsTracer::testExtent()
274+
{
275+
// check whether the tracer correctly handles the extent limitation
276+
277+
// same shape as in testSimple()
278+
QStringList wkts;
279+
wkts << "LINESTRING(0 0, 0 10)"
280+
<< "LINESTRING(0 0, 10 0)"
281+
<< "LINESTRING(0 10, 20 10)"
282+
<< "LINESTRING(10 0, 20 10)";
283+
284+
QgsVectorLayer* vl = make_layer( wkts );
285+
286+
QgsTracer tracer;
287+
tracer.setLayers( QList<QgsVectorLayer*>() << vl );
288+
tracer.setExtent( QgsRectangle( 0, 0, 5, 5 ) );
289+
tracer.init();
290+
291+
QgsPolyline points1 = tracer.findShortestPath( QgsPoint( 0, 0 ), QgsPoint( 10, 0 ) );
292+
QCOMPARE( points1.count(), 2 );
293+
QCOMPARE( points1[0], QgsPoint( 0, 0 ) );
294+
QCOMPARE( points1[1], QgsPoint( 10, 0 ) );
295+
296+
QgsPolyline points2 = tracer.findShortestPath( QgsPoint( 0, 0 ), QgsPoint( 20, 10 ) );
297+
QCOMPARE( points2.count(), 0 );
298+
}
299+
300+
void TestQgsTracer::testReprojection()
301+
{
302+
QStringList wkts;
303+
wkts << "LINESTRING(1 0, 2 0)";
304+
305+
QgsVectorLayer* vl = make_layer( wkts );
306+
307+
QgsCoordinateReferenceSystem dstCrs( "EPSG:3857" );
308+
QgsCoordinateTransform ct( QgsCoordinateReferenceSystem( "EPSG:4326" ), dstCrs );
309+
QgsPoint p1 = ct.transform( QgsPoint( 1, 0 ) );
310+
QgsPoint p2 = ct.transform( QgsPoint( 2, 0 ) );
311+
312+
QgsTracer tracer;
313+
tracer.setLayers( QList<QgsVectorLayer*>() << vl );
314+
tracer.setDestinationCrs( dstCrs );
315+
tracer.init();
316+
317+
QgsPolyline points1 = tracer.findShortestPath( p1, p2 );
318+
QCOMPARE( points1.count(), 2 );
319+
}
320+
271321

272322
QTEST_MAIN( TestQgsTracer )
273323
#include "testqgstracer.moc"

0 commit comments

Comments
 (0)
Please sign in to comment.