Skip to content

Commit

Permalink
Fixes #18902 Snapping and tracing inconsistent behaviour
Browse files Browse the repository at this point in the history
  • Loading branch information
lbartoletti committed Sep 24, 2018
1 parent 6286cf1 commit f18bc52
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 6 deletions.
7 changes: 6 additions & 1 deletion python/core/auto_generated/qgstracer.sip.in
Expand Up @@ -48,11 +48,16 @@ Returns the CRS used for tracing.
.. seealso:: :py:func:`setDestinationCrs`
%End

void setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context );
void setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &transform );
%Docstring
Sets the ``crs`` and transform ``context`` used for tracing.

.. seealso:: :py:func:`destinationCrs`
%End

void setRenderContext( const QgsRenderContext *render );
%Docstring
Sets the ``render`` context used for tracing only on visible features.
%End

QgsRectangle extent() const;
Expand Down
69 changes: 65 additions & 4 deletions src/core/qgstracer.cpp
Expand Up @@ -23,6 +23,7 @@
#include "qgslogger.h"
#include "qgsvectorlayer.h"
#include "qgsexception.h"
#include "qgsrenderer.h"

#include <queue>
#include <vector>
Expand Down Expand Up @@ -458,7 +459,8 @@ QgsTracer::QgsTracer() = default;
bool QgsTracer::initGraph()
{
if ( mGraph )
return true; // already initialized
return true;
// already initialized

mHasTopologyProblem = false;

Expand All @@ -476,7 +478,28 @@ bool QgsTracer::initGraph()
for ( QgsVectorLayer *vl : qgis::as_const( mLayers ) )
{
QgsFeatureRequest request;
request.setSubsetOfAttributes( QgsAttributeList() );

bool filter = false;
std::unique_ptr< QgsFeatureRenderer > renderer( vl->renderer() ? vl->renderer()->clone() : nullptr );
QgsRenderContext *ctx = nullptr;
if ( mRenderContext )
{
mRenderContext->expressionContext() << QgsExpressionContextUtils::layerScope( vl );
ctx = mRenderContext.get();
if ( renderer )
{
// setup scale for scale dependent visibility (rule based)
renderer->startRender( *ctx, vl->fields() );
filter = renderer->capabilities() & QgsFeatureRenderer::Filter;
request.setSubsetOfAttributes( renderer->usedAttributes( *ctx ), vl->fields() );
}
}
else
{
request.setSubsetOfAttributes( QgsAttributeList() );

}

request.setDestinationCrs( mCRS, mTransformContext );
if ( !mExtent.isEmpty() )
request.setFilterRect( mExtent );
Expand All @@ -487,12 +510,26 @@ bool QgsTracer::initGraph()
if ( !f.hasGeometry() )
continue;

if ( filter && ctx && renderer )
{
ctx->expressionContext().setFeature( f );
if ( !renderer->willRenderFeature( f, *ctx ) )
{
continue;
}
}

extractLinework( f.geometry(), mpl );

++featuresCounted;
if ( mMaxFeatureCount != 0 && featuresCounted >= mMaxFeatureCount )
return false;
}

if ( ctx && renderer )
{
renderer->stopRender( *ctx );
}
}
int timeExtract = t1.elapsed();

Expand Down Expand Up @@ -544,6 +581,7 @@ bool QgsTracer::initGraph()
Q_UNUSED( timeMake );
QgsDebugMsg( QString( "tracer extract %1 ms, noding %2 ms (call %3 ms), make %4 ms" )
.arg( timeExtract ).arg( timeNoding ).arg( timeNodingCall ).arg( timeMake ) );

return true;
}

Expand All @@ -562,6 +600,8 @@ void QgsTracer::setLayers( const QList<QgsVectorLayer *> &layers )
disconnect( layer, &QgsVectorLayer::featureAdded, this, &QgsTracer::onFeatureAdded );
disconnect( layer, &QgsVectorLayer::featureDeleted, this, &QgsTracer::onFeatureDeleted );
disconnect( layer, &QgsVectorLayer::geometryChanged, this, &QgsTracer::onGeometryChanged );
disconnect( layer, &QgsVectorLayer::attributeValueChanged, this, &QgsTracer::onAttributeValueChanged );
disconnect( layer, &QgsVectorLayer::dataChanged, this, &QgsTracer::onDataChanged );
disconnect( layer, &QObject::destroyed, this, &QgsTracer::onLayerDestroyed );
}

