Skip to content
Permalink
Browse files

[tracer] Fix issues with rubber bands

  • Loading branch information
wonder-sk committed Jan 10, 2016
1 parent bbe3598 commit 70c5fe5553225e4db02620b429a4cfc549d6fc22
Showing with 79 additions and 28 deletions.
  1. +14 −4 src/core/qgstracer.cpp
  2. +3 −0 src/core/qgstracer.h
  3. +61 −23 src/gui/qgsmaptoolcapture.cpp
  4. +1 −1 src/gui/qgsmaptoolcapture.h
@@ -265,7 +265,7 @@ int point2vertex( const QgsTracerGraph& g, const QgsPoint& pt )
}


int point2edge( const QgsTracerGraph& g, const QgsPoint& pt, int& lineVertexAfter, double epsilon )
int point2edge( const QgsTracerGraph& g, const QgsPoint& pt, int& lineVertexAfter, double epsilon = 1e-6 )
{
int vertexAfter;

@@ -305,11 +305,9 @@ void split_linestring( const QgsPolyline& points, const QgsPoint& pt, int lineVe

int join_vertex_to_graph( QgsTracerGraph& g, const QgsPoint& pt )
{
const double epsilon = 1e-6;

// find edge where the point is
int lineVertexAfter;
int eIdx = point2edge( g, pt, lineVertexAfter, epsilon );
int eIdx = point2edge( g, pt, lineVertexAfter );

//qDebug("e: %d", eIdx);

@@ -625,3 +623,15 @@ QVector<QgsPoint> QgsTracer::findShortestPath( const QgsPoint& p1, const QgsPoin

return points;
}

bool QgsTracer::isPointSnapped( const QgsPoint& pt )
{
init(); // does nothing if the graph exists already

if ( point2vertex( *mGraph, pt ) != -1 )
return true;

int lineVertexAfter;
int e = point2edge( *mGraph, pt, lineVertexAfter );
return e != -1;
}
@@ -63,6 +63,9 @@ class CORE_EXPORT QgsTracer : public QObject
//! if the two points are not connected.
QVector<QgsPoint> findShortestPath( const QgsPoint& p1, const QgsPoint& p2 );

//! Find out whether the point is snapped to a vertex or edge (i.e. it can be used for tracing start/stop)
bool isPointSnapped( const QgsPoint& pt );

private:
void initGraph();
void invalidateGraph();
@@ -148,47 +148,70 @@ void QgsMapToolCapture::tracingMouseMove( QgsMapMouseEvent* e )
if ( !e->isSnapped() )
return;

QgsPointV2 v;
QgsVertexId::VertexType vt;
mCaptureCurve.pointAt( mCaptureCurve.numPoints() - 1, v, vt );
QgsPointV2 v = mCaptureCurve.endPoint();

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

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

QVector<QgsPoint> points = tracer->findShortestPath( QgsPoint( v.x(), v.y() ), e->mapPoint() );
if ( points.isEmpty() )
return;

if ( mCaptureMode == CapturePolygon )
mTempRubberBand->addPoint( *mRubberBand->getPoint( 0, 0 ), false );

// update rubberband
mTempRubberBand->reset( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line );
for ( int i = 0; i < points.count(); ++i )
mTempRubberBand->addPoint( points.at( i ), i == points.count() - 1 );
}


void QgsMapToolCapture::tracingAddVertex( const QgsPoint& point )
bool QgsMapToolCapture::tracingAddVertex( const QgsPoint& point )
{
QgsMapCanvasTracer* tracer = QgsMapCanvasTracer::tracerForCanvas( mCanvas );
if ( !tracer )
return; // this should not happen!
return false; // this should not happen!

QgsPointV2 v;
QgsVertexId::VertexType vt;
mCaptureCurve.pointAt( mCaptureCurve.numPoints() - 1, v, vt );
if ( mCaptureCurve.numPoints() == 0 )
{
// only accept first point if it is snapped to the graph (to vertex or edge)
bool res = tracer->isPointSnapped( point );
if ( res )
{
QgsPoint layerPoint;
nextPoint( point, layerPoint ); // assuming the transform went fine earlier

mRubberBand->addPoint( point );
mCaptureCurve.addVertex( QgsPointV2( layerPoint.x(), layerPoint.y() ) );
}
return res;
}

QgsPointV2 v = mCaptureCurve.endPoint();

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

// transform points
QList<QgsPointV2> layerPoints;
QgsPoint lp; // in layer coords
for ( int i = 1; i < points.count(); ++i )
{
if ( nextPoint( points[i], lp ) != 0 )
continue; // TODO: should completely abort
return false;
layerPoints << QgsPointV2( lp.x(), lp.y() );
}

for ( int i = 1; i < points.count(); ++i )
{
mRubberBand->addPoint( points[i], i == points.count() - 1 );
mCaptureCurve.addVertex( QgsPointV2( lp.x(), lp.y() ) );
mCaptureCurve.addVertex( layerPoints[i-1] );
}
return true;
}


@@ -232,7 +255,20 @@ void QgsMapToolCapture::cadCanvasMoveEvent( QgsMapMouseEvent * e )
}
else
{
mTempRubberBand->movePoint( point );
if ( mCaptureCurve.numPoints() > 0 &&
(( mCaptureMode == CaptureLine && mTempRubberBand->numberOfVertices() != 2 ) ||
( mCaptureMode == CapturePolygon && mTempRubberBand->numberOfVertices() != 3 ) ) )
{
// fix temporary rubber band after tracing which may have added multiple points
mTempRubberBand->reset( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line );
if ( mCaptureMode == CapturePolygon )
mTempRubberBand->addPoint( *mRubberBand->getPoint( 0, 0 ), false );
QgsPointV2 pt = mCaptureCurve.endPoint();
mTempRubberBand->addPoint( QgsPoint( pt.x(), pt.y() ) );
mTempRubberBand->addPoint( point );
}
else
mTempRubberBand->movePoint( point );
}
}
} // mouseMoveEvent
@@ -287,26 +323,28 @@ int QgsMapToolCapture::addVertex( const QgsPoint& point )
mRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line );
}

