Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Respect clip region when rendering diagrams
  • 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;
}

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

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() );
}

geos::unique_ptr geomCopy;
std::unique_ptr<QgsGeometry> scopedPreparedGeom;
if ( QgsPalLabeling::geometryRequiresPreparation( geom, context, mSettings.coordinateTransform(), extentGeom ) )
{
scopedPreparedGeom.reset( new QgsGeometry( QgsPalLabeling::prepareGeometry( geom, context, mSettings.coordinateTransform(), extentGeom ) ) );
QgsGeometry *preparedGeom = scopedPreparedGeom.get();
if ( preparedGeom->isNull() )
return nullptr;
geomCopy = QgsGeos::asGeos( *preparedGeom );
geom = QgsPalLabeling::prepareGeometry( geom, context, mSettings.coordinateTransform(), extentGeom );
}
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 ( !geomCopy )
return nullptr; // invalid geometry
if ( geom.isEmpty() )
return nullptr;

QgsGeometry preparedObstacleGeom;
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->setFixedPosition( QgsPointXY( ddPosX, ddPosY ) );
lf->setHasFixedAngle( true );
Expand Down Expand Up @@ -342,3 +345,4 @@ QgsLabelFeature *QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature &fea
lf->setDistLabel( dist );
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() );

/**
* 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:
//! initialization method - called from constructors
void init();
Expand All @@ -123,6 +130,8 @@ class CORE_EXPORT QgsVectorLayerDiagramProvider : public QgsAbstractLabelProvide

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

QgsGeometry mLabelClipFeatureGeom;
};

#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 );

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

if ( mDiagramProvider )
mDiagramProvider->setClipFeatureGeometry( mLabelClipFeatureGeom );
}
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" ) );
}

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 )
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.