Expand All @@ -572,16 +612,24 @@ void QgsTracer::setLayers( const QList<QgsVectorLayer *> &layers )
connect( layer, &QgsVectorLayer::featureAdded, this, &QgsTracer::onFeatureAdded );
connect( layer, &QgsVectorLayer::featureDeleted, this, &QgsTracer::onFeatureDeleted );
connect( layer, &QgsVectorLayer::geometryChanged, this, &QgsTracer::onGeometryChanged );
connect( layer, &QgsVectorLayer::attributeValueChanged, this, &QgsTracer::onAttributeValueChanged );
connect( layer, &QgsVectorLayer::dataChanged, this, &QgsTracer::onDataChanged );
connect( layer, &QObject::destroyed, this, &QgsTracer::onLayerDestroyed );
}

invalidateGraph();
}

void QgsTracer::setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context )
void QgsTracer::setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &transform )
{
mCRS = crs;
mTransformContext = context;
mTransformContext = transform;
invalidateGraph();
}

void QgsTracer::setRenderContext( const QgsRenderContext *render )
{
mRenderContext = std::unique_ptr<QgsRenderContext>( new QgsRenderContext( *render ) );
invalidateGraph();
}

Expand Down Expand Up @@ -649,6 +697,19 @@ void QgsTracer::onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom )
invalidateGraph();
}

void QgsTracer::onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value )
{
Q_UNUSED( fid );
Q_UNUSED( idx );
Q_UNUSED( value );
invalidateGraph();
}

void QgsTracer::onDataChanged( )
{
invalidateGraph();
}

void QgsTracer::onLayerDestroyed( QObject *obj )
{
// remove the layer before it is completely invalid (static_cast should be the safest cast)
Expand Down
13 changes: 12 additions & 1 deletion src/core/qgstracer.h
Expand Up @@ -29,6 +29,8 @@ class QgsVectorLayer;
#include "qgsgeometry.h"

struct QgsTracerGraph;
class QgsFeatureRenderer;
class QgsRenderContext;

/**
* \ingroup core
Expand Down Expand Up @@ -64,7 +66,12 @@ class CORE_EXPORT QgsTracer : public QObject
* Sets the \a crs and transform \a context used for tracing.
* \see destinationCrs()
*/
void setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &context );
void setDestinationCrs( const QgsCoordinateReferenceSystem &crs, const QgsCoordinateTransformContext &transform );

/**
* Sets the \a render context used for tracing only on visible features.
*/
void setRenderContext( const QgsRenderContext *render );

//! Gets extent to which graph's features will be limited (empty extent means no limit)
QgsRectangle extent() const { return mExtent; }
Expand Down Expand Up @@ -160,6 +167,8 @@ class CORE_EXPORT QgsTracer : public QObject
void onFeatureAdded( QgsFeatureId fid );
void onFeatureDeleted( QgsFeatureId fid );
void onGeometryChanged( QgsFeatureId fid, const QgsGeometry &geom );
void onAttributeValueChanged( QgsFeatureId fid, int idx, const QVariant &value );
void onDataChanged( );
void onLayerDestroyed( QObject *obj );

private:
Expand All @@ -171,6 +180,8 @@ class CORE_EXPORT QgsTracer : public QObject
QgsCoordinateReferenceSystem mCRS;
//! Coordinate transform context
QgsCoordinateTransformContext mTransformContext;
//! Render context
std::unique_ptr<QgsRenderContext> mRenderContext;
//! Extent for graph building (empty extent means no limit)
QgsRectangle mExtent;

Expand Down
2 changes: 2 additions & 0 deletions src/gui/qgsmapcanvastracer.cpp
Expand Up @@ -98,6 +98,8 @@ void QgsMapCanvasTracer::reportError( QgsTracer::PathError err, bool addingVerte
void QgsMapCanvasTracer::configure()
{
setDestinationCrs( mCanvas->mapSettings().destinationCrs(), mCanvas->mapSettings().transformContext() );
QgsRenderContext ctx = QgsRenderContext::fromMapSettings( mCanvas->mapSettings() );
setRenderContext( &ctx );
setExtent( mCanvas->extent() );

QList<QgsVectorLayer *> layers;
Expand Down

0 comments on commit f18bc52

Please sign in to comment.