Integrate new labeling engine into the map rendering

Now used instead of QgsPalLabeling for labels/diagrams

This code has been funded by Tuscany Region (Italy) - SITA (CIG: 63526840AE) and commissioned to Gis3W s.a.s.
This commit is contained in:
Martin Dobias 2015-09-11 12:59:16 +08:00
parent f3fd96f4ee
commit 8100495df6
15 changed files with 134 additions and 56 deletions

View File

@ -122,7 +122,7 @@ class QgsMapRendererJob : QObject
bool needTemporaryImage( QgsMapLayer* ml );
static void drawLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext, QgsPalLabeling* labelingEngine, QPainter* painter );
// TODO static void drawLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext, QgsPalLabeling* labelingEngine, QPainter* painter );
static void drawOldLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext );
static void drawNewLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext, QgsPalLabeling* labelingEngine );

View File

@ -33,9 +33,8 @@ static bool _palIsCancelled( void* ctx )
}
QgsLabelingEngineV2::QgsLabelingEngineV2( const QgsMapSettings& mapSettings, const QList<QgsAbstractLabelProvider*>& providers )
QgsLabelingEngineV2::QgsLabelingEngineV2( const QgsMapSettings& mapSettings )
: mMapSettings( mapSettings )
, mProviders( providers )
, mFlags( RenderOutlineLabels | UsePartialCandidates )
, mSearchMethod( QgsPalLabeling::Chain )
, mCandPoint( 8 )
@ -43,15 +42,19 @@ QgsLabelingEngineV2::QgsLabelingEngineV2( const QgsMapSettings& mapSettings, con
, mCandPolygon( 8 )
, mResults( 0 )
{
foreach ( QgsAbstractLabelProvider* provider, mProviders )
provider->setEngine( this );
mResults = new QgsLabelingResults;
}
QgsLabelingEngineV2::~QgsLabelingEngineV2()
{
delete mResults;
qDeleteAll( mProviders );
}
void QgsLabelingEngineV2::addProvider( QgsAbstractLabelProvider* provider )
{
provider->setEngine( this );
mProviders << provider;
}
void QgsLabelingEngineV2::run( QgsRenderContext& context )

View File

@ -210,7 +210,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS( QgsAbstractLabelProvider::Flags )
class CORE_EXPORT QgsLabelingEngineV2
{
public:
QgsLabelingEngineV2( const QgsMapSettings& mapSettings, const QList<QgsAbstractLabelProvider*>& providers );
QgsLabelingEngineV2( const QgsMapSettings& mapSettings );
~QgsLabelingEngineV2();
enum Flag
@ -224,6 +224,9 @@ class CORE_EXPORT QgsLabelingEngineV2
};
Q_DECLARE_FLAGS( Flags, Flag )
//! Add provider of label features. Takes ownership of the provider
void addProvider( QgsAbstractLabelProvider* provider );
//! compute the labeling with given map settings and providers
void run( QgsRenderContext& context );

View File

@ -15,6 +15,7 @@
#include "qgsmaprenderercustompainterjob.h"
#include "qgslabelingenginev2.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
#include "qgsmaplayerrenderer.h"
@ -22,10 +23,13 @@
#include "qgsvectorlayer.h"
#include "qgsrendererv2.h"
#define LABELING_V2
QgsMapRendererCustomPainterJob::QgsMapRendererCustomPainterJob( const QgsMapSettings& settings, QPainter* painter )
: QgsMapRendererJob( settings )
, mPainter( painter )
, mLabelingEngine( 0 )
, mLabelingEngineV2( 0 )
, mActive( false )
, mRenderSynchronously( false )
{
@ -40,6 +44,9 @@ QgsMapRendererCustomPainterJob::~QgsMapRendererCustomPainterJob()
delete mLabelingEngine;
mLabelingEngine = 0;
delete mLabelingEngineV2;
mLabelingEngineV2 = 0;
}
void QgsMapRendererCustomPainterJob::start()
@ -72,14 +79,21 @@ void QgsMapRendererCustomPainterJob::start()
delete mLabelingEngine;
mLabelingEngine = 0;
delete mLabelingEngineV2;
mLabelingEngineV2 = 0;
if ( mSettings.testFlag( QgsMapSettings::DrawLabeling ) )
{
#ifdef LABELING_V2
mLabelingEngineV2 = new QgsLabelingEngineV2( mSettings );
#else
mLabelingEngine = new QgsPalLabeling;
mLabelingEngine->loadEngineSettings();
mLabelingEngine->init( mSettings );
#endif
}
mLayerJobs = prepareJobs( mPainter, mLabelingEngine );
mLayerJobs = prepareJobs( mPainter, mLabelingEngine, mLabelingEngineV2 );
QgsDebugMsg( "Rendering prepared in (seconds): " + QString( "%1" ).arg( prepareTime.elapsed() / 1000.0 ) );
@ -240,13 +254,13 @@ void QgsMapRendererCustomPainterJob::doRender()
QgsDebugMsg( "Done rendering map layers" );
if ( mSettings.testFlag( QgsMapSettings::DrawLabeling ) && !mLabelingRenderContext.renderingStopped() )
drawLabeling( mSettings, mLabelingRenderContext, mLabelingEngine, mPainter );
drawLabeling( mSettings, mLabelingRenderContext, mLabelingEngine, mLabelingEngineV2, mPainter );
QgsDebugMsg( "Rendering completed in (seconds): " + QString( "%1" ).arg( renderTime.elapsed() / 1000.0 ) );
}
void QgsMapRendererJob::drawLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext, QgsPalLabeling* labelingEngine, QPainter* painter )
void QgsMapRendererJob::drawLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext, QgsPalLabeling* labelingEngine, QgsLabelingEngineV2* labelingEngine2, QPainter* painter )
{
QgsDebugMsg( "Draw labeling start" );
@ -266,6 +280,15 @@ void QgsMapRendererJob::drawLabeling( const QgsMapSettings& settings, QgsRenderC
drawNewLabeling( settings, renderContext, labelingEngine );
if ( labelingEngine2 )
{
// set correct extent
renderContext.setExtent( settings.visibleExtent() );
renderContext.setCoordinateTransform( NULL );
labelingEngine2->run( renderContext );
}
QgsDebugMsg( QString( "Draw labeling took (seconds): %1" ).arg( t.elapsed() / 1000. ) );
}

View File

@ -84,6 +84,7 @@ class CORE_EXPORT QgsMapRendererCustomPainterJob : public QgsMapRendererJob
QFutureWatcher<void> mFutureWatcher;
QgsRenderContext mLabelingRenderContext;
QgsPalLabeling* mLabelingEngine;
QgsLabelingEngineV2* mLabelingEngineV2;
bool mActive;
LayerRenderJobs mLayerJobs;

View File

@ -135,7 +135,7 @@ bool QgsMapRendererJob::reprojectToLayerExtent( const QgsCoordinateTransform* ct
LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsPalLabeling* labelingEngine )
LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsPalLabeling* labelingEngine, QgsLabelingEngineV2* labelingEngine2 )
{
LayerRenderJobs layerJobs;
@ -217,6 +217,7 @@ LayerRenderJobs QgsMapRendererJob::prepareJobs( QPainter* painter, QgsPalLabelin
job.context = QgsRenderContext::fromMapSettings( mSettings );
job.context.setPainter( painter );
job.context.setLabelingEngine( labelingEngine );
job.context.setLabelingEngineV2( labelingEngine2 );
job.context.setCoordinateTransform( ct );
job.context.setExtent( r1 );

View File

@ -29,6 +29,7 @@
#include "qgsgeometrycache.h"
class QgsLabelingEngineV2;
class QgsLabelingResults;
class QgsMapLayerRenderer;
class QgsMapRendererCache;
@ -149,7 +150,7 @@ class CORE_EXPORT QgsMapRendererJob : public QObject
static bool reprojectToLayerExtent( const QgsCoordinateTransform* ct, bool layerCrsGeographic, QgsRectangle& extent, QgsRectangle& r2 );
//! @note not available in python bindings
LayerRenderJobs prepareJobs( QPainter* painter, QgsPalLabeling* labelingEngine );
LayerRenderJobs prepareJobs( QPainter* painter, QgsPalLabeling* labelingEngine, QgsLabelingEngineV2* labelingEngine2 );
//! @note not available in python bindings
void cleanupJobs( LayerRenderJobs& jobs );
@ -158,7 +159,7 @@ class CORE_EXPORT QgsMapRendererJob : public QObject
bool needTemporaryImage( QgsMapLayer* ml );
static void drawLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext, QgsPalLabeling* labelingEngine, QPainter* painter );
static void drawLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext, QgsPalLabeling* labelingEngine, QgsLabelingEngineV2* labelingEngine2, QPainter* painter );
static void drawOldLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext );
static void drawNewLabeling( const QgsMapSettings& settings, QgsRenderContext& renderContext, QgsPalLabeling* labelingEngine );

