17#include "moc_qgsarcgisrestutils.cpp"
49#include <QRegularExpression>
61 if ( esriFieldType == QLatin1String(
"esriFieldTypeInteger" ) )
62 return QMetaType::Type::LongLong;
63 if ( esriFieldType == QLatin1String(
"esriFieldTypeSmallInteger" ) )
64 return QMetaType::Type::Int;
65 if ( esriFieldType == QLatin1String(
"esriFieldTypeDouble" ) )
66 return QMetaType::Type::Double;
67 if ( esriFieldType == QLatin1String(
"esriFieldTypeSingle" ) )
68 return QMetaType::Type::Double;
69 if ( esriFieldType == QLatin1String(
"esriFieldTypeString" ) )
70 return QMetaType::Type::QString;
71 if ( esriFieldType == QLatin1String(
"esriFieldTypeDate" ) )
72 return QMetaType::Type::QDateTime;
73 if ( esriFieldType == QLatin1String(
"esriFieldTypeGeometry" ) )
74 return QMetaType::Type::UnknownType;
75 if ( esriFieldType == QLatin1String(
"esriFieldTypeOID" ) )
76 return QMetaType::Type::LongLong;
77 if ( esriFieldType == QLatin1String(
"esriFieldTypeBlob" ) )
78 return QMetaType::Type::QByteArray;
79 if ( esriFieldType == QLatin1String(
"esriFieldTypeGlobalID" ) )
80 return QMetaType::Type::QString;
81 if ( esriFieldType == QLatin1String(
"esriFieldTypeRaster" ) )
82 return QMetaType::Type::QByteArray;
83 if ( esriFieldType == QLatin1String(
"esriFieldTypeGUID" ) )
84 return QMetaType::Type::QString;
85 if ( esriFieldType == QLatin1String(
"esriFieldTypeXML" ) )
86 return QMetaType::Type::QString;
87 return QMetaType::Type::UnknownType;
93 if ( esriGeometryType == QLatin1String(
"esriGeometryNull" ) )
95 else if ( esriGeometryType == QLatin1String(
"esriGeometryPoint" ) )
97 else if ( esriGeometryType == QLatin1String(
"esriGeometryMultipoint" ) )
99 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolyline" ) )
101 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolygon" ) )
103 else if ( esriGeometryType == QLatin1String(
"esriGeometryEnvelope" ) )
123std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertPoint(
const QVariantList &coordList,
Qgis::WkbType pointType )
125 int nCoords = coordList.size();
128 bool xok =
false, yok =
false;
129 const double x = coordList[0].toDouble( &xok );
130 const double y = coordList[1].toDouble( &yok );
134 const double z = hasZ && nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
137 const double m =
QgsWkbTypes::hasM( pointType ) && ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[ hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
138 return std::make_unique< QgsPoint >( pointType, x, y, z, m );
141std::unique_ptr< QgsCircularString > QgsArcGisRestUtils::convertCircularString(
const QVariantMap &curveData,
Qgis::WkbType pointType,
const QgsPoint &startPoint )
143 const QVariantList coordsList = curveData[QStringLiteral(
"c" )].toList();
144 if ( coordsList.isEmpty() )
146 const int coordsListSize = coordsList.size();
148 QVector<QgsPoint> points;
149 points.reserve( coordsListSize + 1 );
150 points.append( startPoint );
152 for (
int i = 0; i < coordsListSize - 1; )
156 std::unique_ptr< QgsPoint > endPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
160 std::unique_ptr< QgsPoint > interiorPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
161 if ( !interiorPoint )
164 points << *interiorPoint;
167 std::unique_ptr< QgsCircularString > curve = std::make_unique< QgsCircularString> ();
168 curve->setPoints( points );
172std::unique_ptr< QgsCompoundCurve > QgsArcGisRestUtils::convertCompoundCurve(
const QVariantList &curvesList,
Qgis::WkbType pointType )
175 std::unique_ptr< QgsCompoundCurve > compoundCurve = std::make_unique< QgsCompoundCurve >();
177 QVector< double > lineX;
178 QVector< double > lineY;
179 QVector< double > lineZ;
180 QVector< double > lineM;
181 int maxCurveListSize = curvesList.size();
182 lineX.resize( maxCurveListSize );
183 lineY.resize( maxCurveListSize );
187 lineZ.resize( maxCurveListSize );
190 lineM.resize( maxCurveListSize );
192 double *outLineX = lineX.data();
193 double *outLineY = lineY.data();
194 double *outLineZ = lineZ.data();
195 double *outLineM = lineM.data();
196 int actualLineSize = 0;
201 int curveListIndex = 0;
202 for (
const QVariant &curveData : curvesList )
204 if ( curveData.userType() == QMetaType::Type::QVariantList )
206 const QVariantList coordList = curveData.toList();
207 const int nCoords = coordList.size();
211 const double x = coordList[0].toDouble( &xok );
212 const double y = coordList[1].toDouble( &yok );
221 *outLineZ++ = nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
227 *outLineM++ = ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[ hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
230 else if ( curveData.userType() == QMetaType::Type::QVariantMap )
234 if ( actualLineSize > 0 )
236 lastLineStringPoint =
QgsPoint( lineX.at( actualLineSize - 1 ),
237 lineY.at( actualLineSize - 1 ),
238 hasZ ? lineZ.at( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN(),
239 hasM ? lineM.at( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN() );
241 std::unique_ptr< QgsCircularString > circularString( convertCircularString( curveData.toMap(), pointType, lastLineStringPoint ) );
242 if ( !circularString )
247 if ( actualLineSize > 0 )
249 lineX.resize( actualLineSize );
250 lineY.resize( actualLineSize );
252 lineZ.resize( actualLineSize );
254 lineM.resize( actualLineSize );
256 compoundCurve->addCurve(
new QgsLineString( lineX, lineY, lineZ, lineM ) );
257 lineX.resize( maxCurveListSize - curveListIndex );
258 lineY.resize( maxCurveListSize - curveListIndex );
260 lineZ.resize( maxCurveListSize - curveListIndex );
262 lineM.resize( maxCurveListSize - curveListIndex );
263 outLineX = lineX.data();
264 outLineY = lineY.data();
265 outLineZ = lineZ.data();
266 outLineM = lineM.data();
270 if ( compoundCurve->curveAt( compoundCurve->nCurves() - 1 )->nCoordinates() < 2 )
271 compoundCurve->removeCurve( compoundCurve->nCurves() - 1 );
273 const QgsPoint endPointCircularString = circularString->endPoint();
274 compoundCurve->addCurve( circularString.release() );
278 *outLineX++ = endPointCircularString.
x();
279 *outLineY++ = endPointCircularString.
y();
281 *outLineZ++ = endPointCircularString.
z();
283 *outLineM++ = endPointCircularString.
m();
288 if ( actualLineSize == 1 && compoundCurve->nCurves() > 0 )
290 const QgsCurve *finalCurve = compoundCurve->curveAt( compoundCurve->nCurves() - 1 );
294 && ( !hasZ ||
qgsDoubleNear( finalCurveEndPoint.
z(), lineZ.at( 0 ) ) )
295 && ( !hasM ||
qgsDoubleNear( finalCurveEndPoint.
m(), lineM.at( 0 ) ) ) )
301 if ( actualLineSize > 0 )
303 lineX.resize( actualLineSize );
304 lineY.resize( actualLineSize );
306 lineZ.resize( actualLineSize );
308 lineM.resize( actualLineSize );
309 compoundCurve->addCurve(
new QgsLineString( lineX, lineY, lineZ, lineM ) );
312 return compoundCurve;
315std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertGeometryPoint(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
318 bool xok =
false, yok =
false;
319 double x = geometryData[QStringLiteral(
"x" )].toDouble( &xok );
320 double y = geometryData[QStringLiteral(
"y" )].toDouble( &yok );
323 double z = geometryData[QStringLiteral(
"z" )].toDouble();
324 double m = geometryData[QStringLiteral(
"m" )].toDouble();
325 return std::make_unique< QgsPoint >( pointType, x, y, z, m );
328std::unique_ptr< QgsMultiPoint > QgsArcGisRestUtils::convertMultiPoint(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
331 const QVariantList coordsList = geometryData[QStringLiteral(
"points" )].toList();
333 std::unique_ptr< QgsMultiPoint > multiPoint = std::make_unique< QgsMultiPoint >();
334 multiPoint->reserve( coordsList.size() );
335 for (
const QVariant &coordData : coordsList )
337 const QVariantList coordList = coordData.toList();
338 std::unique_ptr< QgsPoint > p = convertPoint( coordList, pointType );
343 multiPoint->addGeometry( p.release() );
348 std::unique_ptr< QgsPoint > p = convertGeometryPoint( geometryData, pointType );
350 multiPoint->addGeometry( p.release() );
352 if ( multiPoint->numGeometries() == 0 )
360std::unique_ptr< QgsMultiCurve > QgsArcGisRestUtils::convertGeometryPolyline(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
363 QVariantList pathsList;
364 if ( geometryData[QStringLiteral(
"paths" )].isValid() )
365 pathsList = geometryData[QStringLiteral(
"paths" )].toList();
366 else if ( geometryData[QStringLiteral(
"curvePaths" )].isValid() )
367 pathsList = geometryData[QStringLiteral(
"curvePaths" )].toList();
368 if ( pathsList.isEmpty() )
370 std::unique_ptr< QgsMultiCurve > multiCurve = std::make_unique< QgsMultiCurve >();
371 multiCurve->reserve( pathsList.size() );
372 for (
const QVariant &pathData : std::as_const( pathsList ) )
374 std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( pathData.toList(), pointType );
379 multiCurve->addGeometry( curve.release() );
384std::unique_ptr< QgsMultiSurface > QgsArcGisRestUtils::convertGeometryPolygon(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
387 QVariantList ringsList;
388 if ( geometryData[QStringLiteral(
"rings" )].isValid() )
389 ringsList = geometryData[QStringLiteral(
"rings" )].toList();
390 else if ( geometryData[QStringLiteral(
"ringPaths" )].isValid() )
391 ringsList = geometryData[QStringLiteral(
"ringPaths" )].toList();
392 if ( ringsList.isEmpty() )
395 QList< QgsCompoundCurve * > curves;
396 for (
int i = 0, n = ringsList.size(); i < n; ++i )
398 std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( ringsList[i].toList(), pointType );
403 curves.append( curve.release() );
405 if ( curves.count() == 0 )
408 std::unique_ptr< QgsMultiSurface > result = std::make_unique< QgsMultiSurface >();
409 if ( curves.count() == 1 )
412 std::unique_ptr< QgsCurvePolygon > newPolygon = std::make_unique< QgsCurvePolygon >();
413 newPolygon->setExteriorRing( curves.takeAt( 0 ) );
414 result->addGeometry( newPolygon.release() );
418 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 ); } );
419 result->reserve( curves.size() );
420 while ( !curves.isEmpty() )
426 engine->prepareGeometry();
428 QMutableListIterator< QgsCompoundCurve * > it( curves );
429 while ( it.hasNext() )
436 if ( engine->contains( &point ) )
441 engine->prepareGeometry();
445 result->addGeometry( newPolygon );
447 if ( result->numGeometries() == 0 )
453std::unique_ptr< QgsPolygon > QgsArcGisRestUtils::convertEnvelope(
const QVariantMap &geometryData )
456 bool xminOk =
false, yminOk =
false, xmaxOk =
false, ymaxOk =
false;
457 double xmin = geometryData[QStringLiteral(
"xmin" )].toDouble( &xminOk );
458 double ymin = geometryData[QStringLiteral(
"ymin" )].toDouble( &yminOk );
459 double xmax = geometryData[QStringLiteral(
"xmax" )].toDouble( &xmaxOk );
460 double ymax = geometryData[QStringLiteral(
"ymax" )].toDouble( &ymaxOk );
461 if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk )
463 std::unique_ptr< QgsLineString > ext = std::make_unique< QgsLineString> ();
464 ext->addVertex(
QgsPoint( xmin, ymin ) );
465 ext->addVertex(
QgsPoint( xmax, ymin ) );
466 ext->addVertex(
QgsPoint( xmax, ymax ) );
467 ext->addVertex(
QgsPoint( xmin, ymax ) );
468 ext->addVertex(
QgsPoint( xmin, ymin ) );
469 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
470 poly->setExteriorRing( ext.release() );
483 if ( esriGeometryType == QLatin1String(
"esriGeometryNull" ) )
485 else if ( esriGeometryType == QLatin1String(
"esriGeometryPoint" ) )
486 return convertGeometryPoint( geometryData, pointType ).release();
487 else if ( esriGeometryType == QLatin1String(
"esriGeometryMultipoint" ) )
488 return convertMultiPoint( geometryData, pointType ).release();
489 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolyline" ) )
490 return convertGeometryPolyline( geometryData, pointType ).release();
491 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolygon" ) )
492 return convertGeometryPolygon( geometryData, pointType ).release();
493 else if ( esriGeometryType == QLatin1String(
"esriGeometryEnvelope" ) )
494 return convertEnvelope( geometryData ).release();
517 QString spatialReference = spatialReferenceMap[QStringLiteral(
"latestWkid" )].toString();
518 if ( spatialReference.isEmpty() )
519 spatialReference = spatialReferenceMap[QStringLiteral(
"wkid" )].toString();
522 if ( !spatialReference.isEmpty() )
531 else if ( !spatialReferenceMap[QStringLiteral(
"wkt" )].toString().isEmpty() )
534 crs.
createFromWkt( spatialReferenceMap[QStringLiteral(
"wkt" )].toString() );
549 const QString type = symbolData.value( QStringLiteral(
"type" ) ).toString();
550 if ( type == QLatin1String(
"esriSMS" ) )
553 return parseEsriMarkerSymbolJson( symbolData ).release();
555 else if ( type == QLatin1String(
"esriSLS" ) )
558 return parseEsriLineSymbolJson( symbolData ).release();
560 else if ( type == QLatin1String(
"esriSFS" ) )
563 return parseEsriFillSymbolJson( symbolData ).release();
565 else if ( type == QLatin1String(
"esriPFS" ) )
567 return parseEsriPictureFillSymbolJson( symbolData ).release();
569 else if ( type == QLatin1String(
"esriPMS" ) )
572 return parseEsriPictureMarkerSymbolJson( symbolData ).release();
574 else if ( type == QLatin1String(
"esriTS" ) )
576 return parseEsriTextMarkerSymbolJson( symbolData ).release();
581std::unique_ptr<QgsLineSymbol> QgsArcGisRestUtils::parseEsriLineSymbolJson(
const QVariantMap &symbolData )
583 QColor lineColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
584 if ( !lineColor.isValid() )
588 double widthInPoints = symbolData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
593 Qt::PenStyle penStyle =
convertLineStyle( symbolData.value( QStringLiteral(
"style" ) ).toString() );
594 std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( lineColor, widthInPoints, penStyle );
596 layers.append( lineLayer.release() );
598 std::unique_ptr< QgsLineSymbol > symbol = std::make_unique< QgsLineSymbol >( layers );
602std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriFillSymbolJson(
const QVariantMap &symbolData )
604 QColor fillColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
605 Qt::BrushStyle brushStyle =
convertFillStyle( symbolData.value( QStringLiteral(
"style" ) ).toString() );
607 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
608 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
609 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
611 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
614 std::unique_ptr< QgsSimpleFillSymbolLayer > fillLayer = std::make_unique< QgsSimpleFillSymbolLayer >( fillColor, brushStyle, lineColor, penStyle, penWidthInPoints );
616 layers.append( fillLayer.release() );
618 std::unique_ptr< QgsFillSymbol > symbol = std::make_unique< QgsFillSymbol >( layers );
622std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriPictureFillSymbolJson(
const QVariantMap &symbolData )
626 double widthInPixels = symbolData.value( QStringLiteral(
"width" ) ).toInt( &ok );
630 const double xScale = symbolData.value( QStringLiteral(
"xscale" ) ).toDouble( &ok );
632 widthInPixels *= xScale;
634 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
639 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
640 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
642 QString symbolPath( symbolData.value( QStringLiteral(
"imageData" ) ).toString() );
643 symbolPath.prepend( QLatin1String(
"base64:" ) );
646 std::unique_ptr< QgsRasterFillSymbolLayer > fillLayer = std::make_unique< QgsRasterFillSymbolLayer >( symbolPath );
647 fillLayer->setWidth( widthInPixels );
648 fillLayer->setAngle( angleCW );
650 fillLayer->setOffset( QPointF( xOffset, yOffset ) );
652 layers.append( fillLayer.release() );
654 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
655 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
656 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
657 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
659 std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( lineColor, penWidthInPoints, penStyle );
661 layers.append( lineLayer.release() );
663 std::unique_ptr< QgsFillSymbol > symbol = std::make_unique< QgsFillSymbol >( layers );
667Qgis::MarkerShape QgsArcGisRestUtils::parseEsriMarkerShape(
const QString &style )
669 if ( style == QLatin1String(
"esriSMSCircle" ) )
671 else if ( style == QLatin1String(
"esriSMSCross" ) )
673 else if ( style == QLatin1String(
"esriSMSDiamond" ) )
675 else if ( style == QLatin1String(
"esriSMSSquare" ) )
677 else if ( style == QLatin1String(
"esriSMSX" ) )
679 else if ( style == QLatin1String(
"esriSMSTriangle" ) )
685std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriMarkerSymbolJson(
const QVariantMap &symbolData )
687 QColor fillColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
689 const double sizeInPoints = symbolData.value( QStringLiteral(
"size" ) ).toDouble( &ok );
692 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
697 Qgis::MarkerShape shape = parseEsriMarkerShape( symbolData.value( QStringLiteral(
"style" ) ).toString() );
699 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
700 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
702 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
703 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
704 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
705 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
708 std::unique_ptr< QgsSimpleMarkerSymbolLayer > markerLayer = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, sizeInPoints, angleCW,
Qgis::ScaleMethod::ScaleArea, fillColor, lineColor );
711 markerLayer->setStrokeStyle( penStyle );
712 markerLayer->setStrokeWidth( penWidthInPoints );
713 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
715 layers.append( markerLayer.release() );
717 std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
721std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriPictureMarkerSymbolJson(
const QVariantMap &symbolData )
724 const double widthInPixels = symbolData.value( QStringLiteral(
"width" ) ).toInt( &ok );
727 const double heightInPixels = symbolData.value( QStringLiteral(
"height" ) ).toInt( &ok );
731 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
736 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
737 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
741 QString symbolPath( symbolData.value( QStringLiteral(
"imageData" ) ).toString() );
742 symbolPath.prepend( QLatin1String(
"base64:" ) );
745 std::unique_ptr< QgsRasterMarkerSymbolLayer > markerLayer = std::make_unique< QgsRasterMarkerSymbolLayer >( symbolPath, widthInPixels, angleCW,
Qgis::ScaleMethod::ScaleArea );
749 if ( !
qgsDoubleNear(
static_cast< double >( heightInPixels ) / widthInPixels, markerLayer->defaultAspectRatio() ) )
750 markerLayer->setFixedAspectRatio(
static_cast< double >( heightInPixels ) / widthInPixels );
752 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
754 layers.append( markerLayer.release() );
756 std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
760std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriTextMarkerSymbolJson(
const QVariantMap &symbolData )
764 const QString fontFamily = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"family" ) ).toString();
766 const QString chr = symbolData.value( QStringLiteral(
"text" ) ).toString();
768 const double pointSize = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"size" ) ).toDouble();
770 const QColor color =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
772 const double esriAngle = symbolData.value( QStringLiteral(
"angle" ) ).toDouble();
774 const double angle = 90.0 - esriAngle;
776 std::unique_ptr< QgsFontMarkerSymbolLayer > markerLayer = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, chr, pointSize, color, angle );
778 QColor strokeColor =
convertColor( symbolData.value( QStringLiteral(
"borderLineColor" ) ) );
779 markerLayer->setStrokeColor( strokeColor );
781 double borderLineSize = symbolData.value( QStringLiteral(
"borderLineSize" ) ).toDouble();
782 markerLayer->setStrokeWidth( borderLineSize );
784 const QString fontStyle = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"style" ) ).toString();
785 markerLayer->setFontStyle( fontStyle );
787 double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
788 double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
790 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
799 QString horizontalAnchorPoint = symbolData.value( QStringLiteral(
"horizontalAlignment" ) ).toString();
800 QString verticalAnchorPoint = symbolData.value( QStringLiteral(
"verticalAlignment" ) ).toString();
802 if ( horizontalAnchorPoint == QString(
"center" ) )
806 else if ( horizontalAnchorPoint == QString(
"left" ) )
810 else if ( horizontalAnchorPoint == QString(
"right" ) )
815 if ( verticalAnchorPoint == QString(
"center" ) )
819 else if ( verticalAnchorPoint == QString(
"top" ) )
823 else if ( verticalAnchorPoint == QString(
"bottom" ) )
828 markerLayer->setHorizontalAnchorPoint( hAlign );
829 markerLayer->setVerticalAnchorPoint( vAlign );
831 layers.append( markerLayer.release() );
833 std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
839 if ( labelingData.empty() )
846 for (
const QVariant &lbl : labelingData )
848 const QVariantMap labeling = lbl.toMap();
853 const QString placement = labeling.value( QStringLiteral(
"labelPlacement" ) ).toString();
854 if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveCenter" ) )
859 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowCenter" ) )
864 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterCenter" ) )
869 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveLeft" ) )
874 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowLeft" ) )
879 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterLeft" ) )
884 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveRight" ) )
889 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowRight" ) )
894 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterRight" ) )
899 else if ( placement == QLatin1String(
"esriServerLinePlacementAboveAfter" ) ||
900 placement == QLatin1String(
"esriServerLinePlacementAboveStart" ) ||
901 placement == QLatin1String(
"esriServerLinePlacementAboveAlong" ) )
906 else if ( placement == QLatin1String(
"esriServerLinePlacementBelowAfter" ) ||
907 placement == QLatin1String(
"esriServerLinePlacementBelowStart" ) ||
908 placement == QLatin1String(
"esriServerLinePlacementBelowAlong" ) )
913 else if ( placement == QLatin1String(
"esriServerLinePlacementCenterAfter" ) ||
914 placement == QLatin1String(
"esriServerLinePlacementCenterStart" ) ||
915 placement == QLatin1String(
"esriServerLinePlacementCenterAlong" ) )
920 else if ( placement == QLatin1String(
"esriServerPolygonPlacementAlwaysHorizontal" ) )
925 const double minScale = labeling.value( QStringLiteral(
"minScale" ) ).toDouble();
926 const double maxScale = labeling.value( QStringLiteral(
"maxScale" ) ).toDouble();
928 QVariantMap symbol = labeling.value( QStringLiteral(
"symbol" ) ).toMap();
930 const double haloSize = symbol.value( QStringLiteral(
"haloSize" ) ).toDouble();
941 const QString fontFamily = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"family" ) ).toString();
942 const QString fontStyle = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"style" ) ).toString();
943 const QString fontWeight = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"weight" ) ).toString();
944 const int fontSize = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"size" ) ).toInt();
945 QFont font( fontFamily, fontSize );
946 font.setStyleName( fontStyle );
947 font.setWeight( fontWeight == QLatin1String(
"bold" ) ? QFont::Bold : QFont::Normal );
955 QString where = labeling.value( QStringLiteral(
"where" ) ).toString();
974 const QString type = rendererData.value( QStringLiteral(
"type" ) ).toString();
975 if ( type == QLatin1String(
"simple" ) )
977 const QVariantMap symbolProps = rendererData.value( QStringLiteral(
"symbol" ) ).toMap();
978 std::unique_ptr< QgsSymbol > symbol(
convertSymbol( symbolProps ) );
984 else if ( type == QLatin1String(
"uniqueValue" ) )
986 const QString field1 = rendererData.value( QStringLiteral(
"field1" ) ).toString();
987 const QString field2 = rendererData.value( QStringLiteral(
"field2" ) ).toString();
988 const QString field3 = rendererData.value( QStringLiteral(
"field3" ) ).toString();
990 if ( !field2.isEmpty() || !field3.isEmpty() )
992 const QString delimiter = rendererData.value( QStringLiteral(
"fieldDelimiter" ) ).toString();
993 if ( !field3.isEmpty() )
995 attribute = QStringLiteral(
"concat(\"%1\",'%2',\"%3\",'%4',\"%5\")" ).arg( field1, delimiter, field2, delimiter, field3 );
999 attribute = QStringLiteral(
"concat(\"%1\",'%2',\"%3\")" ).arg( field1, delimiter, field2 );
1007 const QVariantList categories = rendererData.value( QStringLiteral(
"uniqueValueInfos" ) ).toList();
1009 for (
const QVariant &category : categories )
1011 const QVariantMap categoryData = category.toMap();
1012 const QString value = categoryData.value( QStringLiteral(
"value" ) ).toString();
1013 const QString label = categoryData.value( QStringLiteral(
"label" ) ).toString();
1021 std::unique_ptr< QgsSymbol > defaultSymbol(
convertSymbol( rendererData.value( QStringLiteral(
"defaultSymbol" ) ).toMap() ) );
1022 if ( defaultSymbol )
1024 categoryList.append(
QgsRendererCategory( QVariant(), defaultSymbol.release(), rendererData.value( QStringLiteral(
"defaultLabel" ) ).toString() ) );
1027 if ( categoryList.empty() )
1032 else if ( type == QLatin1String(
"classBreaks" ) )
1034 const QString attrName = rendererData.value( QStringLiteral(
"field" ) ).toString();
1036 const QVariantList classBreakInfos = rendererData.value( QStringLiteral(
"classBreakInfos" ) ).toList();
1037 const QVariantMap authoringInfo = rendererData.value( QStringLiteral(
"authoringInfo" ) ).toMap();
1038 QVariantMap symbolData;
1040 QString esriMode = authoringInfo.value( QStringLiteral(
"classificationMethod" ) ).toString();
1041 if ( esriMode.isEmpty() )
1043 esriMode = rendererData.value( QStringLiteral(
"classificationMethod" ) ).toString();
1046 if ( !classBreakInfos.isEmpty() )
1048 symbolData = classBreakInfos.at( 0 ).toMap().value( QStringLiteral(
"symbol" ) ).toMap();
1054 const double transparency = rendererData.value( QStringLiteral(
"transparency" ) ).toDouble();
1055 const double opacity = ( 100.0 - transparency ) / 100.0;
1056 symbol->setOpacity( opacity );
1058 const QVariantList visualVariablesData = rendererData.value( QStringLiteral(
"visualVariables" ) ).toList();
1060 for (
const QVariant &visualVariable : visualVariablesData )
1062 const QVariantMap visualVariableData = visualVariable.toMap();
1063 const QString variableType = visualVariableData.value( QStringLiteral(
"type" ) ).toString();
1064 if ( variableType == QLatin1String(
"sizeInfo" ) )
1068 else if ( variableType == QLatin1String(
"colorInfo" ) )
1070 const QVariantList stops = visualVariableData.value( QStringLiteral(
"stops" ) ).toList();
1071 if ( stops.size() < 2 )
1076 const double minValue = stops.front().toMap().value( QStringLiteral(
"value" ) ).toDouble( &ok );
1079 const QColor minColor =
convertColor( stops.front().toMap().value( QStringLiteral(
"color" ) ) );
1081 const double maxValue = stops.back().toMap().value( QStringLiteral(
"value" ) ).toDouble( &ok );
1084 const QColor maxColor =
convertColor( stops.back().toMap().value( QStringLiteral(
"color" ) ) );
1087 for (
int i = 1; i < stops.size() - 1; ++i )
1089 const QVariantMap stopData = stops.at( i ).toMap();
1090 const double breakpoint = stopData.value( QStringLiteral(
"value" ) ).toDouble();
1091 const double scaledBreakpoint = ( breakpoint - minValue ) / ( maxValue - minValue );
1092 const QColor fillColor =
convertColor( stopData.value( QStringLiteral(
"color" ) ) );
1094 gradientStops.append(
QgsGradientStop( scaledBreakpoint, fillColor ) );
1097 std::unique_ptr< QgsGradientColorRamp > colorRamp = std::make_unique< QgsGradientColorRamp >(
1098 minColor, maxColor,
false, gradientStops
1105 for (
int layer = 0; layer < symbol->symbolLayerCount(); ++layer )
1110 std::unique_ptr< QgsSingleSymbolRenderer > singleSymbolRenderer = std::make_unique< QgsSingleSymbolRenderer >( symbol.release() );
1112 return singleSymbolRenderer.release();
1116 QgsDebugError( QStringLiteral(
"ESRI visualVariable type %1 is not currently supported" ).arg( variableType ) );
1120 double lastValue = rendererData.value( QStringLiteral(
"minValue" ) ).toDouble();
1122 std::unique_ptr< QgsGraduatedSymbolRenderer > graduatedRenderer = std::make_unique< QgsGraduatedSymbolRenderer >( attrName );
1124 graduatedRenderer->setSourceSymbol( symbol.release() );
1126 if ( esriMode == QLatin1String(
"esriClassifyDefinedInterval" ) )
1129 graduatedRenderer->setClassificationMethod( method );
1131 else if ( esriMode == QLatin1String(
"esriClassifyEqualInterval" ) )
1134 graduatedRenderer->setClassificationMethod( method );
1136 else if ( esriMode == QLatin1String(
"esriClassifyGeometricalInterval" ) )
1139 graduatedRenderer->setClassificationMethod( method );
1141 else if ( esriMode == QLatin1String(
"esriClassifyManual" ) )
1144 graduatedRenderer->setClassificationMethod( method );
1146 else if ( esriMode == QLatin1String(
"esriClassifyNaturalBreaks" ) )
1149 graduatedRenderer->setClassificationMethod( method );
1151 else if ( esriMode == QLatin1String(
"esriClassifyQuantile" ) )
1154 graduatedRenderer->setClassificationMethod( method );
1156 else if ( esriMode == QLatin1String(
"esriClassifyStandardDeviation" ) )
1159 graduatedRenderer->setClassificationMethod( method );
1161 else if ( !esriMode.isEmpty() )
1163 QgsDebugError( QStringLiteral(
"ESRI classification mode %1 is not currently supported" ).arg( esriMode ) );
1166 for (
const QVariant &classBreakInfo : classBreakInfos )
1168 const QVariantMap symbolData = classBreakInfo.toMap().value( QStringLiteral(
"symbol" ) ).toMap();
1170 double classMaxValue = classBreakInfo.toMap().value( QStringLiteral(
"classMaxValue" ) ).toDouble();
1171 const QString label = classBreakInfo.toMap().value( QStringLiteral(
"label" ) ).toString();
1180 lastValue = classMaxValue;
1181 graduatedRenderer->addClass( range );
1184 return graduatedRenderer.release();
1186 else if ( type == QLatin1String(
"heatmap" ) )
1191 else if ( type == QLatin1String(
"vectorField" ) )
1201 QString expression = string;
1204 const thread_local QRegularExpression rx1 = QRegularExpression( QStringLiteral(
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)CONCAT(\\s|$)" ) );
1205 expression = expression.replace( rx1, QStringLiteral(
"\\4||\\5" ) );
1207 const thread_local QRegularExpression rx2 = QRegularExpression( QStringLiteral(
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)NEWLINE(\\s|$)" ) );
1208 expression = expression.replace( rx2, QStringLiteral(
"\\4'\\n'\\5" ) );
1211 const thread_local QRegularExpression rx3 = QRegularExpression( QStringLiteral(
"\"(.*?(?<!\\\\))\"" ) );
1212 expression = expression.replace( rx3, QStringLiteral(
"'\\1'" ) );
1213 const thread_local QRegularExpression rx4 = QRegularExpression( QStringLiteral(
"\\\\\"" ) );
1214 expression = expression.replace( rx4, QStringLiteral(
"\"" ) );
1217 const thread_local QRegularExpression rx5 = QRegularExpression( QStringLiteral(
"\\[([^]]*)\\]" ) );
1218 expression = expression.replace( rx5, QStringLiteral(
"\"\\1\"" ) );
1225 const QVariantList colorParts = colorData.toList();
1226 if ( colorParts.count() < 4 )
1229 int red = colorParts.at( 0 ).toInt();
1230 int green = colorParts.at( 1 ).toInt();
1231 int blue = colorParts.at( 2 ).toInt();
1232 int alpha = colorParts.at( 3 ).toInt();
1233 return QColor( red, green, blue, alpha );
1238 if ( style == QLatin1String(
"esriSLSSolid" ) )
1239 return Qt::SolidLine;
1240 else if ( style == QLatin1String(
"esriSLSDash" ) )
1241 return Qt::DashLine;
1242 else if ( style == QLatin1String(
"esriSLSDashDot" ) )
1243 return Qt::DashDotLine;
1244 else if ( style == QLatin1String(
"esriSLSDashDotDot" ) )
1245 return Qt::DashDotDotLine;
1246 else if ( style == QLatin1String(
"esriSLSDot" ) )
1248 else if ( style == QLatin1String(
"esriSLSNull" ) )
1251 return Qt::SolidLine;
1256 if ( style == QLatin1String(
"esriSFSBackwardDiagonal" ) )
1257 return Qt::BDiagPattern;
1258 else if ( style == QLatin1String(
"esriSFSCross" ) )
1259 return Qt::CrossPattern;
1260 else if ( style == QLatin1String(
"esriSFSDiagonalCross" ) )
1261 return Qt::DiagCrossPattern;
1262 else if ( style == QLatin1String(
"esriSFSForwardDiagonal" ) )
1263 return Qt::FDiagPattern;
1264 else if ( style == QLatin1String(
"esriSFSHorizontal" ) )
1265 return Qt::HorPattern;
1266 else if ( style == QLatin1String(
"esriSFSNull" ) )
1268 else if ( style == QLatin1String(
"esriSFSSolid" ) )
1269 return Qt::SolidPattern;
1270 else if ( style == QLatin1String(
"esriSFSVertical" ) )
1271 return Qt::VerPattern;
1273 return Qt::SolidPattern;
1281 QDateTime dt = QDateTime::fromMSecsSinceEpoch( value.toLongLong( &ok ) );
1284 QgsDebugError( QStringLiteral(
"Invalid value %1 for datetime" ).arg( value.toString() ) );
1296 const QVariantMap coords = value.toMap();
1301 const double xmin = coords.value( QStringLiteral(
"xmin" ) ).toDouble( &ok );
1304 const double ymin = coords.value( QStringLiteral(
"ymin" ) ).toDouble( &ok );
1307 const double xmax = coords.value( QStringLiteral(
"xmax" ) ).toDouble( &ok );
1310 const double ymax = coords.value( QStringLiteral(
"ymax" ) ).toDouble( &ok );
1322 return QVariantMap();
1329 return QVariantMap();
1332 res = pointToJson( qgsgeometry_cast< const QgsPoint * >( geom ) );
1336 res = lineStringToJson( qgsgeometry_cast< const QgsLineString * >( geom ) );
1341 res = curveToJson( qgsgeometry_cast< const QgsCurve * >( geom ) );
1345 res = polygonToJson( qgsgeometry_cast< const QgsPolygon * >( geom ) );
1349 res = multiPointToJson( qgsgeometry_cast< const QgsMultiPoint * >( geom ) );
1353 res = multiLineStringToJson( qgsgeometry_cast< const QgsMultiLineString * >( geom ) );
1357 res = multiCurveToJson( qgsgeometry_cast< const QgsMultiCurve * >( geom ) );
1361 res = multiPolygonToJson( qgsgeometry_cast< const QgsMultiPolygon * >( geom ) );
1365 res = curvePolygonToJson( qgsgeometry_cast< const QgsCurvePolygon * >( geom ) );
1369 res = multiSurfaceToJson( qgsgeometry_cast< const QgsMultiSurface * >( geom ) );
1373 return QVariantMap();
1376 return QVariantMap();
1379 return QVariantMap();
1386 res.insert( QStringLiteral(
"spatialReference" ),
crsToJson(
crs ) );
1392QVariantMap QgsArcGisRestUtils::pointToJson(
const QgsPoint *point )
1396 data[QStringLiteral(
"x" )] = QStringLiteral(
"NaN" );
1399 data[QStringLiteral(
"x" )] = point->
x();
1400 data[QStringLiteral(
"y" )] = point->
y();
1402 if ( point->
is3D() )
1403 data[QStringLiteral(
"z" )] = !std::isnan( point->
z() ) ? QVariant( point->
z() ) : QVariant( QStringLiteral(
"NaN" ) );
1406 data[QStringLiteral(
"m" )] = !std::isnan( point->
m() ) ? QVariant( point->
m() ) : QVariant( QStringLiteral(
"NaN" ) );
1411QVariantMap QgsArcGisRestUtils::multiPointToJson(
const QgsMultiPoint *multiPoint )
1414 const bool hasZ = multiPoint->
is3D();
1415 const bool hasM = multiPoint->
isMeasure();
1416 data[QStringLiteral(
"hasM" )] = hasM;
1417 data[QStringLiteral(
"hasZ" )] = hasZ;
1419 QVariantList pointsList;
1421 pointsList.reserve( size );
1423 QVariantList pointList;
1424 for (
int i = 0; i < size; ++i )
1429 pointList.append( point->
x() );
1430 pointList.append( point->
y() );
1432 pointList.append( point->
z() );
1433 if ( hasM && !std::isnan( point->
m() ) )
1434 pointList.append( point->
m() );
1436 pointsList.push_back( pointList );
1439 data[QStringLiteral(
"points" )] = pointsList;
1443QVariantList QgsArcGisRestUtils::lineStringToJsonPath(
const QgsLineString *line )
1445 const bool hasZ = line->
is3D();
1448 QVariantList pointsList;
1450 pointsList.reserve( size );
1452 QVariantList pointList;
1453 const double *xData = line->
xData();
1454 const double *yData = line->
yData();
1455 const double *zData = hasZ ? line->
zData() :
nullptr;
1456 const double *mData = hasM ? line->
mData() :
nullptr;
1458 for (
int i = 0; i < size; ++i )
1461 pointList.append( *xData++ );
1462 pointList.append( *yData++ );
1465 pointList.append( *zData++ );
1467 if ( hasM && !std::isnan( *mData ) )
1468 pointList.append( *mData );
1472 pointsList.push_back( pointList );
1477QVariantList QgsArcGisRestUtils::curveToJsonCurve(
const QgsCurve *curve,
bool includeStart )
1479 const bool hasZ = curve->
is3D();
1482 auto pointToList = [hasZ, hasM](
const QgsPoint & point ) -> QVariantList
1484 QVariantList pointList;
1486 pointList.append( point.
x() );
1487 pointList.append( point.
y() );
1490 pointList.append( point.
z() );
1492 if ( hasM && !std::isnan( point.
m() ) )
1493 pointList.append( point.
m() );
1503 QVariantList part = lineStringToJsonPath( qgsgeometry_cast< const QgsLineString *>( curve ) );
1504 if ( !part.isEmpty() && !includeStart )
1512 const QgsCircularString *circularString = qgsgeometry_cast<const QgsCircularString * >( curve );
1513 if ( includeStart && !circularString->
isEmpty() )
1515 res.push_back( pointToList( circularString->
startPoint() ) );
1518 const int size = circularString->
numPoints();
1519 for (
int i = 1; i + 1 < size; i += 2 )
1522 QVariantMap curvePart;
1523 QVariantList curveList;
1524 curveList.push_back( pointToList( circularString->
pointN( i + 1 ) ) );
1526 curveList.push_back( pointToList( circularString->
pointN( i ) ) );
1528 curvePart.insert( QStringLiteral(
"c" ), curveList );
1529 res.push_back( curvePart );
1536 const QgsCompoundCurve *compoundCurve = qgsgeometry_cast<const QgsCompoundCurve * >( curve );
1538 const int size = compoundCurve->
nCurves();
1539 for (
int i = 0; i < size; ++i )
1542 res.append( curveToJsonCurve( subCurve, i == 0 ) );
1553QVariantMap QgsArcGisRestUtils::lineStringToJson(
const QgsLineString *line )
1556 const bool hasZ = line->
is3D();
1558 data[QStringLiteral(
"hasM" )] = hasM;
1559 data[QStringLiteral(
"hasZ" )] = hasZ;
1561 const QVariantList pointsList = lineStringToJsonPath( line );
1563 QVariantList pointsData = QVariantList();
1564 pointsData.push_back( pointsList );
1565 data[QStringLiteral(
"paths" )] = pointsData;
1570QVariantMap QgsArcGisRestUtils::curveToJson(
const QgsCurve *curve )
1573 const bool hasZ = curve->
is3D();
1575 data[QStringLiteral(
"hasM" )] = hasM;
1576 data[QStringLiteral(
"hasZ" )] = hasZ;
1578 const QVariantList curveList = curveToJsonCurve( curve,
true );
1580 QVariantList curveData = QVariantList();
1581 curveData.push_back( curveList );
1582 data[QStringLiteral(
"curvePaths" )] = curveData;
1587QVariantMap QgsArcGisRestUtils::multiLineStringToJson(
const QgsMultiLineString *multiLine )
1590 const bool hasZ = multiLine->
is3D();
1591 const bool hasM = multiLine->
isMeasure();
1592 data[QStringLiteral(
"hasM" )] = hasM;
1593 data[QStringLiteral(
"hasZ" )] = hasZ;
1597 paths.reserve( size );
1598 for (
int i = 0; i < size; ++i )
1601 paths.push_back( lineStringToJsonPath( line ) );
1604 data[QStringLiteral(
"paths" )] = paths;
1608QVariantMap QgsArcGisRestUtils::multiCurveToJson(
const QgsMultiCurve *multiCurve )
1611 const bool hasZ = multiCurve->
is3D();
1612 const bool hasM = multiCurve->
isMeasure();
1613 data[QStringLiteral(
"hasM" )] = hasM;
1614 data[QStringLiteral(
"hasZ" )] = hasZ;
1618 paths.reserve( size );
1619 for (
int i = 0; i < size; ++i )
1622 paths.push_back( curveToJsonCurve( curve,
true ) );
1625 data[QStringLiteral(
"curvePaths" )] = paths;
1629QVariantList QgsArcGisRestUtils::polygonToJsonRings(
const QgsPolygon *polygon )
1633 rings.reserve( numInteriorRings + 1 );
1641 rings.push_back( lineStringToJsonPath( exterior ) );
1646 std::unique_ptr< QgsLineString > reversed( exterior->
reversed() );
1647 rings.push_back( lineStringToJsonPath( reversed.get() ) );
1655 for (
int i = 0; i < numInteriorRings; ++i )
1662 rings.push_back( lineStringToJsonPath( ring ) );
1667 std::unique_ptr< QgsLineString > reversed( ring->
reversed() );
1668 rings.push_back( lineStringToJsonPath( reversed.get() ) );
1678QVariantList QgsArcGisRestUtils::curvePolygonToJsonRings(
const QgsCurvePolygon *polygon )
1682 rings.reserve( numInteriorRings + 1 );
1684 if (
const QgsCurve *exterior = qgsgeometry_cast< const QgsCurve * >( polygon->
exteriorRing() ) )
1690 rings.push_back( curveToJsonCurve( exterior,
true ) );
1695 std::unique_ptr< QgsCurve > reversed( exterior->
reversed() );
1696 rings.push_back( curveToJsonCurve( reversed.get(),
true ) );
1704 for (
int i = 0; i < numInteriorRings; ++i )
1711 rings.push_back( curveToJsonCurve( ring,
true ) );
1716 std::unique_ptr< QgsCurve > reversed( ring->
reversed() );
1717 rings.push_back( curveToJsonCurve( reversed.get(),
true ) );
1727QVariantMap QgsArcGisRestUtils::polygonToJson(
const QgsPolygon *polygon )
1730 const bool hasZ = polygon->
is3D();
1732 data[QStringLiteral(
"hasM" )] = hasM;
1733 data[QStringLiteral(
"hasZ" )] = hasZ;
1734 data[QStringLiteral(
"rings" )] = polygonToJsonRings( polygon );
1738QVariantMap QgsArcGisRestUtils::curvePolygonToJson(
const QgsCurvePolygon *polygon )
1741 const bool hasZ = polygon->
is3D();
1743 data[QStringLiteral(
"hasM" )] = hasM;
1744 data[QStringLiteral(
"hasZ" )] = hasZ;
1745 data[QStringLiteral(
"curveRings" )] = curvePolygonToJsonRings( polygon );
1749QVariantMap QgsArcGisRestUtils::multiPolygonToJson(
const QgsMultiPolygon *multiPolygon )
1752 const bool hasZ = multiPolygon->
is3D();
1753 const bool hasM = multiPolygon->
isMeasure();
1754 data[QStringLiteral(
"hasM" )] = hasM;
1755 data[QStringLiteral(
"hasZ" )] = hasZ;
1759 for (
int i = 0; i < size; ++i )
1762 rings.append( polygonToJsonRings( polygon ) );
1765 data[QStringLiteral(
"rings" )] = rings;
1769QVariantMap QgsArcGisRestUtils::multiSurfaceToJson(
const QgsMultiSurface *multiSurface )
1772 const bool hasZ = multiSurface->
is3D();
1773 const bool hasM = multiSurface->
isMeasure();
1774 data[QStringLiteral(
"hasM" )] = hasM;
1775 data[QStringLiteral(
"hasZ" )] = hasZ;
1779 for (
int i = 0; i < size; ++i )
1785 rings.append( curvePolygonToJsonRings( polygon ) );
1788 data[QStringLiteral(
"curveRings" )] = rings;
1799 if ( !authid.isEmpty() )
1801 const thread_local QRegularExpression rxAuthid( QStringLiteral(
"(\\w+):(\\d+)" ) );
1802 const QRegularExpressionMatch match = rxAuthid.match( authid );
1803 if ( match.hasMatch()
1805 ( match.captured( 1 ).compare( QLatin1String(
"EPSG" ), Qt::CaseInsensitive ) == 0 )
1806 || ( match.captured( 1 ).compare( QLatin1String(
"ESRI" ), Qt::CaseInsensitive ) == 0 )
1810 const QString wkid = match.captured( 2 );
1811 res.insert( QStringLiteral(
"wkid" ), wkid );
1830 QVariantMap attributes;
1832 for (
const QgsField &field : fields )
1837 if ( !attributes.isEmpty() )
1839 res.insert( QStringLiteral(
"attributes" ), attributes );
1849 switch ( expectedType )
1851 case QMetaType::Type::QString:
1853 const QString escaped = variant.toString().replace(
'\\', QLatin1String(
"\\\\" ) ).replace(
'"', QLatin1String(
"\\\"" ) );
1854 return QString( QUrl::toPercentEncoding( escaped,
"'" ) );
1857 case QMetaType::Type::QDateTime:
1858 case QMetaType::Type::QDate:
1860 switch ( variant.userType() )
1862 case QMetaType::Type::QDateTime:
1863 return variant.toDateTime().toMSecsSinceEpoch();
1865 case QMetaType::Type::QDate:
1867 if ( context.
timeZone().isValid() )
1868 return QDateTime( variant.toDate(), QTime( 0, 0, 0 ), context.
timeZone() ).toMSecsSinceEpoch();
1870 return QDateTime( variant.toDate(), QTime( 0, 0, 0 ) ).toMSecsSinceEpoch();
1885 res.insert( QStringLiteral(
"name" ), field.
name() );
1888 switch ( field.
type() )
1890 case QMetaType::Type::LongLong:
1891 fieldType = QStringLiteral(
"esriFieldTypeInteger" );
1894 case QMetaType::Type::Int:
1895 fieldType = QStringLiteral(
"esriFieldTypeSmallInteger" );
1898 case QMetaType::Type::Double:
1899 fieldType = QStringLiteral(
"esriFieldTypeDouble" );
1902 case QMetaType::Type::QString:
1903 fieldType = QStringLiteral(
"esriFieldTypeString" );
1906 case QMetaType::Type::QDateTime:
1907 case QMetaType::Type::QDate:
1908 fieldType = QStringLiteral(
"esriFieldTypeDate" );
1911 case QMetaType::Type::QByteArray:
1912 fieldType = QStringLiteral(
"esriFieldTypeBlob" );
1917 fieldType = QStringLiteral(
"esriFieldTypeString" );
1920 res.insert( QStringLiteral(
"type" ), fieldType );
1922 if ( !field.
alias().isEmpty() )
1923 res.insert( QStringLiteral(
"alias" ), field.
alias() );
1927 res.insert( QStringLiteral(
"nullable" ), !notNullable );
1930 res.insert( QStringLiteral(
"editable" ),
true );
1937 if ( type.compare( QLatin1String(
"FeatureServer" ), Qt::CaseInsensitive ) == 0 )
1939 else if ( type.compare( QLatin1String(
"MapServer" ), Qt::CaseInsensitive ) == 0 )
1941 else if ( type.compare( QLatin1String(
"ImageServer" ), Qt::CaseInsensitive ) == 0 )
1943 else if ( type.compare( QLatin1String(
"GlobeServer" ), Qt::CaseInsensitive ) == 0 )
1945 else if ( type.compare( QLatin1String(
"GPServer" ), Qt::CaseInsensitive ) == 0 )
1947 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, Qgis::GeosCreationFlags flags=Qgis::GeosCreationFlag::SkipEmptyInteriorRings)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
Represents a color stop within a QgsGradientColorRamp color ramp.
void setPlacementFlags(Qgis::LabelLinePlacementFlags flags)
Returns the line placement flags, which dictate how line labels can be placed above or below the line...
void setQuadrant(Qgis::LabelQuadrantPosition quadrant)
Sets the quadrant in which to offset labels from the point.
Line string geometry type, with support for z-dimension and m-values.
const double * yData() const
Returns a const pointer to the y vertex data.
const double * xData() const
Returns a const pointer to the x vertex data.
const double * zData() const
Returns a const pointer to the z vertex data, or nullptr if the linestring does not have z values.
int numPoints() const override
Returns the number of points in the curve.
QgsLineString * reversed() const override
Returns a reversed copy of the curve, where the direction of the curve has been flipped.
const double * mData() const
Returns a const pointer to the m vertex data, or nullptr if the linestring does not have m values.
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