Skip to content

Commit

Permalink
[FEATURE][AFS] Automatically convert ESRI picture marker symbols
Browse files Browse the repository at this point in the history
and use as default style for remote layers with picture marker symbology
  • Loading branch information
nyalldawson committed Dec 5, 2018
1 parent 51b2ce4 commit 543acff
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 2 deletions.
39 changes: 37 additions & 2 deletions src/providers/arcgisrest/qgsarcgisrestutils.cpp
Expand Up @@ -576,8 +576,8 @@ std::unique_ptr<QgsSymbol> 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" ) )
{
Expand Down Expand Up @@ -682,6 +682,41 @@ std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriMarkerSymbolJson(
return symbol;
}

std::unique_ptr<QgsMarkerSymbol> 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();
Expand Down
1 change: 1 addition & 0 deletions src/providers/arcgisrest/qgsarcgisrestutils.h
Expand Up @@ -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 );
Expand Down
33 changes: 33 additions & 0 deletions tests/src/providers/testqgsarcgisrestutils.cpp
Expand Up @@ -43,6 +43,7 @@ class TestQgsArcGisRestUtils : public QObject
void testParseEsriLineStyle();
void testParseEsriColorJson();
void testParseMarkerSymbol();
void testPictureMarkerSymbol();
void testParseLineSymbol();
void testParseFillSymbol();
void testParseRendererSimple();
Expand Down Expand Up @@ -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<QgsSymbol> 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( "{"
Expand Down

0 comments on commit 543acff

Please sign in to comment.