Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Correctly handle rendering/labelling polygon features from vector til…
…es using

a point symbol

This is permitted in JS vector tile libraries, and is treated as
the centroid of the polygon

Fixes #46587
  • Loading branch information
nyalldawson committed Jan 7, 2022
1 parent 0cca400 commit 612f5dc
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 2 deletions.
28 changes: 26 additions & 2 deletions src/core/vectortile/qgsvectortilebasiclabeling.cpp
Expand Up @@ -231,8 +231,20 @@ void QgsVectorTileBasicLabelProvider::registerTileFeatures( const QgsVectorTileR
if ( filterExpression.isValid() && !filterExpression.evaluate( &context.expressionContext() ).toBool() )
continue;

if ( QgsWkbTypes::geometryType( f.geometry().wkbType() ) == layerStyle.geometryType() )
const QgsWkbTypes::GeometryType featureType = QgsWkbTypes::geometryType( f.geometry().wkbType() );
if ( featureType == layerStyle.geometryType() )
{
subProvider->registerFeature( f, context );
}
else if ( featureType == QgsWkbTypes::PolygonGeometry && layerStyle.geometryType() == QgsWkbTypes::PointGeometry )
{
// be tolerant and permit labeling polygons with a point layer style, as some style definitions use this approach
// to label the polygon center
QgsFeature centroid = f;
const QgsRectangle boundingBox = f.geometry().boundingBox();
centroid.setGeometry( f.geometry().poleOfInaccessibility( std::min( boundingBox.width(), boundingBox.height() ) / 20 ) );
subProvider->registerFeature( centroid, context );
}
}
}
}
Expand All @@ -245,8 +257,20 @@ void QgsVectorTileBasicLabelProvider::registerTileFeatures( const QgsVectorTileR
if ( filterExpression.isValid() && !filterExpression.evaluate( &context.expressionContext() ).toBool() )
continue;

if ( QgsWkbTypes::geometryType( f.geometry().wkbType() ) == layerStyle.geometryType() )
const QgsWkbTypes::GeometryType featureType = QgsWkbTypes::geometryType( f.geometry().wkbType() );
if ( featureType == layerStyle.geometryType() )
{
subProvider->registerFeature( f, context );
}
else if ( featureType == QgsWkbTypes::PolygonGeometry && layerStyle.geometryType() == QgsWkbTypes::PointGeometry )
{
// be tolerant and permit labeling polygons with a point layer style, as some style definitions use this approach
// to label the polygon center
QgsFeature centroid = f;
const QgsRectangle boundingBox = f.geometry().boundingBox();
centroid.setGeometry( f.geometry().poleOfInaccessibility( std::min( boundingBox.width(), boundingBox.height() ) / 20 ) );
subProvider->registerFeature( centroid, context );
}
}
}
}
Expand Down
18 changes: 18 additions & 0 deletions src/core/vectortile/qgsvectortilebasicrenderer.cpp
Expand Up @@ -212,6 +212,15 @@ void QgsVectorTileBasicRenderer::renderTile( const QgsVectorTileRendererData &ti
exterior.setGeometry( QgsGeometry( f.geometry().constGet()->boundary() ) );
sym->renderFeature( exterior, context );
}
else if ( featureType == QgsWkbTypes::PolygonGeometry && layerStyle.geometryType() == QgsWkbTypes::PointGeometry )
{
// be tolerant and permit rendering polygons with a point layer style, as some style definitions use this approach
// to render the polygon center
QgsFeature centroid = f;
const QgsRectangle boundingBox = f.geometry().boundingBox();
centroid.setGeometry( f.geometry().poleOfInaccessibility( std::min( boundingBox.width(), boundingBox.height() ) / 20 ) );
sym->renderFeature( centroid, context );
}
}
}
}
Expand All @@ -237,6 +246,15 @@ void QgsVectorTileBasicRenderer::renderTile( const QgsVectorTileRendererData &ti
exterior.setGeometry( QgsGeometry( f.geometry().constGet()->boundary() ) );
sym->renderFeature( exterior, context );
}
else if ( featureType == QgsWkbTypes::PolygonGeometry && layerStyle.geometryType() == QgsWkbTypes::PointGeometry )
{
// be tolerant and permit rendering polygons with a point layer style, as some style definitions use this approach
// to render the polygon center
QgsFeature centroid = f;
const QgsRectangle boundingBox = f.geometry().boundingBox();
centroid.setGeometry( f.geometry().poleOfInaccessibility( std::min( boundingBox.width(), boundingBox.height() ) / 20 ) );
sym->renderFeature( centroid, context );
}
}
}
sym->stopRender( context );
Expand Down
39 changes: 39 additions & 0 deletions tests/src/core/testqgsvectortilelayer.cpp
Expand Up @@ -30,6 +30,8 @@
#include "qgslinesymbol.h"
#include "qgsfillsymbollayer.h"
#include "qgsfillsymbol.h"
#include "qgsmarkersymbol.h"
#include "qgsmarkersymbollayer.h"

