56#include <QRegularExpression>
59#include "moc_qgsarcgisrestutils.cpp"
63 if ( esriFieldType == QLatin1String(
"esriFieldTypeInteger" ) )
64 return QMetaType::Type::LongLong;
65 if ( esriFieldType == QLatin1String(
"esriFieldTypeSmallInteger" ) )
66 return QMetaType::Type::Int;
67 if ( esriFieldType == QLatin1String(
"esriFieldTypeDouble" ) )
68 return QMetaType::Type::Double;
69 if ( esriFieldType == QLatin1String(
"esriFieldTypeSingle" ) )
70 return QMetaType::Type::Double;
71 if ( esriFieldType == QLatin1String(
"esriFieldTypeString" ) )
72 return QMetaType::Type::QString;
73 if ( esriFieldType == QLatin1String(
"esriFieldTypeDate" ) )
74 return QMetaType::Type::QDateTime;
75 if ( esriFieldType == QLatin1String(
"esriFieldTypeGeometry" ) )
76 return QMetaType::Type::UnknownType;
77 if ( esriFieldType == QLatin1String(
"esriFieldTypeOID" ) )
78 return QMetaType::Type::LongLong;
79 if ( esriFieldType == QLatin1String(
"esriFieldTypeBlob" ) )
80 return QMetaType::Type::QByteArray;
81 if ( esriFieldType == QLatin1String(
"esriFieldTypeGlobalID" ) )
82 return QMetaType::Type::QString;
83 if ( esriFieldType == QLatin1String(
"esriFieldTypeRaster" ) )
84 return QMetaType::Type::QByteArray;
85 if ( esriFieldType == QLatin1String(
"esriFieldTypeGUID" ) )
86 return QMetaType::Type::QString;
87 if ( esriFieldType == QLatin1String(
"esriFieldTypeXML" ) )
88 return QMetaType::Type::QString;
89 return QMetaType::Type::UnknownType;
95 if ( esriGeometryType == QLatin1String(
"esriGeometryNull" ) )
97 else if ( esriGeometryType == QLatin1String(
"esriGeometryPoint" ) )
99 else if ( esriGeometryType == QLatin1String(
"esriGeometryMultipoint" ) )
101 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolyline" ) )
103 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolygon" ) )
105 else if ( esriGeometryType == QLatin1String(
"esriGeometryEnvelope" ) )
125std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertPoint(
const QVariantList &coordList,
Qgis::WkbType pointType )
127 int nCoords = coordList.size();
130 bool xok =
false, yok =
false;
131 const double x = coordList[0].toDouble( &xok );
132 const double y = coordList[1].toDouble( &yok );
136 const double z = hasZ && nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
139 const double m =
QgsWkbTypes::hasM( pointType ) && ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[ hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
140 return std::make_unique< QgsPoint >( pointType, x, y, z, m );
143std::unique_ptr< QgsCircularString > QgsArcGisRestUtils::convertCircularString(
const QVariantMap &curveData,
Qgis::WkbType pointType,
const QgsPoint &startPoint )
145 const QVariantList coordsList = curveData[QStringLiteral(
"c" )].toList();
146 if ( coordsList.isEmpty() )
148 const int coordsListSize = coordsList.size();
150 QVector<QgsPoint> points;
151 points.reserve( coordsListSize + 1 );
152 points.append( startPoint );
154 for (
int i = 0; i < coordsListSize - 1; )
158 std::unique_ptr< QgsPoint > endPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
162 std::unique_ptr< QgsPoint > interiorPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
163 if ( !interiorPoint )
166 points << *interiorPoint;
169 auto curve = std::make_unique< QgsCircularString> ();
170 curve->setPoints( points );
174std::unique_ptr< QgsCompoundCurve > QgsArcGisRestUtils::convertCompoundCurve(
const QVariantList &curvesList,
Qgis::WkbType pointType )
177 auto compoundCurve = std::make_unique< QgsCompoundCurve >();
179 QVector< double > lineX;
180 QVector< double > lineY;
181 QVector< double > lineZ;
182 QVector< double > lineM;
183 int maxCurveListSize = curvesList.size();
184 lineX.resize( maxCurveListSize );
185 lineY.resize( maxCurveListSize );
189 lineZ.resize( maxCurveListSize );
192 lineM.resize( maxCurveListSize );
194 double *outLineX = lineX.data();
195 double *outLineY = lineY.data();
196 double *outLineZ = lineZ.data();
197 double *outLineM = lineM.data();
198 int actualLineSize = 0;
203 int curveListIndex = 0;
204 for (
const QVariant &curveData : curvesList )
206 if ( curveData.userType() == QMetaType::Type::QVariantList )
208 const QVariantList coordList = curveData.toList();
209 const int nCoords = coordList.size();
213 const double x = coordList[0].toDouble( &xok );
214 const double y = coordList[1].toDouble( &yok );
223 *outLineZ++ = nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
229 *outLineM++ = ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[ hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
232 else if ( curveData.userType() == QMetaType::Type::QVariantMap )
235 QgsPoint lastLineStringPoint;
236 if ( actualLineSize > 0 )
238 lastLineStringPoint = QgsPoint( lineX.at( actualLineSize - 1 ),
239 lineY.at( actualLineSize - 1 ),
240 hasZ ? lineZ.at( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN(),
241 hasM ? lineM.at( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN() );
243 std::unique_ptr< QgsCircularString > circularString( convertCircularString( curveData.toMap(), pointType, lastLineStringPoint ) );
244 if ( !circularString )
249 if ( actualLineSize > 0 )
251 lineX.resize( actualLineSize );
252 lineY.resize( actualLineSize );
254 lineZ.resize( actualLineSize );
256 lineM.resize( actualLineSize );
258 compoundCurve->addCurve(
new QgsLineString( lineX, lineY, lineZ, lineM ) );
259 lineX.resize( maxCurveListSize - curveListIndex );
260 lineY.resize( maxCurveListSize - curveListIndex );
262 lineZ.resize( maxCurveListSize - curveListIndex );
264 lineM.resize( maxCurveListSize - curveListIndex );
265 outLineX = lineX.data();
266 outLineY = lineY.data();
267 outLineZ = lineZ.data();
268 outLineM = lineM.data();
272 if ( compoundCurve->curveAt( compoundCurve->nCurves() - 1 )->nCoordinates() < 2 )
273 compoundCurve->removeCurve( compoundCurve->nCurves() - 1 );
275 const QgsPoint endPointCircularString = circularString->endPoint();
276 compoundCurve->addCurve( circularString.release() );
280 *outLineX++ = endPointCircularString.
x();
281 *outLineY++ = endPointCircularString.
y();
283 *outLineZ++ = endPointCircularString.
z();
285 *outLineM++ = endPointCircularString.
m();
290 if ( actualLineSize == 1 && compoundCurve->nCurves() > 0 )
292 const QgsCurve *finalCurve = compoundCurve->curveAt( compoundCurve->nCurves() - 1 );
293 const QgsPoint finalCurveEndPoint = finalCurve->
endPoint();
296 && ( !hasZ ||
qgsDoubleNear( finalCurveEndPoint.
z(), lineZ.at( 0 ) ) )
297 && ( !hasM ||
qgsDoubleNear( finalCurveEndPoint.
m(), lineM.at( 0 ) ) ) )
303 if ( actualLineSize > 0 )
305 lineX.resize( actualLineSize );
306 lineY.resize( actualLineSize );
308 lineZ.resize( actualLineSize );
310 lineM.resize( actualLineSize );
311 compoundCurve->addCurve(
new QgsLineString( lineX, lineY, lineZ, lineM ) );
314 return compoundCurve;
317std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertGeometryPoint(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
320 bool xok =
false, yok =
false;
321 double x = geometryData[QStringLiteral(
"x" )].toDouble( &xok );
322 double y = geometryData[QStringLiteral(
"y" )].toDouble( &yok );
325 double z = geometryData[QStringLiteral(
"z" )].toDouble();
326 double m = geometryData[QStringLiteral(
"m" )].toDouble();
327 return std::make_unique< QgsPoint >( pointType, x, y, z, m );
330std::unique_ptr< QgsMultiPoint > QgsArcGisRestUtils::convertMultiPoint(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
333 const QVariantList coordsList = geometryData[QStringLiteral(
"points" )].toList();
335 auto multiPoint = std::make_unique< QgsMultiPoint >();
336 multiPoint->reserve( coordsList.size() );
337 for (
const QVariant &coordData : coordsList )
339 const QVariantList coordList = coordData.toList();
340 std::unique_ptr< QgsPoint > p = convertPoint( coordList, pointType );
345 multiPoint->addGeometry( p.release() );
350 std::unique_ptr< QgsPoint > p = convertGeometryPoint( geometryData, pointType );
352 multiPoint->addGeometry( p.release() );
354 if ( multiPoint->numGeometries() == 0 )
362std::unique_ptr< QgsMultiCurve > QgsArcGisRestUtils::convertGeometryPolyline(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
365 QVariantList pathsList;
366 if ( geometryData[QStringLiteral(
"paths" )].isValid() )
367 pathsList = geometryData[QStringLiteral(
"paths" )].toList();
368 else if ( geometryData[QStringLiteral(
"curvePaths" )].isValid() )
369 pathsList = geometryData[QStringLiteral(
"curvePaths" )].toList();
370 if ( pathsList.isEmpty() )
372 auto multiCurve = std::make_unique< QgsMultiCurve >();
373 multiCurve->reserve( pathsList.size() );
374 for (
const QVariant &pathData : std::as_const( pathsList ) )
376 std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( pathData.toList(), pointType );
381 multiCurve->addGeometry( curve.release() );
386std::unique_ptr< QgsMultiSurface > QgsArcGisRestUtils::convertGeometryPolygon(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
389 QVariantList ringsList;
390 if ( geometryData[QStringLiteral(
"rings" )].isValid() )
391 ringsList = geometryData[QStringLiteral(
"rings" )].toList();
392 else if ( geometryData[QStringLiteral(
"ringPaths" )].isValid() )
393 ringsList = geometryData[QStringLiteral(
"ringPaths" )].toList();
394 if ( ringsList.isEmpty() )
397 QList< QgsCompoundCurve * > curves;
398 for (
int i = 0, n = ringsList.size(); i < n; ++i )
400 std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( ringsList[i].toList(), pointType );
405 curves.append( curve.release() );
407 if ( curves.count() == 0 )
410 auto result = std::make_unique< QgsMultiSurface >();
411 if ( curves.count() == 1 )
414 auto newPolygon = std::make_unique< QgsCurvePolygon >();
415 newPolygon->setExteriorRing( curves.takeAt( 0 ) );
416 result->addGeometry( newPolygon.release() );
420 std::sort( curves.begin(), curves.end(), [](
const QgsCompoundCurve * a,
const QgsCompoundCurve * b )->bool{ double a_area = 0.0; double b_area = 0.0; a->sumUpArea( a_area ); b->sumUpArea( b_area ); return std::abs( a_area ) > std::abs( b_area ); } );
421 result->reserve( curves.size() );
422 while ( !curves.isEmpty() )
424 QgsCompoundCurve *exterior = curves.takeFirst();
425 QgsCurvePolygon *newPolygon =
new QgsCurvePolygon();
428 engine->prepareGeometry();
430 QMutableListIterator< QgsCompoundCurve * > it( curves );
431 while ( it.hasNext() )
433 QgsCompoundCurve *curve = it.next();
434 QgsRectangle boundingBox = newPolygon->
boundingBox();
438 if ( engine->contains( &point ) )
443 engine->prepareGeometry();
447 result->addGeometry( newPolygon );
449 if ( result->numGeometries() == 0 )
455std::unique_ptr< QgsPolygon > QgsArcGisRestUtils::convertEnvelope(
const QVariantMap &geometryData )
458 bool xminOk =
false, yminOk =
false, xmaxOk =
false, ymaxOk =
false;
459 double xmin = geometryData[QStringLiteral(
"xmin" )].toDouble( &xminOk );
460 double ymin = geometryData[QStringLiteral(
"ymin" )].toDouble( &yminOk );
461 double xmax = geometryData[QStringLiteral(
"xmax" )].toDouble( &xmaxOk );
462 double ymax = geometryData[QStringLiteral(
"ymax" )].toDouble( &ymaxOk );
463 if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk )
465 auto ext = std::make_unique< QgsLineString> ();
466 ext->addVertex( QgsPoint( xmin, ymin ) );
467 ext->addVertex( QgsPoint( xmax, ymin ) );
468 ext->addVertex( QgsPoint( xmax, ymax ) );
469 ext->addVertex( QgsPoint( xmin, ymax ) );
470 ext->addVertex( QgsPoint( xmin, ymin ) );
471 auto poly = std::make_unique< QgsPolygon >();
472 poly->setExteriorRing( ext.release() );
485 if ( esriGeometryType == QLatin1String(
"esriGeometryNull" ) )
487 else if ( esriGeometryType == QLatin1String(
"esriGeometryPoint" ) )
488 return convertGeometryPoint( geometryData, pointType ).release();
489 else if ( esriGeometryType == QLatin1String(
"esriGeometryMultipoint" ) )
490 return convertMultiPoint( geometryData, pointType ).release();
491 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolyline" ) )
492 return convertGeometryPolyline( geometryData, pointType ).release();
493 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolygon" ) )
494 return convertGeometryPolygon( geometryData, pointType ).release();
495 else if ( esriGeometryType == QLatin1String(
"esriGeometryEnvelope" ) )
496 return convertEnvelope( geometryData ).release();
519 QString spatialReference = spatialReferenceMap[QStringLiteral(
"latestWkid" )].toString();
520 if ( spatialReference.isEmpty() )
521 spatialReference = spatialReferenceMap[QStringLiteral(
"wkid" )].toString();
524 if ( !spatialReference.isEmpty() )
526 crs.
createFromString( QStringLiteral(
"EPSG:%1" ).arg( spatialReference ) );
530 crs.
createFromString( QStringLiteral(
"ESRI:%1" ).arg( spatialReference ) );
533 else if ( !spatialReferenceMap[QStringLiteral(
"wkt" )].toString().isEmpty() )
536 crs.
createFromWkt( spatialReferenceMap[QStringLiteral(
"wkt" )].toString() );
551 const QString type = symbolData.value( QStringLiteral(
"type" ) ).toString();
552 if ( type == QLatin1String(
"esriSMS" ) )
555 return parseEsriMarkerSymbolJson( symbolData ).release();
557 else if ( type == QLatin1String(
"esriSLS" ) )
560 return parseEsriLineSymbolJson( symbolData ).release();
562 else if ( type == QLatin1String(
"esriSFS" ) )
565 return parseEsriFillSymbolJson( symbolData ).release();
567 else if ( type == QLatin1String(
"esriPFS" ) )
569 return parseEsriPictureFillSymbolJson( symbolData ).release();
571 else if ( type == QLatin1String(
"esriPMS" ) )
574 return parseEsriPictureMarkerSymbolJson( symbolData ).release();
576 else if ( type == QLatin1String(
"esriTS" ) )
578 return parseEsriTextMarkerSymbolJson( symbolData ).release();
583std::unique_ptr<QgsLineSymbol> QgsArcGisRestUtils::parseEsriLineSymbolJson(
const QVariantMap &symbolData )
585 QColor lineColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
586 if ( !lineColor.isValid() )
590 double widthInPoints = symbolData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
595 Qt::PenStyle penStyle =
convertLineStyle( symbolData.value( QStringLiteral(
"style" ) ).toString() );
596 auto lineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( lineColor, widthInPoints, penStyle );
598 layers.append( lineLayer.release() );
600 auto symbol = std::make_unique< QgsLineSymbol >( layers );
604std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriFillSymbolJson(
const QVariantMap &symbolData )
606 QColor fillColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
607 Qt::BrushStyle brushStyle =
convertFillStyle( symbolData.value( QStringLiteral(
"style" ) ).toString() );
609 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
610 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
611 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
613 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
616 auto fillLayer = std::make_unique< QgsSimpleFillSymbolLayer >( fillColor, brushStyle, lineColor, penStyle, penWidthInPoints );
618 layers.append( fillLayer.release() );
620 auto symbol = std::make_unique< QgsFillSymbol >( layers );
624std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriPictureFillSymbolJson(
const QVariantMap &symbolData )
628 double widthInPixels = symbolData.value( QStringLiteral(
"width" ) ).toInt( &ok );
632 const double xScale = symbolData.value( QStringLiteral(
"xscale" ) ).toDouble( &ok );
634 widthInPixels *= xScale;
636 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
641 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
642 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
644 QString symbolPath( symbolData.value( QStringLiteral(
"imageData" ) ).toString() );
645 symbolPath.prepend( QLatin1String(
"base64:" ) );
648 auto fillLayer = std::make_unique< QgsRasterFillSymbolLayer >( symbolPath );
649 fillLayer->setWidth( widthInPixels );
650 fillLayer->setAngle( angleCW );
652 fillLayer->setOffset( QPointF( xOffset, yOffset ) );
654 layers.append( fillLayer.release() );
656 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
657 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
658 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
659 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
661 auto lineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( lineColor, penWidthInPoints, penStyle );
663 layers.append( lineLayer.release() );
665 auto symbol = std::make_unique< QgsFillSymbol >( layers );
669Qgis::MarkerShape QgsArcGisRestUtils::parseEsriMarkerShape(
const QString &style )
671 if ( style == QLatin1String(
"esriSMSCircle" ) )
673 else if ( style == QLatin1String(
"esriSMSCross" ) )
675 else if ( style == QLatin1String(
"esriSMSDiamond" ) )
677 else if ( style == QLatin1String(
"esriSMSSquare" ) )
679 else if ( style == QLatin1String(
"esriSMSX" ) )
681 else if ( style == QLatin1String(
"esriSMSTriangle" ) )
687std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriMarkerSymbolJson(
const QVariantMap &symbolData )
689 QColor fillColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
691 const double sizeInPoints = symbolData.value( QStringLiteral(
"size" ) ).toDouble( &ok );
694 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
699 Qgis::MarkerShape shape = parseEsriMarkerShape( symbolData.value( QStringLiteral(
"style" ) ).toString() );
701 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
702 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
704 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
705 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
706 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
707 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
710 auto markerLayer = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, sizeInPoints, angleCW,
Qgis::ScaleMethod::ScaleArea, fillColor, lineColor );
713 markerLayer->setStrokeStyle( penStyle );
714 markerLayer->setStrokeWidth( penWidthInPoints );
715 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
717 layers.append( markerLayer.release() );
719 auto symbol = std::make_unique< QgsMarkerSymbol >( layers );
723std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriPictureMarkerSymbolJson(
const QVariantMap &symbolData )
726 const double widthInPixels = symbolData.value( QStringLiteral(
"width" ) ).toInt( &ok );
729 const double heightInPixels = symbolData.value( QStringLiteral(
"height" ) ).toInt( &ok );
733 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
738 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
739 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
743 QString symbolPath( symbolData.value( QStringLiteral(
"imageData" ) ).toString() );
744 symbolPath.prepend( QLatin1String(
"base64:" ) );
751 if ( !
qgsDoubleNear(
static_cast< double >( heightInPixels ) / widthInPixels, markerLayer->defaultAspectRatio() ) )
752 markerLayer->setFixedAspectRatio(
static_cast< double >( heightInPixels ) / widthInPixels );
754 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
756 layers.append( markerLayer.release() );
758 auto symbol = std::make_unique< QgsMarkerSymbol >( layers );
762std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriTextMarkerSymbolJson(
const QVariantMap &symbolData )
766 const QString fontFamily = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"family" ) ).toString();
768 const QString chr = symbolData.value( QStringLiteral(
"text" ) ).toString();
770 const double pointSize = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"size" ) ).toDouble();
772 const QColor color =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
774 const double esriAngle = symbolData.value( QStringLiteral(
"angle" ) ).toDouble();
776 const double angle = 90.0 - esriAngle;
778 auto markerLayer = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, chr, pointSize, color, angle );
780 QColor strokeColor =
convertColor( symbolData.value( QStringLiteral(
"borderLineColor" ) ) );
781 markerLayer->setStrokeColor( strokeColor );
783 double borderLineSize = symbolData.value( QStringLiteral(
"borderLineSize" ) ).toDouble();
784 markerLayer->setStrokeWidth( borderLineSize );
786 const QString fontStyle = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"style" ) ).toString();
787 markerLayer->setFontStyle( fontStyle );
789 double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
790 double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
792 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
801 QString horizontalAnchorPoint = symbolData.value( QStringLiteral(
"horizontalAlignment" ) ).toString();
802 QString verticalAnchorPoint = symbolData.value( QStringLiteral(
"verticalAlignment" ) ).toString();
804 if ( horizontalAnchorPoint == QString(
"center" ) )
808 else if ( horizontalAnchorPoint == QString(
"left" ) )
812 else if ( horizontalAnchorPoint == QString(
"right" ) )
817 if ( verticalAnchorPoint == QString(
"center" ) )
821 else if ( verticalAnchorPoint == QString(
"top" ) )
825 else if ( verticalAnchorPoint == QString(
"bottom" ) )
830 markerLayer->setHorizontalAnchorPoint( hAlign );
831 markerLayer->setVerticalAnchorPoint( vAlign );
833 layers.append( markerLayer.release() );
835 auto symbol = std::make_unique< QgsMarkerSymbol >( layers );
841 if ( labelingData.empty() )
848 for (
const QVariant &lbl : labelingData )
850 const QVariantMap labeling = lbl.toMap();
855 const QString placement = labeling.value( QStringLiteral(
"labelPlacement" ) ).toString();
856 if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveCenter" ) )
861 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowCenter" ) )
866 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterCenter" ) )
871 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveLeft" ) )
876 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowLeft" ) )
881 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterLeft" ) )
886 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveRight" ) )
891 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowRight" ) )
896 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterRight" ) )
901 else if ( placement == QLatin1String(
"esriServerLinePlacementAboveAfter" ) ||
902 placement == QLatin1String(
"esriServerLinePlacementAboveStart" ) ||
903 placement == QLatin1String(
"esriServerLinePlacementAboveAlong" ) )
908 else if ( placement == QLatin1String(
"esriServerLinePlacementBelowAfter" ) ||
909 placement == QLatin1String(
"esriServerLinePlacementBelowStart" ) ||
910 placement == QLatin1String(
"esriServerLinePlacementBelowAlong" ) )
915 else if ( placement == QLatin1String(
"esriServerLinePlacementCenterAfter" ) ||
916 placement == QLatin1String(
"esriServerLinePlacementCenterStart" ) ||
917 placement == QLatin1String(
"esriServerLinePlacementCenterAlong" ) )
922 else if ( placement == QLatin1String(
"esriServerPolygonPlacementAlwaysHorizontal" ) )
927 const double minScale = labeling.value( QStringLiteral(
"minScale" ) ).toDouble();
928 const double maxScale = labeling.value( QStringLiteral(
"maxScale" ) ).toDouble();
930 QVariantMap symbol = labeling.value( QStringLiteral(
"symbol" ) ).toMap();
932 const double haloSize = symbol.value( QStringLiteral(
"haloSize" ) ).toDouble();
943 const QString fontFamily = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"family" ) ).toString();
944 const QString fontStyle = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"style" ) ).toString();
945 const QString fontWeight = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"weight" ) ).toString();
946 const int fontSize = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"size" ) ).toInt();
947 QFont font( fontFamily, fontSize );
948 font.setStyleName( fontStyle );
949 font.setWeight( fontWeight == QLatin1String(
"bold" ) ? QFont::Bold : QFont::Normal );
957 QString where = labeling.value( QStringLiteral(
"where" ) ).toString();
976 const QString type = rendererData.value( QStringLiteral(
"type" ) ).toString();
977 if ( type == QLatin1String(
"simple" ) )
979 const QVariantMap symbolProps = rendererData.value( QStringLiteral(
"symbol" ) ).toMap();
980 std::unique_ptr< QgsSymbol > symbol(
convertSymbol( symbolProps ) );
986 else if ( type == QLatin1String(
"uniqueValue" ) )
988 const QString field1 = rendererData.value( QStringLiteral(
"field1" ) ).toString();
989 const QString field2 = rendererData.value( QStringLiteral(
"field2" ) ).toString();
990 const QString field3 = rendererData.value( QStringLiteral(
"field3" ) ).toString();
992 if ( !field2.isEmpty() || !field3.isEmpty() )
994 const QString delimiter = rendererData.value( QStringLiteral(
"fieldDelimiter" ) ).toString();
995 if ( !field3.isEmpty() )
997 attribute = QStringLiteral(
"concat(\"%1\",'%2',\"%3\",'%4',\"%5\")" ).arg( field1, delimiter, field2, delimiter, field3 );
1001 attribute = QStringLiteral(
"concat(\"%1\",'%2',\"%3\")" ).arg( field1, delimiter, field2 );
1009 const QVariantList categories = rendererData.value( QStringLiteral(
"uniqueValueInfos" ) ).toList();
1011 for (
const QVariant &category : categories )
1013 const QVariantMap categoryData = category.toMap();
1014 const QString value = categoryData.value( QStringLiteral(
"value" ) ).toString();
1015 const QString label = categoryData.value( QStringLiteral(
"label" ) ).toString();
1023 std::unique_ptr< QgsSymbol > defaultSymbol(
convertSymbol( rendererData.value( QStringLiteral(
"defaultSymbol" ) ).toMap() ) );
1024 if ( defaultSymbol )
1026 categoryList.append(
QgsRendererCategory( QVariant(), defaultSymbol.release(), rendererData.value( QStringLiteral(
"defaultLabel" ) ).toString() ) );
1029 if ( categoryList.empty() )
1034 else if ( type == QLatin1String(
"classBreaks" ) )
1036 const QString attrName = rendererData.value( QStringLiteral(
"field" ) ).toString();
1038 const QVariantList classBreakInfos = rendererData.value( QStringLiteral(
"classBreakInfos" ) ).toList();
1039 const QVariantMap authoringInfo = rendererData.value( QStringLiteral(
"authoringInfo" ) ).toMap();
1040 QVariantMap symbolData;
1042 QString esriMode = authoringInfo.value( QStringLiteral(
"classificationMethod" ) ).toString();
1043 if ( esriMode.isEmpty() )
1045 esriMode = rendererData.value( QStringLiteral(
"classificationMethod" ) ).toString();
1048 if ( !classBreakInfos.isEmpty() )
1050 symbolData = classBreakInfos.at( 0 ).toMap().value( QStringLiteral(
"symbol" ) ).toMap();
1056 const double transparency = rendererData.value( QStringLiteral(
"transparency" ) ).toDouble();
1057 const double opacity = ( 100.0 - transparency ) / 100.0;
1058 symbol->setOpacity( opacity );
1060 const QVariantList visualVariablesData = rendererData.value( QStringLiteral(
"visualVariables" ) ).toList();
1062 for (
const QVariant &visualVariable : visualVariablesData )
1064 const QVariantMap visualVariableData = visualVariable.toMap();
1065 const QString variableType = visualVariableData.value( QStringLiteral(
"type" ) ).toString();
1066 if ( variableType == QLatin1String(
"sizeInfo" ) )
1070 else if ( variableType == QLatin1String(
"colorInfo" ) )
1072 const QVariantList stops = visualVariableData.value( QStringLiteral(
"stops" ) ).toList();
1073 if ( stops.size() < 2 )
1078 const double minValue = stops.front().toMap().value( QStringLiteral(
"value" ) ).toDouble( &ok );
1081 const QColor minColor =
convertColor( stops.front().toMap().value( QStringLiteral(
"color" ) ) );
1083 const double maxValue = stops.back().toMap().value( QStringLiteral(
"value" ) ).toDouble( &ok );
1086 const QColor maxColor =
convertColor( stops.back().toMap().value( QStringLiteral(
"color" ) ) );
1089 for (
int i = 1; i < stops.size() - 1; ++i )
1091 const QVariantMap stopData = stops.at( i ).toMap();
1092 const double breakpoint = stopData.value( QStringLiteral(
"value" ) ).toDouble();
1093 const double scaledBreakpoint = ( breakpoint - minValue ) / ( maxValue - minValue );
1094 const QColor fillColor =
convertColor( stopData.value( QStringLiteral(
"color" ) ) );
1096 gradientStops.append(
QgsGradientStop( scaledBreakpoint, fillColor ) );
1099 auto colorRamp = std::make_unique< QgsGradientColorRamp >(
1100 minColor, maxColor,
false, gradientStops
1107 for (
int layer = 0; layer < symbol->symbolLayerCount(); ++layer )
1112 auto singleSymbolRenderer = std::make_unique< QgsSingleSymbolRenderer >( symbol.release() );
1114 return singleSymbolRenderer.release();
1118 QgsDebugError( QStringLiteral(
"ESRI visualVariable type %1 is not currently supported" ).arg( variableType ) );
1122 double lastValue = rendererData.value( QStringLiteral(
"minValue" ) ).toDouble();
1124 auto graduatedRenderer = std::make_unique< QgsGraduatedSymbolRenderer >( attrName );
1126 graduatedRenderer->setSourceSymbol( symbol.release() );
1128 if ( esriMode == QLatin1String(
"esriClassifyDefinedInterval" ) )
1131 graduatedRenderer->setClassificationMethod( method );
1133 else if ( esriMode == QLatin1String(
"esriClassifyEqualInterval" ) )
1136 graduatedRenderer->setClassificationMethod( method );
1138 else if ( esriMode == QLatin1String(
"esriClassifyGeometricalInterval" ) )
1141 graduatedRenderer->setClassificationMethod( method );
1143 else if ( esriMode == QLatin1String(
"esriClassifyManual" ) )
1146 graduatedRenderer->setClassificationMethod( method );
1148 else if ( esriMode == QLatin1String(
"esriClassifyNaturalBreaks" ) )
1151 graduatedRenderer->setClassificationMethod( method );
1153 else if ( esriMode == QLatin1String(
"esriClassifyQuantile" ) )
1156 graduatedRenderer->setClassificationMethod( method );
1158 else if ( esriMode == QLatin1String(
"esriClassifyStandardDeviation" ) )
1161 graduatedRenderer->setClassificationMethod( method );
1163 else if ( !esriMode.isEmpty() )
1165 QgsDebugError( QStringLiteral(
"ESRI classification mode %1 is not currently supported" ).arg( esriMode ) );
1168 for (
const QVariant &classBreakInfo : classBreakInfos )
1170 const QVariantMap symbolData = classBreakInfo.toMap().value( QStringLiteral(
"symbol" ) ).toMap();
1172 double classMaxValue = classBreakInfo.toMap().value( QStringLiteral(
"classMaxValue" ) ).toDouble();
1173 const QString label = classBreakInfo.toMap().value( QStringLiteral(
"label" ) ).toString();
1182 lastValue = classMaxValue;
1183 graduatedRenderer->addClass( range );
1186 return graduatedRenderer.release();
1188 else if ( type == QLatin1String(
"heatmap" ) )
1193 else if ( type == QLatin1String(
"vectorField" ) )
1203 QString expression = string;
1206 const thread_local QRegularExpression rx1 = QRegularExpression( QStringLiteral(
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)CONCAT(\\s|$)" ) );
1207 expression = expression.replace( rx1, QStringLiteral(
"\\4||\\5" ) );
1209 const thread_local QRegularExpression rx2 = QRegularExpression( QStringLiteral(
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)NEWLINE(\\s|$)" ) );
1210 expression = expression.replace( rx2, QStringLiteral(
"\\4'\\n'\\5" ) );
1213 const thread_local QRegularExpression rx3 = QRegularExpression( QStringLiteral(
"\"(.*?(?<!\\\\))\"" ) );
1214 expression = expression.replace( rx3, QStringLiteral(
"'\\1'" ) );
1215 const thread_local QRegularExpression rx4 = QRegularExpression( QStringLiteral(
"\\\\\"" ) );
1216 expression = expression.replace( rx4, QStringLiteral(
"\"" ) );
1219 const thread_local QRegularExpression rx5 = QRegularExpression( QStringLiteral(
"\\[([^]]*)\\]" ) );
1220 expression = expression.replace( rx5, QStringLiteral(
"\"\\1\"" ) );
1227 const QVariantList colorParts = colorData.toList();
1228 if ( colorParts.count() < 4 )
1231 int red = colorParts.at( 0 ).toInt();
1232 int green = colorParts.at( 1 ).toInt();
1233 int blue = colorParts.at( 2 ).toInt();
1234 int alpha = colorParts.at( 3 ).toInt();
1235 return QColor( red, green, blue, alpha );
1240 if ( style == QLatin1String(
"esriSLSSolid" ) )
1241 return Qt::SolidLine;
1242 else if ( style == QLatin1String(
"esriSLSDash" ) )
1243 return Qt::DashLine;
1244 else if ( style == QLatin1String(
"esriSLSDashDot" ) )
1245 return Qt::DashDotLine;
1246 else if ( style == QLatin1String(
"esriSLSDashDotDot" ) )
1247 return Qt::DashDotDotLine;
1248 else if ( style == QLatin1String(
"esriSLSDot" ) )
1250 else if ( style == QLatin1String(
"esriSLSNull" ) )
1253 return Qt::SolidLine;
1258 if ( style == QLatin1String(
"esriSFSBackwardDiagonal" ) )
1259 return Qt::BDiagPattern;
1260 else if ( style == QLatin1String(
"esriSFSCross" ) )
1261 return Qt::CrossPattern;
1262 else if ( style == QLatin1String(
"esriSFSDiagonalCross" ) )
1263 return Qt::DiagCrossPattern;
1264 else if ( style == QLatin1String(
"esriSFSForwardDiagonal" ) )
1265 return Qt::FDiagPattern;
1266 else if ( style == QLatin1String(
"esriSFSHorizontal" ) )
1267 return Qt::HorPattern;
1268 else if ( style == QLatin1String(
"esriSFSNull" ) )
1270 else if ( style == QLatin1String(
"esriSFSSolid" ) )
1271 return Qt::SolidPattern;
1272 else if ( style == QLatin1String(
"esriSFSVertical" ) )
1273 return Qt::VerPattern;
1275 return Qt::SolidPattern;
1283 QDateTime dt = QDateTime::fromMSecsSinceEpoch( value.toLongLong( &ok ) );
1286 QgsDebugError( QStringLiteral(
"Invalid value %1 for datetime" ).arg( value.toString() ) );
1298 const QVariantMap coords = value.toMap();
1303 const double xmin = coords.value( QStringLiteral(
"xmin" ) ).toDouble( &ok );
1306 const double ymin = coords.value( QStringLiteral(
"ymin" ) ).toDouble( &ok );
1309 const double xmax = coords.value( QStringLiteral(
"xmax" ) ).toDouble( &ok );
1312 const double ymax = coords.value( QStringLiteral(
"ymax" ) ).toDouble( &ok );
1324 return QVariantMap();
1331 return QVariantMap();
1375 return QVariantMap();
1378 return QVariantMap();
1381 return QVariantMap();
1388 res.insert( QStringLiteral(
"spatialReference" ),
crsToJson( crs ) );
1394QVariantMap QgsArcGisRestUtils::pointToJson(
const QgsPoint *point )
1398 data[QStringLiteral(
"x" )] = QStringLiteral(
"NaN" );
1401 data[QStringLiteral(
"x" )] = point->
x();
1402 data[QStringLiteral(
"y" )] = point->
y();
1404 if ( point->
is3D() )
1405 data[QStringLiteral(
"z" )] = !std::isnan( point->
z() ) ? QVariant( point->
z() ) : QVariant( QStringLiteral(
"NaN" ) );
1408 data[QStringLiteral(
"m" )] = !std::isnan( point->
m() ) ? QVariant( point->
m() ) : QVariant( QStringLiteral(
"NaN" ) );
1413QVariantMap QgsArcGisRestUtils::multiPointToJson(
const QgsMultiPoint *multiPoint )
1416 const bool hasZ = multiPoint->
is3D();
1417 const bool hasM = multiPoint->
isMeasure();
1418 data[QStringLiteral(
"hasM" )] = hasM;
1419 data[QStringLiteral(
"hasZ" )] = hasZ;
1421 QVariantList pointsList;
1423 pointsList.reserve( size );
1425 QVariantList pointList;
1426 for (
int i = 0; i < size; ++i )
1428 const QgsPoint *point = multiPoint->
pointN( i );
1431 pointList.append( point->
x() );
1432 pointList.append( point->
y() );
1434 pointList.append( point->
z() );
1435 if ( hasM && !std::isnan( point->
m() ) )
1436 pointList.append( point->
m() );
1438 pointsList.push_back( pointList );
1441 data[QStringLiteral(
"points" )] = pointsList;
1445QVariantList QgsArcGisRestUtils::lineStringToJsonPath(
const QgsLineString *line )
1447 const bool hasZ = line->
is3D();
1450 QVariantList pointsList;
1452 pointsList.reserve( size );
1454 QVariantList pointList;
1455 const double *xData = line->
xData();
1456 const double *yData = line->
yData();
1457 const double *zData = hasZ ? line->
zData() :
nullptr;
1458 const double *mData = hasM ? line->
mData() :
nullptr;
1460 for (
int i = 0; i < size; ++i )
1463 pointList.append( *xData++ );
1464 pointList.append( *yData++ );
1467 pointList.append( *zData++ );
1469 if ( hasM && !std::isnan( *mData ) )
1470 pointList.append( *mData );
1474 pointsList.push_back( pointList );
1479QVariantList QgsArcGisRestUtils::curveToJsonCurve(
const QgsCurve *curve,
bool includeStart )
1481 const bool hasZ = curve->
is3D();
1484 auto pointToList = [hasZ, hasM](
const QgsPoint & point ) -> QVariantList
1486 QVariantList pointList;
1488 pointList.append( point.
x() );
1489 pointList.append( point.
y() );
1492 pointList.append( point.
z() );
1494 if ( hasM && !std::isnan( point.
m() ) )
1495 pointList.append( point.
m() );
1506 if ( !part.isEmpty() && !includeStart )
1515 if ( includeStart && !circularString->
isEmpty() )
1517 res.push_back( pointToList( circularString->
startPoint() ) );
1520 const int size = circularString->
numPoints();
1521 for (
int i = 1; i + 1 < size; i += 2 )
1524 QVariantMap curvePart;
1525 QVariantList curveList;
1526 curveList.push_back( pointToList( circularString->
pointN( i + 1 ) ) );
1528 curveList.push_back( pointToList( circularString->
pointN( i ) ) );
1530 curvePart.insert( QStringLiteral(
"c" ), curveList );
1531 res.push_back( curvePart );
1540 const int size = compoundCurve->
nCurves();
1541 for (
int i = 0; i < size; ++i )
1543 const QgsCurve *subCurve = compoundCurve->
curveAt( i );
1544 res.append( curveToJsonCurve( subCurve, i == 0 ) );
1555QVariantMap QgsArcGisRestUtils::lineStringToJson(
const QgsLineString *line )
1558 const bool hasZ = line->
is3D();
1560 data[QStringLiteral(
"hasM" )] = hasM;
1561 data[QStringLiteral(
"hasZ" )] = hasZ;
1563 const QVariantList pointsList = lineStringToJsonPath( line );
1565 QVariantList pointsData = QVariantList();
1566 pointsData.push_back( pointsList );
1567 data[QStringLiteral(
"paths" )] = pointsData;
1572QVariantMap QgsArcGisRestUtils::curveToJson(
const QgsCurve *curve )
1575 const bool hasZ = curve->
is3D();
1577 data[QStringLiteral(
"hasM" )] = hasM;
1578 data[QStringLiteral(
"hasZ" )] = hasZ;
1580 const QVariantList curveList = curveToJsonCurve( curve,
true );
1582 QVariantList curveData = QVariantList();
1583 curveData.push_back( curveList );
1584 data[QStringLiteral(
"curvePaths" )] = curveData;
1589QVariantMap QgsArcGisRestUtils::multiLineStringToJson(
const QgsMultiLineString *multiLine )
1592 const bool hasZ = multiLine->
is3D();
1593 const bool hasM = multiLine->
isMeasure();
1594 data[QStringLiteral(
"hasM" )] = hasM;
1595 data[QStringLiteral(
"hasZ" )] = hasZ;
1599 paths.reserve( size );
1600 for (
int i = 0; i < size; ++i )
1602 const QgsLineString *line = multiLine->
lineStringN( i );
1603 paths.push_back( lineStringToJsonPath( line ) );
1606 data[QStringLiteral(
"paths" )] = paths;
1610QVariantMap QgsArcGisRestUtils::multiCurveToJson(
const QgsMultiCurve *multiCurve )
1613 const bool hasZ = multiCurve->
is3D();
1614 const bool hasM = multiCurve->
isMeasure();
1615 data[QStringLiteral(
"hasM" )] = hasM;
1616 data[QStringLiteral(
"hasZ" )] = hasZ;
1620 paths.reserve( size );
1621 for (
int i = 0; i < size; ++i )
1623 const QgsCurve *curve = multiCurve->
curveN( i );
1624 paths.push_back( curveToJsonCurve( curve,
true ) );
1627 data[QStringLiteral(
"curvePaths" )] = paths;
1631QVariantList QgsArcGisRestUtils::polygonToJsonRings(
const QgsPolygon *polygon )
1635 rings.reserve( numInteriorRings + 1 );
1643 rings.push_back( lineStringToJsonPath( exterior ) );
1648 std::unique_ptr< QgsLineString > reversed( exterior->
reversed() );
1649 rings.push_back( lineStringToJsonPath( reversed.get() ) );
1657 for (
int i = 0; i < numInteriorRings; ++i )
1664 rings.push_back( lineStringToJsonPath( ring ) );
1669 std::unique_ptr< QgsLineString > reversed( ring->
reversed() );
1670 rings.push_back( lineStringToJsonPath( reversed.get() ) );
1680QVariantList QgsArcGisRestUtils::curvePolygonToJsonRings(
const QgsCurvePolygon *polygon )
1684 rings.reserve( numInteriorRings + 1 );
1692 rings.push_back( curveToJsonCurve( exterior,
true ) );
1697 std::unique_ptr< QgsCurve > reversed( exterior->
reversed() );
1698 rings.push_back( curveToJsonCurve( reversed.get(),
true ) );
1706 for (
int i = 0; i < numInteriorRings; ++i )
1713 rings.push_back( curveToJsonCurve( ring,
true ) );
1718 std::unique_ptr< QgsCurve > reversed( ring->
reversed() );
1719 rings.push_back( curveToJsonCurve( reversed.get(),
true ) );
1729QVariantMap QgsArcGisRestUtils::polygonToJson(
const QgsPolygon *polygon )
1732 const bool hasZ = polygon->
is3D();
1734 data[QStringLiteral(
"hasM" )] = hasM;
1735 data[QStringLiteral(
"hasZ" )] = hasZ;
1736 data[QStringLiteral(
"rings" )] = polygonToJsonRings( polygon );
1740QVariantMap QgsArcGisRestUtils::curvePolygonToJson(
const QgsCurvePolygon *polygon )
1743 const bool hasZ = polygon->
is3D();
1745 data[QStringLiteral(
"hasM" )] = hasM;
1746 data[QStringLiteral(
"hasZ" )] = hasZ;
1747 data[QStringLiteral(
"curveRings" )] = curvePolygonToJsonRings( polygon );
1751QVariantMap QgsArcGisRestUtils::multiPolygonToJson(
const QgsMultiPolygon *multiPolygon )
1754 const bool hasZ = multiPolygon->
is3D();
1755 const bool hasM = multiPolygon->
isMeasure();
1756 data[QStringLiteral(
"hasM" )] = hasM;
1757 data[QStringLiteral(
"hasZ" )] = hasZ;
1761 for (
int i = 0; i < size; ++i )
1763 const QgsPolygon *polygon = multiPolygon->
polygonN( i );
1764 rings.append( polygonToJsonRings( polygon ) );
1767 data[QStringLiteral(
"rings" )] = rings;
1771QVariantMap QgsArcGisRestUtils::multiSurfaceToJson(
const QgsMultiSurface *multiSurface )
1774 const bool hasZ = multiSurface->
is3D();
1775 const bool hasM = multiSurface->
isMeasure();
1776 data[QStringLiteral(
"hasM" )] = hasM;
1777 data[QStringLiteral(
"hasZ" )] = hasZ;
1781 for (
int i = 0; i < size; ++i )
1787 rings.append( curvePolygonToJsonRings( polygon ) );
1790 data[QStringLiteral(
"curveRings" )] = rings;
1800 const QString authid = crs.
authid();
1801 if ( !authid.isEmpty() )
1803 const thread_local QRegularExpression rxAuthid( QStringLiteral(
"(\\w+):(\\d+)" ) );
1804 const QRegularExpressionMatch match = rxAuthid.match( authid );
1805 if ( match.hasMatch()
1807 ( match.captured( 1 ).compare( QLatin1String(
"EPSG" ), Qt::CaseInsensitive ) == 0 )
1808 || ( match.captured( 1 ).compare( QLatin1String(
"ESRI" ), Qt::CaseInsensitive ) == 0 )
1812 const QString wkid = match.captured( 2 );
1813 res.insert( QStringLiteral(
"wkid" ), wkid );
1832 QVariantMap attributes;
1834 for (
const QgsField &field : fields )
1836 QVariant value = feature.
attribute( field.name() );
1837 if ( value.userType() == qMetaTypeId< QgsUnsetAttributeValue >() )
1848 if ( !attributes.isEmpty() )
1850 res.insert( QStringLiteral(
"attributes" ), attributes );
1860 switch ( expectedType )
1862 case QMetaType::Type::QString:
1864 const QString escaped = variant.toString().replace(
'\\', QLatin1String(
"\\\\" ) ).replace(
'"', QLatin1String(
"\\\"" ) );
1865 return QString( QUrl::toPercentEncoding( escaped,
"'" ) );
1868 case QMetaType::Type::QDateTime:
1869 case QMetaType::Type::QDate:
1871 switch ( variant.userType() )
1873 case QMetaType::Type::QDateTime:
1874 return variant.toDateTime().toMSecsSinceEpoch();
1876 case QMetaType::Type::QDate:
1878 if ( context.
timeZone().isValid() )
1879 return QDateTime( variant.toDate(), QTime( 0, 0, 0 ), context.
timeZone() ).toMSecsSinceEpoch();
1881 return QDateTime( variant.toDate(), QTime( 0, 0, 0 ) ).toMSecsSinceEpoch();
1896 res.insert( QStringLiteral(
"name" ), field.
name() );
1899 switch ( field.
type() )
1901 case QMetaType::Type::LongLong:
1902 fieldType = QStringLiteral(
"esriFieldTypeInteger" );
1905 case QMetaType::Type::Int:
1906 fieldType = QStringLiteral(
"esriFieldTypeSmallInteger" );
1909 case QMetaType::Type::Double:
1910 fieldType = QStringLiteral(
"esriFieldTypeDouble" );
1913 case QMetaType::Type::QString:
1914 fieldType = QStringLiteral(
"esriFieldTypeString" );
1917 case QMetaType::Type::QDateTime:
1918 case QMetaType::Type::QDate:
1919 fieldType = QStringLiteral(
"esriFieldTypeDate" );
1922 case QMetaType::Type::QByteArray:
1923 fieldType = QStringLiteral(
"esriFieldTypeBlob" );
1928 fieldType = QStringLiteral(
"esriFieldTypeString" );
1931 res.insert( QStringLiteral(
"type" ), fieldType );
1933 if ( !field.
alias().isEmpty() )
1934 res.insert( QStringLiteral(
"alias" ), field.
alias() );
1938 res.insert( QStringLiteral(
"nullable" ), !notNullable );
1941 res.insert( QStringLiteral(
"editable" ),
true );
1948 if ( type.compare( QLatin1String(
"FeatureServer" ), Qt::CaseInsensitive ) == 0 )
1950 else if ( type.compare( QLatin1String(
"MapServer" ), Qt::CaseInsensitive ) == 0 )
1952 else if ( type.compare( QLatin1String(
"ImageServer" ), Qt::CaseInsensitive ) == 0 )
1954 else if ( type.compare( QLatin1String(
"GlobeServer" ), Qt::CaseInsensitive ) == 0 )
1956 else if ( type.compare( QLatin1String(
"GPServer" ), Qt::CaseInsensitive ) == 0 )
1958 else if ( type.compare( QLatin1String(
"GeocodeServer" ), Qt::CaseInsensitive ) == 0 )
1960 else if ( type.compare( QLatin1String(
"SceneServer" ), Qt::CaseInsensitive ) == 0 )
@ BelowLine
Labels can be placed below a line feature. Unless MapOrientation is also specified this mode respects...
@ MapOrientation
Signifies that the AboveLine and BelowLine flags should respect the map's orientation rather than the...
@ OnLine
Labels can be placed directly over a line feature.
@ AboveLine
Labels can be placed above a line feature. Unless MapOrientation is also specified this mode respects...
@ NoOrientation
Unknown orientation or sentinel value.
@ CounterClockwise
Counter-clockwise direction.
@ Clockwise
Clockwise direction.
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
@ ScaleArea
Calculate scale by the area.
ArcGisRestServiceType
Available ArcGIS REST service types.
@ GeocodeServer
GeocodeServer.
@ SceneServer
SceneServer.
@ Unknown
Other unknown/unsupported type.
@ GlobeServer
GlobeServer.
@ ImageServer
ImageServer.
@ FeatureServer
FeatureServer.
MarkerShape
Marker shapes.
@ Cross2
Rotated cross (lines only), 'x' shape.
@ Cross
Cross (lines only).
VerticalAnchorPoint
Marker symbol vertical anchor points.
@ Bottom
Align to bottom of symbol.
@ Center
Align to vertical center of symbol.
@ Top
Align to top of symbol.
@ Points
Points (e.g., for font sizes).
WkbType
The WKB type describes the number of dimensions a geometry has.
@ CompoundCurve
CompoundCurve.
@ MultiPolygon
MultiPolygon.
@ MultiLineString
MultiLineString.
@ CircularString
CircularString.
@ GeometryCollection
GeometryCollection.
@ CurvePolygon
CurvePolygon.
@ MultiSurface
MultiSurface.
@ Wkt2_2019Simplified
WKT2_2019 with the simplification rule of WKT2_SIMPLIFIED.
HorizontalAnchorPoint
Marker symbol horizontal anchor points.
@ Center
Align to horizontal center of symbol.
@ Right
Align to right side of symbol.
@ Left
Align to left side of symbol.
Abstract base class for all geometries.
virtual const QgsAbstractGeometry * simplifiedTypeRef() const
Returns a reference to the simplest lossless representation of this geometry, e.g.
bool isMeasure() const
Returns true if the geometry contains m values.
virtual QgsRectangle boundingBox() const
Returns the minimal bounding box for the geometry.
bool is3D() const
Returns true if the geometry is 3D and contains a z-value.
Qgis::WkbType wkbType() const
Returns the WKB type of the geometry.
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
Contains the context of a ArcGIS REST service operation.
QTimeZone timeZone() const
Returns the time zone for datetime values.
QString objectIdFieldName() const
Returns the name of the objectId field.
static QVariantMap fieldDefinitionToJson(const QgsField &field)
Converts a field's definition to an ArcGIS REST JSON representation.
static QgsCoordinateReferenceSystem convertSpatialReference(const QVariantMap &spatialReferenceMap)
Converts a spatial reference JSON definition to a QgsCoordinateReferenceSystem value.
static QDateTime convertDateTime(const QVariant &value)
Converts a date time value to a QDateTime.
static Qgis::WkbType convertGeometryType(const QString &type)
Converts an ESRI REST geometry type to a WKB type.
static QString convertLabelingExpression(const QString &string)
Converts an ESRI labeling expression to a QGIS expression string.
static QgsSymbol * convertSymbol(const QVariantMap &definition)
Converts a symbol JSON definition to a QgsSymbol.
static QVariantMap geometryToJson(const QgsGeometry &geometry, const QgsArcGisRestContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Converts a geometry to an ArcGIS REST JSON representation.
static Qgis::ArcGisRestServiceType serviceTypeFromString(const QString &type)
Converts a string value to a REST service type.
static QVariant variantToAttributeValue(const QVariant &variant, QMetaType::Type expectedType, const QgsArcGisRestContext &context)
Converts a variant to a REST attribute value.
static QgsAbstractGeometry * convertGeometry(const QVariantMap &geometry, const QString &esriGeometryType, bool hasM, bool hasZ, QgsCoordinateReferenceSystem *crs=nullptr)
Converts an ESRI REST geometry JSON definition to a QgsAbstractGeometry.
static QVariantMap featureToJson(const QgsFeature &feature, const QgsArcGisRestContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem(), QgsArcGisRestUtils::FeatureToJsonFlags flags=QgsArcGisRestUtils::FeatureToJsonFlags(static_cast< int >(QgsArcGisRestUtils::FeatureToJsonFlag::IncludeGeometry)|static_cast< int >(QgsArcGisRestUtils::FeatureToJsonFlag::IncludeNonObjectIdAttributes)))
Converts a feature to an ArcGIS REST JSON representation.
static Qt::PenStyle convertLineStyle(const QString &style)
Converts an ESRI line style to a Qt pen style.
@ IncludeGeometry
Whether to include the geometry definition.
@ IncludeNonObjectIdAttributes
Whether to include any non-objectId attributes.
@ SkipUnsetAttributes
Skip unset attributes.
static QgsFeatureRenderer * convertRenderer(const QVariantMap &rendererData)
Converts renderer JSON data to an equivalent QgsFeatureRenderer.
static QMetaType::Type convertFieldType(const QString &type)
Converts an ESRI REST field type to a QVariant type.
static Qt::BrushStyle convertFillStyle(const QString &style)
Converts an ESRI fill style to a Qt brush style.
static QVariantMap crsToJson(const QgsCoordinateReferenceSystem &crs)
Converts a crs to an ArcGIS REST JSON representation.
QFlags< FeatureToJsonFlag > FeatureToJsonFlags
Flags which control the behavior of converting features to JSON.
static QgsAbstractVectorLayerLabeling * convertLabeling(const QVariantList &data)
Converts labeling JSON data to an equivalent QGIS vector labeling.
static QColor convertColor(const QVariant &data)
Converts ESRI JSON color data to a QColor object.
static QgsRectangle convertRectangle(const QVariant &value)
Converts a rectangle value to a QgsRectangle.
A feature renderer which represents features using a list of renderer categories.
QgsPoint startPoint() const override
Returns the starting point of the curve.
bool isEmpty() const override
Returns true if the geometry is empty.
int numPoints() const override
Returns the number of points in the curve.
QgsPoint pointN(int i) const
Returns the point at index i within the circular string.
A dummy implementation class method which does not compute any breaks.
A classification method which uses equal width intervals.
Implementation of a fixed interval classification.
A classification method for natural breaks, based on Jenks method.
A classification method which creates classes based on quantiles.
A classification method which classifies based on standard deviation of values.
QgsCompoundCurve * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
int nCurves() const
Returns the number of curves in the geometry.
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
QgsPoint startPoint() const override
Returns the starting point of the curve.
Represents a coordinate reference system (CRS).
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromWkt(const QString &wkt)
Sets this CRS using a WKT definition.
bool createFromString(const QString &definition)
Set up this CRS from a string definition.
QString toWkt(Qgis::CrsWktVariant variant=Qgis::CrsWktVariant::Wkt1Gdal, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
Curve polygon geometry type.
int numInteriorRings() const
Returns the number of interior rings contained with the curve polygon.
const QgsCurve * exteriorRing() const
Returns the curve polygon's exterior ring.
const QgsCurve * interiorRing(int i) const
Retrieves an interior ring from the curve polygon.
virtual void setExteriorRing(QgsCurve *ring)
Sets the exterior ring of the polygon.
virtual void addInteriorRing(QgsCurve *ring)
Adds an interior ring to the geometry (takes ownership).
Abstract base class for curved geometry type.
Qgis::AngularDirection orientation() const
Returns the curve's orientation, e.g.
virtual QgsCurve * reversed() const =0
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
virtual QgsPoint endPoint() const =0
Returns the end point of the curve.
Handles parsing and evaluation of expressions (formerly called "search strings").
bool isValid() const
Checks if this expression is valid.
Abstract base class for all 2D vector feature renderers.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
@ ConstraintNotNull
Field may not be null.
Encapsulate a field in an attribute table or data source.
QgsFieldConstraints constraints
Container of fields for a vector layer.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Represents a color stop within a QgsGradientColorRamp color ramp.
void setPlacementFlags(Qgis::LabelLinePlacementFlags flags)
Returns the line placement flags, which dictate how line labels can be placed above or below the line...
void setQuadrant(Qgis::LabelQuadrantPosition quadrant)
Sets the quadrant in which to offset labels from the point.
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
const double * zData() const
Returns a const pointer to the z vertex data, or nullptr if the linestring does not have z values.
int numPoints() const override
Returns the number of points in the curve.
QgsLineString * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
const double * mData() const
Returns a const pointer to the m vertex data, or nullptr if the linestring does not have m values.
Multi curve geometry collection.
QgsCurve * curveN(int index)
Returns the curve with the specified index.
Multi line string geometry collection.
QgsLineString * lineStringN(int index)
Returns the line string with the specified index.
Multi point geometry collection.
QgsPoint * pointN(int index)
Returns the point with the specified index.
Multi polygon geometry collection.
QgsPolygon * polygonN(int index)
Returns the polygon with the specified index.
Multi surface geometry collection.
Contains settings for how a map layer will be labeled.
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
Qgis::LabelPlacement placement
Label placement mode.
bool isExpression
true if this label is made from a expression string, e.g., FieldName || 'mm'
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
QString fieldName
Name of field (or an expression) to use for label text.
const QgsLabelPointSettings & pointSettings() const
Returns the label point settings, which contain settings related to how the label engine places and f...
Point geometry type, with support for z-dimension and m-values.
void clear() override
Clears the geometry, ie reset it to a null geometry.
bool isEmpty() const override
Returns true if the geometry is empty.
A store for object properties.
void setTransformer(QgsPropertyTransformer *transformer)
Sets an optional transformer to use for manipulating the calculated values for the property.
static QgsProperty fromField(const QString &fieldName, bool isActive=true)
Returns a new FieldBasedProperty created from the specified field name.
A rectangle specified with double values.
bool intersects(const QgsRectangle &rect) const
Returns true when rectangle intersects with other rectangle.
Represents an individual category (class) from a QgsCategorizedSymbolRenderer.
Represents a value range for a QgsGraduatedSymbolRenderer.
void setUpperValue(double upperValue)
Sets the upper bound of the range.
void setSymbol(QgsSymbol *s)
Sets the symbol used for the range.
void setLabel(const QString &label)
Sets the label used for the range.
void setLowerValue(double lowerValue)
Sets the lower bound of the range.
A child rule for QgsRuleBasedLabeling.
void setActive(bool state)
Sets if this rule is active.
void appendChild(QgsRuleBasedLabeling::Rule *rule)
add child rule, take ownership, sets this as parent
Rule based labeling for a vector layer.
A feature renderer which renders all features with the same symbol.
Abstract base class for all rendered symbols.
Container for settings relating to a text buffer.
void setColor(const QColor &color)
Sets the color for the buffer.
void setSizeUnit(Qgis::RenderUnit unit)
Sets the units used for the buffer size.
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
void setSize(double size)
Sets the size of the buffer.
Container for all settings relating to text rendering.
void setColor(const QColor &color)
Sets the color that text will be rendered in.
void setSize(double size)
Sets the size for rendered text.
void setFont(const QFont &font)
Sets the font used for rendering text.
void setSizeUnit(Qgis::RenderUnit unit)
Sets the units for the size of rendered text.
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text's buffer settings.
static bool isNull(const QVariant &variant, bool silenceNullWarnings=false)
Returns true if the specified variant should be considered a NULL value.
static Qgis::WkbType zmType(Qgis::WkbType type, bool hasZ, bool hasM)
Returns the modified input geometry type according to hasZ / hasM.
static Q_INVOKABLE bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static Q_INVOKABLE bool hasM(Qgis::WkbType type)
Tests whether a WKB type contains m values.
static Qgis::WkbType flatType(Qgis::WkbType type)
Returns the flat type for a WKB type.
double ANALYSIS_EXPORT angle(QgsPoint *p1, QgsPoint *p2, QgsPoint *p3, QgsPoint *p4)
Calculates the angle between two segments (in 2 dimension, z-values are ignored).
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference).
T qgsgeometry_cast(QgsAbstractGeometry *geom)
QList< QgsRendererCategory > QgsCategoryList
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
#define QgsDebugError(str)
QList< QgsSymbolLayer * > QgsSymbolLayerList