Skip to content

Commit

Permalink
Respect clip region when rendering diagrams
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Jul 2, 2020
1 parent e028067 commit 4e815b9
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 13 deletions.
30 changes: 17 additions & 13 deletions src/core/qgsvectorlayerdiagramprovider.cpp
Expand Up @@ -173,6 +173,10 @@ void QgsVectorLayerDiagramProvider::registerFeature( QgsFeature &feature, QgsRen
mFeatures << label; mFeatures << label;
} }


void QgsVectorLayerDiagramProvider::setClipFeatureGeometry( const QgsGeometry &geometry )
{
mLabelClipFeatureGeom = geometry;
}


QgsLabelFeature *QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature &feat, QgsRenderContext &context, const QgsGeometry &obstacleGeometry ) QgsLabelFeature *QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature &feat, QgsRenderContext &context, const QgsGeometry &obstacleGeometry )
{ {
Expand Down Expand Up @@ -214,23 +218,22 @@ QgsLabelFeature *QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature &fea
extentGeom.rotate( -mapSettings.rotation(), mapSettings.visibleExtent().center() ); extentGeom.rotate( -mapSettings.rotation(), mapSettings.visibleExtent().center() );
} }


geos::unique_ptr geomCopy;
std::unique_ptr<QgsGeometry> scopedPreparedGeom;
if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, mSettings.coordinateTransform(), extentGeom ) ) if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, mSettings.coordinateTransform(), extentGeom ) )
{ {
scopedPreparedGeom.reset( new QgsGeometry( QgsPalLabeling::prepareGeometry( geom, context, mSettings.coordinateTransform(), extentGeom ) ) ); geom = QgsPalLabeling::prepareGeometry( geom, context, mSettings.coordinateTransform(), extentGeom );
QgsGeometry *preparedGeom = scopedPreparedGeom.get();
if ( preparedGeom->isNull() )
return nullptr;
geomCopy = QgsGeos::asGeos( *preparedGeom );
} }
else if ( geom.isEmpty() )
return nullptr;

const QgsGeometry clipGeometry = mLabelClipFeatureGeom.isNull() ? context.featureClipGeometry() : mLabelClipFeatureGeom;
if ( !clipGeometry.isEmpty() )
{ {
geomCopy = QgsGeos::asGeos( geom ); const QgsWkbTypes::GeometryType expectedType = geom.type();
geom = geom.intersection( clipGeometry );
geom.convertGeometryCollectionToSubclass( expectedType );
} }

if ( geom.isEmpty() )
if ( !geomCopy ) return nullptr;
return nullptr; // invalid geometry


QgsGeometry preparedObstacleGeom; QgsGeometry preparedObstacleGeom;
if ( isObstacle && !obstacleGeometry.isNull() && QgsPalLabeling::geometryRequiresPreparation( obstacleGeometry, context, mSettings.coordinateTransform(), extentGeom ) ) if ( isObstacle && !obstacleGeometry.isNull() && QgsPalLabeling::geometryRequiresPreparation( obstacleGeometry, context, mSettings.coordinateTransform(), extentGeom ) )
Expand Down Expand Up @@ -287,7 +290,7 @@ QgsLabelFeature *QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature &fea
} }
} }


QgsDiagramLabelFeature *lf = new QgsDiagramLabelFeature( feat.id(), std::move( geomCopy ), QSizeF( diagramWidth, diagramHeight ) ); QgsDiagramLabelFeature *lf = new QgsDiagramLabelFeature( feat.id(), QgsGeos::asGeos( geom ), QSizeF( diagramWidth, diagramHeight ) );
lf->setHasFixedPosition( ddPos ); lf->setHasFixedPosition( ddPos );
lf->setFixedPosition( QgsPointXY( ddPosX, ddPosY ) ); lf->setFixedPosition( QgsPointXY( ddPosX, ddPosY ) );
lf->setHasFixedAngle( true ); lf->setHasFixedAngle( true );
Expand Down Expand Up @@ -342,3 +345,4 @@ QgsLabelFeature *QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature &fea
lf->setDistLabel( dist ); lf->setDistLabel( dist );
return lf; return lf;
} }

9 changes: 9 additions & 0 deletions src/core/qgsvectorlayerdiagramprovider.h
Expand Up @@ -97,6 +97,13 @@ class CORE_EXPORT QgsVectorLayerDiagramProvider : public QgsAbstractLabelProvide
*/ */
virtual void registerFeature( QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry = QgsGeometry() ); virtual void registerFeature( QgsFeature &feature, QgsRenderContext &context, const QgsGeometry &obstacleGeometry = QgsGeometry() );


/**
* Sets a \a geometry to use to clip features to when registering them as diagrams.
*
* \since QGIS 3.16
*/
void setClipFeatureGeometry( const QgsGeometry &geometry );

