Skip to content

Commit

Permalink
[FEATURE][AFS] Automatically convert ESRI picture fill symbols
Browse files Browse the repository at this point in the history
  • Loading branch information
nirvn committed Dec 6, 2018
1 parent def29e8 commit 31b82de
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 2 deletions.
48 changes: 46 additions & 2 deletions src/providers/arcgisrest/qgsarcgisrestutils.cpp
Expand Up @@ -571,8 +571,7 @@ std::unique_ptr<QgsSymbol> QgsArcGisRestUtils::parseEsriSymbolJson( const QVaria
}
else if ( type == QLatin1String( "esriPFS" ) )
{
// picture fill - not supported
return nullptr;
return parseEsriPictureFillSymbolJson( symbolData );
}
else if ( type == QLatin1String( "esriPMS" ) )
{
Expand Down Expand Up @@ -628,6 +627,51 @@ std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriFillSymbolJson( cons
return symbol;
}

std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriPictureFillSymbolJson( const QVariantMap &symbolData )
{
bool ok = false;

double widthInPixels = symbolData.value( QStringLiteral( "width" ) ).toInt( &ok );
if ( !ok )
return nullptr;

const double xScale = symbolData.value( QStringLiteral( "xscale" ) ).toDouble( &ok );
if ( !qgsDoubleNear( xScale, 0.0 ) )
widthInPixels *= xScale;

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();

QString symbolPath( symbolData.value( QStringLiteral( "imageData" ) ).toString() );
symbolPath.prepend( QLatin1String( "base64:" ) );

QgsSymbolLayerList layers;
std::unique_ptr< QgsRasterFillSymbolLayer > fillLayer = qgis::make_unique< QgsRasterFillSymbolLayer >( symbolPath );
fillLayer->setWidth( widthInPixels );
fillLayer->setAngle( angleCW );
fillLayer->setWidthUnit( QgsUnitTypes::RenderPixels );
fillLayer->setOffset( QPointF( xOffset, yOffset ) );
fillLayer->setOffsetUnit( QgsUnitTypes::RenderPoints );
layers.append( fillLayer.release() );

const QVariantMap outlineData = symbolData.value( QStringLiteral( "outline" ) ).toMap();
QColor lineColor = parseEsriColorJson( outlineData.value( QStringLiteral( "color" ) ) );
Qt::PenStyle penStyle = parseEsriLineStyle( outlineData.value( QStringLiteral( "style" ) ).toString() );
double penWidthInPoints = outlineData.value( QStringLiteral( "width" ) ).toDouble( &ok );

std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = qgis::make_unique< QgsSimpleLineSymbolLayer >( lineColor, penWidthInPoints, penStyle );
lineLayer->setWidthUnit( QgsUnitTypes::RenderPoints );
layers.append( lineLayer.release() );

std::unique_ptr< QgsFillSymbol > symbol = qgis::make_unique< QgsFillSymbol >( layers );
return symbol;
}

QgsSimpleMarkerSymbolLayerBase::Shape parseEsriMarkerShape( const QString &style )
{
if ( style == QLatin1String( "esriSMSCircle" ) )
Expand Down
1 change: 1 addition & 0 deletions src/providers/arcgisrest/qgsarcgisrestutils.h
Expand Up @@ -54,6 +54,7 @@ class QgsArcGisRestUtils
static std::unique_ptr< QgsSymbol > parseEsriSymbolJson( const QVariantMap &symbolData );
static std::unique_ptr< QgsLineSymbol > parseEsriLineSymbolJson( const QVariantMap &symbolData );
static std::unique_ptr< QgsFillSymbol > parseEsriFillSymbolJson( const QVariantMap &symbolData );
static std::unique_ptr< QgsFillSymbol > parseEsriPictureFillSymbolJson( 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 );
Expand Down
41 changes: 41 additions & 0 deletions tests/src/providers/testqgsarcgisrestutils.cpp
Expand Up @@ -46,6 +46,7 @@ class TestQgsArcGisRestUtils : public QObject
void testPictureMarkerSymbol();
void testParseLineSymbol();
void testParseFillSymbol();
void testParsePictureFillSymbol();
void testParseRendererSimple();
void testParseRendererCategorized();

Expand Down Expand Up @@ -299,6 +300,46 @@ void TestQgsArcGisRestUtils::testParseFillSymbol()
QCOMPARE( fillLayer->strokeStyle(), Qt::DashDotLine );
}


void TestQgsArcGisRestUtils::testParsePictureFillSymbol()
{
QVariantMap map = jsonStringToMap( "{"
"\"type\": \"esriPFS\","
"\"url\": \"866880A0\","
"\"imageData\": \"abcdef\","
"\"contentType\": \"image/png\","
"\"width\": 20,"
"\"height\": 25,"
"\"angle\": 0,"
"\"outline\": {"
"\"type\": \"esriSLS\","
"\"style\": \"esriSLSDashDot\","
"\"color\": ["
"110,"
"120,"
"130,"
"215"
"],"
"\"width\": 5"
"}"
"}" );
std::unique_ptr<QgsSymbol> symbol = QgsArcGisRestUtils::parseEsriSymbolJson( map );
QgsFillSymbol *fill = dynamic_cast< QgsFillSymbol * >( symbol.get() );
QVERIFY( fill );
QCOMPARE( fill->symbolLayerCount(), 2 );
QgsRasterFillSymbolLayer *fillLayer = dynamic_cast< QgsRasterFillSymbolLayer * >( fill->symbolLayer( 0 ) );
QVERIFY( fillLayer );
QCOMPARE( fillLayer->imageFilePath(), QString( "base64:abcdef" ) );
QCOMPARE( fillLayer->width(), 20.0 );
QCOMPARE( fillLayer->widthUnit(), QgsUnitTypes::RenderPixels );
QgsSimpleLineSymbolLayer *lineLayer = dynamic_cast< QgsSimpleLineSymbolLayer * >( fill->symbolLayer( 1 ) );
QVERIFY( lineLayer );
QCOMPARE( lineLayer->color(), QColor( 110, 120, 130, 215 ) );
QCOMPARE( lineLayer->width(), 5.0 );
QCOMPARE( lineLayer->widthUnit(), QgsUnitTypes::RenderPoints );
QCOMPARE( lineLayer->penStyle(), Qt::DashDotLine );
}

void TestQgsArcGisRestUtils::testParseRendererSimple()
{
QVariantMap map = jsonStringToMap( "{"
Expand Down

0 comments on commit 31b82de

Please sign in to comment.