/**
* \ingroup UnitTests
Expand Down Expand Up @@ -62,6 +64,7 @@ class TestQgsVectorTileLayer : public QObject
void test_labeling();
void test_relativePaths();
void test_polygonWithLineStyle();
void test_polygonWithMarker();
};


Expand Down Expand Up @@ -284,6 +287,42 @@ void TestQgsVectorTileLayer::test_polygonWithLineStyle()
QVERIFY( imageCheck( "render_test_polygon_with_line_style", layer.get(), layer->extent() ) );
}

void TestQgsVectorTileLayer::test_polygonWithMarker()
{
// a polygon in a vector tile layer which is matched by a marker rule should result in a point-inside-polygon placement
QgsDataSourceUri ds;
ds.setParam( "type", "xyz" );
ds.setParam( "url", QString( "file://%1/{z}-{x}-{y}.pbf" ).arg( mDataDir ) );
ds.setParam( "zmax", "1" );
std::unique_ptr< QgsVectorTileLayer > layer = std::make_unique< QgsVectorTileLayer >( ds.encodedUri(), "Vector Tiles Test" );
QVERIFY( layer->isValid() );

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

const QColor markerColor = Qt::blue;

QgsSimpleMarkerSymbolLayer *markerSymbolLayer = new QgsSimpleMarkerSymbolLayer;
markerSymbolLayer->setColor( markerColor );
QgsMarkerSymbol *markerSymbol = new QgsMarkerSymbol( QgsSymbolLayerList() << markerSymbolLayer );

QgsVectorTileBasicRendererStyle st( QStringLiteral( "Polygons" ), QString(), QgsWkbTypes::PointGeometry );
st.setSymbol( markerSymbol );

QgsSimpleFillSymbolLayer *fillSymbolLayer = new QgsSimpleFillSymbolLayer;
fillSymbolLayer->setColor( Qt::white );
fillSymbolLayer->setStrokeStyle( Qt::NoPen );
QgsFillSymbol *fillSymbol = new QgsFillSymbol( QgsSymbolLayerList() << fillSymbolLayer );

QgsVectorTileBasicRendererStyle bgst( QStringLiteral( "background" ), QStringLiteral( "background" ), QgsWkbTypes::PolygonGeometry );
bgst.setSymbol( fillSymbol );

QgsVectorTileBasicRenderer *rend = new QgsVectorTileBasicRenderer;
rend->setStyles( QList<QgsVectorTileBasicRendererStyle>() << bgst << st );
layer->setRenderer( rend ); // takes ownership

QVERIFY( imageCheck( "render_test_polygon_with_marker", layer.get(), layer->extent() ) );
}


QGSTEST_MAIN( TestQgsVectorTileLayer )
#include "testqgsvectortilelayer.moc"
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 612f5dc

Please sign in to comment.