protected: protected:
//! initialization method - called from constructors //! initialization method - called from constructors
void init(); void init();
Expand All @@ -123,6 +130,8 @@ class CORE_EXPORT QgsVectorLayerDiagramProvider : public QgsAbstractLabelProvide


//! List of generated label features (owned by the provider) //! List of generated label features (owned by the provider)
QList<QgsLabelFeature *> mFeatures; QList<QgsLabelFeature *> mFeatures;

QgsGeometry mLabelClipFeatureGeom;
}; };


#endif // QGSVECTORLAYERDIAGRAMPROVIDER_H #endif // QGSVECTORLAYERDIAGRAMPROVIDER_H
3 changes: 3 additions & 0 deletions src/core/qgsvectorlayerrenderer.cpp
Expand Up @@ -196,6 +196,9 @@ bool QgsVectorLayerRenderer::render()
context.painter()->setClipPath( path, Qt::IntersectClip ); context.painter()->setClipPath( path, Qt::IntersectClip );


mLabelClipFeatureGeom = QgsMapClippingUtils::calculateLabelIntersectionGeometry( mClippingRegions, context, mApplyLabelClipGeometries ); mLabelClipFeatureGeom = QgsMapClippingUtils::calculateLabelIntersectionGeometry( mClippingRegions, context, mApplyLabelClipGeometries );

if ( mDiagramProvider )
mDiagramProvider->setClipFeatureGeometry( mLabelClipFeatureGeom );
} }
mRenderer->modifyRequestExtent( requestExtent, context ); mRenderer->modifyRequestExtent( requestExtent, context );


Expand Down
57 changes: 57 additions & 0 deletions tests/src/core/testqgsdiagram.cpp
Expand Up @@ -894,6 +894,63 @@ class TestQgsDiagram : public QObject
QVERIFY( imageCheck( "textdiagram_datadefined_background" ) ); QVERIFY( imageCheck( "textdiagram_datadefined_background" ) );
} }


void testClipping()
{
const QString filename = QStringLiteral( TEST_DATA_DIR ) + "/lines.shp";
std::unique_ptr< QgsVectorLayer> vl2( new QgsVectorLayer( filename, QStringLiteral( "lines" ), QStringLiteral( "ogr" ) ) );

QgsStringMap props;
props.insert( QStringLiteral( "outline_color" ), QStringLiteral( "#487bb6" ) );
props.insert( QStringLiteral( "outline_width" ), QStringLiteral( "1" ) );
std::unique_ptr< QgsLineSymbol > symbol( QgsLineSymbol::createSimple( props ) );
vl2->setRenderer( new QgsSingleSymbolRenderer( symbol.release() ) );

QgsDiagramSettings ds;
QColor col1 = Qt::red;
QColor col2 = Qt::yellow;
col1.setAlphaF( 0.5 );
col2.setAlphaF( 0.5 );
ds.categoryColors = QList<QColor>() << col1;
ds.categoryAttributes = QList<QString>() << QStringLiteral( "\"Value\"" );
ds.minimumScale = -1;
ds.maximumScale = -1;
ds.minimumSize = 0;
ds.penColor = Qt::green;
ds.penWidth = .5;
ds.scaleByArea = true;
ds.sizeType = QgsUnitTypes::RenderMillimeters;
ds.size = QSizeF( 5, 5 );
ds.rotationOffset = 0;

QgsSingleCategoryDiagramRenderer *dr = new QgsSingleCategoryDiagramRenderer();
dr->setDiagram( new QgsPieDiagram() );
dr->setDiagramSettings( ds );
vl2->setDiagramRenderer( dr );

QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
dls.setPlacement( QgsDiagramLayerSettings::Line );
dls.setShowAllDiagrams( true );
vl2->setDiagramLayerSettings( dls );

mMapSettings->setLayers( QList<QgsMapLayer *>() << vl2.get() );

QgsMapClippingRegion region1( QgsGeometry::fromWkt( "Polygon ((-92 45, -99 36, -94 29, -82 29, -81 45, -92 45))" ) );
region1.setFeatureClip( QgsMapClippingRegion::FeatureClippingType::Intersect );
mMapSettings->addClippingRegion( region1 );

QgsMapClippingRegion region2( QgsGeometry::fromWkt( "Polygon ((-85 36, -85 46, -107 47, -108 28, -85 28, -85 36))" ) );
region2.setFeatureClip( QgsMapClippingRegion::FeatureClippingType::PainterClip );
mMapSettings->addClippingRegion( region2 );

const bool res = imageCheck( QStringLiteral( "diagram_clipping" ) );
mMapSettings->setClippingRegions( QList< QgsMapClippingRegion >() );
mMapSettings->setLayers( QList<QgsMapLayer *>() << mPointsLayer );

QVERIFY( res );
}



}; };


bool TestQgsDiagram::imageCheck( const QString &testType ) bool TestQgsDiagram::imageCheck( const QString &testType )
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 4e815b9

Please sign in to comment.