48#include <QRegularExpression>
60 if ( esriFieldType == QLatin1String(
"esriFieldTypeInteger" ) )
61 return QMetaType::Type::LongLong;
62 if ( esriFieldType == QLatin1String(
"esriFieldTypeSmallInteger" ) )
63 return QMetaType::Type::Int;
64 if ( esriFieldType == QLatin1String(
"esriFieldTypeDouble" ) )
65 return QMetaType::Type::Double;
66 if ( esriFieldType == QLatin1String(
"esriFieldTypeSingle" ) )
67 return QMetaType::Type::Double;
68 if ( esriFieldType == QLatin1String(
"esriFieldTypeString" ) )
69 return QMetaType::Type::QString;
70 if ( esriFieldType == QLatin1String(
"esriFieldTypeDate" ) )
71 return QMetaType::Type::QDateTime;
72 if ( esriFieldType == QLatin1String(
"esriFieldTypeGeometry" ) )
73 return QMetaType::Type::UnknownType;
74 if ( esriFieldType == QLatin1String(
"esriFieldTypeOID" ) )
75 return QMetaType::Type::LongLong;
76 if ( esriFieldType == QLatin1String(
"esriFieldTypeBlob" ) )
77 return QMetaType::Type::QByteArray;
78 if ( esriFieldType == QLatin1String(
"esriFieldTypeGlobalID" ) )
79 return QMetaType::Type::QString;
80 if ( esriFieldType == QLatin1String(
"esriFieldTypeRaster" ) )
81 return QMetaType::Type::QByteArray;
82 if ( esriFieldType == QLatin1String(
"esriFieldTypeGUID" ) )
83 return QMetaType::Type::QString;
84 if ( esriFieldType == QLatin1String(
"esriFieldTypeXML" ) )
85 return QMetaType::Type::QString;
86 return QMetaType::Type::UnknownType;
92 if ( esriGeometryType == QLatin1String(
"esriGeometryNull" ) )
94 else if ( esriGeometryType == QLatin1String(
"esriGeometryPoint" ) )
96 else if ( esriGeometryType == QLatin1String(
"esriGeometryMultipoint" ) )
98 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolyline" ) )
100 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolygon" ) )
102 else if ( esriGeometryType == QLatin1String(
"esriGeometryEnvelope" ) )
122std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertPoint(
const QVariantList &coordList,
Qgis::WkbType pointType )
124 int nCoords = coordList.size();
127 bool xok =
false, yok =
false;
128 const double x = coordList[0].toDouble( &xok );
129 const double y = coordList[1].toDouble( &yok );
133 const double z = hasZ && nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
136 const double m =
QgsWkbTypes::hasM( pointType ) && ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[ hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
137 return std::make_unique< QgsPoint >( pointType, x, y, z, m );
140std::unique_ptr< QgsCircularString > QgsArcGisRestUtils::convertCircularString(
const QVariantMap &curveData,
Qgis::WkbType pointType,
const QgsPoint &startPoint )
142 const QVariantList coordsList = curveData[QStringLiteral(
"c" )].toList();
143 if ( coordsList.isEmpty() )
145 const int coordsListSize = coordsList.size();
147 QVector<QgsPoint> points;
148 points.reserve( coordsListSize + 1 );
149 points.append( startPoint );
151 for (
int i = 0; i < coordsListSize - 1; )
155 std::unique_ptr< QgsPoint > endPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
159 std::unique_ptr< QgsPoint > interiorPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
160 if ( !interiorPoint )
163 points << *interiorPoint;
166 std::unique_ptr< QgsCircularString > curve = std::make_unique< QgsCircularString> ();
167 curve->setPoints( points );
171std::unique_ptr< QgsCompoundCurve > QgsArcGisRestUtils::convertCompoundCurve(
const QVariantList &curvesList,
Qgis::WkbType pointType )
174 std::unique_ptr< QgsCompoundCurve > compoundCurve = std::make_unique< QgsCompoundCurve >();
176 QVector< double > lineX;
177 QVector< double > lineY;
178 QVector< double > lineZ;
179 QVector< double > lineM;
180 int maxCurveListSize = curvesList.size();
181 lineX.resize( maxCurveListSize );
182 lineY.resize( maxCurveListSize );
186 lineZ.resize( maxCurveListSize );
189 lineM.resize( maxCurveListSize );
191 double *outLineX = lineX.data();
192 double *outLineY = lineY.data();
193 double *outLineZ = lineZ.data();
194 double *outLineM = lineM.data();
195 int actualLineSize = 0;
200 int curveListIndex = 0;
201 for (
const QVariant &curveData : curvesList )
203 if ( curveData.userType() == QMetaType::Type::QVariantList )
205 const QVariantList coordList = curveData.toList();
206 const int nCoords = coordList.size();
210 const double x = coordList[0].toDouble( &xok );
211 const double y = coordList[1].toDouble( &yok );
220 *outLineZ++ = nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
226 *outLineM++ = ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[ hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
229 else if ( curveData.userType() == QMetaType::Type::QVariantMap )
233 if ( actualLineSize > 0 )
235 lastLineStringPoint =
QgsPoint( lineX.at( actualLineSize - 1 ),
236 lineY.at( actualLineSize - 1 ),
237 hasZ ? lineZ.at( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN(),
238 hasM ? lineM.at( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN() );
240 std::unique_ptr< QgsCircularString > circularString( convertCircularString( curveData.toMap(), pointType, lastLineStringPoint ) );
241 if ( !circularString )
246 if ( actualLineSize > 0 )
248 lineX.resize( actualLineSize );
249 lineY.resize( actualLineSize );
251 lineZ.resize( actualLineSize );
253 lineM.resize( actualLineSize );
255 compoundCurve->addCurve(
new QgsLineString( lineX, lineY, lineZ, lineM ) );
256 lineX.resize( maxCurveListSize - curveListIndex );
257 lineY.resize( maxCurveListSize - curveListIndex );
259 lineZ.resize( maxCurveListSize - curveListIndex );
261 lineM.resize( maxCurveListSize - curveListIndex );
262 outLineX = lineX.data();
263 outLineY = lineY.data();
264 outLineZ = lineZ.data();
265 outLineM = lineM.data();
269 if ( compoundCurve->curveAt( compoundCurve->nCurves() - 1 )->nCoordinates() < 2 )
270 compoundCurve->removeCurve( compoundCurve->nCurves() - 1 );
272 const QgsPoint endPointCircularString = circularString->endPoint();
273 compoundCurve->addCurve( circularString.release() );
277 *outLineX++ = endPointCircularString.
x();
278 *outLineY++ = endPointCircularString.
y();
280 *outLineZ++ = endPointCircularString.
z();
282 *outLineM++ = endPointCircularString.
m();
287 if ( actualLineSize == 1 && compoundCurve->nCurves() > 0 )
289 const QgsCurve *finalCurve = compoundCurve->curveAt( compoundCurve->nCurves() - 1 );
293 && ( !hasZ ||
qgsDoubleNear( finalCurveEndPoint.
z(), lineZ.at( 0 ) ) )
294 && ( !hasM ||
qgsDoubleNear( finalCurveEndPoint.
m(), lineM.at( 0 ) ) ) )
300 if ( actualLineSize > 0 )
302 lineX.resize( actualLineSize );
303 lineY.resize( actualLineSize );
305 lineZ.resize( actualLineSize );
307 lineM.resize( actualLineSize );
308 compoundCurve->addCurve(
new QgsLineString( lineX, lineY, lineZ, lineM ) );
311 return compoundCurve;
314std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertGeometryPoint(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
317 bool xok =
false, yok =
false;
318 double x = geometryData[QStringLiteral(
"x" )].toDouble( &xok );
319 double y = geometryData[QStringLiteral(
"y" )].toDouble( &yok );
322 double z = geometryData[QStringLiteral(
"z" )].toDouble();
323 double m = geometryData[QStringLiteral(
"m" )].toDouble();
324 return std::make_unique< QgsPoint >( pointType, x, y, z, m );
327std::unique_ptr< QgsMultiPoint > QgsArcGisRestUtils::convertMultiPoint(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
330 const QVariantList coordsList = geometryData[QStringLiteral(
"points" )].toList();
332 std::unique_ptr< QgsMultiPoint > multiPoint = std::make_unique< QgsMultiPoint >();
333 multiPoint->reserve( coordsList.size() );
334 for (
const QVariant &coordData : coordsList )
336 const QVariantList coordList = coordData.toList();
337 std::unique_ptr< QgsPoint > p = convertPoint( coordList, pointType );
342 multiPoint->addGeometry( p.release() );
347 std::unique_ptr< QgsPoint > p = convertGeometryPoint( geometryData, pointType );
349 multiPoint->addGeometry( p.release() );
351 if ( multiPoint->numGeometries() == 0 )
359std::unique_ptr< QgsMultiCurve > QgsArcGisRestUtils::convertGeometryPolyline(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
362 QVariantList pathsList;
363 if ( geometryData[QStringLiteral(
"paths" )].isValid() )
364 pathsList = geometryData[QStringLiteral(
"paths" )].toList();
365 else if ( geometryData[QStringLiteral(
"curvePaths" )].isValid() )
366 pathsList = geometryData[QStringLiteral(
"curvePaths" )].toList();
367 if ( pathsList.isEmpty() )
369 std::unique_ptr< QgsMultiCurve > multiCurve = std::make_unique< QgsMultiCurve >();
370 multiCurve->reserve( pathsList.size() );
371 for (
const QVariant &pathData : std::as_const( pathsList ) )
373 std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( pathData.toList(), pointType );
378 multiCurve->addGeometry( curve.release() );
383std::unique_ptr< QgsMultiSurface > QgsArcGisRestUtils::convertGeometryPolygon(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
386 QVariantList ringsList;
387 if ( geometryData[QStringLiteral(
"rings" )].isValid() )
388 ringsList = geometryData[QStringLiteral(
"rings" )].toList();
389 else if ( geometryData[QStringLiteral(
"ringPaths" )].isValid() )
390 ringsList = geometryData[QStringLiteral(
"ringPaths" )].toList();
391 if ( ringsList.isEmpty() )
394 QList< QgsCompoundCurve * > curves;
395 for (
int i = 0, n = ringsList.size(); i < n; ++i )
397 std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( ringsList[i].toList(), pointType );
402 curves.append( curve.release() );
404 if ( curves.count() == 0 )
407 std::unique_ptr< QgsMultiSurface > result = std::make_unique< QgsMultiSurface >();
408 if ( curves.count() == 1 )
411 std::unique_ptr< QgsCurvePolygon > newPolygon = std::make_unique< QgsCurvePolygon >();
412 newPolygon->setExteriorRing( curves.takeAt( 0 ) );
413 result->addGeometry( newPolygon.release() );
417 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 ); } );
418 result->reserve( curves.size() );
419 while ( !curves.isEmpty() )
425 engine->prepareGeometry();
427 QMutableListIterator< QgsCompoundCurve * > it( curves );
428 while ( it.hasNext() )
435 if ( engine->contains( &point ) )
440 engine->prepareGeometry();
444 result->addGeometry( newPolygon );
446 if ( result->numGeometries() == 0 )
452std::unique_ptr< QgsPolygon > QgsArcGisRestUtils::convertEnvelope(
const QVariantMap &geometryData )
455 bool xminOk =
false, yminOk =
false, xmaxOk =
false, ymaxOk =
false;
456 double xmin = geometryData[QStringLiteral(
"xmin" )].toDouble( &xminOk );
457 double ymin = geometryData[QStringLiteral(
"ymin" )].toDouble( &yminOk );
458 double xmax = geometryData[QStringLiteral(
"xmax" )].toDouble( &xmaxOk );
459 double ymax = geometryData[QStringLiteral(
"ymax" )].toDouble( &ymaxOk );
460 if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk )
462 std::unique_ptr< QgsLineString > ext = std::make_unique< QgsLineString> ();
463 ext->addVertex(
QgsPoint( xmin, ymin ) );
464 ext->addVertex(
QgsPoint( xmax, ymin ) );
465 ext->addVertex(
QgsPoint( xmax, ymax ) );
466 ext->addVertex(
QgsPoint( xmin, ymax ) );
467 ext->addVertex(
QgsPoint( xmin, ymin ) );
468 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
469 poly->setExteriorRing( ext.release() );
482 if ( esriGeometryType == QLatin1String(
"esriGeometryNull" ) )
484 else if ( esriGeometryType == QLatin1String(
"esriGeometryPoint" ) )
485 return convertGeometryPoint( geometryData, pointType ).release();
486 else if ( esriGeometryType == QLatin1String(
"esriGeometryMultipoint" ) )
487 return convertMultiPoint( geometryData, pointType ).release();
488 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolyline" ) )
489 return convertGeometryPolyline( geometryData, pointType ).release();
490 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolygon" ) )
491 return convertGeometryPolygon( geometryData, pointType ).release();
492 else if ( esriGeometryType == QLatin1String(
"esriGeometryEnvelope" ) )
493 return convertEnvelope( geometryData ).release();
516 QString spatialReference = spatialReferenceMap[QStringLiteral(
"latestWkid" )].toString();
517 if ( spatialReference.isEmpty() )
518 spatialReference = spatialReferenceMap[QStringLiteral(
"wkid" )].toString();
521 if ( !spatialReference.isEmpty() )
530 else if ( !spatialReferenceMap[QStringLiteral(
"wkt" )].toString().isEmpty() )
533 crs.
createFromWkt( spatialReferenceMap[QStringLiteral(
"wkt" )].toString() );
548 const QString type = symbolData.value( QStringLiteral(
"type" ) ).toString();
549 if ( type == QLatin1String(
"esriSMS" ) )
552 return parseEsriMarkerSymbolJson( symbolData ).release();
554 else if ( type == QLatin1String(
"esriSLS" ) )
557 return parseEsriLineSymbolJson( symbolData ).release();
559 else if ( type == QLatin1String(
"esriSFS" ) )
562 return parseEsriFillSymbolJson( symbolData ).release();
564 else if ( type == QLatin1String(
"esriPFS" ) )
566 return parseEsriPictureFillSymbolJson( symbolData ).release();
568 else if ( type == QLatin1String(
"esriPMS" ) )
571 return parseEsriPictureMarkerSymbolJson( symbolData ).release();
573 else if ( type == QLatin1String(
"esriTS" ) )
575 return parseEsriTextMarkerSymbolJson( symbolData ).release();
580std::unique_ptr<QgsLineSymbol> QgsArcGisRestUtils::parseEsriLineSymbolJson(
const QVariantMap &symbolData )
582 QColor lineColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
583 if ( !lineColor.isValid() )
587 double widthInPoints = symbolData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
592 Qt::PenStyle penStyle =
convertLineStyle( symbolData.value( QStringLiteral(
"style" ) ).toString() );
593 std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( lineColor, widthInPoints, penStyle );
595 layers.append( lineLayer.release() );
597 std::unique_ptr< QgsLineSymbol > symbol = std::make_unique< QgsLineSymbol >( layers );
601std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriFillSymbolJson(
const QVariantMap &symbolData )
603 QColor fillColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
604 Qt::BrushStyle brushStyle =
convertFillStyle( symbolData.value( QStringLiteral(
"style" ) ).toString() );
606 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
607 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
608 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
610 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
613 std::unique_ptr< QgsSimpleFillSymbolLayer > fillLayer = std::make_unique< QgsSimpleFillSymbolLayer >( fillColor, brushStyle, lineColor, penStyle, penWidthInPoints );
615 layers.append( fillLayer.release() );
617 std::unique_ptr< QgsFillSymbol > symbol = std::make_unique< QgsFillSymbol >( layers );
621std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriPictureFillSymbolJson(
const QVariantMap &symbolData )
625 double widthInPixels = symbolData.value( QStringLiteral(
"width" ) ).toInt( &ok );
629 const double xScale = symbolData.value( QStringLiteral(
"xscale" ) ).toDouble( &ok );
631 widthInPixels *= xScale;
633 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
638 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
639 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
641 QString symbolPath( symbolData.value( QStringLiteral(
"imageData" ) ).toString() );
642 symbolPath.prepend( QLatin1String(
"base64:" ) );
645 std::unique_ptr< QgsRasterFillSymbolLayer > fillLayer = std::make_unique< QgsRasterFillSymbolLayer >( symbolPath );
646 fillLayer->setWidth( widthInPixels );
647 fillLayer->setAngle( angleCW );
649 fillLayer->setOffset( QPointF( xOffset, yOffset ) );
651 layers.append( fillLayer.release() );
653 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
654 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
655 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
656 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
658 std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( lineColor, penWidthInPoints, penStyle );
660 layers.append( lineLayer.release() );
662 std::unique_ptr< QgsFillSymbol > symbol = std::make_unique< QgsFillSymbol >( layers );
666Qgis::MarkerShape QgsArcGisRestUtils::parseEsriMarkerShape(
const QString &style )
668 if ( style == QLatin1String(
"esriSMSCircle" ) )
670 else if ( style == QLatin1String(
"esriSMSCross" ) )
672 else if ( style == QLatin1String(
"esriSMSDiamond" ) )
674 else if ( style == QLatin1String(
"esriSMSSquare" ) )
676 else if ( style == QLatin1String(
"esriSMSX" ) )
678 else if ( style == QLatin1String(
"esriSMSTriangle" ) )
684std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriMarkerSymbolJson(
const QVariantMap &symbolData )
686 QColor fillColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
688 const double sizeInPoints = symbolData.value( QStringLiteral(
"size" ) ).toDouble( &ok );
691 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
696 Qgis::MarkerShape shape = parseEsriMarkerShape( symbolData.value( QStringLiteral(
"style" ) ).toString() );
698 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
699 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
701 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
702 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
703 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
704 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
707 std::unique_ptr< QgsSimpleMarkerSymbolLayer > markerLayer = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, sizeInPoints, angleCW,
Qgis::ScaleMethod::ScaleArea, fillColor, lineColor );
710 markerLayer->setStrokeStyle( penStyle );
711 markerLayer->setStrokeWidth( penWidthInPoints );
712 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
714 layers.append( markerLayer.release() );
716 std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
720std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriPictureMarkerSymbolJson(
const QVariantMap &symbolData )
723 const double widthInPixels = symbolData.value( QStringLiteral(
"width" ) ).toInt( &ok );
726 const double heightInPixels = symbolData.value( QStringLiteral(
"height" ) ).toInt( &ok );
730 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
735 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
736 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
740 QString symbolPath( symbolData.value( QStringLiteral(
"imageData" ) ).toString() );
741 symbolPath.prepend( QLatin1String(
"base64:" ) );
744 std::unique_ptr< QgsRasterMarkerSymbolLayer > markerLayer = std::make_unique< QgsRasterMarkerSymbolLayer >( symbolPath, widthInPixels, angleCW,
Qgis::ScaleMethod::ScaleArea );
748 if ( !
qgsDoubleNear(
static_cast< double >( heightInPixels ) / widthInPixels, markerLayer->defaultAspectRatio() ) )
749 markerLayer->setFixedAspectRatio(
static_cast< double >( heightInPixels ) / widthInPixels );
751 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
753 layers.append( markerLayer.release() );
755 std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
759std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriTextMarkerSymbolJson(
const QVariantMap &symbolData )
763 const QString fontFamily = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"family" ) ).toString();
765 const QString chr = symbolData.value( QStringLiteral(
"text" ) ).toString();
767 const double pointSize = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"size" ) ).toDouble();
769 const QColor color =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
771 const double esriAngle = symbolData.value( QStringLiteral(
"angle" ) ).toDouble();
773 const double angle = 90.0 - esriAngle;
775 std::unique_ptr< QgsFontMarkerSymbolLayer > markerLayer = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, chr, pointSize, color, angle );
777 QColor strokeColor =
convertColor( symbolData.value( QStringLiteral(
"borderLineColor" ) ) );
778 markerLayer->setStrokeColor( strokeColor );
780 double borderLineSize = symbolData.value( QStringLiteral(
"borderLineSize" ) ).toDouble();
781 markerLayer->setStrokeWidth( borderLineSize );
783 const QString fontStyle = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"style" ) ).toString();
784 markerLayer->setFontStyle( fontStyle );
786 double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
787 double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
789 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
798 QString horizontalAnchorPoint = symbolData.value( QStringLiteral(
"horizontalAlignment" ) ).toString();
799 QString verticalAnchorPoint = symbolData.value( QStringLiteral(
"verticalAlignment" ) ).toString();
801 if ( horizontalAnchorPoint == QString(
"center" ) )
805 else if ( horizontalAnchorPoint == QString(
"left" ) )
809 else if ( horizontalAnchorPoint == QString(
"right" ) )
814 if ( verticalAnchorPoint == QString(
"center" ) )
818 else if ( verticalAnchorPoint == QString(
"top" ) )
822 else if ( verticalAnchorPoint == QString(
"bottom" ) )
827 markerLayer->setHorizontalAnchorPoint( hAlign );
828 markerLayer->setVerticalAnchorPoint( vAlign );
830 layers.append( markerLayer.release() );
832 std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
838 if ( labelingData.empty() )
845 for (
const QVariant &lbl : labelingData )
847 const QVariantMap labeling = lbl.toMap();
852 const QString placement = labeling.value( QStringLiteral(
"labelPlacement" ) ).toString();
853 if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveCenter" ) )
858 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowCenter" ) )
863 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterCenter" ) )
868 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveLeft" ) )
873 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowLeft" ) )
878 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterLeft" ) )
883 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveRight" ) )
888 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowRight" ) )
893 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterRight" ) )
898 else if ( placement == QLatin1String(
"esriServerLinePlacementAboveAfter" ) ||
899 placement == QLatin1String(
"esriServerLinePlacementAboveStart" ) ||
900 placement == QLatin1String(
"esriServerLinePlacementAboveAlong" ) )
905 else if ( placement == QLatin1String(
"esriServerLinePlacementBelowAfter" ) ||
906 placement == QLatin1String(
"esriServerLinePlacementBelowStart" ) ||
907 placement == QLatin1String(
"esriServerLinePlacementBelowAlong" ) )
912 else if ( placement == QLatin1String(
"esriServerLinePlacementCenterAfter" ) ||
913 placement == QLatin1String(
"esriServerLinePlacementCenterStart" ) ||
914 placement == QLatin1String(
"esriServerLinePlacementCenterAlong" ) )
919 else if ( placement == QLatin1String(
"esriServerPolygonPlacementAlwaysHorizontal" ) )
924 const double minScale = labeling.value( QStringLiteral(
"minScale" ) ).toDouble();
925 const double maxScale = labeling.value( QStringLiteral(
"maxScale" ) ).toDouble();
927 QVariantMap symbol = labeling.value( QStringLiteral(
"symbol" ) ).toMap();
929 const double haloSize = symbol.value( QStringLiteral(
"haloSize" ) ).toDouble();
940 const QString fontFamily = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"family" ) ).toString();
941 const QString fontStyle = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"style" ) ).toString();
942 const QString fontWeight = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"weight" ) ).toString();
943 const int fontSize = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"size" ) ).toInt();
944 QFont font( fontFamily, fontSize );
945 font.setStyleName( fontStyle );
946 font.setWeight( fontWeight == QLatin1String(
"bold" ) ? QFont::Bold : QFont::Normal );
954 QString where = labeling.value( QStringLiteral(
"where" ) ).toString();
973 const QString type = rendererData.value( QStringLiteral(
"type" ) ).toString();
974 if ( type == QLatin1String(
"simple" ) )
976 const QVariantMap symbolProps = rendererData.value( QStringLiteral(
"symbol" ) ).toMap();
977 std::unique_ptr< QgsSymbol > symbol(
convertSymbol( symbolProps ) );
983 else if ( type == QLatin1String(
"uniqueValue" ) )
985 const QString field1 = rendererData.value( QStringLiteral(
"field1" ) ).toString();
986 const QString field2 = rendererData.value( QStringLiteral(
"field2" ) ).toString();
987 const QString field3 = rendererData.value( QStringLiteral(
"field3" ) ).toString();
989 if ( !field2.isEmpty() || !field3.isEmpty() )
991 const QString delimiter = rendererData.value( QStringLiteral(
"fieldDelimiter" ) ).toString();
992 if ( !field3.isEmpty() )
994 attribute = QStringLiteral(
"concat(\"%1\",'%2',\"%3\",'%4',\"%5\")" ).arg( field1, delimiter, field2, delimiter, field3 );
998 attribute = QStringLiteral(
"concat(\"%1\",'%2',\"%3\")" ).arg( field1, delimiter, field2 );
1006 const QVariantList categories = rendererData.value( QStringLiteral(
"uniqueValueInfos" ) ).toList();
1008 for (
const QVariant &category : categories )
1010 const QVariantMap categoryData = category.toMap();
1011 const QString value = categoryData.value( QStringLiteral(
"value" ) ).toString();
1012 const QString label = categoryData.value( QStringLiteral(
"label" ) ).toString();
1020 std::unique_ptr< QgsSymbol > defaultSymbol(
convertSymbol( rendererData.value( QStringLiteral(
"defaultSymbol" ) ).toMap() ) );
1021 if ( defaultSymbol )
1023 categoryList.append(
QgsRendererCategory( QVariant(), defaultSymbol.release(), rendererData.value( QStringLiteral(
"defaultLabel" ) ).toString() ) );
1026 if ( categoryList.empty() )
1031 else if ( type == QLatin1String(
"classBreaks" ) )
1033 const QString attrName = rendererData.value( QStringLiteral(
"field" ) ).toString();
1035 const QVariantList classBreakInfos = rendererData.value( QStringLiteral(
"classBreakInfos" ) ).toList();
1036 const QVariantMap authoringInfo = rendererData.value( QStringLiteral(
"authoringInfo" ) ).toMap();
1037 QVariantMap symbolData;
1039 QString esriMode = authoringInfo.value( QStringLiteral(
"classificationMethod" ) ).toString();
1040 if ( esriMode.isEmpty() )
1042 esriMode = rendererData.value( QStringLiteral(
"classificationMethod" ) ).toString();
1045 if ( !classBreakInfos.isEmpty() )
1047 symbolData = classBreakInfos.at( 0 ).toMap().value( QStringLiteral(
"symbol" ) ).toMap();
1053 const double transparency = rendererData.value( QStringLiteral(
"transparency" ) ).toDouble();
1054 const double opacity = ( 100.0 - transparency ) / 100.0;
1055 symbol->setOpacity( opacity );
1057 const QVariantList visualVariablesData = rendererData.value( QStringLiteral(
"visualVariables" ) ).toList();
1059 for (
const QVariant &visualVariable : visualVariablesData )
1061 const QVariantMap visualVariableData = visualVariable.toMap();
1062 const QString variableType = visualVariableData.value( QStringLiteral(
"type" ) ).toString();
1063 if ( variableType == QLatin1String(
"sizeInfo" ) )
1067 else if ( variableType == QLatin1String(
"colorInfo" ) )
1069 const QVariantList stops = visualVariableData.value( QStringLiteral(
"stops" ) ).toList();
1070 if ( stops.size() < 2 )
1075 const double minValue = stops.front().toMap().value( QStringLiteral(
"value" ) ).toDouble( &ok );
1078 const QColor minColor =
convertColor( stops.front().toMap().value( QStringLiteral(
"color" ) ) );
1080 const double maxValue = stops.back().toMap().value( QStringLiteral(
"value" ) ).toDouble( &ok );
1083 const QColor maxColor =
convertColor( stops.back().toMap().value( QStringLiteral(
"color" ) ) );
1086 for (
int i = 1; i < stops.size() - 1; ++i )
1088 const QVariantMap stopData = stops.at( i ).toMap();
1089 const double breakpoint = stopData.value( QStringLiteral(
"value" ) ).toDouble();
1090 const double scaledBreakpoint = ( breakpoint - minValue ) / ( maxValue - minValue );
1091 const QColor fillColor =
convertColor( stopData.value( QStringLiteral(
"color" ) ) );
1093 gradientStops.append(
QgsGradientStop( scaledBreakpoint, fillColor ) );
1096 std::unique_ptr< QgsGradientColorRamp > colorRamp = std::make_unique< QgsGradientColorRamp >(
1097 minColor, maxColor,
false, gradientStops
1104 for (
int layer = 0; layer < symbol->symbolLayerCount(); ++layer )
1109 std::unique_ptr< QgsSingleSymbolRenderer > singleSymbolRenderer = std::make_unique< QgsSingleSymbolRenderer >( symbol.release() );
1111 return singleSymbolRenderer.release();
1115 QgsDebugError( QStringLiteral(
"ESRI visualVariable type %1 is not currently supported" ).arg( variableType ) );
1119 double lastValue = rendererData.value( QStringLiteral(
"minValue" ) ).toDouble();
1121 std::unique_ptr< QgsGraduatedSymbolRenderer > graduatedRenderer = std::make_unique< QgsGraduatedSymbolRenderer >( attrName );
1123 graduatedRenderer->setSourceSymbol( symbol.release() );
1125 if ( esriMode == QLatin1String(
"esriClassifyDefinedInterval" ) )
1128 graduatedRenderer->setClassificationMethod( method );
1130 else if ( esriMode == QLatin1String(
"esriClassifyEqualInterval" ) )
1133 graduatedRenderer->setClassificationMethod( method );
1135 else if ( esriMode == QLatin1String(
"esriClassifyGeometricalInterval" ) )
1138 graduatedRenderer->setClassificationMethod( method );
1140 else if ( esriMode == QLatin1String(
"esriClassifyManual" ) )
1143 graduatedRenderer->setClassificationMethod( method );
1145 else if ( esriMode == QLatin1String(
"esriClassifyNaturalBreaks" ) )
1148 graduatedRenderer->setClassificationMethod( method );
1150 else if ( esriMode == QLatin1String(
"esriClassifyQuantile" ) )
1153 graduatedRenderer->setClassificationMethod( method );
1155 else if ( esriMode == QLatin1String(
"esriClassifyStandardDeviation" ) )
1158 graduatedRenderer->setClassificationMethod( method );
1160 else if ( !esriMode.isEmpty() )
1162 QgsDebugError( QStringLiteral(
"ESRI classification mode %1 is not currently supported" ).arg( esriMode ) );
1165 for (
const QVariant &classBreakInfo : classBreakInfos )
1167 const QVariantMap symbolData = classBreakInfo.toMap().value( QStringLiteral(
"symbol" ) ).toMap();
1169 double classMaxValue = classBreakInfo.toMap().value( QStringLiteral(
"classMaxValue" ) ).toDouble();
1170 const QString label = classBreakInfo.toMap().value( QStringLiteral(
"label" ) ).toString();
1179 lastValue = classMaxValue;
1180 graduatedRenderer->addClass( range );
1183 return graduatedRenderer.release();
1185 else if ( type == QLatin1String(
"heatmap" ) )
1190 else if ( type == QLatin1String(
"vectorField" ) )
1200 QString expression = string;
1203 const thread_local QRegularExpression rx1 = QRegularExpression( QStringLiteral(
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)CONCAT(\\s|$)" ) );
1204 expression = expression.replace( rx1, QStringLiteral(
"\\4||\\5" ) );
1206 const thread_local QRegularExpression rx2 = QRegularExpression( QStringLiteral(
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)NEWLINE(\\s|$)" ) );
1207 expression = expression.replace( rx2, QStringLiteral(
"\\4'\\n'\\5" ) );
1210 const thread_local QRegularExpression rx3 = QRegularExpression( QStringLiteral(
"\"(.*?(?<!\\\\))\"" ) );
1211 expression = expression.replace( rx3, QStringLiteral(
"'\\1'" ) );
1212 const thread_local QRegularExpression rx4 = QRegularExpression( QStringLiteral(
"\\\\\"" ) );
1213 expression = expression.replace( rx4, QStringLiteral(
"\"" ) );
1216 const thread_local QRegularExpression rx5 = QRegularExpression( QStringLiteral(
"\\[([^]]*)\\]" ) );
1217 expression = expression.replace( rx5, QStringLiteral(
"\"\\1\"" ) );
1224 const QVariantList colorParts = colorData.toList();
1225 if ( colorParts.count() < 4 )
1228 int red = colorParts.at( 0 ).toInt();
1229 int green = colorParts.at( 1 ).toInt();
1230 int blue = colorParts.at( 2 ).toInt();
1231 int alpha = colorParts.at( 3 ).toInt();
1232 return QColor( red, green, blue, alpha );
1237 if ( style == QLatin1String(
"esriSLSSolid" ) )
1238 return Qt::SolidLine;
1239 else if ( style == QLatin1String(
"esriSLSDash" ) )
1240 return Qt::DashLine;
1241 else if ( style == QLatin1String(
"esriSLSDashDot" ) )
1242 return Qt::DashDotLine;
1243 else if ( style == QLatin1String(
"esriSLSDashDotDot" ) )
1244 return Qt::DashDotDotLine;
1245 else if ( style == QLatin1String(
"esriSLSDot" ) )
1247 else if ( style == QLatin1String(
"esriSLSNull" ) )
1250 return Qt::SolidLine;
1255 if ( style == QLatin1String(
"esriSFSBackwardDiagonal" ) )
1256 return Qt::BDiagPattern;
1257 else if ( style == QLatin1String(
"esriSFSCross" ) )
1258 return Qt::CrossPattern;
1259 else if ( style == QLatin1String(
"esriSFSDiagonalCross" ) )
1260 return Qt::DiagCrossPattern;
1261 else if ( style == QLatin1String(
"esriSFSForwardDiagonal" ) )
1262 return Qt::FDiagPattern;
1263 else if ( style == QLatin1String(
"esriSFSHorizontal" ) )
1264 return Qt::HorPattern;
1265 else if ( style == QLatin1String(
"esriSFSNull" ) )
1267 else if ( style == QLatin1String(
"esriSFSSolid" ) )
1268 return Qt::SolidPattern;
1269 else if ( style == QLatin1String(
"esriSFSVertical" ) )
1270 return Qt::VerPattern;
1272 return Qt::SolidPattern;
1280 QDateTime dt = QDateTime::fromMSecsSinceEpoch( value.toLongLong( &ok ) );
1283 QgsDebugError( QStringLiteral(
"Invalid value %1 for datetime" ).arg( value.toString() ) );
1295 const QVariantMap coords = value.toMap();
1300 const double xmin = coords.value( QStringLiteral(
"xmin" ) ).toDouble( &ok );
1303 const double ymin = coords.value( QStringLiteral(
"ymin" ) ).toDouble( &ok );
1306 const double xmax = coords.value( QStringLiteral(
"xmax" ) ).toDouble( &ok );
1309 const double ymax = coords.value( QStringLiteral(
"ymax" ) ).toDouble( &ok );
1321 return QVariantMap();
1328 return QVariantMap();
1331 res = pointToJson( qgsgeometry_cast< const QgsPoint * >( geom ) );
1335 res = lineStringToJson( qgsgeometry_cast< const QgsLineString * >( geom ) );
1340 res = curveToJson( qgsgeometry_cast< const QgsCurve * >( geom ) );
1344 res = polygonToJson( qgsgeometry_cast< const QgsPolygon * >( geom ) );
1348 res = multiPointToJson( qgsgeometry_cast< const QgsMultiPoint * >( geom ) );
1352 res = multiLineStringToJson( qgsgeometry_cast< const QgsMultiLineString * >( geom ) );
1356 res = multiCurveToJson( qgsgeometry_cast< const QgsMultiCurve * >( geom ) );
1360 res = multiPolygonToJson( qgsgeometry_cast< const QgsMultiPolygon * >( geom ) );
1364 res = curvePolygonToJson( qgsgeometry_cast< const QgsCurvePolygon * >( geom ) );
1368 res = multiSurfaceToJson( qgsgeometry_cast< const QgsMultiSurface * >( geom ) );
1372 return QVariantMap();
1375 return QVariantMap();
1378 return QVariantMap();
1385 res.insert( QStringLiteral(
"spatialReference" ),
crsToJson(
crs ) );
1391QVariantMap QgsArcGisRestUtils::pointToJson(
const QgsPoint *point )
1395 data[QStringLiteral(
"x" )] = QStringLiteral(
"NaN" );
1398 data[QStringLiteral(
"x" )] = point->
x();
1399 data[QStringLiteral(
"y" )] = point->
y();
1401 if ( point->
is3D() )
1402 data[QStringLiteral(
"z" )] = !std::isnan( point->
z() ) ? QVariant( point->
z() ) : QVariant( QStringLiteral(
"NaN" ) );
1405 data[QStringLiteral(
"m" )] = !std::isnan( point->
m() ) ? QVariant( point->
m() ) : QVariant( QStringLiteral(
"NaN" ) );
1410QVariantMap QgsArcGisRestUtils::multiPointToJson(
const QgsMultiPoint *multiPoint )
1413 const bool hasZ = multiPoint->
is3D();
1414 const bool hasM = multiPoint->
isMeasure();
1415 data[QStringLiteral(
"hasM" )] = hasM;
1416 data[QStringLiteral(
"hasZ" )] = hasZ;
1418 QVariantList pointsList;
1420 pointsList.reserve( size );
1422 QVariantList pointList;
1423 for (
int i = 0; i < size; ++i )
1428 pointList.append( point->
x() );
1429 pointList.append( point->
y() );
1431 pointList.append( point->
z() );
1432 if ( hasM && !std::isnan( point->
m() ) )
1433 pointList.append( point->
m() );
1435 pointsList.push_back( pointList );
1438 data[QStringLiteral(
"points" )] = pointsList;
1442QVariantList QgsArcGisRestUtils::lineStringToJsonPath(
const QgsLineString *line )
1444 const bool hasZ = line->
is3D();
1447 QVariantList pointsList;
1449 pointsList.reserve( size );
1451 QVariantList pointList;
1452 const double *xData = line->
xData();
1453 const double *yData = line->
yData();
1454 const double *zData = hasZ ? line->
zData() :
nullptr;
1455 const double *mData = hasM ? line->
mData() :
nullptr;
1457 for (
int i = 0; i < size; ++i )
1460 pointList.append( *xData++ );
1461 pointList.append( *yData++ );
1464 pointList.append( *zData++ );
1466 if ( hasM && !std::isnan( *mData ) )
1467 pointList.append( *mData );
1471 pointsList.push_back( pointList );
1476QVariantList QgsArcGisRestUtils::curveToJsonCurve(
const QgsCurve *curve,
bool includeStart )
1478 const bool hasZ = curve->
is3D();
1481 auto pointToList = [hasZ, hasM](
const QgsPoint & point ) -> QVariantList
1483 QVariantList pointList;
1485 pointList.append( point.
x() );
1486 pointList.append( point.
y() );
1489 pointList.append( point.
z() );
1491 if ( hasM && !std::isnan( point.
m() ) )
1492 pointList.append( point.
m() );
1502 QVariantList part = lineStringToJsonPath( qgsgeometry_cast< const QgsLineString *>( curve ) );
1503 if ( !part.isEmpty() && !includeStart )
1511 const QgsCircularString *circularString = qgsgeometry_cast<const QgsCircularString * >( curve );
1512 if ( includeStart && !circularString->
isEmpty() )
1514 res.push_back( pointToList( circularString->
startPoint() ) );
1517 const int size = circularString->
numPoints();
1518 for (
int i = 1; i + 1 < size; i += 2 )
1521 QVariantMap curvePart;
1522 QVariantList curveList;
1523 curveList.push_back( pointToList( circularString->
pointN( i + 1 ) ) );
1525 curveList.push_back( pointToList( circularString->
pointN( i ) ) );
1527 curvePart.insert( QStringLiteral(
"c" ), curveList );
1528 res.push_back( curvePart );
1535 const QgsCompoundCurve *compoundCurve = qgsgeometry_cast<const QgsCompoundCurve * >( curve );
1537 const int size = compoundCurve->
nCurves();
1538 for (
int i = 0; i < size; ++i )
1541 res.append( curveToJsonCurve( subCurve, i == 0 ) );
1552QVariantMap QgsArcGisRestUtils::lineStringToJson(
const QgsLineString *line )
1555 const bool hasZ = line->
is3D();
1557 data[QStringLiteral(
"hasM" )] = hasM;
1558 data[QStringLiteral(
"hasZ" )] = hasZ;
1560 const QVariantList pointsList = lineStringToJsonPath( line );
1562 QVariantList pointsData = QVariantList();
1563 pointsData.push_back( pointsList );
1564 data[QStringLiteral(
"paths" )] = pointsData;
1569QVariantMap QgsArcGisRestUtils::curveToJson(
const QgsCurve *curve )
1572 const bool hasZ = curve->
is3D();
1574 data[QStringLiteral(
"hasM" )] = hasM;
1575 data[QStringLiteral(
"hasZ" )] = hasZ;
1577 const QVariantList curveList = curveToJsonCurve( curve,
true );
1579 QVariantList curveData = QVariantList();
1580 curveData.push_back( curveList );
1581 data[QStringLiteral(
"curvePaths" )] = curveData;
1586QVariantMap QgsArcGisRestUtils::multiLineStringToJson(
const QgsMultiLineString *multiLine )
1589 const bool hasZ = multiLine->
is3D();
1590 const bool hasM = multiLine->
isMeasure();
1591 data[QStringLiteral(
"hasM" )] = hasM;
1592 data[QStringLiteral(
"hasZ" )] = hasZ;
1596 paths.reserve( size );
1597 for (
int i = 0; i < size; ++i )
1600 paths.push_back( lineStringToJsonPath( line ) );
1603 data[QStringLiteral(
"paths" )] = paths;
1607QVariantMap QgsArcGisRestUtils::multiCurveToJson(
const QgsMultiCurve *multiCurve )
1610 const bool hasZ = multiCurve->
is3D();
1611 const bool hasM = multiCurve->
isMeasure();
1612 data[QStringLiteral(
"hasM" )] = hasM;
1613 data[QStringLiteral(
"hasZ" )] = hasZ;
1617 paths.reserve( size );
1618 for (
int i = 0; i < size; ++i )
1621 paths.push_back( curveToJsonCurve( curve,
true ) );
1624 data[QStringLiteral(
"curvePaths" )] = paths;
1628QVariantList QgsArcGisRestUtils::polygonToJsonRings(
const QgsPolygon *polygon )
1632 rings.reserve( numInteriorRings + 1 );
1640 rings.push_back( lineStringToJsonPath( exterior ) );
1645 std::unique_ptr< QgsLineString > reversed( exterior->
reversed() );
1646 rings.push_back( lineStringToJsonPath( reversed.get() ) );
1654 for (
int i = 0; i < numInteriorRings; ++i )
1661 rings.push_back( lineStringToJsonPath( ring ) );
1666 std::unique_ptr< QgsLineString > reversed( ring->
reversed() );
1667 rings.push_back( lineStringToJsonPath( reversed.get() ) );
1677QVariantList QgsArcGisRestUtils::curvePolygonToJsonRings(
const QgsCurvePolygon *polygon )
1681 rings.reserve( numInteriorRings + 1 );
1683 if (
const QgsCurve *exterior = qgsgeometry_cast< const QgsCurve * >( polygon->
exteriorRing() ) )
1689 rings.push_back( curveToJsonCurve( exterior,
true ) );
1694 std::unique_ptr< QgsCurve > reversed( exterior->
reversed() );
1695 rings.push_back( curveToJsonCurve( reversed.get(),
true ) );
1703 for (
int i = 0; i < numInteriorRings; ++i )
1710 rings.push_back( curveToJsonCurve( ring,
true ) );
1715 std::unique_ptr< QgsCurve > reversed( ring->
reversed() );
1716 rings.push_back( curveToJsonCurve( reversed.get(),
true ) );
1726QVariantMap QgsArcGisRestUtils::polygonToJson(
const QgsPolygon *polygon )
1729 const bool hasZ = polygon->
is3D();
1731 data[QStringLiteral(
"hasM" )] = hasM;
1732 data[QStringLiteral(
"hasZ" )] = hasZ;
1733 data[QStringLiteral(
"rings" )] = polygonToJsonRings( polygon );
1737QVariantMap QgsArcGisRestUtils::curvePolygonToJson(
const QgsCurvePolygon *polygon )
1740 const bool hasZ = polygon->
is3D();
1742 data[QStringLiteral(
"hasM" )] = hasM;
1743 data[QStringLiteral(
"hasZ" )] = hasZ;
1744 data[QStringLiteral(
"curveRings" )] = curvePolygonToJsonRings( polygon );
1748QVariantMap QgsArcGisRestUtils::multiPolygonToJson(
const QgsMultiPolygon *multiPolygon )
1751 const bool hasZ = multiPolygon->
is3D();
1752 const bool hasM = multiPolygon->
isMeasure();
1753 data[QStringLiteral(
"hasM" )] = hasM;
1754 data[QStringLiteral(
"hasZ" )] = hasZ;
1758 for (
int i = 0; i < size; ++i )
1761 rings.append( polygonToJsonRings( polygon ) );
1764 data[QStringLiteral(
"rings" )] = rings;
1768QVariantMap QgsArcGisRestUtils::multiSurfaceToJson(
const QgsMultiSurface *multiSurface )
1771 const bool hasZ = multiSurface->
is3D();
1772 const bool hasM = multiSurface->
isMeasure();
1773 data[QStringLiteral(
"hasM" )] = hasM;
1774 data[QStringLiteral(
"hasZ" )] = hasZ;
1778 for (
int i = 0; i < size; ++i )
1784 rings.append( curvePolygonToJsonRings( polygon ) );
1787 data[QStringLiteral(
"curveRings" )] = rings;
1798 if ( !authid.isEmpty() )
1800 const thread_local QRegularExpression rxAuthid( QStringLiteral(
"(\\w+):(\\d+)" ) );
1801 const QRegularExpressionMatch match = rxAuthid.match( authid );
1802 if ( match.hasMatch()
1804 ( match.captured( 1 ).compare( QLatin1String(
"EPSG" ), Qt::CaseInsensitive ) == 0 )
1805 || ( match.captured( 1 ).compare( QLatin1String(
"ESRI" ), Qt::CaseInsensitive ) == 0 )
1809 const QString wkid = match.captured( 2 );
1810 res.insert( QStringLiteral(
"wkid" ), wkid );
1829 QVariantMap attributes;
1831 for (
const QgsField &field : fields )
1836 if ( !attributes.isEmpty() )
1838 res.insert( QStringLiteral(
"attributes" ), attributes );
1848 switch ( expectedType )
1850 case QMetaType::Type::QString:
1852 const QString escaped = variant.toString().replace(
'\\', QLatin1String(
"\\\\" ) ).replace(
'"', QLatin1String(
"\\\"" ) );
1853 return QString( QUrl::toPercentEncoding( escaped,
"'" ) );
1856 case QMetaType::Type::QDateTime:
1857 case QMetaType::Type::QDate:
1859 switch ( variant.userType() )
1861 case QMetaType::Type::QDateTime:
1862 return variant.toDateTime().toMSecsSinceEpoch();
1864 case QMetaType::Type::QDate:
1866 if ( context.
timeZone().isValid() )
1867 return QDateTime( variant.toDate(), QTime( 0, 0, 0 ), context.
timeZone() ).toMSecsSinceEpoch();
1869 return QDateTime( variant.toDate(), QTime( 0, 0, 0 ) ).toMSecsSinceEpoch();
1884 res.insert( QStringLiteral(
"name" ), field.
name() );
1887 switch ( field.
type() )
1889 case QMetaType::Type::LongLong:
1890 fieldType = QStringLiteral(
"esriFieldTypeInteger" );
1893 case QMetaType::Type::Int:
1894 fieldType = QStringLiteral(
"esriFieldTypeSmallInteger" );
1897 case QMetaType::Type::Double:
1898 fieldType = QStringLiteral(
"esriFieldTypeDouble" );
1901 case QMetaType::Type::QString:
1902 fieldType = QStringLiteral(
"esriFieldTypeString" );
1905 case QMetaType::Type::QDateTime:
1906 case QMetaType::Type::QDate:
1907 fieldType = QStringLiteral(
"esriFieldTypeDate" );
1910 case QMetaType::Type::QByteArray:
1911 fieldType = QStringLiteral(
"esriFieldTypeBlob" );
1916 fieldType = QStringLiteral(
"esriFieldTypeString" );
1919 res.insert( QStringLiteral(
"type" ), fieldType );
1921 if ( !field.
alias().isEmpty() )
1922 res.insert( QStringLiteral(
"alias" ), field.
alias() );
1926 res.insert( QStringLiteral(
"nullable" ), !notNullable );
1929 res.insert( QStringLiteral(
"editable" ),
true );
1936 if ( type.compare( QLatin1String(
"FeatureServer" ), Qt::CaseInsensitive ) == 0 )
1938 else if ( type.compare( QLatin1String(
"MapServer" ), Qt::CaseInsensitive ) == 0 )
1940 else if ( type.compare( QLatin1String(
"ImageServer" ), Qt::CaseInsensitive ) == 0 )
1942 else if ( type.compare( QLatin1String(
"GlobeServer" ), Qt::CaseInsensitive ) == 0 )
1944 else if ( type.compare( QLatin1String(
"GPServer" ), Qt::CaseInsensitive ) == 0 )
1946 else if ( type.compare( QLatin1String(
"GeocodeServer" ), 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.
@ 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)
@ 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.
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.
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.
Circular string geometry type.
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.
QgsClassificationCustom is a dummy implementation of QgsClassification which does not compute any bre...
QgsClassificationEqualInterval is an implementation of QgsClassificationMethod for equal intervals.
Implementation of a fixed interval classification.
QgsClassificationJenks is an implementation of QgsClassificationMethod for natural breaks based on Je...
QgsClassificationQuantile is an implementation of QgsClassificationMethod based on quantiles.
QgsClassificationCustom is an implementation of QgsClassificationMethod based on standard deviation.
Compound curve geometry type.
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.
This class 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.
Class for 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)
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.
HorizontalAnchorPoint
Symbol horizontal anchor points.
@ Right
Align to right side of symbol.
@ HCenter
Align to horizontal center of symbol.
@ Left
Align to left side of symbol.
VerticalAnchorPoint
Symbol vertical anchor points.
@ VCenter
Align to vertical center of symbol.
@ Bottom
Align to bottom of symbol.
@ Top
Align to top of symbol.
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.
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.
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 bool hasZ(Qgis::WkbType type)
Tests whether a WKB type contains the z-dimension.
static 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)
QList< QgsRendererCategory > QgsCategoryList
QList< QgsGradientStop > QgsGradientStopsList
List of gradient stops.
#define QgsDebugError(str)
QList< QgsSymbolLayer * > QgsSymbolLayerList
const QgsCoordinateReferenceSystem & crs