52#include <QRegularExpression>
56#include "moc_qgsarcgisrestutils.cpp"
58using namespace Qt::StringLiterals;
62 if ( esriFieldType ==
"esriFieldTypeInteger"_L1 )
63 return QMetaType::Type::LongLong;
64 if ( esriFieldType ==
"esriFieldTypeSmallInteger"_L1 )
65 return QMetaType::Type::Int;
66 if ( esriFieldType ==
"esriFieldTypeDouble"_L1 )
67 return QMetaType::Type::Double;
68 if ( esriFieldType ==
"esriFieldTypeSingle"_L1 )
69 return QMetaType::Type::Double;
70 if ( esriFieldType ==
"esriFieldTypeString"_L1 )
71 return QMetaType::Type::QString;
72 if ( esriFieldType ==
"esriFieldTypeDate"_L1 )
73 return QMetaType::Type::QDateTime;
74 if ( esriFieldType ==
"esriFieldTypeGeometry"_L1 )
75 return QMetaType::Type::UnknownType;
76 if ( esriFieldType ==
"esriFieldTypeOID"_L1 )
77 return QMetaType::Type::LongLong;
78 if ( esriFieldType ==
"esriFieldTypeBlob"_L1 )
79 return QMetaType::Type::QByteArray;
80 if ( esriFieldType ==
"esriFieldTypeGlobalID"_L1 )
81 return QMetaType::Type::QString;
82 if ( esriFieldType ==
"esriFieldTypeRaster"_L1 )
83 return QMetaType::Type::QByteArray;
84 if ( esriFieldType ==
"esriFieldTypeGUID"_L1 )
85 return QMetaType::Type::QString;
86 if ( esriFieldType ==
"esriFieldTypeXML"_L1 )
87 return QMetaType::Type::QString;
88 return QMetaType::Type::UnknownType;
94 if ( esriGeometryType ==
"esriGeometryNull"_L1 )
96 else if ( esriGeometryType ==
"esriGeometryPoint"_L1 )
98 else if ( esriGeometryType ==
"esriGeometryMultipoint"_L1 )
100 else if ( esriGeometryType ==
"esriGeometryPolyline"_L1 )
102 else if ( esriGeometryType ==
"esriGeometryPolygon"_L1 )
104 else if ( esriGeometryType ==
"esriGeometryEnvelope"_L1 )
124std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertPoint(
const QVariantList &coordList,
Qgis::WkbType pointType )
126 const int nCoords =
static_cast< int >( coordList.size() );
129 bool xok =
false, yok =
false;
130 const double x = coordList[0].toDouble( &xok );
131 const double y = coordList[1].toDouble( &yok );
135 const double z = hasZ && nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
138 const double m =
QgsWkbTypes::hasM( pointType ) && ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
139 return std::make_unique< QgsPoint >( pointType, x, y, z, m );
142std::unique_ptr< QgsCircularString > QgsArcGisRestUtils::convertCircularString(
const QVariantMap &curveData,
Qgis::WkbType pointType,
const QgsPoint &startPoint )
144 const QVariantList coordsList = curveData[u
"c"_s].toList();
145 if ( coordsList.isEmpty() )
147 const int coordsListSize =
static_cast< int >( coordsList.size() );
149 QVector<QgsPoint> points;
150 points.reserve( coordsListSize + 1 );
151 points.append( startPoint );
153 for (
int i = 0; i < coordsListSize - 1; )
157 std::unique_ptr< QgsPoint > endPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
161 std::unique_ptr< QgsPoint > interiorPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
162 if ( !interiorPoint )
165 points << *interiorPoint;
168 auto curve = std::make_unique< QgsCircularString>();
169 curve->setPoints( points );
173std::unique_ptr< QgsCurve > QgsArcGisRestUtils::convertCompoundCurve(
const QVariantList &curvesList,
Qgis::WkbType pointType )
176 auto compoundCurve = std::make_unique< QgsCompoundCurve >();
178 QVector< double > lineX;
179 QVector< double > lineY;
180 QVector< double > lineZ;
181 QVector< double > lineM;
182 const int maxCurveListSize =
static_cast< int >( curvesList.size() );
183 lineX.resize( maxCurveListSize );
184 lineY.resize( maxCurveListSize );
188 lineZ.resize( maxCurveListSize );
191 lineM.resize( maxCurveListSize );
193 double *outLineX = lineX.data();
194 double *outLineY = lineY.data();
195 double *outLineZ = lineZ.data();
196 double *outLineM = lineM.data();
197 int actualLineSize = 0;
202 int curveListIndex = 0;
203 for (
const QVariant &curveData : curvesList )
205 if ( curveData.userType() == QMetaType::Type::QVariantList )
207 const QVariantList coordList = curveData.toList();
208 const int nCoords =
static_cast< int >( coordList.size() );
212 const double x = coordList[0].toDouble( &xok );
213 const double y = coordList[1].toDouble( &yok );
222 *outLineZ++ = nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
228 *outLineM++ = ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
231 else if ( curveData.userType() == QMetaType::Type::QVariantMap )
234 QgsPoint lastLineStringPoint;
235 if ( actualLineSize > 0 )
238 = QgsPoint( lineX.at( actualLineSize - 1 ), lineY.at( actualLineSize - 1 ), hasZ ? lineZ.at( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN(), 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 );
290 const QgsPoint finalCurveEndPoint = finalCurve->
endPoint();
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<QgsLineString> QgsArcGisRestUtils::convertLineString(
const QVariantList &curvesList,
Qgis::WkbType pointType )
316 auto linestring = std::make_unique< QgsLineString >();
318 QVector< double > lineX;
319 QVector< double > lineY;
320 QVector< double > lineZ;
321 QVector< double > lineM;
322 const int maxCurveListSize =
static_cast< int >( curvesList.size() );
323 lineX.resize( maxCurveListSize );
324 lineY.resize( maxCurveListSize );
328 lineZ.resize( maxCurveListSize );
331 lineM.resize( maxCurveListSize );
333 double *outLineX = lineX.data();
334 double *outLineY = lineY.data();
335 double *outLineZ = lineZ.data();
336 double *outLineM = lineM.data();
341 int actualLineSize = 0;
342 for (
const QVariant &curveData : curvesList )
344 if ( curveData.userType() == QMetaType::Type::QVariantList )
346 const QVariantList coordList = curveData.toList();
347 const int nCoords =
static_cast< int >( coordList.size() );
351 const double x = coordList[0].toDouble( &xok );
352 const double y = coordList[1].toDouble( &yok );
361 *outLineZ++ = nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
367 *outLineM++ = ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
372 QgsDebugError( u
"Found unexpected value when parsing ESRI json line string. Expected list, got %1"_s.arg( curveData.metaType().name() ) );
377 if ( actualLineSize == 0 )
380 lineX.resize( actualLineSize );
381 lineY.resize( actualLineSize );
383 lineZ.resize( actualLineSize );
385 lineM.resize( actualLineSize );
386 return std::make_unique< QgsLineString>( lineX, lineY, lineZ, lineM );
389std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertGeometryPoint(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
392 bool xok =
false, yok =
false;
393 double x = geometryData[u
"x"_s].toDouble( &xok );
394 double y = geometryData[u
"y"_s].toDouble( &yok );
397 double z = geometryData[u
"z"_s].toDouble();
398 double m = geometryData[u
"m"_s].toDouble();
399 return std::make_unique< QgsPoint >( pointType, x, y, z, m );
402std::unique_ptr< QgsMultiPoint > QgsArcGisRestUtils::convertMultiPoint(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
405 const QVariantList coordsList = geometryData[u
"points"_s].toList();
407 auto multiPoint = std::make_unique< QgsMultiPoint >();
408 multiPoint->reserve(
static_cast< int >( coordsList.size() ) );
409 for (
const QVariant &coordData : coordsList )
411 const QVariantList coordList = coordData.toList();
412 std::unique_ptr< QgsPoint > p = convertPoint( coordList, pointType );
417 multiPoint->addGeometry( p.release() );
422 std::unique_ptr< QgsPoint > p = convertGeometryPoint( geometryData, pointType );
424 multiPoint->addGeometry( p.release() );
426 if ( multiPoint->numGeometries() == 0 )
434std::unique_ptr< QgsMultiCurve > QgsArcGisRestUtils::convertGeometryPolyline(
const QVariantMap &geometryData,
Qgis::WkbType pointType,
bool allowCurves )
437 QVariantList pathsList;
438 if ( geometryData[u
"paths"_s].isValid() )
439 pathsList = geometryData[u
"paths"_s].toList();
440 else if ( geometryData[u
"curvePaths"_s].isValid() )
441 pathsList = geometryData[u
"curvePaths"_s].toList();
442 if ( pathsList.isEmpty() )
444 std::unique_ptr< QgsMultiCurve > multiCurve = allowCurves ? std::make_unique< QgsMultiCurve >() : std::make_unique< QgsMultiLineString >();
445 multiCurve->reserve(
static_cast< int >( pathsList.size() ) );
446 for (
const QVariant &pathData : std::as_const( pathsList ) )
448 std::unique_ptr< QgsCurve > curve = allowCurves ? convertCompoundCurve( pathData.toList(), pointType ) : convertLineString( pathData.toList(), pointType );
453 multiCurve->addGeometry( curve.release() );
458std::unique_ptr< QgsMultiSurface > QgsArcGisRestUtils::convertGeometryPolygon(
const QVariantMap &geometryData,
Qgis::WkbType pointType,
bool allowCurves )
461 QVariantList ringsList;
462 if ( geometryData[u
"rings"_s].isValid() )
463 ringsList = geometryData[u
"rings"_s].toList();
464 else if ( geometryData[u
"ringPaths"_s].isValid() )
465 ringsList = geometryData[u
"ringPaths"_s].toList();
466 if ( ringsList.isEmpty() )
469 QList< QgsCurve * > curves;
470 for (
int i = 0, n =
static_cast< int >( ringsList.size() ); i < n; ++i )
472 std::unique_ptr< QgsCurve > curve = allowCurves ? convertCompoundCurve( ringsList[i].toList(), pointType ) : convertLineString( ringsList[i].toList(), pointType );
477 curves.append( curve.release() );
479 if ( curves.count() == 0 )
482 std::unique_ptr< QgsMultiSurface > result = allowCurves ? std::make_unique< QgsMultiSurface >() : std::make_unique< QgsMultiPolygon >();
483 if ( curves.count() == 1 )
486 std::unique_ptr< QgsCurvePolygon > newPolygon = allowCurves ? std::make_unique< QgsCurvePolygon >() : std::make_unique< QgsPolygon >();
487 newPolygon->setExteriorRing( curves.takeAt( 0 ) );
488 result->addGeometry( newPolygon.release() );
492 std::sort( curves.begin(), curves.end(), [](
const QgsCurve *a,
const QgsCurve *b ) ->
bool {
495 a->sumUpArea( a_area );
496 b->sumUpArea( b_area );
497 return std::abs( a_area ) > std::abs( b_area );
499 result->reserve(
static_cast< int >( curves.size() ) );
500 while ( !curves.isEmpty() )
502 QgsCurve *exterior = curves.takeFirst();
503 QgsCurvePolygon *newPolygon = allowCurves ? new QgsCurvePolygon() : new QgsPolygon();
504 newPolygon->setExteriorRing( exterior );
505 std::unique_ptr<QgsGeometryEngine> engine( QgsGeometry::createGeometryEngine( newPolygon ) );
506 engine->prepareGeometry();
508 QMutableListIterator< QgsCurve * > it( curves );
509 while ( it.hasNext() )
511 QgsCurve *curve = it.next();
512 QgsRectangle boundingBox = newPolygon->boundingBox();
513 if ( boundingBox.intersects( curve->boundingBox() ) )
515 QgsPoint point = curve->startPoint();
516 if ( engine->contains( &point ) )
518 newPolygon->addInteriorRing( curve );
520 engine.reset( QgsGeometry::createGeometryEngine( newPolygon ) );
521 engine->prepareGeometry();
525 result->addGeometry( newPolygon );
527 if ( result->numGeometries() == 0 )
533std::unique_ptr< QgsPolygon > QgsArcGisRestUtils::convertEnvelope(
const QVariantMap &geometryData )
536 bool xminOk =
false, yminOk =
false, xmaxOk =
false, ymaxOk =
false;
537 double xmin = geometryData[u
"xmin"_s].toDouble( &xminOk );
538 double ymin = geometryData[u
"ymin"_s].toDouble( &yminOk );
539 double xmax = geometryData[u
"xmax"_s].toDouble( &xmaxOk );
540 double ymax = geometryData[u
"ymax"_s].toDouble( &ymaxOk );
541 if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk )
543 auto ext = std::make_unique< QgsLineString>();
544 ext->addVertex( QgsPoint( xmin, ymin ) );
545 ext->addVertex( QgsPoint( xmax, ymin ) );
546 ext->addVertex( QgsPoint( xmax, ymax ) );
547 ext->addVertex( QgsPoint( xmin, ymax ) );
548 ext->addVertex( QgsPoint( xmin, ymin ) );
549 auto poly = std::make_unique< QgsPolygon >();
550 poly->setExteriorRing( ext.release() );
555 const QVariantMap &geometryData,
const QString &esriGeometryType,
bool readM,
bool readZ,
bool allowCurves,
QgsCoordinateReferenceSystem *crs
565 if ( esriGeometryType ==
"esriGeometryNull"_L1 )
567 else if ( esriGeometryType ==
"esriGeometryPoint"_L1 )
568 return convertGeometryPoint( geometryData, pointType );
569 else if ( esriGeometryType ==
"esriGeometryMultipoint"_L1 )
570 return convertMultiPoint( geometryData, pointType );
571 else if ( esriGeometryType ==
"esriGeometryPolyline"_L1 )
572 return convertGeometryPolyline( geometryData, pointType, allowCurves );
573 else if ( esriGeometryType ==
"esriGeometryPolygon"_L1 )
574 return convertGeometryPolygon( geometryData, pointType, allowCurves );
575 else if ( esriGeometryType ==
"esriGeometryEnvelope"_L1 )
576 return convertEnvelope( geometryData );
599 QString spatialReference = spatialReferenceMap[u
"latestWkid"_s].toString();
600 if ( spatialReference.isEmpty() )
601 spatialReference = spatialReferenceMap[u
"wkid"_s].toString();
604 if ( !spatialReference.isEmpty() )
613 else if ( !spatialReferenceMap[u
"wkt"_s].toString().isEmpty() )
616 crs.
createFromWkt( spatialReferenceMap[u
"wkt"_s].toString() );
638 if ( labelingData.empty() )
645 for (
const QVariant &lbl : labelingData )
647 const QVariantMap labeling = lbl.toMap();
652 const QString placement = labeling.value( u
"labelPlacement"_s ).toString();
653 if ( placement ==
"esriServerPointLabelPlacementAboveCenter"_L1 )
658 else if ( placement ==
"esriServerPointLabelPlacementBelowCenter"_L1 )
663 else if ( placement ==
"esriServerPointLabelPlacementCenterCenter"_L1 )
668 else if ( placement ==
"esriServerPointLabelPlacementAboveLeft"_L1 )
673 else if ( placement ==
"esriServerPointLabelPlacementBelowLeft"_L1 )
678 else if ( placement ==
"esriServerPointLabelPlacementCenterLeft"_L1 )
683 else if ( placement ==
"esriServerPointLabelPlacementAboveRight"_L1 )
688 else if ( placement ==
"esriServerPointLabelPlacementBelowRight"_L1 )
693 else if ( placement ==
"esriServerPointLabelPlacementCenterRight"_L1 )
698 else if ( placement ==
"esriServerLinePlacementAboveAfter"_L1 || placement ==
"esriServerLinePlacementAboveStart"_L1 || placement ==
"esriServerLinePlacementAboveAlong"_L1 )
703 else if ( placement ==
"esriServerLinePlacementBelowAfter"_L1 || placement ==
"esriServerLinePlacementBelowStart"_L1 || placement ==
"esriServerLinePlacementBelowAlong"_L1 )
708 else if ( placement ==
"esriServerLinePlacementCenterAfter"_L1 || placement ==
"esriServerLinePlacementCenterStart"_L1 || placement ==
"esriServerLinePlacementCenterAlong"_L1 )
713 else if ( placement ==
"esriServerPolygonPlacementAlwaysHorizontal"_L1 )
718 const double minScale = labeling.value( u
"minScale"_s ).toDouble();
719 const double maxScale = labeling.value( u
"maxScale"_s ).toDouble();
721 QVariantMap symbol = labeling.value( u
"symbol"_s ).toMap();
723 const double haloSize = symbol.value( u
"haloSize"_s ).toDouble();
734 const QString fontFamily = symbol.value( u
"font"_s ).toMap().value( u
"family"_s ).toString();
735 const QString fontStyle = symbol.value( u
"font"_s ).toMap().value( u
"style"_s ).toString();
736 const QString fontWeight = symbol.value( u
"font"_s ).toMap().value( u
"weight"_s ).toString();
737 const int fontSize = symbol.value( u
"font"_s ).toMap().value( u
"size"_s ).toInt();
738 QFont font( fontFamily, fontSize );
739 font.setStyleName( fontStyle );
740 font.setWeight( fontWeight ==
"bold"_L1 ? QFont::Bold : QFont::Normal );
748 QString where = labeling.value( u
"where"_s ).toString();
762 return std::make_unique< QgsRuleBasedLabeling >( root );
767 const QString type = rendererData.value( u
"type"_s ).toString();
768 if ( type ==
"simple"_L1 )
770 const QVariantMap symbolProps = rendererData.value( u
"symbol"_s ).toMap();
771 std::unique_ptr< QgsSymbol > symbol(
convertSymbol( symbolProps ) );
773 return std::make_unique< QgsSingleSymbolRenderer >( symbol.release() );
777 else if ( type ==
"uniqueValue"_L1 )
779 const QString field1 = rendererData.value( u
"field1"_s ).toString();
780 const QString field2 = rendererData.value( u
"field2"_s ).toString();
781 const QString field3 = rendererData.value( u
"field3"_s ).toString();
783 if ( !field2.isEmpty() || !field3.isEmpty() )
785 const QString delimiter = rendererData.value( u
"fieldDelimiter"_s ).toString();
786 if ( !field3.isEmpty() )
788 attribute = u
"concat(\"%1\",'%2',\"%3\",'%4',\"%5\")"_s.arg( field1, delimiter, field2, delimiter, field3 );
792 attribute = u
"concat(\"%1\",'%2',\"%3\")"_s.arg( field1, delimiter, field2 );
800 const QVariantList categories = rendererData.value( u
"uniqueValueInfos"_s ).toList();
802 for (
const QVariant &category : categories )
804 const QVariantMap categoryData = category.toMap();
805 const QString value = categoryData.value( u
"value"_s ).toString();
806 const QString label = categoryData.value( u
"label"_s ).toString();
814 std::unique_ptr< QgsSymbol > defaultSymbol(
convertSymbol( rendererData.value( u
"defaultSymbol"_s ).toMap() ) );
817 categoryList.append(
QgsRendererCategory( QVariant(), defaultSymbol.release(), rendererData.value( u
"defaultLabel"_s ).toString() ) );
820 if ( categoryList.empty() )
823 return std::make_unique< QgsCategorizedSymbolRenderer >( attribute, categoryList );
825 else if ( type ==
"classBreaks"_L1 )
827 const QString attrName = rendererData.value( u
"field"_s ).toString();
829 const QVariantList classBreakInfos = rendererData.value( u
"classBreakInfos"_s ).toList();
830 const QVariantMap authoringInfo = rendererData.value( u
"authoringInfo"_s ).toMap();
831 QVariantMap symbolData;
833 QString esriMode = authoringInfo.value( u
"classificationMethod"_s ).toString();
834 if ( esriMode.isEmpty() )
836 esriMode = rendererData.value( u
"classificationMethod"_s ).toString();
839 if ( !classBreakInfos.isEmpty() )
841 symbolData = classBreakInfos.at( 0 ).toMap().value( u
"symbol"_s ).toMap();
847 const double transparency = rendererData.value( u
"transparency"_s ).toDouble();
848 const double opacity = ( 100.0 - transparency ) / 100.0;
849 symbol->setOpacity( opacity );
851 const QVariantList visualVariablesData = rendererData.value( u
"visualVariables"_s ).toList();
853 for (
const QVariant &visualVariable : visualVariablesData )
855 const QVariantMap visualVariableData = visualVariable.toMap();
856 const QString variableType = visualVariableData.value( u
"type"_s ).toString();
857 if ( variableType ==
"sizeInfo"_L1 )
861 else if ( variableType ==
"colorInfo"_L1 )
863 const QVariantList stops = visualVariableData.value( u
"stops"_s ).toList();
864 if ( stops.size() < 2 )
869 const double minValue = stops.front().toMap().value( u
"value"_s ).toDouble( &ok );
872 const QColor minColor =
convertColor( stops.front().toMap().value( u
"color"_s ) );
874 const double maxValue = stops.back().toMap().value( u
"value"_s ).toDouble( &ok );
877 const QColor maxColor =
convertColor( stops.back().toMap().value( u
"color"_s ) );
880 for (
int i = 1; i < stops.size() - 1; ++i )
882 const QVariantMap stopData = stops.at( i ).toMap();
883 const double breakpoint = stopData.value( u
"value"_s ).toDouble();
884 const double scaledBreakpoint = ( breakpoint - minValue ) / ( maxValue - minValue );
885 const QColor fillColor =
convertColor( stopData.value( u
"color"_s ) );
887 gradientStops.append(
QgsGradientStop( scaledBreakpoint, fillColor ) );
890 auto colorRamp = std::make_unique< QgsGradientColorRamp >( minColor, maxColor,
false, gradientStops );
894 for (
int layer = 0; layer < symbol->symbolLayerCount(); ++layer )
899 return std::make_unique< QgsSingleSymbolRenderer >( symbol.release() );
903 QgsDebugError( u
"ESRI visualVariable type %1 is not currently supported"_s.arg( variableType ) );
907 double lastValue = rendererData.value( u
"minValue"_s ).toDouble();
909 auto graduatedRenderer = std::make_unique< QgsGraduatedSymbolRenderer >( attrName );
911 graduatedRenderer->setSourceSymbol( symbol.release() );
913 if ( esriMode ==
"esriClassifyDefinedInterval"_L1 )
916 graduatedRenderer->setClassificationMethod( method );
918 else if ( esriMode ==
"esriClassifyEqualInterval"_L1 )
921 graduatedRenderer->setClassificationMethod( method );
923 else if ( esriMode ==
"esriClassifyGeometricalInterval"_L1 )
926 graduatedRenderer->setClassificationMethod( method );
928 else if ( esriMode ==
"esriClassifyManual"_L1 )
931 graduatedRenderer->setClassificationMethod( method );
933 else if ( esriMode ==
"esriClassifyNaturalBreaks"_L1 )
936 graduatedRenderer->setClassificationMethod( method );
938 else if ( esriMode ==
"esriClassifyQuantile"_L1 )
941 graduatedRenderer->setClassificationMethod( method );
943 else if ( esriMode ==
"esriClassifyStandardDeviation"_L1 )
946 graduatedRenderer->setClassificationMethod( method );
948 else if ( !esriMode.isEmpty() )
950 QgsDebugError( u
"ESRI classification mode %1 is not currently supported"_s.arg( esriMode ) );
953 for (
const QVariant &classBreakInfo : classBreakInfos )
955 const QVariantMap symbolData = classBreakInfo.toMap().value( u
"symbol"_s ).toMap();
957 double classMaxValue = classBreakInfo.toMap().value( u
"classMaxValue"_s ).toDouble();
958 const QString label = classBreakInfo.toMap().value( u
"label"_s ).toString();
967 lastValue = classMaxValue;
968 graduatedRenderer->addClass( range );
971 return graduatedRenderer;
973 else if ( type ==
"heatmap"_L1 )
978 else if ( type ==
"vectorField"_L1 )
988 QString expression = string;
991 const thread_local QRegularExpression rx1 = QRegularExpression( u
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)CONCAT(\\s|$)"_s );
992 expression = expression.replace( rx1, u
"\\4||\\5"_s );
994 const thread_local QRegularExpression rx2 = QRegularExpression( u
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)NEWLINE(\\s|$)"_s );
995 expression = expression.replace( rx2, u
"\\4'\\n'\\5"_s );
998 const thread_local QRegularExpression rx3 = QRegularExpression( u
"\"(.*?(?<!\\\\))\""_s );
999 expression = expression.replace( rx3, u
"'\\1'"_s );
1000 const thread_local QRegularExpression rx4 = QRegularExpression( u
"\\\\\""_s );
1001 expression = expression.replace( rx4, u
"\""_s );
1004 const thread_local QRegularExpression rx5 = QRegularExpression( u
"\\[([^]]*)\\]"_s );
1005 expression = expression.replace( rx5, u
"\"\\1\""_s );
1030 QDateTime dt = QDateTime::fromMSecsSinceEpoch( value.toLongLong( &ok ) );
1033 QgsDebugError( u
"Invalid value %1 for datetime"_s.arg( value.toString() ) );
1045 const QVariantMap coords = value.toMap();
1046 if ( coords.isEmpty() )
1051 const double xmin = coords.value( u
"xmin"_s ).toDouble( &ok );
1055 const double ymin = coords.value( u
"ymin"_s ).toDouble( &ok );
1059 const double xmax = coords.value( u
"xmax"_s ).toDouble( &ok );
1063 const double ymax = coords.value( u
"ymax"_s ).toDouble( &ok );
1075 return QVariantMap();
1082 return QVariantMap();
1126 return QVariantMap();
1129 return QVariantMap();
1132 return QVariantMap();
1138 res.insert( u
"spatialReference"_s,
crsToJson( crs ) );
1144QVariantMap QgsArcGisRestUtils::pointToJson(
const QgsPoint *point )
1148 data[u
"x"_s] = u
"NaN"_s;
1151 data[u
"x"_s] = point->
x();
1152 data[u
"y"_s] = point->
y();
1154 if ( point->
is3D() )
1155 data[u
"z"_s] = !std::isnan( point->
z() ) ? QVariant( point->
z() ) : QVariant( u
"NaN"_s );
1158 data[u
"m"_s] = !std::isnan( point->
m() ) ? QVariant( point->
m() ) : QVariant( u
"NaN"_s );
1163QVariantMap QgsArcGisRestUtils::multiPointToJson(
const QgsMultiPoint *multiPoint )
1166 const bool hasZ = multiPoint->
is3D();
1167 const bool hasM = multiPoint->
isMeasure();
1168 data[u
"hasM"_s] = hasM;
1169 data[u
"hasZ"_s] = hasZ;
1171 QVariantList pointsList;
1173 pointsList.reserve( size );
1175 QVariantList pointList;
1176 for (
int i = 0; i < size; ++i )
1178 const QgsPoint *point = multiPoint->
pointN( i );
1181 pointList.append( point->
x() );
1182 pointList.append( point->
y() );
1184 pointList.append( point->
z() );
1185 if ( hasM && !std::isnan( point->
m() ) )
1186 pointList.append( point->
m() );
1188 pointsList.push_back( pointList );
1191 data[u
"points"_s] = pointsList;
1195QVariantList QgsArcGisRestUtils::lineStringToJsonPath(
const QgsLineString *line )
1197 const bool hasZ = line->
is3D();
1200 QVariantList pointsList;
1202 pointsList.reserve( size );
1204 QVariantList pointList;
1205 const double *xData = line->
xData();
1206 const double *yData = line->
yData();
1207 const double *zData = hasZ ? line->
zData() :
nullptr;
1208 const double *mData = hasM ? line->
mData() :
nullptr;
1210 for (
int i = 0; i < size; ++i )
1213 pointList.append( *xData++ );
1214 pointList.append( *yData++ );
1217 pointList.append( *zData++ );
1219 if ( hasM && !std::isnan( *mData ) )
1220 pointList.append( *mData );
1224 pointsList.push_back( pointList );
1229QVariantList QgsArcGisRestUtils::curveToJsonCurve(
const QgsCurve *curve,
bool includeStart )
1231 const bool hasZ = curve->
is3D();
1234 auto pointToList = [hasZ, hasM](
const QgsPoint &point ) -> QVariantList {
1235 QVariantList pointList;
1237 pointList.append( point.
x() );
1238 pointList.append( point.
y() );
1241 pointList.append( point.
z() );
1243 if ( hasM && !std::isnan( point.
m() ) )
1244 pointList.append( point.
m() );
1255 if ( !part.isEmpty() && !includeStart )
1264 if ( includeStart && !circularString->
isEmpty() )
1266 res.push_back( pointToList( circularString->
startPoint() ) );
1269 const int size = circularString->
numPoints();
1270 for (
int i = 1; i + 1 < size; i += 2 )
1273 QVariantMap curvePart;
1274 QVariantList curveList;
1275 curveList.push_back( pointToList( circularString->
pointN( i + 1 ) ) );
1277 curveList.push_back( pointToList( circularString->
pointN( i ) ) );
1279 curvePart.insert( u
"c"_s, curveList );
1280 res.push_back( curvePart );
1289 const int size = compoundCurve->
nCurves();
1290 for (
int i = 0; i < size; ++i )
1292 const QgsCurve *subCurve = compoundCurve->
curveAt( i );
1293 res.append( curveToJsonCurve( subCurve, i == 0 ) );
1304QVariantMap QgsArcGisRestUtils::lineStringToJson(
const QgsLineString *line )
1307 const bool hasZ = line->
is3D();
1309 data[u
"hasM"_s] = hasM;
1310 data[u
"hasZ"_s] = hasZ;
1312 const QVariantList pointsList = lineStringToJsonPath( line );
1314 QVariantList pointsData = QVariantList();
1315 pointsData.push_back( pointsList );
1316 data[u
"paths"_s] = pointsData;
1321QVariantMap QgsArcGisRestUtils::curveToJson(
const QgsCurve *curve )
1324 const bool hasZ = curve->
is3D();
1326 data[u
"hasM"_s] = hasM;
1327 data[u
"hasZ"_s] = hasZ;
1329 const QVariantList curveList = curveToJsonCurve( curve,
true );
1331 QVariantList curveData = QVariantList();
1332 curveData.push_back( curveList );
1333 data[u
"curvePaths"_s] = curveData;
1338QVariantMap QgsArcGisRestUtils::multiLineStringToJson(
const QgsMultiLineString *multiLine )
1341 const bool hasZ = multiLine->
is3D();
1342 const bool hasM = multiLine->
isMeasure();
1343 data[u
"hasM"_s] = hasM;
1344 data[u
"hasZ"_s] = hasZ;
1348 paths.reserve( size );
1349 for (
int i = 0; i < size; ++i )
1351 const QgsLineString *line = multiLine->
lineStringN( i );
1352 paths.push_back( lineStringToJsonPath( line ) );
1355 data[u
"paths"_s] = paths;
1359QVariantMap QgsArcGisRestUtils::multiCurveToJson(
const QgsMultiCurve *multiCurve )
1362 const bool hasZ = multiCurve->
is3D();
1363 const bool hasM = multiCurve->
isMeasure();
1364 data[u
"hasM"_s] = hasM;
1365 data[u
"hasZ"_s] = hasZ;
1369 paths.reserve( size );
1370 for (
int i = 0; i < size; ++i )
1372 const QgsCurve *curve = multiCurve->
curveN( i );
1373 paths.push_back( curveToJsonCurve( curve,
true ) );
1376 data[u
"curvePaths"_s] = paths;
1380QVariantList QgsArcGisRestUtils::polygonToJsonRings(
const QgsPolygon *polygon )
1384 rings.reserve( numInteriorRings + 1 );
1389 switch ( exterior->orientation() )
1392 rings.push_back( lineStringToJsonPath( exterior ) );
1397 std::unique_ptr< QgsLineString > reversed( exterior->reversed() );
1398 rings.push_back( lineStringToJsonPath( reversed.get() ) );
1406 for (
int i = 0; i < numInteriorRings; ++i )
1413 rings.push_back( lineStringToJsonPath( ring ) );
1418 std::unique_ptr< QgsLineString > reversed( ring->
reversed() );
1419 rings.push_back( lineStringToJsonPath( reversed.get() ) );
1429QVariantList QgsArcGisRestUtils::curvePolygonToJsonRings(
const QgsCurvePolygon *polygon )
1433 rings.reserve( numInteriorRings + 1 );
1438 switch ( exterior->orientation() )
1441 rings.push_back( curveToJsonCurve( exterior,
true ) );
1446 std::unique_ptr< QgsCurve > reversed( exterior->reversed() );
1447 rings.push_back( curveToJsonCurve( reversed.get(),
true ) );
1455 for (
int i = 0; i < numInteriorRings; ++i )
1462 rings.push_back( curveToJsonCurve( ring,
true ) );
1467 std::unique_ptr< QgsCurve > reversed( ring->
reversed() );
1468 rings.push_back( curveToJsonCurve( reversed.get(),
true ) );
1478QVariantMap QgsArcGisRestUtils::polygonToJson(
const QgsPolygon *polygon )
1481 const bool hasZ = polygon->
is3D();
1483 data[u
"hasM"_s] = hasM;
1484 data[u
"hasZ"_s] = hasZ;
1485 data[u
"rings"_s] = polygonToJsonRings( polygon );
1489QVariantMap QgsArcGisRestUtils::curvePolygonToJson(
const QgsCurvePolygon *polygon )
1492 const bool hasZ = polygon->
is3D();
1494 data[u
"hasM"_s] = hasM;
1495 data[u
"hasZ"_s] = hasZ;
1496 data[u
"curveRings"_s] = curvePolygonToJsonRings( polygon );
1500QVariantMap QgsArcGisRestUtils::multiPolygonToJson(
const QgsMultiPolygon *multiPolygon )
1503 const bool hasZ = multiPolygon->
is3D();
1504 const bool hasM = multiPolygon->
isMeasure();
1505 data[u
"hasM"_s] = hasM;
1506 data[u
"hasZ"_s] = hasZ;
1510 for (
int i = 0; i < size; ++i )
1512 const QgsPolygon *polygon = multiPolygon->
polygonN( i );
1513 rings.append( polygonToJsonRings( polygon ) );
1516 data[u
"rings"_s] = rings;
1520QVariantMap QgsArcGisRestUtils::multiSurfaceToJson(
const QgsMultiSurface *multiSurface )
1523 const bool hasZ = multiSurface->
is3D();
1524 const bool hasM = multiSurface->
isMeasure();
1525 data[u
"hasM"_s] = hasM;
1526 data[u
"hasZ"_s] = hasZ;
1530 for (
int i = 0; i < size; ++i )
1536 rings.append( curvePolygonToJsonRings( polygon ) );
1539 data[u
"curveRings"_s] = rings;
1549 const QString authid = crs.
authid();
1550 if ( !authid.isEmpty() )
1552 const thread_local QRegularExpression rxAuthid( u
"(\\w+):(\\d+)"_s );
1553 const QRegularExpressionMatch match = rxAuthid.match( authid );
1554 if ( match.hasMatch() && ( ( match.captured( 1 ).compare(
"EPSG"_L1, Qt::CaseInsensitive ) == 0 ) || ( match.captured( 1 ).compare(
"ESRI"_L1, Qt::CaseInsensitive ) == 0 ) ) )
1556 const QString wkid = match.captured( 2 );
1557 res.insert( u
"wkid"_s, wkid );
1576 QVariantMap attributes;
1578 for (
const QgsField &field : fields )
1580 QVariant value = feature.
attribute( field.name() );
1581 if ( value.userType() == qMetaTypeId< QgsUnsetAttributeValue >() )
1592 if ( !attributes.isEmpty() )
1594 res.insert( u
"attributes"_s, attributes );
1604 switch ( expectedType )
1606 case QMetaType::Type::QString:
1608 const QString escaped = variant.toString().replace(
'\\',
"\\\\"_L1 ).replace(
'"',
"\\\""_L1 );
1609 return QString( QUrl::toPercentEncoding( escaped,
"'" ) );
1612 case QMetaType::Type::QDateTime:
1613 case QMetaType::Type::QDate:
1615 switch ( variant.userType() )
1617 case QMetaType::Type::QDateTime:
1618 return variant.toDateTime().toMSecsSinceEpoch();
1620 case QMetaType::Type::QDate:
1622 if ( context.
timeZone().isValid() )
1623 return QDateTime( variant.toDate(), QTime( 0, 0, 0 ), context.
timeZone() ).toMSecsSinceEpoch();
1625 return QDateTime( variant.toDate(), QTime( 0, 0, 0 ) ).toMSecsSinceEpoch();
1640 res.insert( u
"name"_s, field.
name() );
1643 switch ( field.
type() )
1645 case QMetaType::Type::LongLong:
1646 fieldType = u
"esriFieldTypeInteger"_s;
1649 case QMetaType::Type::Int:
1650 fieldType = u
"esriFieldTypeSmallInteger"_s;
1653 case QMetaType::Type::Double:
1654 fieldType = u
"esriFieldTypeDouble"_s;
1657 case QMetaType::Type::QString:
1658 fieldType = u
"esriFieldTypeString"_s;
1661 case QMetaType::Type::QDateTime:
1662 case QMetaType::Type::QDate:
1663 fieldType = u
"esriFieldTypeDate"_s;
1666 case QMetaType::Type::QByteArray:
1667 fieldType = u
"esriFieldTypeBlob"_s;
1672 fieldType = u
"esriFieldTypeString"_s;
1675 res.insert( u
"type"_s, fieldType );
1677 if ( !field.
alias().isEmpty() )
1678 res.insert( u
"alias"_s, field.
alias() );
1682 res.insert( u
"nullable"_s, !notNullable );
1685 res.insert( u
"editable"_s,
true );
1692 if ( type.compare(
"FeatureServer"_L1, Qt::CaseInsensitive ) == 0 )
1694 else if ( type.compare(
"MapServer"_L1, Qt::CaseInsensitive ) == 0 )
1696 else if ( type.compare(
"ImageServer"_L1, Qt::CaseInsensitive ) == 0 )
1698 else if ( type.compare(
"GlobeServer"_L1, Qt::CaseInsensitive ) == 0 )
1700 else if ( type.compare(
"GPServer"_L1, Qt::CaseInsensitive ) == 0 )
1702 else if ( type.compare(
"GeocodeServer"_L1, Qt::CaseInsensitive ) == 0 )
1704 else if ( type.compare(
"SceneServer"_L1, Qt::CaseInsensitive ) == 0 )
1712 const QStringList parts = capabilities.split(
',' );
1728 if ( pixelType.compare(
"U8"_L1, Qt::CaseInsensitive ) == 0
1729 || pixelType.compare(
"U4"_L1, Qt::CaseInsensitive ) == 0
1730 || pixelType.compare(
"U2"_L1, Qt::CaseInsensitive ) == 0
1731 || pixelType.compare(
"U1"_L1, Qt::CaseInsensitive ) == 0 )
1735 else if ( pixelType.compare(
"S8"_L1, Qt::CaseInsensitive ) == 0 )
1739 else if ( pixelType.compare(
"U16"_L1, Qt::CaseInsensitive ) == 0 )
1743 else if ( pixelType.compare(
"S16"_L1, Qt::CaseInsensitive ) == 0 )
1747 else if ( pixelType.compare(
"U32"_L1, Qt::CaseInsensitive ) == 0 )
1751 else if ( pixelType.compare(
"S32"_L1, Qt::CaseInsensitive ) == 0 )
1755 else if ( pixelType.compare(
"F32"_L1, Qt::CaseInsensitive ) == 0 )
1759 else if ( pixelType.compare(
"F64"_L1, Qt::CaseInsensitive ) == 0 )
1763 else if ( pixelType.compare(
"C64"_L1, Qt::CaseInsensitive ) == 0 )
1768 else if ( pixelType.compare(
"C128"_L1, Qt::CaseInsensitive ) == 0 )
1775 QgsDebugError( u
"Unknown pixelType: %1"_s.arg( pixelType ) );
1783 if ( bandName.isEmpty() )
1788 if ( bandName.compare(
"Red"_L1, Qt::CaseInsensitive ) == 0 )
1790 else if ( bandName.compare(
"Green"_L1, Qt::CaseInsensitive ) == 0 )
1792 else if ( bandName.compare(
"Blue"_L1, Qt::CaseInsensitive ) == 0 )
1794 else if ( bandName.compare(
"Alpha"_L1, Qt::CaseInsensitive ) == 0 )
1796 else if ( bandName.compare(
"NIR"_L1, Qt::CaseInsensitive ) == 0
1797 || bandName.compare(
"NearInfrared"_L1, Qt::CaseInsensitive ) == 0
1798 || bandName.compare(
"NearIR"_L1, Qt::CaseInsensitive ) == 0
1799 || bandName.compare(
"NarrowNIR"_L1, Qt::CaseInsensitive ) == 0 )
1801 else if ( bandName.startsWith(
"SWIR"_L1, Qt::CaseInsensitive ) )
1803 else if ( bandName.startsWith(
"VRE"_L1, Qt::CaseInsensitive ) || bandName.compare(
"RedEdge"_L1, Qt::CaseInsensitive ) == 0 )
1805 else if ( bandName.startsWith(
"Coastal"_L1, Qt::CaseInsensitive ) )
1807 else if ( bandName.startsWith(
"Pan"_L1, Qt::CaseInsensitive ) )
1809 else if ( bandName.startsWith(
"Thermal"_L1, Qt::CaseInsensitive ) || bandName.startsWith(
"TIR"_L1, Qt::CaseInsensitive ) )
1811 else if ( bandName.compare(
"Gray"_L1, Qt::CaseInsensitive ) == 0 || bandName.compare(
"Grey"_L1, Qt::CaseInsensitive ) == 0 )
1813 else if ( bandName.compare(
"Cyan"_L1, Qt::CaseInsensitive ) == 0 )
1815 else if ( bandName.compare(
"Magenta"_L1, Qt::CaseInsensitive ) == 0 )
1817 else if ( bandName.compare(
"Yellow"_L1, Qt::CaseInsensitive ) == 0 )
1819 else if ( bandName.compare(
"Black"_L1, Qt::CaseInsensitive ) == 0 )
1821 else if ( bandName.compare(
"Hue"_L1, Qt::CaseInsensitive ) == 0 )
1823 else if ( bandName.compare(
"Saturation"_L1, Qt::CaseInsensitive ) == 0 )
1825 else if ( bandName.compare(
"Lightness"_L1, Qt::CaseInsensitive ) == 0 )
1843 return std::numeric_limits<quint8>::max();
1847 return std::numeric_limits<qint8>::lowest();
1851 return std::numeric_limits<quint16>::max();
1855 return std::numeric_limits<qint16>::lowest();
1859 return std::numeric_limits<quint32>::max();
1863 return std::numeric_limits<qint32>::lowest();
1867 return std::numeric_limits<float>::quiet_NaN();
1871 return std::numeric_limits<double>::quiet_NaN();
@ 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...
ArcGisRestServiceType
Available ArcGIS REST service types.
@ GeocodeServer
GeocodeServer.
@ SceneServer
SceneServer.
@ Unknown
Other unknown/unsupported type.
@ GlobeServer
GlobeServer.
@ ImageServer
ImageServer.
@ FeatureServer
FeatureServer.
DataType
Raster data types.
@ Float32
Thirty two bit floating point (float).
@ CFloat64
Complex Float64.
@ Int16
Sixteen bit signed integer (qint16).
@ ARGB32_Premultiplied
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32_Premultiplied.
@ Int8
Eight bit signed integer (qint8) (added in QGIS 3.30).
@ UInt16
Sixteen bit unsigned integer (quint16).
@ Byte
Eight bit unsigned integer (quint8).
@ UnknownDataType
Unknown or unspecified type.
@ ARGB32
Color, alpha, red, green, blue, 4 bytes the same as QImage::Format_ARGB32.
@ Int32
Thirty two bit signed integer (qint32).
@ Float64
Sixty four bit floating point (double).
@ CFloat32
Complex Float32.
@ UInt32
Thirty two bit unsigned integer (quint32).
@ Points
Points (e.g., for font sizes).
QFlags< ArcGisRestServiceCapability > ArcGisRestServiceCapabilities
Available ArcGIS REST service capabilities.
@ TilesOnly
Service supports tiled image requests only.
@ Image
Image capabilities.
RasterColorInterpretation
Raster color interpretation.
@ NIRBand
Near-InfraRed (NIR) band [0.75 - 1.40 um].
@ GreenBand
Green band of RGBA image, or green spectral band [0.51 - 0.60 um].
@ SaturationBand
Saturation band of HLS image.
@ MagentaBand
Magenta band of CMYK image.
@ BlackBand
Black band of CMLY image.
@ AlphaBand
Alpha (0=transparent, 255=opaque).
@ SWIRBand
Short-Wavelength InfraRed (SWIR) band [1.40 - 3.00 um].
@ BlueBand
Blue band of RGBA image, or blue spectral band [0.45 - 0.53 um].
@ RedEdgeBand
Red-edge band [0.69 - 0.79 um].
@ YellowBand
Yellow band of CMYK image, or yellow spectral band [0.58 - 0.62 um].
@ CyanBand
Cyan band of CMYK image.
@ LightnessBand
Lightness band of HLS image.
@ CoastalBand
Coastal band [0.40 - 0.45 um].
@ HueBand
Hue band of HLS image.
@ TIRBand
Thermal InfraRed (TIR) band (MWIR or LWIR) [3 - 15 um].
@ RedBand
Red band of RGBA image, or red spectral band [0.62 - 0.69 um].
@ PanBand
Panchromatic band [0.40 - 1.00 um].
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.
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.
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 std::unique_ptr< QgsAbstractGeometry > convertGeometry(const QVariantMap &geometry, const QString &esriGeometryType, bool hasM, bool hasZ, bool allowCurves=true, QgsCoordinateReferenceSystem *crs=nullptr)
Converts an ESRI REST geometry JSON definition to a QgsAbstractGeometry.
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 QVariantMap geometryToJson(const QgsGeometry &geometry, const QgsArcGisRestContext &context, const QgsCoordinateReferenceSystem &crs=QgsCoordinateReferenceSystem())
Converts a geometry to an ArcGIS REST JSON representation.
static double defaultNoDataForDataType(Qgis::DataType type, bool &ok)
Returns a sensible no-data value to use for the specified data type.
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 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 Qgis::ArcGisRestServiceCapabilities serviceCapabilitiesFromString(const QString &capabilities)
Parses a capabilities string to known values.
static std::unique_ptr< QgsSymbol > convertSymbol(const QVariantMap &definition)
Converts a symbol JSON definition to a QgsSymbol.
static std::unique_ptr< 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 Qgis::RasterColorInterpretation colorInterpretationFromBandName(const QString &bandName)
Attempts to match arbitrary band name strings to a QGIS raster color interpretation.
static QVariantMap crsToJson(const QgsCoordinateReferenceSystem &crs)
Converts a crs to an ArcGIS REST JSON representation.
static std::unique_ptr< QgsAbstractVectorLayerLabeling > convertLabeling(const QVariantList &data)
Converts labeling JSON data to an equivalent QGIS vector labeling.
QFlags< FeatureToJsonFlag > FeatureToJsonFlags
Flags which control the behavior of converting features to JSON.
static Qgis::DataType dataTypeFromString(const QString &pixelType)
Returns the raster data type corresponding to an ESRI pixelType string.
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.
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.
int nCurves() const
Returns the number of curves in the geometry.
const QgsCurve * curveAt(int i) const
Returns the curve at the specified index.
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.
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.
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.
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 container for the context for various read/write operations on objects.
A rectangle specified with double values.
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
Represents the context in which a QgsSymbolConverter conversion occurs.
A symbol converter for converting ESRI REST JSON symbols.
static Qt::PenStyle convertLineStyle(const QString &style)
Converts an ESRI line style to a Qt pen style.
std::unique_ptr< QgsSymbol > createSymbol(const QVariant &variant, QgsSymbolConverterContext &context) const override
Creates a new QgsSymbol from a QVariant representation.
static Qt::BrushStyle convertFillStyle(const QString &style)
Converts an ESRI fill style to a Qt brush style.
static QColor convertColor(const QVariant &data)
Converts ESRI JSON color data to a QColor object.
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.
#define BUILTIN_UNREACHABLE
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)