From 543acff4fec5f38b5a10bcf47d02307aa656eae9 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Wed, 5 Dec 2018 21:51:58 +1000 Subject: [PATCH] [FEATURE][AFS] Automatically convert ESRI picture marker symbols and use as default style for remote layers with picture marker symbology --- .../arcgisrest/qgsarcgisrestutils.cpp | 39 ++++++++++++++++++- src/providers/arcgisrest/qgsarcgisrestutils.h | 1 + .../src/providers/testqgsarcgisrestutils.cpp | 33 ++++++++++++++++ 3 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/providers/arcgisrest/qgsarcgisrestutils.cpp b/src/providers/arcgisrest/qgsarcgisrestutils.cpp index 6d8551ff9fb..9ddc970955c 100644 --- a/src/providers/arcgisrest/qgsarcgisrestutils.cpp +++ b/src/providers/arcgisrest/qgsarcgisrestutils.cpp @@ -576,8 +576,8 @@ std::unique_ptr QgsArcGisRestUtils::parseEsriSymbolJson( const QVaria } else if ( type == QLatin1String( "esriPMS" ) ) { - // picture marker - not supported - return nullptr; + // picture marker + return parseEsriPictureMarkerSymbolJson( symbolData ); } else if ( type == QLatin1String( "esriTS" ) ) { @@ -682,6 +682,41 @@ std::unique_ptr QgsArcGisRestUtils::parseEsriMarkerSymbolJson( return symbol; } +std::unique_ptr QgsArcGisRestUtils::parseEsriPictureMarkerSymbolJson( const QVariantMap &symbolData ) +{ + bool ok = false; + const double widthInPixels = symbolData.value( QStringLiteral( "width" ) ).toInt( &ok ); + if ( !ok ) + return nullptr; + const double heightInPixels = symbolData.value( QStringLiteral( "height" ) ).toInt( &ok ); + if ( !ok ) + return nullptr; + + const double angleCCW = symbolData.value( QStringLiteral( "angle" ) ).toDouble( &ok ); + double angleCW = 0; + if ( ok ) + angleCW = -angleCCW; + + const double xOffset = symbolData.value( QStringLiteral( "xoffset" ) ).toDouble(); + const double yOffset = symbolData.value( QStringLiteral( "yoffset" ) ).toDouble(); + + //const QString contentType = symbolData.value( QStringLiteral( "contentType" ) ).toString(); + + QString symbolPath( symbolData.value( QStringLiteral( "imageData" ) ).toString() ); + symbolPath.prepend( QLatin1String( "base64:" ) ); + + QgsSymbolLayerList layers; + std::unique_ptr< QgsRasterMarkerSymbolLayer > markerLayer = qgis::make_unique< QgsRasterMarkerSymbolLayer >( symbolPath, widthInPixels, angleCW, QgsSymbol::ScaleArea ); + markerLayer->setSizeUnit( QgsUnitTypes::RenderPixels ); + markerLayer->setFixedAspectRatio( static_cast< double >( widthInPixels ) / heightInPixels ); + markerLayer->setOffset( QPointF( xOffset, yOffset ) ); + markerLayer->setOffsetUnit( QgsUnitTypes::RenderPoints ); + layers.append( markerLayer.release() ); + + std::unique_ptr< QgsMarkerSymbol > symbol = qgis::make_unique< QgsMarkerSymbol >( layers ); + return symbol; +} + QgsFeatureRenderer *QgsArcGisRestUtils::parseEsriRenderer( const QVariantMap &rendererData ) { const QString type = rendererData.value( QStringLiteral( "type" ) ).toString(); diff --git a/src/providers/arcgisrest/qgsarcgisrestutils.h b/src/providers/arcgisrest/qgsarcgisrestutils.h index 26e15dc9038..b81be1bddb6 100644 --- a/src/providers/arcgisrest/qgsarcgisrestutils.h +++ b/src/providers/arcgisrest/qgsarcgisrestutils.h @@ -55,6 +55,7 @@ class QgsArcGisRestUtils static std::unique_ptr< QgsLineSymbol > parseEsriLineSymbolJson( const QVariantMap &symbolData ); static std::unique_ptr< QgsFillSymbol > parseEsriFillSymbolJson( const QVariantMap &symbolData ); static std::unique_ptr< QgsMarkerSymbol > parseEsriMarkerSymbolJson( const QVariantMap &symbolData ); + static std::unique_ptr< QgsMarkerSymbol > parseEsriPictureMarkerSymbolJson( const QVariantMap &symbolData ); static QgsFeatureRenderer *parseEsriRenderer( const QVariantMap &rendererData ); static QColor parseEsriColorJson( const QVariant &colorData ); diff --git a/tests/src/providers/testqgsarcgisrestutils.cpp b/tests/src/providers/testqgsarcgisrestutils.cpp index d498435ef55..8fc3ce6abbb 100644 --- a/tests/src/providers/testqgsarcgisrestutils.cpp +++ b/tests/src/providers/testqgsarcgisrestutils.cpp @@ -43,6 +43,7 @@ class TestQgsArcGisRestUtils : public QObject void testParseEsriLineStyle(); void testParseEsriColorJson(); void testParseMarkerSymbol(); + void testPictureMarkerSymbol(); void testParseLineSymbol(); void testParseFillSymbol(); void testParseRendererSimple(); @@ -200,6 +201,38 @@ void TestQgsArcGisRestUtils::testParseMarkerSymbol() QVERIFY( !symbol ); } +void TestQgsArcGisRestUtils::testPictureMarkerSymbol() +{ + QVariantMap map = jsonStringToMap( "{" + "\"type\": \"esriPMS\"," + "\"url\": \"471E7E31\"," + "\"imageData\": \"abcdef\"," + "\"contentType\": \"image/png\"," + "\"width\": 20," + "\"height\": 25," + "\"angle\": 10," + "\"xoffset\": 7," + "\"yoffset\": 17" + "}" ); + std::unique_ptr symbol = QgsArcGisRestUtils::parseEsriSymbolJson( map ); + QgsMarkerSymbol *marker = dynamic_cast< QgsMarkerSymbol * >( symbol.get() ); + QVERIFY( marker ); + QCOMPARE( marker->symbolLayerCount(), 1 ); + QgsRasterMarkerSymbolLayer *markerLayer = dynamic_cast< QgsRasterMarkerSymbolLayer * >( marker->symbolLayer( 0 ) ); + QVERIFY( markerLayer ); + QCOMPARE( markerLayer->path(), QStringLiteral( "base64:abcdef" ) ); + QCOMPARE( markerLayer->size(), 20.0 ); + QCOMPARE( markerLayer->fixedAspectRatio(), 0.8 ); + QCOMPARE( markerLayer->sizeUnit(), QgsUnitTypes::RenderPixels ); + QCOMPARE( markerLayer->angle(), -10.0 ); // opposite direction to esri spec! + QCOMPARE( markerLayer->offset(), QPointF( 7, 17 ) ); + QCOMPARE( markerLayer->offsetUnit(), QgsUnitTypes::RenderPoints ); + + // invalid json + symbol = QgsArcGisRestUtils::parseEsriPictureMarkerSymbolJson( QVariantMap() ); + QVERIFY( !symbol ); +} + void TestQgsArcGisRestUtils::testParseLineSymbol() { QVariantMap map = jsonStringToMap( "{"