46#include <QRegularExpression>
58 if ( esriFieldType == QLatin1String(
"esriFieldTypeInteger" ) )
59 return QMetaType::Type::LongLong;
60 if ( esriFieldType == QLatin1String(
"esriFieldTypeSmallInteger" ) )
61 return QMetaType::Type::Int;
62 if ( esriFieldType == QLatin1String(
"esriFieldTypeDouble" ) )
63 return QMetaType::Type::Double;
64 if ( esriFieldType == QLatin1String(
"esriFieldTypeSingle" ) )
65 return QMetaType::Type::Double;
66 if ( esriFieldType == QLatin1String(
"esriFieldTypeString" ) )
67 return QMetaType::Type::QString;
68 if ( esriFieldType == QLatin1String(
"esriFieldTypeDate" ) )
69 return QMetaType::Type::QDateTime;
70 if ( esriFieldType == QLatin1String(
"esriFieldTypeGeometry" ) )
71 return QMetaType::Type::UnknownType;
72 if ( esriFieldType == QLatin1String(
"esriFieldTypeOID" ) )
73 return QMetaType::Type::LongLong;
74 if ( esriFieldType == QLatin1String(
"esriFieldTypeBlob" ) )
75 return QMetaType::Type::QByteArray;
76 if ( esriFieldType == QLatin1String(
"esriFieldTypeGlobalID" ) )
77 return QMetaType::Type::QString;
78 if ( esriFieldType == QLatin1String(
"esriFieldTypeRaster" ) )
79 return QMetaType::Type::QByteArray;
80 if ( esriFieldType == QLatin1String(
"esriFieldTypeGUID" ) )
81 return QMetaType::Type::QString;
82 if ( esriFieldType == QLatin1String(
"esriFieldTypeXML" ) )
83 return QMetaType::Type::QString;
84 return QMetaType::Type::UnknownType;
90 if ( esriGeometryType == QLatin1String(
"esriGeometryNull" ) )
92 else if ( esriGeometryType == QLatin1String(
"esriGeometryPoint" ) )
94 else if ( esriGeometryType == QLatin1String(
"esriGeometryMultipoint" ) )
96 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolyline" ) )
98 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolygon" ) )
100 else if ( esriGeometryType == QLatin1String(
"esriGeometryEnvelope" ) )
120std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertPoint(
const QVariantList &coordList,
Qgis::WkbType pointType )
122 int nCoords = coordList.size();
125 bool xok =
false, yok =
false;
126 const double x = coordList[0].toDouble( &xok );
127 const double y = coordList[1].toDouble( &yok );
131 const double z = hasZ && nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
134 const double m =
QgsWkbTypes::hasM( pointType ) && ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[ hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
135 return std::make_unique< QgsPoint >( pointType, x, y, z, m );
138std::unique_ptr< QgsCircularString > QgsArcGisRestUtils::convertCircularString(
const QVariantMap &curveData,
Qgis::WkbType pointType,
const QgsPoint &startPoint )
140 const QVariantList coordsList = curveData[QStringLiteral(
"c" )].toList();
141 if ( coordsList.isEmpty() )
143 const int coordsListSize = coordsList.size();
145 QVector<QgsPoint> points;
146 points.reserve( coordsListSize + 1 );
147 points.append( startPoint );
149 for (
int i = 0; i < coordsListSize - 1; )
153 std::unique_ptr< QgsPoint > endPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
157 std::unique_ptr< QgsPoint > interiorPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
158 if ( !interiorPoint )
161 points << *interiorPoint;
164 std::unique_ptr< QgsCircularString > curve = std::make_unique< QgsCircularString> ();
165 curve->setPoints( points );
169std::unique_ptr< QgsCompoundCurve > QgsArcGisRestUtils::convertCompoundCurve(
const QVariantList &curvesList,
Qgis::WkbType pointType )
172 std::unique_ptr< QgsCompoundCurve > compoundCurve = std::make_unique< QgsCompoundCurve >();
174 QVector< double > lineX;
175 QVector< double > lineY;
176 QVector< double > lineZ;
177 QVector< double > lineM;
178 int maxCurveListSize = curvesList.size();
179 lineX.resize( maxCurveListSize );
180 lineY.resize( maxCurveListSize );
184 lineZ.resize( maxCurveListSize );
187 lineM.resize( maxCurveListSize );
189 double *outLineX = lineX.data();
190 double *outLineY = lineY.data();
191 double *outLineZ = lineZ.data();
192 double *outLineM = lineM.data();
193 int actualLineSize = 0;
198 int curveListIndex = 0;
199 for (
const QVariant &curveData : curvesList )
201 if ( curveData.userType() == QMetaType::Type::QVariantList )
203 const QVariantList coordList = curveData.toList();
204 const int nCoords = coordList.size();
208 const double x = coordList[0].toDouble( &xok );
209 const double y = coordList[1].toDouble( &yok );
218 *outLineZ++ = nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
224 *outLineM++ = ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[ hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
227 else if ( curveData.userType() == QMetaType::Type::QVariantMap )
231 if ( actualLineSize > 0 )
233 lastLineStringPoint =
QgsPoint( lineX.at( actualLineSize - 1 ),
234 lineY.at( actualLineSize - 1 ),
235 hasZ ? lineZ.at( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN(),
236 hasM ? lineM.at( actualLineSize - 1 ) : std::numeric_limits< double >::quiet_NaN() );
238 std::unique_ptr< QgsCircularString > circularString( convertCircularString( curveData.toMap(), pointType, lastLineStringPoint ) );
239 if ( !circularString )
244 if ( actualLineSize > 0 )
246 lineX.resize( actualLineSize );
247 lineY.resize( actualLineSize );
249 lineZ.resize( actualLineSize );
251 lineM.resize( actualLineSize );
253 compoundCurve->addCurve(
new QgsLineString( lineX, lineY, lineZ, lineM ) );
254 lineX.resize( maxCurveListSize - curveListIndex );
255 lineY.resize( maxCurveListSize - curveListIndex );
257 lineZ.resize( maxCurveListSize - curveListIndex );
259 lineM.resize( maxCurveListSize - curveListIndex );
260 outLineX = lineX.data();
261 outLineY = lineY.data();
262 outLineZ = lineZ.data();
263 outLineM = lineM.data();
267 if ( compoundCurve->curveAt( compoundCurve->nCurves() - 1 )->nCoordinates() < 2 )
268 compoundCurve->removeCurve( compoundCurve->nCurves() - 1 );
270 const QgsPoint endPointCircularString = circularString->endPoint();
271 compoundCurve->addCurve( circularString.release() );
275 *outLineX++ = endPointCircularString.
x();
276 *outLineY++ = endPointCircularString.
y();
278 *outLineZ++ = endPointCircularString.
z();
280 *outLineM++ = endPointCircularString.
m();
285 if ( actualLineSize == 1 && compoundCurve->nCurves() > 0 )
287 const QgsCurve *finalCurve = compoundCurve->curveAt( compoundCurve->nCurves() - 1 );
291 && ( !hasZ ||
qgsDoubleNear( finalCurveEndPoint.
z(), lineZ.at( 0 ) ) )
292 && ( !hasM ||
qgsDoubleNear( finalCurveEndPoint.
m(), lineM.at( 0 ) ) ) )
298 if ( actualLineSize > 0 )
300 lineX.resize( actualLineSize );
301 lineY.resize( actualLineSize );
303 lineZ.resize( actualLineSize );
305 lineM.resize( actualLineSize );
306 compoundCurve->addCurve(
new QgsLineString( lineX, lineY, lineZ, lineM ) );
309 return compoundCurve;
312std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertGeometryPoint(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
315 bool xok =
false, yok =
false;
316 double x = geometryData[QStringLiteral(
"x" )].toDouble( &xok );
317 double y = geometryData[QStringLiteral(
"y" )].toDouble( &yok );
320 double z = geometryData[QStringLiteral(
"z" )].toDouble();
321 double m = geometryData[QStringLiteral(
"m" )].toDouble();
322 return std::make_unique< QgsPoint >( pointType, x, y, z, m );
325std::unique_ptr< QgsMultiPoint > QgsArcGisRestUtils::convertMultiPoint(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
328 const QVariantList coordsList = geometryData[QStringLiteral(
"points" )].toList();
330 std::unique_ptr< QgsMultiPoint > multiPoint = std::make_unique< QgsMultiPoint >();
331 multiPoint->reserve( coordsList.size() );
332 for (
const QVariant &coordData : coordsList )
334 const QVariantList coordList = coordData.toList();
335 std::unique_ptr< QgsPoint > p = convertPoint( coordList, pointType );
340 multiPoint->addGeometry( p.release() );
345 std::unique_ptr< QgsPoint > p = convertGeometryPoint( geometryData, pointType );
347 multiPoint->addGeometry( p.release() );
349 if ( multiPoint->numGeometries() == 0 )
357std::unique_ptr< QgsMultiCurve > QgsArcGisRestUtils::convertGeometryPolyline(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
360 QVariantList pathsList;
361 if ( geometryData[QStringLiteral(
"paths" )].isValid() )
362 pathsList = geometryData[QStringLiteral(
"paths" )].toList();
363 else if ( geometryData[QStringLiteral(
"curvePaths" )].isValid() )
364 pathsList = geometryData[QStringLiteral(
"curvePaths" )].toList();
365 if ( pathsList.isEmpty() )
367 std::unique_ptr< QgsMultiCurve > multiCurve = std::make_unique< QgsMultiCurve >();
368 multiCurve->reserve( pathsList.size() );
369 for (
const QVariant &pathData : std::as_const( pathsList ) )
371 std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( pathData.toList(), pointType );
376 multiCurve->addGeometry( curve.release() );
381std::unique_ptr< QgsMultiSurface > QgsArcGisRestUtils::convertGeometryPolygon(
const QVariantMap &geometryData,
Qgis::WkbType pointType )
384 QVariantList ringsList;
385 if ( geometryData[QStringLiteral(
"rings" )].isValid() )
386 ringsList = geometryData[QStringLiteral(
"rings" )].toList();
387 else if ( geometryData[QStringLiteral(
"ringPaths" )].isValid() )
388 ringsList = geometryData[QStringLiteral(
"ringPaths" )].toList();
389 if ( ringsList.isEmpty() )
392 QList< QgsCompoundCurve * > curves;
393 for (
int i = 0, n = ringsList.size(); i < n; ++i )
395 std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( ringsList[i].toList(), pointType );
400 curves.append( curve.release() );
402 if ( curves.count() == 0 )
405 std::unique_ptr< QgsMultiSurface > result = std::make_unique< QgsMultiSurface >();
406 if ( curves.count() == 1 )
409 std::unique_ptr< QgsCurvePolygon > newPolygon = std::make_unique< QgsCurvePolygon >();
410 newPolygon->setExteriorRing( curves.takeAt( 0 ) );
411 result->addGeometry( newPolygon.release() );
415 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 ); } );
416 result->reserve( curves.size() );
417 while ( !curves.isEmpty() )
423 engine->prepareGeometry();
425 QMutableListIterator< QgsCompoundCurve * > it( curves );
426 while ( it.hasNext() )
433 if ( engine->contains( &point ) )
438 engine->prepareGeometry();
442 result->addGeometry( newPolygon );
444 if ( result->numGeometries() == 0 )
450std::unique_ptr< QgsPolygon > QgsArcGisRestUtils::convertEnvelope(
const QVariantMap &geometryData )
453 bool xminOk =
false, yminOk =
false, xmaxOk =
false, ymaxOk =
false;
454 double xmin = geometryData[QStringLiteral(
"xmin" )].toDouble( &xminOk );
455 double ymin = geometryData[QStringLiteral(
"ymin" )].toDouble( &yminOk );
456 double xmax = geometryData[QStringLiteral(
"xmax" )].toDouble( &xmaxOk );
457 double ymax = geometryData[QStringLiteral(
"ymax" )].toDouble( &ymaxOk );
458 if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk )
460 std::unique_ptr< QgsLineString > ext = std::make_unique< QgsLineString> ();
461 ext->addVertex(
QgsPoint( xmin, ymin ) );
462 ext->addVertex(
QgsPoint( xmax, ymin ) );
463 ext->addVertex(
QgsPoint( xmax, ymax ) );
464 ext->addVertex(
QgsPoint( xmin, ymax ) );
465 ext->addVertex(
QgsPoint( xmin, ymin ) );
466 std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
467 poly->setExteriorRing( ext.release() );
480 if ( esriGeometryType == QLatin1String(
"esriGeometryNull" ) )
482 else if ( esriGeometryType == QLatin1String(
"esriGeometryPoint" ) )
483 return convertGeometryPoint( geometryData, pointType ).release();
484 else if ( esriGeometryType == QLatin1String(
"esriGeometryMultipoint" ) )
485 return convertMultiPoint( geometryData, pointType ).release();
486 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolyline" ) )
487 return convertGeometryPolyline( geometryData, pointType ).release();
488 else if ( esriGeometryType == QLatin1String(
"esriGeometryPolygon" ) )
489 return convertGeometryPolygon( geometryData, pointType ).release();
490 else if ( esriGeometryType == QLatin1String(
"esriGeometryEnvelope" ) )
491 return convertEnvelope( geometryData ).release();
514 QString spatialReference = spatialReferenceMap[QStringLiteral(
"latestWkid" )].toString();
515 if ( spatialReference.isEmpty() )
516 spatialReference = spatialReferenceMap[QStringLiteral(
"wkid" )].toString();
519 if ( !spatialReference.isEmpty() )
528 else if ( !spatialReferenceMap[QStringLiteral(
"wkt" )].toString().isEmpty() )
531 crs.
createFromWkt( spatialReferenceMap[QStringLiteral(
"wkt" )].toString() );
546 const QString type = symbolData.value( QStringLiteral(
"type" ) ).toString();
547 if ( type == QLatin1String(
"esriSMS" ) )
550 return parseEsriMarkerSymbolJson( symbolData ).release();
552 else if ( type == QLatin1String(
"esriSLS" ) )
555 return parseEsriLineSymbolJson( symbolData ).release();
557 else if ( type == QLatin1String(
"esriSFS" ) )
560 return parseEsriFillSymbolJson( symbolData ).release();
562 else if ( type == QLatin1String(
"esriPFS" ) )
564 return parseEsriPictureFillSymbolJson( symbolData ).release();
566 else if ( type == QLatin1String(
"esriPMS" ) )
569 return parseEsriPictureMarkerSymbolJson( symbolData ).release();
571 else if ( type == QLatin1String(
"esriTS" ) )
573 return parseEsriTextMarkerSymbolJson( symbolData ).release();
578std::unique_ptr<QgsLineSymbol> QgsArcGisRestUtils::parseEsriLineSymbolJson(
const QVariantMap &symbolData )
580 QColor lineColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
581 if ( !lineColor.isValid() )
585 double widthInPoints = symbolData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
590 Qt::PenStyle penStyle =
convertLineStyle( symbolData.value( QStringLiteral(
"style" ) ).toString() );
591 std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( lineColor, widthInPoints, penStyle );
593 layers.append( lineLayer.release() );
595 std::unique_ptr< QgsLineSymbol > symbol = std::make_unique< QgsLineSymbol >( layers );
599std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriFillSymbolJson(
const QVariantMap &symbolData )
601 QColor fillColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
602 Qt::BrushStyle brushStyle =
convertFillStyle( symbolData.value( QStringLiteral(
"style" ) ).toString() );
604 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
605 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
606 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
608 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
611 std::unique_ptr< QgsSimpleFillSymbolLayer > fillLayer = std::make_unique< QgsSimpleFillSymbolLayer >( fillColor, brushStyle, lineColor, penStyle, penWidthInPoints );
613 layers.append( fillLayer.release() );
615 std::unique_ptr< QgsFillSymbol > symbol = std::make_unique< QgsFillSymbol >( layers );
619std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriPictureFillSymbolJson(
const QVariantMap &symbolData )
623 double widthInPixels = symbolData.value( QStringLiteral(
"width" ) ).toInt( &ok );
627 const double xScale = symbolData.value( QStringLiteral(
"xscale" ) ).toDouble( &ok );
629 widthInPixels *= xScale;
631 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
636 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
637 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
639 QString symbolPath( symbolData.value( QStringLiteral(
"imageData" ) ).toString() );
640 symbolPath.prepend( QLatin1String(
"base64:" ) );
643 std::unique_ptr< QgsRasterFillSymbolLayer > fillLayer = std::make_unique< QgsRasterFillSymbolLayer >( symbolPath );
644 fillLayer->setWidth( widthInPixels );
645 fillLayer->setAngle( angleCW );
647 fillLayer->setOffset( QPointF( xOffset, yOffset ) );
649 layers.append( fillLayer.release() );
651 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
652 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
653 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
654 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
656 std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( lineColor, penWidthInPoints, penStyle );
658 layers.append( lineLayer.release() );
660 std::unique_ptr< QgsFillSymbol > symbol = std::make_unique< QgsFillSymbol >( layers );
664Qgis::MarkerShape QgsArcGisRestUtils::parseEsriMarkerShape(
const QString &style )
666 if ( style == QLatin1String(
"esriSMSCircle" ) )
668 else if ( style == QLatin1String(
"esriSMSCross" ) )
670 else if ( style == QLatin1String(
"esriSMSDiamond" ) )
672 else if ( style == QLatin1String(
"esriSMSSquare" ) )
674 else if ( style == QLatin1String(
"esriSMSX" ) )
676 else if ( style == QLatin1String(
"esriSMSTriangle" ) )
682std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriMarkerSymbolJson(
const QVariantMap &symbolData )
684 QColor fillColor =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
686 const double sizeInPoints = symbolData.value( QStringLiteral(
"size" ) ).toDouble( &ok );
689 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
694 Qgis::MarkerShape shape = parseEsriMarkerShape( symbolData.value( QStringLiteral(
"style" ) ).toString() );
696 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
697 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
699 const QVariantMap outlineData = symbolData.value( QStringLiteral(
"outline" ) ).toMap();
700 QColor lineColor =
convertColor( outlineData.value( QStringLiteral(
"color" ) ) );
701 Qt::PenStyle penStyle =
convertLineStyle( outlineData.value( QStringLiteral(
"style" ) ).toString() );
702 double penWidthInPoints = outlineData.value( QStringLiteral(
"width" ) ).toDouble( &ok );
705 std::unique_ptr< QgsSimpleMarkerSymbolLayer > markerLayer = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, sizeInPoints, angleCW,
Qgis::ScaleMethod::ScaleArea, fillColor, lineColor );
708 markerLayer->setStrokeStyle( penStyle );
709 markerLayer->setStrokeWidth( penWidthInPoints );
710 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
712 layers.append( markerLayer.release() );
714 std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
718std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriPictureMarkerSymbolJson(
const QVariantMap &symbolData )
721 const double widthInPixels = symbolData.value( QStringLiteral(
"width" ) ).toInt( &ok );
724 const double heightInPixels = symbolData.value( QStringLiteral(
"height" ) ).toInt( &ok );
728 const double angleCCW = symbolData.value( QStringLiteral(
"angle" ) ).toDouble( &ok );
733 const double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
734 const double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
738 QString symbolPath( symbolData.value( QStringLiteral(
"imageData" ) ).toString() );
739 symbolPath.prepend( QLatin1String(
"base64:" ) );
742 std::unique_ptr< QgsRasterMarkerSymbolLayer > markerLayer = std::make_unique< QgsRasterMarkerSymbolLayer >( symbolPath, widthInPixels, angleCW,
Qgis::ScaleMethod::ScaleArea );
746 if ( !
qgsDoubleNear(
static_cast< double >( heightInPixels ) / widthInPixels, markerLayer->defaultAspectRatio() ) )
747 markerLayer->setFixedAspectRatio(
static_cast< double >( heightInPixels ) / widthInPixels );
749 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
751 layers.append( markerLayer.release() );
753 std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
757std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriTextMarkerSymbolJson(
const QVariantMap &symbolData )
761 const QString fontFamily = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"family" ) ).toString();
763 const QString chr = symbolData.value( QStringLiteral(
"text" ) ).toString();
765 const double pointSize = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"size" ) ).toDouble();
767 const QColor color =
convertColor( symbolData.value( QStringLiteral(
"color" ) ) );
769 const double esriAngle = symbolData.value( QStringLiteral(
"angle" ) ).toDouble();
771 const double angle = 90.0 - esriAngle;
773 std::unique_ptr< QgsFontMarkerSymbolLayer > markerLayer = std::make_unique< QgsFontMarkerSymbolLayer >( fontFamily, chr, pointSize, color, angle );
775 QColor strokeColor =
convertColor( symbolData.value( QStringLiteral(
"borderLineColor" ) ) );
776 markerLayer->setStrokeColor( strokeColor );
778 double borderLineSize = symbolData.value( QStringLiteral(
"borderLineSize" ) ).toDouble();
779 markerLayer->setStrokeWidth( borderLineSize );
781 const QString fontStyle = symbolData.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"style" ) ).toString();
782 markerLayer->setFontStyle( fontStyle );
784 double xOffset = symbolData.value( QStringLiteral(
"xoffset" ) ).toDouble();
785 double yOffset = symbolData.value( QStringLiteral(
"yoffset" ) ).toDouble();
787 markerLayer->setOffset( QPointF( xOffset, yOffset ) );
796 QString horizontalAnchorPoint = symbolData.value( QStringLiteral(
"horizontalAlignment" ) ).toString();
797 QString verticalAnchorPoint = symbolData.value( QStringLiteral(
"verticalAlignment" ) ).toString();
799 if ( horizontalAnchorPoint == QString(
"center" ) )
803 else if ( horizontalAnchorPoint == QString(
"left" ) )
807 else if ( horizontalAnchorPoint == QString(
"right" ) )
812 if ( verticalAnchorPoint == QString(
"center" ) )
816 else if ( verticalAnchorPoint == QString(
"top" ) )
820 else if ( verticalAnchorPoint == QString(
"bottom" ) )
825 markerLayer->setHorizontalAnchorPoint( hAlign );
826 markerLayer->setVerticalAnchorPoint( vAlign );
828 layers.append( markerLayer.release() );
830 std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
836 if ( labelingData.empty() )
843 for (
const QVariant &lbl : labelingData )
845 const QVariantMap labeling = lbl.toMap();
850 const QString placement = labeling.value( QStringLiteral(
"labelPlacement" ) ).toString();
851 if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveCenter" ) )
856 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowCenter" ) )
861 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterCenter" ) )
866 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveLeft" ) )
871 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowLeft" ) )
876 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterLeft" ) )
881 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementAboveRight" ) )
886 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementBelowRight" ) )
891 else if ( placement == QLatin1String(
"esriServerPointLabelPlacementCenterRight" ) )
896 else if ( placement == QLatin1String(
"esriServerLinePlacementAboveAfter" ) ||
897 placement == QLatin1String(
"esriServerLinePlacementAboveStart" ) ||
898 placement == QLatin1String(
"esriServerLinePlacementAboveAlong" ) )
903 else if ( placement == QLatin1String(
"esriServerLinePlacementBelowAfter" ) ||
904 placement == QLatin1String(
"esriServerLinePlacementBelowStart" ) ||
905 placement == QLatin1String(
"esriServerLinePlacementBelowAlong" ) )
910 else if ( placement == QLatin1String(
"esriServerLinePlacementCenterAfter" ) ||
911 placement == QLatin1String(
"esriServerLinePlacementCenterStart" ) ||
912 placement == QLatin1String(
"esriServerLinePlacementCenterAlong" ) )
917 else if ( placement == QLatin1String(
"esriServerPolygonPlacementAlwaysHorizontal" ) )
922 const double minScale = labeling.value( QStringLiteral(
"minScale" ) ).toDouble();
923 const double maxScale = labeling.value( QStringLiteral(
"maxScale" ) ).toDouble();
925 QVariantMap symbol = labeling.value( QStringLiteral(
"symbol" ) ).toMap();
927 const double haloSize = symbol.value( QStringLiteral(
"haloSize" ) ).toDouble();
938 const QString fontFamily = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"family" ) ).toString();
939 const QString fontStyle = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"style" ) ).toString();
940 const QString fontWeight = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"weight" ) ).toString();
941 const int fontSize = symbol.value( QStringLiteral(
"font" ) ).toMap().value( QStringLiteral(
"size" ) ).toInt();
942 QFont font( fontFamily, fontSize );
943 font.setStyleName( fontStyle );
944 font.setWeight( fontWeight == QLatin1String(
"bold" ) ? QFont::Bold : QFont::Normal );
952 QString where = labeling.value( QStringLiteral(
"where" ) ).toString();
971 const QString type = rendererData.value( QStringLiteral(
"type" ) ).toString();
972 if ( type == QLatin1String(
"simple" ) )
974 const QVariantMap symbolProps = rendererData.value( QStringLiteral(
"symbol" ) ).toMap();
975 std::unique_ptr< QgsSymbol > symbol(
convertSymbol( symbolProps ) );
981 else if ( type == QLatin1String(
"uniqueValue" ) )
983 const QString field1 = rendererData.value( QStringLiteral(
"field1" ) ).toString();
984 const QString field2 = rendererData.value( QStringLiteral(
"field2" ) ).toString();
985 const QString field3 = rendererData.value( QStringLiteral(
"field3" ) ).toString();
987 if ( !field2.isEmpty() || !field3.isEmpty() )
989 const QString delimiter = rendererData.value( QStringLiteral(
"fieldDelimiter" ) ).toString();
990 if ( !field3.isEmpty() )
992 attribute = QStringLiteral(
"concat(\"%1\",'%2',\"%3\",'%4',\"%5\")" ).arg( field1, delimiter, field2, delimiter, field3 );
996 attribute = QStringLiteral(
"concat(\"%1\",'%2',\"%3\")" ).arg( field1, delimiter, field2 );
1004 const QVariantList categories = rendererData.value( QStringLiteral(
"uniqueValueInfos" ) ).toList();
1006 for (
const QVariant &category : categories )
1008 const QVariantMap categoryData = category.toMap();
1009 const QString value = categoryData.value( QStringLiteral(
"value" ) ).toString();
1010 const QString label = categoryData.value( QStringLiteral(
"label" ) ).toString();
1018 std::unique_ptr< QgsSymbol > defaultSymbol(
convertSymbol( rendererData.value( QStringLiteral(
"defaultSymbol" ) ).toMap() ) );
1019 if ( defaultSymbol )
1021 categoryList.append(
QgsRendererCategory( QVariant(), defaultSymbol.release(), rendererData.value( QStringLiteral(
"defaultLabel" ) ).toString() ) );
1024 if ( categoryList.empty() )
1029 else if ( type == QLatin1String(
"classBreaks" ) )
1031 const QString attrName = rendererData.value( QStringLiteral(
"field" ) ).toString();
1032 std::unique_ptr< QgsGraduatedSymbolRenderer > graduatedRenderer = std::make_unique< QgsGraduatedSymbolRenderer >( attrName );
1034 const QVariantList classBreakInfos = rendererData.value( QStringLiteral(
"classBreakInfos" ) ).toList();
1035 const QVariantMap authoringInfo = rendererData.value( QStringLiteral(
"authoringInfo" ) ).toMap();
1036 QVariantMap symbolData;
1038 QString esriMode = authoringInfo.value( QStringLiteral(
"classificationMethod" ) ).toString();
1039 if ( esriMode.isEmpty() )
1041 esriMode = rendererData.value( QStringLiteral(
"classificationMethod" ) ).toString();
1044 if ( esriMode == QLatin1String(
"esriClassifyDefinedInterval" ) )
1047 graduatedRenderer->setClassificationMethod( method );
1049 else if ( esriMode == QLatin1String(
"esriClassifyEqualInterval" ) )
1052 graduatedRenderer->setClassificationMethod( method );
1054 else if ( esriMode == QLatin1String(
"esriClassifyGeometricalInterval" ) )
1057 graduatedRenderer->setClassificationMethod( method );
1059 else if ( esriMode == QLatin1String(
"esriClassifyManual" ) )
1062 graduatedRenderer->setClassificationMethod( method );
1064 else if ( esriMode == QLatin1String(
"esriClassifyNaturalBreaks" ) )
1067 graduatedRenderer->setClassificationMethod( method );
1069 else if ( esriMode == QLatin1String(
"esriClassifyQuantile" ) )
1072 graduatedRenderer->setClassificationMethod( method );
1074 else if ( esriMode == QLatin1String(
"esriClassifyStandardDeviation" ) )
1077 graduatedRenderer->setClassificationMethod( method );
1081 QgsDebugError( QStringLiteral(
"ESRI classification mode %1 is not currently supported" ).arg( esriMode ) );
1085 if ( !classBreakInfos.isEmpty() )
1087 symbolData = classBreakInfos.at( 0 ).toMap().value( QStringLiteral(
"symbol" ) ).toMap();
1090 double transparency = rendererData.value( QStringLiteral(
"transparency" ) ).toDouble();
1092 double opacity = ( 100.0 - transparency ) / 100.0;
1098 symbol->setOpacity( opacity );
1099 graduatedRenderer->setSourceSymbol( symbol.release() );
1102 const QVariantList visualVariablesData = rendererData.value( QStringLiteral(
"visualVariables" ) ).toList();
1103 double lastValue = rendererData.value( QStringLiteral(
"minValue" ) ).toDouble();
1104 for (
const QVariant &visualVariable : visualVariablesData )
1106 const QVariantList stops = visualVariable.toMap().value( QStringLiteral(
"stops" ) ).toList();
1107 for (
const QVariant &stop : stops )
1109 const QVariantMap stopData = stop.toMap();
1110 const QString label = stopData.value( QStringLiteral(
"label" ) ).toString();
1111 const double breakpoint = stopData.value( QStringLiteral(
"value" ) ).toDouble();
1112 std::unique_ptr< QgsSymbol > symbolForStop( graduatedRenderer->sourceSymbol()->clone() );
1114 if ( visualVariable.toMap().value( QStringLiteral(
"type" ) ).toString() == QStringLiteral(
"colorInfo" ) )
1117 QColor fillColor =
convertColor( stopData.value( QStringLiteral(
"color" ) ) );
1118 symbolForStop->setColor( fillColor );
1125 range.
setSymbol( symbolForStop.release() );
1127 lastValue = breakpoint;
1128 graduatedRenderer->addClass( range );
1132 lastValue = rendererData.value( QStringLiteral(
"minValue" ) ).toDouble();
1133 for (
const QVariant &classBreakInfo : classBreakInfos )
1135 const QVariantMap symbolData = classBreakInfo.toMap().value( QStringLiteral(
"symbol" ) ).toMap();
1137 double classMaxValue = classBreakInfo.toMap().value( QStringLiteral(
"classMaxValue" ) ).toDouble();
1138 const QString label = classBreakInfo.toMap().value( QStringLiteral(
"label" ) ).toString();
1147 lastValue = classMaxValue;
1148 graduatedRenderer->addClass( range );
1151 return graduatedRenderer.release();
1153 else if ( type == QLatin1String(
"heatmap" ) )
1158 else if ( type == QLatin1String(
"vectorField" ) )
1168 QString expression = string;
1171 const thread_local QRegularExpression rx1 = QRegularExpression( QStringLiteral(
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)CONCAT(\\s|$)" ) );
1172 expression = expression.replace( rx1, QStringLiteral(
"\\4||\\5" ) );
1174 const thread_local QRegularExpression rx2 = QRegularExpression( QStringLiteral(
"(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)NEWLINE(\\s|$)" ) );
1175 expression = expression.replace( rx2, QStringLiteral(
"\\4'\\n'\\5" ) );
1178 const thread_local QRegularExpression rx3 = QRegularExpression( QStringLiteral(
"\"(.*?(?<!\\\\))\"" ) );
1179 expression = expression.replace( rx3, QStringLiteral(
"'\\1'" ) );
1180 const thread_local QRegularExpression rx4 = QRegularExpression( QStringLiteral(
"\\\\\"" ) );
1181 expression = expression.replace( rx4, QStringLiteral(
"\"" ) );
1184 const thread_local QRegularExpression rx5 = QRegularExpression( QStringLiteral(
"\\[([^]]*)\\]" ) );
1185 expression = expression.replace( rx5, QStringLiteral(
"\"\\1\"" ) );
1192 const QVariantList colorParts = colorData.toList();
1193 if ( colorParts.count() < 4 )
1196 int red = colorParts.at( 0 ).toInt();
1197 int green = colorParts.at( 1 ).toInt();
1198 int blue = colorParts.at( 2 ).toInt();
1199 int alpha = colorParts.at( 3 ).toInt();
1200 return QColor( red, green, blue, alpha );
1205 if ( style == QLatin1String(
"esriSLSSolid" ) )
1206 return Qt::SolidLine;
1207 else if ( style == QLatin1String(
"esriSLSDash" ) )
1208 return Qt::DashLine;
1209 else if ( style == QLatin1String(
"esriSLSDashDot" ) )
1210 return Qt::DashDotLine;
1211 else if ( style == QLatin1String(
"esriSLSDashDotDot" ) )
1212 return Qt::DashDotDotLine;
1213 else if ( style == QLatin1String(
"esriSLSDot" ) )
1215 else if ( style == QLatin1String(
"esriSLSNull" ) )
1218 return Qt::SolidLine;
1223 if ( style == QLatin1String(
"esriSFSBackwardDiagonal" ) )
1224 return Qt::BDiagPattern;
1225 else if ( style == QLatin1String(
"esriSFSCross" ) )
1226 return Qt::CrossPattern;
1227 else if ( style == QLatin1String(
"esriSFSDiagonalCross" ) )
1228 return Qt::DiagCrossPattern;
1229 else if ( style == QLatin1String(
"esriSFSForwardDiagonal" ) )
1230 return Qt::FDiagPattern;
1231 else if ( style == QLatin1String(
"esriSFSHorizontal" ) )
1232 return Qt::HorPattern;
1233 else if ( style == QLatin1String(
"esriSFSNull" ) )
1235 else if ( style == QLatin1String(
"esriSFSSolid" ) )
1236 return Qt::SolidPattern;
1237 else if ( style == QLatin1String(
"esriSFSVertical" ) )
1238 return Qt::VerPattern;
1240 return Qt::SolidPattern;
1248 QDateTime dt = QDateTime::fromMSecsSinceEpoch( value.toLongLong( &ok ) );
1251 QgsDebugError( QStringLiteral(
"Invalid value %1 for datetime" ).arg( value.toString() ) );
1263 const QVariantMap coords = value.toMap();
1268 const double xmin = coords.value( QStringLiteral(
"xmin" ) ).toDouble( &ok );
1271 const double ymin = coords.value( QStringLiteral(
"ymin" ) ).toDouble( &ok );
1274 const double xmax = coords.value( QStringLiteral(
"xmax" ) ).toDouble( &ok );
1277 const double ymax = coords.value( QStringLiteral(
"ymax" ) ).toDouble( &ok );
1289 return QVariantMap();
1296 return QVariantMap();
1299 res = pointToJson( qgsgeometry_cast< const QgsPoint * >( geom ) );
1303 res = lineStringToJson( qgsgeometry_cast< const QgsLineString * >( geom ) );
1308 res = curveToJson( qgsgeometry_cast< const QgsCurve * >( geom ) );
1312 res = polygonToJson( qgsgeometry_cast< const QgsPolygon * >( geom ) );
1316 res = multiPointToJson( qgsgeometry_cast< const QgsMultiPoint * >( geom ) );
1320 res = multiLineStringToJson( qgsgeometry_cast< const QgsMultiLineString * >( geom ) );
1324 res = multiCurveToJson( qgsgeometry_cast< const QgsMultiCurve * >( geom ) );
1328 res = multiPolygonToJson( qgsgeometry_cast< const QgsMultiPolygon * >( geom ) );
1332 res = curvePolygonToJson( qgsgeometry_cast< const QgsCurvePolygon * >( geom ) );
1336 res = multiSurfaceToJson( qgsgeometry_cast< const QgsMultiSurface * >( geom ) );
1340 return QVariantMap();
1343 return QVariantMap();
1346 return QVariantMap();
1353 res.insert( QStringLiteral(
"spatialReference" ),
crsToJson(
crs ) );
1359QVariantMap QgsArcGisRestUtils::pointToJson(
const QgsPoint *point )
1363 data[QStringLiteral(
"x" )] = QStringLiteral(
"NaN" );
1366 data[QStringLiteral(
"x" )] = point->
x();
1367 data[QStringLiteral(
"y" )] = point->
y();
1369 if ( point->
is3D() )
1370 data[QStringLiteral(
"z" )] = !std::isnan( point->
z() ) ? QVariant( point->
z() ) : QVariant( QStringLiteral(
"NaN" ) );
1373 data[QStringLiteral(
"m" )] = !std::isnan( point->
m() ) ? QVariant( point->
m() ) : QVariant( QStringLiteral(
"NaN" ) );
1378QVariantMap QgsArcGisRestUtils::multiPointToJson(
const QgsMultiPoint *multiPoint )
1381 const bool hasZ = multiPoint->
is3D();
1382 const bool hasM = multiPoint->
isMeasure();
1383 data[QStringLiteral(
"hasM" )] = hasM;
1384 data[QStringLiteral(
"hasZ" )] = hasZ;
1386 QVariantList pointsList;
1388 pointsList.reserve( size );
1390 QVariantList pointList;
1391 for (
int i = 0; i < size; ++i )
1396 pointList.append( point->
x() );
1397 pointList.append( point->
y() );
1399 pointList.append( point->
z() );
1400 if ( hasM && !std::isnan( point->
m() ) )
1401 pointList.append( point->
m() );
1403 pointsList.push_back( pointList );
1406 data[QStringLiteral(
"points" )] = pointsList;
1410QVariantList QgsArcGisRestUtils::lineStringToJsonPath(
const QgsLineString *line )
1412 const bool hasZ = line->
is3D();
1415 QVariantList pointsList;
1417 pointsList.reserve( size );
1419 QVariantList pointList;
1420 const double *xData = line->
xData();
1421 const double *yData = line->
yData();
1422 const double *zData = hasZ ? line->
zData() :
nullptr;
1423 const double *mData = hasM ? line->
mData() :
nullptr;
1425 for (
int i = 0; i < size; ++i )
1428 pointList.append( *xData++ );
1429 pointList.append( *yData++ );
1432 pointList.append( *zData++ );
1434 if ( hasM && !std::isnan( *mData ) )
1435 pointList.append( *mData );
1439 pointsList.push_back( pointList );
1444QVariantList QgsArcGisRestUtils::curveToJsonCurve(
const QgsCurve *curve,
bool includeStart )
1446 const bool hasZ = curve->
is3D();
1449 auto pointToList = [hasZ, hasM](
const QgsPoint & point ) -> QVariantList
1451 QVariantList pointList;
1453 pointList.append( point.
x() );
1454 pointList.append( point.
y() );
1457 pointList.append( point.
z() );
1459 if ( hasM && !std::isnan( point.
m() ) )
1460 pointList.append( point.
m() );
1470 QVariantList part = lineStringToJsonPath( qgsgeometry_cast< const QgsLineString *>( curve ) );
1471 if ( !part.isEmpty() && !includeStart )
1479 const QgsCircularString *circularString = qgsgeometry_cast<const QgsCircularString * >( curve );
1480 if ( includeStart && !circularString->
isEmpty() )
1482 res.push_back( pointToList( circularString->
startPoint() ) );
1485 const int size = circularString->
numPoints();
1486 for (
int i = 1; i + 1 < size; i += 2 )
1489 QVariantMap curvePart;
1490 QVariantList curveList;
1491 curveList.push_back( pointToList( circularString->
pointN( i + 1 ) ) );
1493 curveList.push_back( pointToList( circularString->
pointN( i ) ) );
1495 curvePart.insert( QStringLiteral(
"c" ), curveList );
1496 res.push_back( curvePart );
1503 const QgsCompoundCurve *compoundCurve = qgsgeometry_cast<const QgsCompoundCurve * >( curve );
1505 const int size = compoundCurve->
nCurves();
1506 for (
int i = 0; i < size; ++i )
1509 res.append( curveToJsonCurve( subCurve, i == 0 ) );
1520QVariantMap QgsArcGisRestUtils::lineStringToJson(
const QgsLineString *line )
1523 const bool hasZ = line->
is3D();
1525 data[QStringLiteral(
"hasM" )] = hasM;
1526 data[QStringLiteral(
"hasZ" )] = hasZ;
1528 const QVariantList pointsList = lineStringToJsonPath( line );
1530 QVariantList pointsData = QVariantList();
1531 pointsData.push_back( pointsList );
1532 data[QStringLiteral(
"paths" )] = pointsData;
1537QVariantMap QgsArcGisRestUtils::curveToJson(
const QgsCurve *curve )
1540 const bool hasZ = curve->
is3D();
1542 data[QStringLiteral(
"hasM" )] = hasM;
1543 data[QStringLiteral(
"hasZ" )] = hasZ;
1545 const QVariantList curveList = curveToJsonCurve( curve,
true );
1547 QVariantList curveData = QVariantList();
1548 curveData.push_back( curveList );
1549 data[QStringLiteral(
"curvePaths" )] = curveData;
1554QVariantMap QgsArcGisRestUtils::multiLineStringToJson(
const QgsMultiLineString *multiLine )
1557 const bool hasZ = multiLine->
is3D();
1558 const bool hasM = multiLine->
isMeasure();
1559 data[QStringLiteral(
"hasM" )] = hasM;
1560 data[QStringLiteral(
"hasZ" )] = hasZ;
1564 paths.reserve( size );
1565 for (
int i = 0; i < size; ++i )
1568 paths.push_back( lineStringToJsonPath( line ) );
1571 data[QStringLiteral(
"paths" )] = paths;
1575QVariantMap QgsArcGisRestUtils::multiCurveToJson(
const QgsMultiCurve *multiCurve )
1578 const bool hasZ = multiCurve->
is3D();
1579 const bool hasM = multiCurve->
isMeasure();
1580 data[QStringLiteral(
"hasM" )] = hasM;
1581 data[QStringLiteral(
"hasZ" )] = hasZ;
1585 paths.reserve( size );
1586 for (
int i = 0; i < size; ++i )
1589 paths.push_back( curveToJsonCurve( curve,
true ) );
1592 data[QStringLiteral(
"curvePaths" )] = paths;
1596QVariantList QgsArcGisRestUtils::polygonToJsonRings(
const QgsPolygon *polygon )
1600 rings.reserve( numInteriorRings + 1 );
1608 rings.push_back( lineStringToJsonPath( exterior ) );
1613 std::unique_ptr< QgsLineString > reversed( exterior->
reversed() );
1614 rings.push_back( lineStringToJsonPath( reversed.get() ) );
1622 for (
int i = 0; i < numInteriorRings; ++i )
1629 rings.push_back( lineStringToJsonPath( ring ) );
1634 std::unique_ptr< QgsLineString > reversed( ring->
reversed() );
1635 rings.push_back( lineStringToJsonPath( reversed.get() ) );
1645QVariantList QgsArcGisRestUtils::curvePolygonToJsonRings(
const QgsCurvePolygon *polygon )
1649 rings.reserve( numInteriorRings + 1 );
1651 if (
const QgsCurve *exterior = qgsgeometry_cast< const QgsCurve * >( polygon->
exteriorRing() ) )
1657 rings.push_back( curveToJsonCurve( exterior,
true ) );
1662 std::unique_ptr< QgsCurve > reversed( exterior->
reversed() );
1663 rings.push_back( curveToJsonCurve( reversed.get(),
true ) );
1671 for (
int i = 0; i < numInteriorRings; ++i )
1678 rings.push_back( curveToJsonCurve( ring,
true ) );
1683 std::unique_ptr< QgsCurve > reversed( ring->
reversed() );
1684 rings.push_back( curveToJsonCurve( reversed.get(),
true ) );
1694QVariantMap QgsArcGisRestUtils::polygonToJson(
const QgsPolygon *polygon )
1697 const bool hasZ = polygon->
is3D();
1699 data[QStringLiteral(
"hasM" )] = hasM;
1700 data[QStringLiteral(
"hasZ" )] = hasZ;
1701 data[QStringLiteral(
"rings" )] = polygonToJsonRings( polygon );
1705QVariantMap QgsArcGisRestUtils::curvePolygonToJson(
const QgsCurvePolygon *polygon )
1708 const bool hasZ = polygon->
is3D();
1710 data[QStringLiteral(
"hasM" )] = hasM;
1711 data[QStringLiteral(
"hasZ" )] = hasZ;
1712 data[QStringLiteral(
"curveRings" )] = curvePolygonToJsonRings( polygon );
1716QVariantMap QgsArcGisRestUtils::multiPolygonToJson(
const QgsMultiPolygon *multiPolygon )
1719 const bool hasZ = multiPolygon->
is3D();
1720 const bool hasM = multiPolygon->
isMeasure();
1721 data[QStringLiteral(
"hasM" )] = hasM;
1722 data[QStringLiteral(
"hasZ" )] = hasZ;
1726 for (
int i = 0; i < size; ++i )
1729 rings.append( polygonToJsonRings( polygon ) );
1732 data[QStringLiteral(
"rings" )] = rings;
1736QVariantMap QgsArcGisRestUtils::multiSurfaceToJson(
const QgsMultiSurface *multiSurface )
1739 const bool hasZ = multiSurface->
is3D();
1740 const bool hasM = multiSurface->
isMeasure();
1741 data[QStringLiteral(
"hasM" )] = hasM;
1742 data[QStringLiteral(
"hasZ" )] = hasZ;
1746 for (
int i = 0; i < size; ++i )
1752 rings.append( curvePolygonToJsonRings( polygon ) );
1755 data[QStringLiteral(
"curveRings" )] = rings;
1766 if ( !authid.isEmpty() )
1768 const thread_local QRegularExpression rxAuthid( QStringLiteral(
"(\\w+):(\\d+)" ) );
1769 const QRegularExpressionMatch match = rxAuthid.match( authid );
1770 if ( match.hasMatch()
1772 ( match.captured( 1 ).compare( QLatin1String(
"EPSG" ), Qt::CaseInsensitive ) == 0 )
1773 || ( match.captured( 1 ).compare( QLatin1String(
"ESRI" ), Qt::CaseInsensitive ) == 0 )
1777 const QString wkid = match.captured( 2 );
1778 res.insert( QStringLiteral(
"wkid" ), wkid );
1797 QVariantMap attributes;
1799 for (
const QgsField &field : fields )
1804 if ( !attributes.isEmpty() )
1806 res.insert( QStringLiteral(
"attributes" ), attributes );
1816 switch ( expectedType )
1818 case QMetaType::Type::QString:
1820 const QString escaped = variant.toString().replace(
'\\', QLatin1String(
"\\\\" ) ).replace(
'"', QLatin1String(
"\\\"" ) );
1821 return QString( QUrl::toPercentEncoding( escaped,
"'" ) );
1824 case QMetaType::Type::QDateTime:
1825 case QMetaType::Type::QDate:
1827 switch ( variant.userType() )
1829 case QMetaType::Type::QDateTime:
1830 return variant.toDateTime().toMSecsSinceEpoch();
1832 case QMetaType::Type::QDate:
1834 if ( context.
timeZone().isValid() )
1835 return QDateTime( variant.toDate(), QTime( 0, 0, 0 ), context.
timeZone() ).toMSecsSinceEpoch();
1837 return QDateTime( variant.toDate(), QTime( 0, 0, 0 ) ).toMSecsSinceEpoch();
1852 res.insert( QStringLiteral(
"name" ), field.
name() );
1855 switch ( field.
type() )
1857 case QMetaType::Type::LongLong:
1858 fieldType = QStringLiteral(
"esriFieldTypeInteger" );
1861 case QMetaType::Type::Int:
1862 fieldType = QStringLiteral(
"esriFieldTypeSmallInteger" );
1865 case QMetaType::Type::Double:
1866 fieldType = QStringLiteral(
"esriFieldTypeDouble" );
1869 case QMetaType::Type::QString:
1870 fieldType = QStringLiteral(
"esriFieldTypeString" );
1873 case QMetaType::Type::QDateTime:
1874 case QMetaType::Type::QDate:
1875 fieldType = QStringLiteral(
"esriFieldTypeDate" );
1878 case QMetaType::Type::QByteArray:
1879 fieldType = QStringLiteral(
"esriFieldTypeBlob" );
1884 fieldType = QStringLiteral(
"esriFieldTypeString" );
1887 res.insert( QStringLiteral(
"type" ), fieldType );
1889 if ( !field.
alias().isEmpty() )
1890 res.insert( QStringLiteral(
"alias" ), field.
alias() );
1894 res.insert( QStringLiteral(
"nullable" ), !notNullable );
1897 res.insert( QStringLiteral(
"editable" ),
true );
1904 if ( type.compare( QLatin1String(
"FeatureServer" ), Qt::CaseInsensitive ) == 0 )
1906 else if ( type.compare( QLatin1String(
"MapServer" ), Qt::CaseInsensitive ) == 0 )
1908 else if ( type.compare( QLatin1String(
"ImageServer" ), Qt::CaseInsensitive ) == 0 )
1910 else if ( type.compare( QLatin1String(
"GlobeServer" ), Qt::CaseInsensitive ) == 0 )
1912 else if ( type.compare( QLatin1String(
"GPServer" ), Qt::CaseInsensitive ) == 0 )
1914 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.
The feature class encapsulates a single feature including its unique ID, geometry and a list of field...
bool hasGeometry() const
Returns true if the feature has an associated geometry.
Q_INVOKABLE QVariant attribute(const QString &name) const
Lookup attribute value by attribute name.
@ ConstraintNotNull
Field may not be null.
Encapsulate a field in an attribute table or data source.
QgsFieldConstraints constraints
Container of fields for a vector layer.
int numGeometries() const
Returns the number of geometries within the collection.
const QgsAbstractGeometry * geometryN(int n) const
Returns a const reference to a geometry from within the collection.
A geometry is the spatial representation of a feature.
const QgsAbstractGeometry * constGet() const
Returns a non-modifiable (const) reference to the underlying abstract geometry primitive.
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry, double precision=0.0)
Creates and returns a new geometry engine representing the specified geometry using precision on a gr...
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 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
#define QgsDebugError(str)
QList< QgsSymbolLayer * > QgsSymbolLayerList
const QgsCoordinateReferenceSystem & crs