Skip to content
Permalink
Browse files
Add support for more data definable properties to diagrams:
- Distance
- Priority
- ZIndex
- IsObstacle
- Show
- AlwaysShow
- Diagram Start Angle
  • Loading branch information
nyalldawson committed Jan 23, 2017
1 parent 07315bf commit 336b603b3aea2316b49549db533811208596a542
@@ -44,6 +44,13 @@ class QgsDiagramLayerSettings
OutlineWidth, /*!< Outline width */
PositionX, /*! x-coordinate data defined diagram position */
PositionY, /*! y-coordinate data defined diagram position */
Distance, /*! Distance to diagram from feature */
Priority, /*! Diagram priority (between 0 and 10) */
ZIndex, /*! Z-index for diagram ordering */
IsObstacle, /*! Whether diagram features act as obstacles for other diagrams/labels */
Show, /*! Whether to show the diagram */
AlwaysShow, /*! Whether the diagram should always be shown, even if it overlaps other diagrams/labels */
StartAngle, /*! Angle offset for pie diagram */
};

QgsDiagramLayerSettings();
@@ -145,6 +145,13 @@ void QgsDiagramLayerSettings::init()
sPropertyNameMap.insert( OutlineWidth, "outlineWidth" );
sPropertyNameMap.insert( PositionX, "positionX" );
sPropertyNameMap.insert( PositionY, "positionY" );
sPropertyNameMap.insert( Distance, "distance" );
sPropertyNameMap.insert( Priority, "priority" );
sPropertyNameMap.insert( ZIndex, "zIndex" );
sPropertyNameMap.insert( IsObstacle, "isObstacle" );
sPropertyNameMap.insert( Show, "show" );
sPropertyNameMap.insert( AlwaysShow, "alwaysShow" );
sPropertyNameMap.insert( StartAngle, "startAngle" );
}
}

@@ -450,6 +457,8 @@ void QgsDiagramRenderer::renderDiagram( const QgsFeature& feature, QgsRenderCont
s.penColor = properties.valueAsColor( QgsDiagramLayerSettings::OutlineColor, c.expressionContext(), s.penColor );
c.expressionContext().setOriginalValueVariable( s.penWidth );
s.penWidth = properties.valueAsDouble( QgsDiagramLayerSettings::OutlineWidth, c.expressionContext(), s.penWidth );
c.expressionContext().setOriginalValueVariable( s.angleOffset / 16.0 );
s.angleOffset = 16.0 * properties.valueAsDouble( QgsDiagramLayerSettings::StartAngle, c.expressionContext(), s.angleOffset / 16.0 );
}

mDiagram->renderDiagram( feature, c, s, pos );
@@ -85,6 +85,13 @@ class CORE_EXPORT QgsDiagramLayerSettings
OutlineWidth, //!< Outline width
PositionX, //! x-coordinate data defined diagram position
PositionY, //! y-coordinate data defined diagram position
Distance, //! Distance to diagram from feature
Priority, //! Diagram priority (between 0 and 10)
ZIndex, //! Z-index for diagram ordering
IsObstacle, //! Whether diagram features act as obstacles for other diagrams/labels
Show, //! Whether to show the diagram
AlwaysShow, //! Whether the diagram should always be shown, even if it overlaps other diagrams/labels
StartAngle, //! Angle offset for pie diagram
};

QgsDiagramLayerSettings();
@@ -217,6 +217,23 @@ QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& fea
}
}

// data defined show diagram? check this before doing any other processing
if ( mSettings.properties().hasProperty( QgsDiagramLayerSettings::Show )
&& mSettings.properties().property( QgsDiagramLayerSettings::Show )->isActive() )
{
bool show = mSettings.properties().valueAsInt( QgsDiagramLayerSettings::Show, context.expressionContext(), true );
if ( !show )
return nullptr;
}

// data defined obstacle?
bool isObstacle = mSettings.isObstacle();
if ( mSettings.properties().hasProperty( QgsDiagramLayerSettings::IsObstacle )
&& mSettings.properties().property( QgsDiagramLayerSettings::IsObstacle )->isActive() )
{
isObstacle = mSettings.properties().valueAsInt( QgsDiagramLayerSettings::IsObstacle, context.expressionContext(), isObstacle );
}