View File

@ -15,17 +15,20 @@
#include "qgsmaprendererparalleljob.h"
#include "qgslabelingenginev2.h"
#include "qgslogger.h"
#include "qgsmaplayerrenderer.h"
#include "qgspallabeling.h"
#include <QtConcurrentMap>
#define LABELING_V2
QgsMapRendererParallelJob::QgsMapRendererParallelJob( const QgsMapSettings& settings )
: QgsMapRendererQImageJob( settings )
, mStatus( Idle )
, mLabelingEngine( 0 )
, mLabelingEngineV2( 0 )
{
}
@ -38,6 +41,9 @@ QgsMapRendererParallelJob::~QgsMapRendererParallelJob()
delete mLabelingEngine;
mLabelingEngine = 0;
delete mLabelingEngineV2;
mLabelingEngineV2 = 0;
}
void QgsMapRendererParallelJob::start()
@ -52,15 +58,21 @@ void QgsMapRendererParallelJob::start()
delete mLabelingEngine;
mLabelingEngine = 0;
delete mLabelingEngineV2;
mLabelingEngineV2 = 0;
if ( mSettings.testFlag( QgsMapSettings::DrawLabeling ) )
{
#ifdef LABELING_V2
mLabelingEngineV2 = new QgsLabelingEngineV2( mSettings );
#else
mLabelingEngine = new QgsPalLabeling;
mLabelingEngine->loadEngineSettings();
mLabelingEngine->init( mSettings );
#endif
}
mLayerJobs = prepareJobs( 0, mLabelingEngine );
mLayerJobs = prepareJobs( 0, mLabelingEngine, mLabelingEngineV2 );
QgsDebugMsg( QString( "QThreadPool max thread count is %1" ).arg( QThreadPool::globalInstance()->maxThreadCount() ) );
@ -239,7 +251,7 @@ void QgsMapRendererParallelJob::renderLabelsStatic( QgsMapRendererParallelJob* s
try
{
drawLabeling( self->mSettings, self->mLabelingRenderContext, self->mLabelingEngine, &painter );
drawLabeling( self->mSettings, self->mLabelingRenderContext, self->mLabelingEngine, self->mLabelingEngineV2, &painter );
}
catch ( QgsException & e )
{

View File

@ -65,6 +65,7 @@ class CORE_EXPORT QgsMapRendererParallelJob : public QgsMapRendererQImageJob
LayerRenderJobs mLayerJobs;
QgsPalLabeling* mLabelingEngine;
QgsLabelingEngineV2* mLabelingEngineV2;
QgsRenderContext mLabelingRenderContext;
QFuture<void> mLabelingFuture;
QFutureWatcher<void> mLabelingFutureWatcher;

View File

@ -30,6 +30,7 @@ class QPainter;
class QgsAbstractGeometryV2;
class QgsLabelingEngineInterface;
class QgsLabelingEngineV2;
class QgsMapSettings;
/** \ingroup core
@ -78,6 +79,9 @@ class CORE_EXPORT QgsRenderContext
QgsLabelingEngineInterface* labelingEngine() const { return mLabelingEngine; }
//! Get access to new labeling engine (may be NULL)
QgsLabelingEngineV2* labelingEngineV2() const { return mLabelingEngine2; }
QColor selectionColor() const { return mSelectionColor; }
/** Returns true if vector selections should be shown in the rendered map
@ -102,6 +106,8 @@ class CORE_EXPORT QgsRenderContext
void setPainter( QPainter* p ) {mPainter = p;}
void setForceVectorOutput( bool force ) {mForceVectorOutput = force;}
void setLabelingEngine( QgsLabelingEngineInterface* iface ) { mLabelingEngine = iface; }
//! Assign new labeling engine
void setLabelingEngineV2( QgsLabelingEngineV2* engine2 ) { mLabelingEngine2 = engine2; }
void setSelectionColor( const QColor& color ) { mSelectionColor = color; }
/** Sets whether vector selections should be shown in the rendered map
@ -182,6 +188,9 @@ class CORE_EXPORT QgsRenderContext
/** Labeling engine (can be NULL)*/
QgsLabelingEngineInterface* mLabelingEngine;
/** Newer labeling engine implementation (can be NULL) */
QgsLabelingEngineV2* mLabelingEngine2;
/** Whether selection should be shown*/
bool mShowSelection;

View File

@ -25,33 +25,34 @@
#include "labelposition.h"
QgsVectorLayerDiagramProvider::QgsVectorLayerDiagramProvider( const QgsDiagramLayerSettings* diagSettings,
const QgsDiagramRendererV2* diagRenderer,
const QString& layerId,
const QgsFields& fields,
const QgsCoordinateReferenceSystem& crs,
QgsAbstractFeatureSource* source,
bool ownsSource )
: mSettings( *diagSettings )
, mDiagRenderer( diagRenderer->clone() )
, mLayerId( layerId )
, mFields( fields )
, mLayerCrs( crs )
, mSource( source )
, mOwnsSource( ownsSource )
QgsVectorLayerDiagramProvider::QgsVectorLayerDiagramProvider(
const QgsDiagramLayerSettings* diagSettings,
const QgsDiagramRendererV2* diagRenderer,
const QString& layerId,
const QgsFields& fields,
const QgsCoordinateReferenceSystem& crs,
QgsAbstractFeatureSource* source,
bool ownsSource )
: mSettings( *diagSettings )
, mDiagRenderer( diagRenderer->clone() )
, mLayerId( layerId )
, mFields( fields )
, mLayerCrs( crs )
, mSource( source )
, mOwnsSource( ownsSource )
{
init();
}
QgsVectorLayerDiagramProvider::QgsVectorLayerDiagramProvider( QgsVectorLayer* layer )
: mSettings( *layer->diagramLayerSettings() )
, mDiagRenderer( layer->diagramRenderer()->clone() )
, mLayerId( layer->id() )
, mFields( layer->fields() )
, mLayerCrs( layer->crs() )
, mSource( new QgsVectorLayerFeatureSource( layer ) )
, mOwnsSource( true )
: mSettings( *layer->diagramLayerSettings() )
, mDiagRenderer( layer->diagramRenderer()->clone() )
, mLayerId( layer->id() )
, mFields( layer->fields() )
, mLayerCrs( layer->crs() )
, mSource( new QgsVectorLayerFeatureSource( layer ) )
, mOwnsSource( true )
{
init();
}
@ -142,9 +143,12 @@ QList<QgsLabelFeature*> QgsVectorLayerDiagramProvider::labelFeatures( const QgsM
if ( mSettings.yPosColumn != -1 )
attributeNames << mFields.at( mSettings.yPosColumn ).name();
QgsRectangle layerExtent = context.extent();
if ( mSettings.ct )
layerExtent = mSettings.ct->transformBoundingBox( context.extent(), QgsCoordinateTransform::ReverseTransform );
QgsFeatureRequest request;
request.setFilterRect( context.extent() );
request.setFilterRect( layerExtent );
request.setSubsetOfAttributes( attributeNames, mFields );
QgsFeatureIterator fit = mSource->getFeatures( request );
@ -213,7 +217,7 @@ QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& fea
if ( dr )
{
QList<QgsDiagramSettings> settingList = dr->diagramSettings();
if ( settingList.size() > 0 )
if ( settingList.size() > 0 && settingList.at( 0 ).scaleBasedVisibility )
{
double minScale = settingList.at( 0 ).minScaleDenominator;
if ( minScale > 0 && context.rendererScale() < minScale )

View File

@ -53,21 +53,25 @@ QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( QgsVectorLayer* layer
mSettings = QgsVectorLayerLabelSettings::fromLayer( layer );
mLayerId = layer->id();
mFields = layer->fields();
mCrs = layer->crs();
mSource = new QgsVectorLayerFeatureSource( layer );
init();
}
QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider( const QgsPalLayerSettings& settings,
const QString& layerId,
const QgsFields& fields,
QgsAbstractFeatureSource* source,
bool ownsSource )
: mSettings( settings )
, mLayerId( layerId )
, mFields( fields )
, mSource( source )
, mOwnsSource( ownsSource )
QgsVectorLayerLabelProvider::QgsVectorLayerLabelProvider(
const QgsPalLayerSettings& settings,
const QString& layerId,
const QgsFields& fields,
const QgsCoordinateReferenceSystem& crs,
QgsAbstractFeatureSource* source,
bool ownsSource )
: mSettings( settings )
, mLayerId( layerId )
, mFields( fields )
, mCrs( crs )
, mSource( source )
, mOwnsSource( ownsSource )
{
init();
}
@ -201,8 +205,8 @@ QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMap
lyr.xform = &mapSettings.mapToPixel();
lyr.ct = 0;
if ( mapSettings.hasCrsTransformEnabled() && ctx.coordinateTransform() )
lyr.ct = ctx.coordinateTransform()->clone();
if ( mapSettings.hasCrsTransformEnabled() )
lyr.ct = new QgsCoordinateTransform( mCrs, mapSettings.destinationCrs() );
lyr.ptZero = lyr.xform->toMapCoordinates( 0, 0 );
lyr.ptOne = lyr.xform->toMapCoordinates( 1, 0 );
@ -216,9 +220,12 @@ QList<QgsLabelFeature*> QgsVectorLayerLabelProvider::labelFeatures( const QgsMap
lyr.mFeatsSendingToPal = 0;
QgsRectangle layerExtent = ctx.extent();
if ( lyr.ct )
layerExtent = lyr.ct->transformBoundingBox( ctx.extent(), QgsCoordinateTransform::ReverseTransform );
QgsFeatureRequest request;
request.setFilterRect( ctx.extent() );
request.setFilterRect( layerExtent );
request.setSubsetOfAttributes( attrNames, mFields );
QgsFeatureIterator fit = mSource->getFeatures( request );

View File

@ -37,6 +37,7 @@ class CORE_EXPORT QgsVectorLayerLabelProvider : public QgsAbstractLabelProvider
QgsVectorLayerLabelProvider( const QgsPalLayerSettings& settings,
const QString& layerId,
const QgsFields& fields,
const QgsCoordinateReferenceSystem& crs,
QgsAbstractFeatureSource* source,
bool ownsSource );
@ -57,6 +58,7 @@ class CORE_EXPORT QgsVectorLayerLabelProvider : public QgsAbstractLabelProvider
QgsPalLayerSettings mSettings;
QString mLayerId;
QgsFields mFields;
QgsCoordinateReferenceSystem mCrs;
QgsAbstractFeatureSource* mSource;
bool mOwnsSource;
};

View File

@ -27,7 +27,9 @@
#include "qgssymbollayerv2.h"
#include "qgssymbolv2.h"
#include "qgsvectorlayer.h"
#include "qgsvectorlayerdiagramprovider.h"
#include "qgsvectorlayerfeatureiterator.h"
#include "qgsvectorlayerlabelprovider.h"
#include "qgspainteffect.h"
#include <QSettings>
@ -463,7 +465,16 @@ void QgsVectorLayerRenderer::stopRendererV2( QgsSingleSymbolRendererV2* selRende
void QgsVectorLayerRenderer::prepareLabeling( QgsVectorLayer* layer, QStringList& attributeNames )
{
if ( !mContext.labelingEngine() )
{
if ( QgsLabelingEngineV2* engine2 = mContext.labelingEngineV2() )
{
if ( layer->labelsEnabled() )
engine2->addProvider( new QgsVectorLayerLabelProvider( layer ) );
if ( layer->diagramsEnabled() )
engine2->addProvider( new QgsVectorLayerDiagramProvider( layer ) );
}
return;
}
if ( mContext.labelingEngine()->prepareLayer( layer, attributeNames, mContext ) )
{

View File

@ -77,8 +77,8 @@ void TestQgsLabelingEngineV2::testBasic()
vl->setCustomProperty( "labeling/enabled", true );
vl->setCustomProperty( "labeling/fieldName", "Class" );
QgsVectorLayerLabelProvider lp( vl );
QgsLabelingEngineV2 engine( mapSettings, QList<QgsAbstractLabelProvider*>() << &lp );
QgsLabelingEngineV2 engine( mapSettings );
engine.addProvider( new QgsVectorLayerLabelProvider( vl ) );
//engine.setFlags( QgsLabelingEngineV2::RenderOutlineLabels | QgsLabelingEngineV2::DrawLabelRectOnly );
engine.run( context );
@ -112,8 +112,8 @@ void TestQgsLabelingEngineV2::testDiagrams()
vl->loadNamedStyle( QString( TEST_DATA_DIR ) + "/points_diagrams.qml", res );
Q_ASSERT( res );
QgsVectorLayerDiagramProvider dp( vl );
QgsLabelingEngineV2 engine( mapSettings, QList<QgsAbstractLabelProvider*>() << &dp );
QgsLabelingEngineV2 engine( mapSettings );
engine.addProvider( new QgsVectorLayerDiagramProvider( vl ) );
engine.run( context );
p.end();