if ( tracingEnabled() && mCaptureCurve.numPoints() != 0 )
if ( !mTempRubberBand )
{
tracingAddVertex( point );
mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line, true );
}
else
{
// ordinary digitizing
mRubberBand->addPoint( point );
mCaptureCurve.addVertex( QgsPointV2( layerPoint.x(), layerPoint.y() ) );
mTempRubberBand->reset( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line );
}

// re-initialize temporary rubber band for further digitizing

if ( !mTempRubberBand )
if ( tracingEnabled() )
{
mTempRubberBand = createRubberBand( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line, true );
if ( !tracingAddVertex( point ) )
{
emit messageEmitted( tr( "Tracing: The point needs to be snapped to a geometry" ), QgsMessageBar::WARNING );
return 1; // early exit if the point cannot be accepted
}
}
else
{
mTempRubberBand->reset( mCaptureMode == CapturePolygon ? QGis::Polygon : QGis::Line );
// ordinary digitizing
mRubberBand->addPoint( point );
mCaptureCurve.addVertex( QgsPointV2( layerPoint.x(), layerPoint.y() ) );
}

if ( mCaptureMode == CaptureLine )
@@ -146,7 +146,7 @@ class GUI_EXPORT QgsMapToolCapture : public QgsMapToolAdvancedDigitizing
//! handle of mouse movement when tracing enabled and capturing has started
void tracingMouseMove( QgsMapMouseEvent* e );
//! handle of addition of clicked point (with the rest of the trace) when tracing enabled
void tracingAddVertex( const QgsPoint& point );
bool tracingAddVertex( const QgsPoint& point );

private:
/** Flag to indicate a map canvas capture operation is taking place */

0 comments on commit 70c5fe5

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