//convert geom to geos
QgsGeometry geom = feat.geometry();
QgsGeometry extentGeom = QgsGeometry::fromRect( mapSettings.visibleExtent() );
@@ -246,7 +263,7 @@ QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& fea

GEOSGeometry* geosObstacleGeomClone = nullptr;
QScopedPointer<QgsGeometry> scopedObstacleGeom;
if ( mSettings.isObstacle() && obstacleGeometry && QgsPalLabeling::geometryRequiresPreparation( *obstacleGeometry, context, mSettings.coordinateTransform(), &extentGeom ) )
if ( isObstacle && obstacleGeometry && QgsPalLabeling::geometryRequiresPreparation( *obstacleGeometry, context, mSettings.coordinateTransform(), &extentGeom ) )
{
QgsGeometry preparedObstacleGeom = QgsPalLabeling::prepareGeometry( *obstacleGeometry, context, mSettings.coordinateTransform(), &extentGeom );
geosObstacleGeomClone = preparedObstacleGeom.exportToGeos();
@@ -270,7 +287,14 @@ QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& fea

// feature to the layer
bool alwaysShow = mSettings.showAllDiagrams();
if ( mSettings.properties().hasProperty( QgsDiagramLayerSettings::AlwaysShow )
&& mSettings.properties().property( QgsDiagramLayerSettings::AlwaysShow )->isActive() )
{
context.expressionContext().setOriginalValueVariable( alwaysShow );
alwaysShow = mSettings.properties().valueAsInt( QgsDiagramLayerSettings::AlwaysShow, context.expressionContext(), alwaysShow );
}

// old style show
int ddColShow = mSettings.showColumn;
if ( ddColShow >= 0 && ! feat.attribute( ddColShow ).isNull() )
{
@@ -330,8 +354,7 @@ QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& fea
lf->setHasFixedAngle( true );
lf->setFixedAngle( 0 );
lf->setAlwaysShow( alwaysShow );
lf->setIsObstacle( mSettings.isObstacle() );
lf->setZIndex( mSettings.zIndex() );
lf->setIsObstacle( isObstacle );
if ( geosObstacleGeomClone )
{
lf->setObstacleGeometry( geosObstacleGeomClone );
@@ -343,8 +366,41 @@ QgsLabelFeature* QgsVectorLayerDiagramProvider::registerDiagram( QgsFeature& fea
lf->setAttributes( feat.attributes() );
}

// data defined priority?
if ( mSettings.properties().hasProperty( QgsDiagramLayerSettings::Priority )
&& mSettings.properties().property( QgsDiagramLayerSettings::Priority )->isActive() )
{
context.expressionContext().setOriginalValueVariable( mSettings.priority() );
double priorityD = mSettings.properties().valueAsDouble( QgsDiagramLayerSettings::Priority, context.expressionContext(), mSettings.getPriority() );
priorityD = qBound( 0.0, priorityD, 10.0 );
priorityD = 1 - priorityD / 10.0; // convert 0..10 --> 1..0
lf->setPriority( priorityD );
}

// z-Index
double zIndex = mSettings.zIndex();
if ( mSettings.properties().hasProperty( QgsDiagramLayerSettings::ZIndex )
&& mSettings.properties().property( QgsDiagramLayerSettings::ZIndex )->isActive() )
{
context.expressionContext().setOriginalValueVariable( zIndex );
zIndex = mSettings.properties().valueAsDouble( QgsDiagramLayerSettings::ZIndex, context.expressionContext(), zIndex );
}
lf->setZIndex( zIndex );

// label distance
QgsPoint ptZero = mapSettings.mapToPixel().toMapCoordinates( 0, 0 );
QgsPoint ptOne = mapSettings.mapToPixel().toMapCoordinates( 1, 0 );
lf->setDistLabel( ptOne.distance( ptZero ) * mSettings.distance() );
double dist = mSettings.distance();

if ( mSettings.properties().hasProperty( QgsDiagramLayerSettings::Distance )
&& mSettings.properties().property( QgsDiagramLayerSettings::Distance )->isActive() )
{
context.expressionContext().setOriginalValueVariable( dist );
dist = mSettings.properties().valueAsDouble( QgsDiagramLayerSettings::Distance, context.expressionContext(), dist );
}

dist *= ptOne.distance( ptZero );

lf->setDistLabel( dist );
return lf;
}
@@ -288,6 +288,223 @@ class TestQgsDiagram : public QObject
QVERIFY( imageCheck( "piediagram_datadefined_outline" ) );
}

void testDataDefinedStartAngle()
{
QgsDiagramSettings ds;
QColor col1 = Qt::red;
QColor col2 = Qt::yellow;
col1.setAlphaF( 0.5 );
col2.setAlphaF( 0.5 );
ds.categoryColors = QList<QColor>() << col1 << col2;
ds.categoryAttributes = QList<QString>() << "\"Pilots\"" << "\"Cabin Crew\"";
ds.maxScaleDenominator = -1;
ds.minScaleDenominator = -1;
ds.minimumSize = 0;
ds.penColor = Qt::green;
ds.penWidth = .5;
ds.scaleByArea = true;
ds.sizeType = QgsUnitTypes::RenderMillimeters;
ds.size = QSizeF( 15, 15 );
ds.angleOffset = 0;

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

QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
dls.setPlacement( QgsDiagramLayerSettings::OverPoint );
dls.setShowAllDiagrams( true );

//setup data defined start angle
dls.properties().setProperty( QgsDiagramLayerSettings::StartAngle, new QgsExpressionBasedProperty( "\"Importance\"/20.0 * 360.0", true ) );

mPointsLayer->setDiagramLayerSettings( dls );

QVERIFY( imageCheck( "piediagram_datadefined_startangle" ) );
}

void testDataDefinedDistance()
{
QgsDiagramSettings ds;
QColor col1 = Qt::red;
QColor col2 = Qt::yellow;
col1.setAlphaF( 0.5 );
col2.setAlphaF( 0.5 );
ds.categoryColors = QList<QColor>() << col1 << col2;
ds.categoryAttributes = QList<QString>() << "\"Pilots\"" << "\"Cabin Crew\"";
ds.maxScaleDenominator = -1;
ds.minScaleDenominator = -1;
ds.minimumSize = 0;
ds.penColor = Qt::green;
ds.penWidth = .5;
ds.scaleByArea = true;
ds.sizeType = QgsUnitTypes::RenderMillimeters;
ds.size = QSizeF( 15, 15 );
ds.angleOffset = 0;

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

QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
dls.setPlacement( QgsDiagramLayerSettings::AroundPoint );
dls.setShowAllDiagrams( true );

//setup data defined distance
dls.properties().setProperty( QgsDiagramLayerSettings::Distance, new QgsExpressionBasedProperty( "\"Staff\"*2", true ) );

mPointsLayer->setDiagramLayerSettings( dls );

QVERIFY( imageCheck( "piediagram_datadefined_distance" ) );
}

void testDataDefinedShow()
{
QgsDiagramSettings ds;
QColor col1 = Qt::red;
QColor col2 = Qt::yellow;
col1.setAlphaF( 0.5 );
col2.setAlphaF( 0.5 );
ds.categoryColors = QList<QColor>() << col1 << col2;
ds.categoryAttributes = QList<QString>() << "\"Pilots\"" << "\"Cabin Crew\"";
ds.maxScaleDenominator = -1;
ds.minScaleDenominator = -1;
ds.minimumSize = 0;
ds.penColor = Qt::green;
ds.penWidth = .5;
ds.scaleByArea = true;
ds.sizeType = QgsUnitTypes::RenderMillimeters;
ds.size = QSizeF( 15, 15 );
ds.angleOffset = 0;

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

QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
dls.setPlacement( QgsDiagramLayerSettings::OverPoint );
dls.setShowAllDiagrams( true );

//setup data defined show
dls.properties().setProperty( QgsDiagramLayerSettings::Show, new QgsExpressionBasedProperty( "\"Pilots\"=1", true ) );

mPointsLayer->setDiagramLayerSettings( dls );

QVERIFY( imageCheck( "piediagram_datadefined_show" ) );
}

void testDataDefinedPriority()
{
QgsDiagramSettings ds;
QColor col1 = Qt::red;
QColor col2 = Qt::yellow;
col1.setAlphaF( 0.5 );
col2.setAlphaF( 0.5 );
ds.categoryColors = QList<QColor>() << col1 << col2;
ds.categoryAttributes = QList<QString>() << "\"Pilots\"" << "\"Cabin Crew\"";
ds.maxScaleDenominator = -1;
ds.minScaleDenominator = -1;
ds.minimumSize = 0;
ds.penColor = Qt::green;
ds.penWidth = .5;
ds.scaleByArea = true;
ds.sizeType = QgsUnitTypes::RenderMillimeters;
ds.size = QSizeF( 50, 50 );
ds.angleOffset = 0;

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

QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
dls.setPlacement( QgsDiagramLayerSettings::OverPoint );
dls.setShowAllDiagrams( false );

//setup data defined priority
dls.properties().setProperty( QgsDiagramLayerSettings::Priority, new QgsExpressionBasedProperty( "\"importance\"/2", true ) );

mPointsLayer->setDiagramLayerSettings( dls );

QVERIFY( imageCheck( "piediagram_datadefined_priority" ) );
}

void testDataDefinedZIndex()
{
QgsDiagramSettings ds;
QColor col1 = Qt::red;
QColor col2 = Qt::yellow;
ds.categoryColors = QList<QColor>() << col1 << col2;
ds.categoryAttributes = QList<QString>() << "\"Pilots\"" << "\"Cabin Crew\"";
ds.maxScaleDenominator = -1;
ds.minScaleDenominator = -1;
ds.minimumSize = 0;
ds.penColor = Qt::green;
ds.penWidth = .5;
ds.scaleByArea = true;
ds.sizeType = QgsUnitTypes::RenderMillimeters;
ds.size = QSizeF( 50, 50 );
ds.angleOffset = 0;

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

QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
dls.setPlacement( QgsDiagramLayerSettings::OverPoint );
dls.setShowAllDiagrams( true );

//setup data defined z index
dls.properties().setProperty( QgsDiagramLayerSettings::ZIndex, new QgsExpressionBasedProperty( "\"importance\"/2", true ) );

mPointsLayer->setDiagramLayerSettings( dls );

QVERIFY( imageCheck( "piediagram_datadefined_zindex" ) );
}

void testDataDefinedAlwaysShow()
{
QgsDiagramSettings ds;
QColor col1 = Qt::red;
QColor col2 = Qt::yellow;
col1.setAlphaF( 0.5 );
col2.setAlphaF( 0.5 );
ds.categoryColors = QList<QColor>() << col1 << col2;
ds.categoryAttributes = QList<QString>() << "\"Pilots\"" << "\"Cabin Crew\"";
ds.maxScaleDenominator = -1;
ds.minScaleDenominator = -1;
ds.minimumSize = 0;
ds.penColor = Qt::green;
ds.penWidth = .5;
ds.scaleByArea = true;
ds.sizeType = QgsUnitTypes::RenderMillimeters;
ds.size = QSizeF( 50, 50 );
ds.angleOffset = 0;

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

QgsDiagramLayerSettings dls = QgsDiagramLayerSettings();
dls.setPlacement( QgsDiagramLayerSettings::OverPoint );
dls.setShowAllDiagrams( false );

//setup data defined priority (required to only show certain diagrams)
dls.properties().setProperty( QgsDiagramLayerSettings::Priority, new QgsExpressionBasedProperty( "\"importance\"/2", true ) );
//setup data defined "always show"
dls.properties().setProperty( QgsDiagramLayerSettings::AlwaysShow, new QgsExpressionBasedProperty( "\"Staff\">=6", true ) );


mPointsLayer->setDiagramLayerSettings( dls );

QVERIFY( imageCheck( "piediagram_datadefined_alwaysshow" ) );
}


void testDataDefinedBackgroundColor()
{
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

0 comments on commit 336b603

Please sign in to comment.