Skip to content

Commit

Permalink
Ensure that the @geometry_part_num variable exactly matches the
Browse files Browse the repository at this point in the history
correct part ordering for polygon features

Because we sort and render polygon parts in descending area order,
we can't use the order of parts rendered for this variable or
we'll be giving a different part number vs the actual geometry
part number.
  • Loading branch information
nyalldawson committed Mar 31, 2021
1 parent 2a1ab9b commit 684a422
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 9 deletions.
18 changes: 9 additions & 9 deletions src/core/symbology/qgssymbol.cpp
Expand Up @@ -1012,11 +1012,12 @@ void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &cont
QPolygonF renderExterior;
QVector< QPolygonF > renderRings;
const QgsCurvePolygon *originalGeometry = nullptr;
int originalPartIndex = 0;
};
QVector< PolygonInfo > polygonsToRender;

std::function< void ( const QgsAbstractGeometry * )> getPartGeometry;
getPartGeometry = [&pointsToRender, &linesToRender, &polygonsToRender, &getPartGeometry, &context, &clippingEnabled, &markers, &feature, &usingSegmentizedGeometry, this]( const QgsAbstractGeometry * part )
std::function< void ( const QgsAbstractGeometry *, int partIndex )> getPartGeometry;
getPartGeometry = [&pointsToRender, &linesToRender, &polygonsToRender, &getPartGeometry, &context, &clippingEnabled, &markers, &feature, &usingSegmentizedGeometry, this]( const QgsAbstractGeometry * part, int partIndex = 0 )
{
Q_UNUSED( feature )

Expand Down Expand Up @@ -1138,6 +1139,7 @@ void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &cont

PolygonInfo info;
info.originalGeometry = qgsgeometry_cast<const QgsCurvePolygon *>( part );
info.originalPartIndex = partIndex;
if ( !qgsgeometry_cast<const QgsPolygon *>( processedGeometry )->exteriorRing() )
{
QgsDebugMsg( QStringLiteral( "cannot render polygon with no exterior ring" ) );
Expand Down Expand Up @@ -1167,7 +1169,7 @@ void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &cont
if ( context.renderingStopped() )
break;

getPartGeometry( geomCollection->geometryN( i ) );
getPartGeometry( geomCollection->geometryN( i ), i );
}
break;
}
Expand Down Expand Up @@ -1205,7 +1207,7 @@ void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &cont
for ( int idx = 0; idx < listPartIndex.size(); ++idx )
{
const unsigned i = listPartIndex[idx];
getPartGeometry( geomCollection->geometryN( i ) );
getPartGeometry( geomCollection->geometryN( i ), i );
}
}
break;
Expand All @@ -1219,7 +1221,7 @@ void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &cont
}
};

getPartGeometry( geom.constGet() );
getPartGeometry( geom.constGet(), 0 );

// step 2 - determine which layers to render
std::vector< int > layers;
Expand Down Expand Up @@ -1295,19 +1297,17 @@ void QgsSymbol::renderFeature( const QgsFeature &feature, QgsRenderContext &cont

case QgsSymbol::Fill:
{
int geometryPartNumber = 0;
for ( const PolygonInfo &info : std::as_const( polygonsToRender ) )
{
if ( context.renderingStopped() )
break;

mSymbolRenderContext->setGeometryPartNum( geometryPartNumber + 1 );
mSymbolRenderContext->setGeometryPartNum( info.originalPartIndex + 1 );
if ( needsExpressionContext )
mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, geometryPartNumber + 1, true ) );
mSymbolRenderContext->expressionContextScope()->addVariable( QgsExpressionContextScope::StaticVariable( QgsExpressionContext::EXPR_GEOMETRY_PART_NUM, info.originalPartIndex + 1, true ) );

context.setGeometry( info.originalGeometry );
static_cast<QgsFillSymbol *>( this )->renderPolygon( info.renderExterior, ( !info.renderRings.isEmpty() ? &info.renderRings : nullptr ), &feature, context, symbolLayerIndex, selected );
geometryPartNumber++;
}

break;
Expand Down
20 changes: 20 additions & 0 deletions tests/src/python/test_qgsmarkerlinesymbollayer.py
Expand Up @@ -186,6 +186,26 @@ def testPartNum(self):
rendered_image = self.renderGeometry(s, g, buffer=4)
assert self.imageCheck('part_count_variable', 'part_count_variable', rendered_image)

def testPartNumPolygon(self):
# test geometry_part_num variable
s = QgsFillSymbol()

marker_line = QgsMarkerLineSymbolLayer(False)
marker_line.setPlacement(QgsMarkerLineSymbolLayer.FirstVertex)
f = QgsFontUtils.getStandardTestFont('Bold', 24)
marker = QgsFontMarkerSymbolLayer(f.family(), 'x', 24, QColor(255, 255, 0))
marker.setDataDefinedProperty(QgsSymbolLayer.PropertyCharacter, QgsProperty.fromExpression('@geometry_part_num'))
marker_symbol = QgsMarkerSymbol()
marker_symbol.changeSymbolLayer(0, marker)
marker_line.setSubSymbol(marker_symbol)
marker_line.setAverageAngleLength(0)
s.changeSymbolLayer(0, marker_line)

# rendering test - a polygon with a smaller part first
g = QgsGeometry.fromWkt('MultiPolygon(((0 0, 2 0, 2 2, 0 0)),((10 0, 10 10, 0 10, 10 0)))')
rendered_image = self.renderGeometry(s, g, buffer=4)
assert self.imageCheck('poly_part_num_variable', 'poly_part_num_variable', rendered_image)

def testCompoundCurve(self):
# test rendering compound curve with markers at vertices and curve points
s = QgsLineSymbol()
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 684a422

Please sign in to comment.