QGIS API Documentation  3.26.3-Buenos Aires (65e4edfdad)
qgsarcgisrestutils.cpp
Go to the documentation of this file.
1 /***************************************************************************
2  qgsarcgisrestutils.cpp
3  ----------------------
4  begin : Nov 25, 2015
5  copyright : (C) 2015 by Sandro Mani
6  email : [email protected]
7  ***************************************************************************
8  * *
9  * This program is free software; you can redistribute it and/or modify *
10  * it under the terms of the GNU General Public License as published by *
11  * the Free Software Foundation; either version 2 of the License, or *
12  * (at your option) any later version. *
13  * *
14  ***************************************************************************/
15 
16 #include "qgsarcgisrestutils.h"
17 #include "qgsfields.h"
18 #include "qgslogger.h"
19 #include "qgsrectangle.h"
20 #include "qgspallabeling.h"
21 #include "qgssymbol.h"
22 #include "qgssymbollayer.h"
23 #include "qgslinesymbollayer.h"
24 #include "qgsfillsymbollayer.h"
25 #include "qgsrenderer.h"
26 #include "qgsrulebasedlabeling.h"
29 #include "qgsvectorlayerlabeling.h"
30 #include "qgscircularstring.h"
31 #include "qgsmulticurve.h"
32 #include "qgspolygon.h"
33 #include "qgslinestring.h"
34 #include "qgscurve.h"
35 #include "qgsgeometryengine.h"
36 #include "qgsmultisurface.h"
37 #include "qgsmultipoint.h"
38 #include "qgsmarkersymbol.h"
39 #include "qgslinesymbol.h"
40 #include "qgsfillsymbol.h"
41 
42 #include <QRegularExpression>
43 
44 QVariant::Type QgsArcGisRestUtils::convertFieldType( const QString &esriFieldType )
45 {
46  if ( esriFieldType == QLatin1String( "esriFieldTypeInteger" ) )
47  return QVariant::LongLong;
48  if ( esriFieldType == QLatin1String( "esriFieldTypeSmallInteger" ) )
49  return QVariant::Int;
50  if ( esriFieldType == QLatin1String( "esriFieldTypeDouble" ) )
51  return QVariant::Double;
52  if ( esriFieldType == QLatin1String( "esriFieldTypeSingle" ) )
53  return QVariant::Double;
54  if ( esriFieldType == QLatin1String( "esriFieldTypeString" ) )
55  return QVariant::String;
56  if ( esriFieldType == QLatin1String( "esriFieldTypeDate" ) )
57  return QVariant::DateTime;
58  if ( esriFieldType == QLatin1String( "esriFieldTypeGeometry" ) )
59  return QVariant::Invalid; // Geometry column should not appear as field
60  if ( esriFieldType == QLatin1String( "esriFieldTypeOID" ) )
61  return QVariant::LongLong;
62  if ( esriFieldType == QLatin1String( "esriFieldTypeBlob" ) )
63  return QVariant::ByteArray;
64  if ( esriFieldType == QLatin1String( "esriFieldTypeGlobalID" ) )
65  return QVariant::String;
66  if ( esriFieldType == QLatin1String( "esriFieldTypeRaster" ) )
67  return QVariant::ByteArray;
68  if ( esriFieldType == QLatin1String( "esriFieldTypeGUID" ) )
69  return QVariant::String;
70  if ( esriFieldType == QLatin1String( "esriFieldTypeXML" ) )
71  return QVariant::String;
72  return QVariant::Invalid;
73 }
74 
76 {
77  // http://resources.arcgis.com/en/help/arcobjects-cpp/componenthelp/index.html#//000w0000001p000000
78  if ( esriGeometryType == QLatin1String( "esriGeometryNull" ) )
79  return QgsWkbTypes::Unknown;
80  else if ( esriGeometryType == QLatin1String( "esriGeometryPoint" ) )
81  return QgsWkbTypes::Point;
82  else if ( esriGeometryType == QLatin1String( "esriGeometryMultipoint" ) )
84  else if ( esriGeometryType == QLatin1String( "esriGeometryPolyline" ) )
86  else if ( esriGeometryType == QLatin1String( "esriGeometryPolygon" ) )
88  else if ( esriGeometryType == QLatin1String( "esriGeometryEnvelope" ) )
89  return QgsWkbTypes::Polygon;
90  // Unsupported (either by qgis, or format unspecified by the specification)
91  // esriGeometryCircularArc
92  // esriGeometryEllipticArc
93  // esriGeometryBezier3Curve
94  // esriGeometryPath
95  // esriGeometryRing
96  // esriGeometryLine
97  // esriGeometryAny
98  // esriGeometryMultiPatch
99  // esriGeometryTriangleStrip
100  // esriGeometryTriangleFan
101  // esriGeometryRay
102  // esriGeometrySphere
103  // esriGeometryTriangles
104  // esriGeometryBag
105  return QgsWkbTypes::Unknown;
106 }
107 
108 std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertPoint( const QVariantList &coordList, QgsWkbTypes::Type pointType )
109 {
110  int nCoords = coordList.size();
111  if ( nCoords < 2 )
112  return nullptr;
113  bool xok = false, yok = false;
114  const double x = coordList[0].toDouble( &xok );
115  const double y = coordList[1].toDouble( &yok );
116  if ( !xok || !yok )
117  return nullptr;
118  const bool hasZ = QgsWkbTypes::hasZ( pointType );
119  const double z = hasZ && nCoords >= 3 ? coordList[2].toDouble() : std::numeric_limits< double >::quiet_NaN();
120 
121  // if point has just M but not Z, then the point dimension list will only have X, Y, M, otherwise it will have X, Y, Z, M
122  const double m = QgsWkbTypes::hasM( pointType ) && ( ( hasZ && nCoords >= 4 ) || ( !hasZ && nCoords >= 3 ) ) ? coordList[ hasZ ? 3 : 2].toDouble() : std::numeric_limits< double >::quiet_NaN();
123  return std::make_unique< QgsPoint >( pointType, x, y, z, m );
124 }
125 
126 std::unique_ptr< QgsCircularString > QgsArcGisRestUtils::convertCircularString( const QVariantMap &curveData, QgsWkbTypes::Type pointType, const QgsPoint &startPoint )
127 {
128  const QVariantList coordsList = curveData[QStringLiteral( "c" )].toList();
129  if ( coordsList.isEmpty() )
130  return nullptr;
131  const int coordsListSize = coordsList.size();
132 
133  QVector<QgsPoint> points;
134  points.reserve( coordsListSize + 1 );
135  points.append( startPoint );
136 
137  for ( int i = 0; i < coordsListSize - 1; )
138  {
139  // first point is end point, second is point on curve
140  // i.e. the opposite to what QGIS requires!
141  std::unique_ptr< QgsPoint > endPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
142  if ( !endPoint )
143  return nullptr;
144  i++;
145  std::unique_ptr< QgsPoint > interiorPoint( convertPoint( coordsList.at( i ).toList(), pointType ) );
146  if ( !interiorPoint )
147  return nullptr;
148  i++;
149  points << *interiorPoint;
150  points << *endPoint;
151  }
152  std::unique_ptr< QgsCircularString > curve = std::make_unique< QgsCircularString> ();
153  curve->setPoints( points );
154  return curve;
155 }
156 
157 std::unique_ptr< QgsCompoundCurve > QgsArcGisRestUtils::convertCompoundCurve( const QVariantList &curvesList, QgsWkbTypes::Type pointType )
158 {
159  // [[6,3],[5,3],{"b":[[3,2],[6,1],[2,4]]},[1,2],{"c": [[3,3],[1,4]]}]
160  std::unique_ptr< QgsCompoundCurve > compoundCurve = std::make_unique< QgsCompoundCurve >();
161  std::unique_ptr< QgsLineString > lineString;
162  for ( const QVariant &curveData : curvesList )
163  {
164  if ( curveData.type() == QVariant::List )
165  {
166  std::unique_ptr< QgsPoint > point( convertPoint( curveData.toList(), pointType ) );
167  if ( !point )
168  {
169  return nullptr;
170  }
171  if ( !lineString )
172  lineString = std::make_unique< QgsLineString >();
173 
174  lineString->addVertex( *point );
175  }
176  else if ( curveData.type() == QVariant::Map )
177  {
178  // The last point of the linestring is the start point of this circular string
179  std::unique_ptr< QgsCircularString > circularString( convertCircularString( curveData.toMap(), pointType, lineString ? lineString->endPoint() : QgsPoint() ) );
180  if ( !circularString )
181  {
182  return nullptr;
183  }
184 
185  if ( lineString )
186  compoundCurve->addCurve( lineString.release() );
187 
188  // If the previous curve had less than two points, remove it
189  if ( compoundCurve->curveAt( compoundCurve->nCurves() - 1 )->nCoordinates() < 2 )
190  compoundCurve->removeCurve( compoundCurve->nCurves() - 1 );
191 
192  const QgsPoint endPointCircularString = circularString->endPoint();
193  compoundCurve->addCurve( circularString.release() );
194 
195  // Prepare a new line string
196  lineString = std::make_unique< QgsLineString >();
197  lineString->addVertex( endPointCircularString );
198  }
199  }
200 
201  if ( lineString && lineString->numPoints() == 1 && compoundCurve->nCurves() > 0 )
202  {
203  const QgsCurve *finalCurve = compoundCurve->curveAt( compoundCurve->nCurves() - 1 );
204  if ( finalCurve->endPoint() == lineString->startPoint() )
205  lineString.reset(); // redundant final curve containing a duplicate vertex
206  }
207 
208  if ( lineString )
209  compoundCurve->addCurve( lineString.release() );
210 
211  return compoundCurve;
212 }
213 
214 std::unique_ptr< QgsPoint > QgsArcGisRestUtils::convertGeometryPoint( const QVariantMap &geometryData, QgsWkbTypes::Type pointType )
215 {
216  // {"x" : <x>, "y" : <y>, "z" : <z>, "m" : <m>}
217  bool xok = false, yok = false;
218  double x = geometryData[QStringLiteral( "x" )].toDouble( &xok );
219  double y = geometryData[QStringLiteral( "y" )].toDouble( &yok );
220  if ( !xok || !yok )
221  return nullptr;
222  double z = geometryData[QStringLiteral( "z" )].toDouble();
223  double m = geometryData[QStringLiteral( "m" )].toDouble();
224  return std::make_unique< QgsPoint >( pointType, x, y, z, m );
225 }
226 
227 std::unique_ptr< QgsMultiPoint > QgsArcGisRestUtils::convertMultiPoint( const QVariantMap &geometryData, QgsWkbTypes::Type pointType )
228 {
229  // {"points" : [[ <x1>, <y1>, <z1>, <m1> ] , [ <x2>, <y2>, <z2>, <m2> ], ... ]}
230  const QVariantList coordsList = geometryData[QStringLiteral( "points" )].toList();
231 
232  std::unique_ptr< QgsMultiPoint > multiPoint = std::make_unique< QgsMultiPoint >();
233  multiPoint->reserve( coordsList.size() );
234  for ( const QVariant &coordData : coordsList )
235  {
236  const QVariantList coordList = coordData.toList();
237  std::unique_ptr< QgsPoint > p = convertPoint( coordList, pointType );
238  if ( !p )
239  {
240  continue;
241  }
242  multiPoint->addGeometry( p.release() );
243  }
244 
245  // second chance -- sometimes layers are reported as multipoint but features have single
246  // point geometries. Silently handle this and upgrade to multipoint.
247  std::unique_ptr< QgsPoint > p = convertGeometryPoint( geometryData, pointType );
248  if ( p )
249  multiPoint->addGeometry( p.release() );
250 
251  if ( multiPoint->numGeometries() == 0 )
252  {
253  // didn't find any points, so reset geometry to null
254  multiPoint.reset();
255  }
256  return multiPoint;
257 }
258 
259 std::unique_ptr< QgsMultiCurve > QgsArcGisRestUtils::convertGeometryPolyline( const QVariantMap &geometryData, QgsWkbTypes::Type pointType )
260 {
261  // {"curvePaths": [[[0,0], {"c": [[3,3],[1,4]]} ]]}
262  QVariantList pathsList;
263  if ( geometryData[QStringLiteral( "paths" )].isValid() )
264  pathsList = geometryData[QStringLiteral( "paths" )].toList();
265  else if ( geometryData[QStringLiteral( "curvePaths" )].isValid() )
266  pathsList = geometryData[QStringLiteral( "curvePaths" )].toList();
267  if ( pathsList.isEmpty() )
268  return nullptr;
269  std::unique_ptr< QgsMultiCurve > multiCurve = std::make_unique< QgsMultiCurve >();
270  multiCurve->reserve( pathsList.size() );
271  for ( const QVariant &pathData : std::as_const( pathsList ) )
272  {
273  std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( pathData.toList(), pointType );
274  if ( !curve )
275  {
276  return nullptr;
277  }
278  multiCurve->addGeometry( curve.release() );
279  }
280  return multiCurve;
281 }
282 
283 std::unique_ptr< QgsMultiSurface > QgsArcGisRestUtils::convertGeometryPolygon( const QVariantMap &geometryData, QgsWkbTypes::Type pointType )
284 {
285  // {"curveRings": [[[0,0], {"c": [[3,3],[1,4]]} ]]}
286  QVariantList ringsList;
287  if ( geometryData[QStringLiteral( "rings" )].isValid() )
288  ringsList = geometryData[QStringLiteral( "rings" )].toList();
289  else if ( geometryData[QStringLiteral( "ringPaths" )].isValid() )
290  ringsList = geometryData[QStringLiteral( "ringPaths" )].toList();
291  if ( ringsList.isEmpty() )
292  return nullptr;
293 
294  QList< QgsCompoundCurve * > curves;
295  for ( int i = 0, n = ringsList.size(); i < n; ++i )
296  {
297  std::unique_ptr< QgsCompoundCurve > curve = convertCompoundCurve( ringsList[i].toList(), pointType );
298  if ( !curve )
299  {
300  continue;
301  }
302  curves.append( curve.release() );
303  }
304  if ( curves.count() == 0 )
305  return nullptr;
306 
307  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 ); } );
308  std::unique_ptr< QgsMultiSurface > result = std::make_unique< QgsMultiSurface >();
309  result->reserve( curves.size() );
310  while ( !curves.isEmpty() )
311  {
312  QgsCompoundCurve *exterior = curves.takeFirst();
313  QgsCurvePolygon *newPolygon = new QgsCurvePolygon();
314  newPolygon->setExteriorRing( exterior );
315  std::unique_ptr<QgsGeometryEngine> engine( QgsGeometry::createGeometryEngine( newPolygon ) );
316  engine->prepareGeometry();
317 
318  QMutableListIterator< QgsCompoundCurve * > it( curves );
319  while ( it.hasNext() )
320  {
321  QgsCompoundCurve *curve = it.next();
322  QgsRectangle boundingBox = newPolygon->boundingBox();
323  if ( boundingBox.intersects( curve->boundingBox() ) )
324  {
325  QgsPoint point = curve->startPoint();
326  if ( engine->contains( &point ) )
327  {
328  newPolygon->addInteriorRing( curve );
329  it.remove();
330  engine.reset( QgsGeometry::createGeometryEngine( newPolygon ) );
331  engine->prepareGeometry();
332  }
333  }
334  }
335  result->addGeometry( newPolygon );
336  }
337  if ( result->numGeometries() == 0 )
338  return nullptr;
339 
340  return result;
341 }
342 
343 std::unique_ptr< QgsPolygon > QgsArcGisRestUtils::convertEnvelope( const QVariantMap &geometryData )
344 {
345  // {"xmin" : -109.55, "ymin" : 25.76, "xmax" : -86.39, "ymax" : 49.94}
346  bool xminOk = false, yminOk = false, xmaxOk = false, ymaxOk = false;
347  double xmin = geometryData[QStringLiteral( "xmin" )].toDouble( &xminOk );
348  double ymin = geometryData[QStringLiteral( "ymin" )].toDouble( &yminOk );
349  double xmax = geometryData[QStringLiteral( "xmax" )].toDouble( &xmaxOk );
350  double ymax = geometryData[QStringLiteral( "ymax" )].toDouble( &ymaxOk );
351  if ( !xminOk || !yminOk || !xmaxOk || !ymaxOk )
352  return nullptr;
353  std::unique_ptr< QgsLineString > ext = std::make_unique< QgsLineString> ();
354  ext->addVertex( QgsPoint( xmin, ymin ) );
355  ext->addVertex( QgsPoint( xmax, ymin ) );
356  ext->addVertex( QgsPoint( xmax, ymax ) );
357  ext->addVertex( QgsPoint( xmin, ymax ) );
358  ext->addVertex( QgsPoint( xmin, ymin ) );
359  std::unique_ptr< QgsPolygon > poly = std::make_unique< QgsPolygon >();
360  poly->setExteriorRing( ext.release() );
361  return poly;
362 }
363 
364 QgsAbstractGeometry *QgsArcGisRestUtils::convertGeometry( const QVariantMap &geometryData, const QString &esriGeometryType, bool readM, bool readZ, QgsCoordinateReferenceSystem *crs )
365 {
366  QgsWkbTypes::Type pointType = QgsWkbTypes::zmType( QgsWkbTypes::Point, readZ, readM );
367  if ( crs )
368  {
369  *crs = convertSpatialReference( geometryData[QStringLiteral( "spatialReference" )].toMap() );
370  }
371 
372  // http://resources.arcgis.com/en/help/arcgis-rest-api/index.html#/Geometry_Objects/02r3000000n1000000/
373  if ( esriGeometryType == QLatin1String( "esriGeometryNull" ) )
374  return nullptr;
375  else if ( esriGeometryType == QLatin1String( "esriGeometryPoint" ) )
376  return convertGeometryPoint( geometryData, pointType ).release();
377  else if ( esriGeometryType == QLatin1String( "esriGeometryMultipoint" ) )
378  return convertMultiPoint( geometryData, pointType ).release();
379  else if ( esriGeometryType == QLatin1String( "esriGeometryPolyline" ) )
380  return convertGeometryPolyline( geometryData, pointType ).release();
381  else if ( esriGeometryType == QLatin1String( "esriGeometryPolygon" ) )
382  return convertGeometryPolygon( geometryData, pointType ).release();
383  else if ( esriGeometryType == QLatin1String( "esriGeometryEnvelope" ) )
384  return convertEnvelope( geometryData ).release();
385  // Unsupported (either by qgis, or format unspecified by the specification)
386  // esriGeometryCircularArc
387  // esriGeometryEllipticArc
388  // esriGeometryBezier3Curve
389  // esriGeometryPath
390  // esriGeometryRing
391  // esriGeometryLine
392  // esriGeometryAny
393  // esriGeometryMultiPatch
394  // esriGeometryTriangleStrip
395  // esriGeometryTriangleFan
396  // esriGeometryRay
397  // esriGeometrySphere
398  // esriGeometryTriangles
399  // esriGeometryBag
400  return nullptr;
401 }
402 
404 {
406 
407  QString spatialReference = spatialReferenceMap[QStringLiteral( "latestWkid" )].toString();
408  if ( spatialReference.isEmpty() )
409  spatialReference = spatialReferenceMap[QStringLiteral( "wkid" )].toString();
410 
411  // prefer using authority/id wherever we can
412  if ( !spatialReference.isEmpty() )
413  {
414  crs.createFromString( QStringLiteral( "EPSG:%1" ).arg( spatialReference ) );
415  if ( !crs.isValid() )
416  {
417  // Try as an ESRI auth
418  crs.createFromString( QStringLiteral( "ESRI:%1" ).arg( spatialReference ) );
419  }
420  }
421  else if ( !spatialReferenceMap[QStringLiteral( "wkt" )].toString().isEmpty() )
422  {
423  // otherwise fallback to WKT
424  crs.createFromWkt( spatialReferenceMap[QStringLiteral( "wkt" )].toString() );
425  }
426 
427  if ( !crs.isValid() )
428  {
429  // If no spatial reference, just use WGS84
430  // TODO -- this needs further investigation! Most ESRI server services default to 3857, so that would likely be
431  // a safer fallback to use...
432  crs.createFromString( QStringLiteral( "EPSG:4326" ) );
433  }
434  return crs;
435 }
436 
437 QgsSymbol *QgsArcGisRestUtils::convertSymbol( const QVariantMap &symbolData )
438 {
439  const QString type = symbolData.value( QStringLiteral( "type" ) ).toString();
440  if ( type == QLatin1String( "esriSMS" ) )
441  {
442  // marker symbol
443  return parseEsriMarkerSymbolJson( symbolData ).release();
444  }
445  else if ( type == QLatin1String( "esriSLS" ) )
446  {
447  // line symbol
448  return parseEsriLineSymbolJson( symbolData ).release();
449  }
450  else if ( type == QLatin1String( "esriSFS" ) )
451  {
452  // fill symbol
453  return parseEsriFillSymbolJson( symbolData ).release();
454  }
455  else if ( type == QLatin1String( "esriPFS" ) )
456  {
457  return parseEsriPictureFillSymbolJson( symbolData ).release();
458  }
459  else if ( type == QLatin1String( "esriPMS" ) )
460  {
461  // picture marker
462  return parseEsriPictureMarkerSymbolJson( symbolData ).release();
463  }
464  else if ( type == QLatin1String( "esriTS" ) )
465  {
466  // text symbol - not supported
467  return nullptr;
468  }
469  return nullptr;
470 }
471 
472 std::unique_ptr<QgsLineSymbol> QgsArcGisRestUtils::parseEsriLineSymbolJson( const QVariantMap &symbolData )
473 {
474  QColor lineColor = convertColor( symbolData.value( QStringLiteral( "color" ) ) );
475  if ( !lineColor.isValid() )
476  return nullptr;
477 
478  bool ok = false;
479  double widthInPoints = symbolData.value( QStringLiteral( "width" ) ).toDouble( &ok );
480  if ( !ok )
481  return nullptr;
482 
483  QgsSymbolLayerList layers;
484  Qt::PenStyle penStyle = convertLineStyle( symbolData.value( QStringLiteral( "style" ) ).toString() );
485  std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( lineColor, widthInPoints, penStyle );
486  lineLayer->setWidthUnit( QgsUnitTypes::RenderPoints );
487  layers.append( lineLayer.release() );
488 
489  std::unique_ptr< QgsLineSymbol > symbol = std::make_unique< QgsLineSymbol >( layers );
490  return symbol;
491 }
492 
493 std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriFillSymbolJson( const QVariantMap &symbolData )
494 {
495  QColor fillColor = convertColor( symbolData.value( QStringLiteral( "color" ) ) );
496  Qt::BrushStyle brushStyle = convertFillStyle( symbolData.value( QStringLiteral( "style" ) ).toString() );
497 
498  const QVariantMap outlineData = symbolData.value( QStringLiteral( "outline" ) ).toMap();
499  QColor lineColor = convertColor( outlineData.value( QStringLiteral( "color" ) ) );
500  Qt::PenStyle penStyle = convertLineStyle( outlineData.value( QStringLiteral( "style" ) ).toString() );
501  bool ok = false;
502  double penWidthInPoints = outlineData.value( QStringLiteral( "width" ) ).toDouble( &ok );
503 
504  QgsSymbolLayerList layers;
505  std::unique_ptr< QgsSimpleFillSymbolLayer > fillLayer = std::make_unique< QgsSimpleFillSymbolLayer >( fillColor, brushStyle, lineColor, penStyle, penWidthInPoints );
506  fillLayer->setStrokeWidthUnit( QgsUnitTypes::RenderPoints );
507  layers.append( fillLayer.release() );
508 
509  std::unique_ptr< QgsFillSymbol > symbol = std::make_unique< QgsFillSymbol >( layers );
510  return symbol;
511 }
512 
513 std::unique_ptr<QgsFillSymbol> QgsArcGisRestUtils::parseEsriPictureFillSymbolJson( const QVariantMap &symbolData )
514 {
515  bool ok = false;
516 
517  double widthInPixels = symbolData.value( QStringLiteral( "width" ) ).toInt( &ok );
518  if ( !ok )
519  return nullptr;
520 
521  const double xScale = symbolData.value( QStringLiteral( "xscale" ) ).toDouble( &ok );
522  if ( !qgsDoubleNear( xScale, 0.0 ) )
523  widthInPixels *= xScale;
524 
525  const double angleCCW = symbolData.value( QStringLiteral( "angle" ) ).toDouble( &ok );
526  double angleCW = 0;
527  if ( ok )
528  angleCW = -angleCCW;
529 
530  const double xOffset = symbolData.value( QStringLiteral( "xoffset" ) ).toDouble();
531  const double yOffset = symbolData.value( QStringLiteral( "yoffset" ) ).toDouble();
532 
533  QString symbolPath( symbolData.value( QStringLiteral( "imageData" ) ).toString() );
534  symbolPath.prepend( QLatin1String( "base64:" ) );
535 
536  QgsSymbolLayerList layers;
537  std::unique_ptr< QgsRasterFillSymbolLayer > fillLayer = std::make_unique< QgsRasterFillSymbolLayer >( symbolPath );
538  fillLayer->setWidth( widthInPixels );
539  fillLayer->setAngle( angleCW );
540  fillLayer->setWidthUnit( QgsUnitTypes::RenderPoints );
541  fillLayer->setOffset( QPointF( xOffset, yOffset ) );
542  fillLayer->setOffsetUnit( QgsUnitTypes::RenderPoints );
543  layers.append( fillLayer.release() );
544 
545  const QVariantMap outlineData = symbolData.value( QStringLiteral( "outline" ) ).toMap();
546  QColor lineColor = convertColor( outlineData.value( QStringLiteral( "color" ) ) );
547  Qt::PenStyle penStyle = convertLineStyle( outlineData.value( QStringLiteral( "style" ) ).toString() );
548  double penWidthInPoints = outlineData.value( QStringLiteral( "width" ) ).toDouble( &ok );
549 
550  std::unique_ptr< QgsSimpleLineSymbolLayer > lineLayer = std::make_unique< QgsSimpleLineSymbolLayer >( lineColor, penWidthInPoints, penStyle );
551  lineLayer->setWidthUnit( QgsUnitTypes::RenderPoints );
552  layers.append( lineLayer.release() );
553 
554  std::unique_ptr< QgsFillSymbol > symbol = std::make_unique< QgsFillSymbol >( layers );
555  return symbol;
556 }
557 
558 Qgis::MarkerShape QgsArcGisRestUtils::parseEsriMarkerShape( const QString &style )
559 {
560  if ( style == QLatin1String( "esriSMSCircle" ) )
562  else if ( style == QLatin1String( "esriSMSCross" ) )
564  else if ( style == QLatin1String( "esriSMSDiamond" ) )
566  else if ( style == QLatin1String( "esriSMSSquare" ) )
568  else if ( style == QLatin1String( "esriSMSX" ) )
570  else if ( style == QLatin1String( "esriSMSTriangle" ) )
572  else
574 }
575 
576 std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriMarkerSymbolJson( const QVariantMap &symbolData )
577 {
578  QColor fillColor = convertColor( symbolData.value( QStringLiteral( "color" ) ) );
579  bool ok = false;
580  const double sizeInPoints = symbolData.value( QStringLiteral( "size" ) ).toDouble( &ok );
581  if ( !ok )
582  return nullptr;
583  const double angleCCW = symbolData.value( QStringLiteral( "angle" ) ).toDouble( &ok );
584  double angleCW = 0;
585  if ( ok )
586  angleCW = -angleCCW;
587 
588  Qgis::MarkerShape shape = parseEsriMarkerShape( symbolData.value( QStringLiteral( "style" ) ).toString() );
589 
590  const double xOffset = symbolData.value( QStringLiteral( "xoffset" ) ).toDouble();
591  const double yOffset = symbolData.value( QStringLiteral( "yoffset" ) ).toDouble();
592 
593  const QVariantMap outlineData = symbolData.value( QStringLiteral( "outline" ) ).toMap();
594  QColor lineColor = convertColor( outlineData.value( QStringLiteral( "color" ) ) );
595  Qt::PenStyle penStyle = convertLineStyle( outlineData.value( QStringLiteral( "style" ) ).toString() );
596  double penWidthInPoints = outlineData.value( QStringLiteral( "width" ) ).toDouble( &ok );
597 
598  QgsSymbolLayerList layers;
599  std::unique_ptr< QgsSimpleMarkerSymbolLayer > markerLayer = std::make_unique< QgsSimpleMarkerSymbolLayer >( shape, sizeInPoints, angleCW, Qgis::ScaleMethod::ScaleArea, fillColor, lineColor );
600  markerLayer->setSizeUnit( QgsUnitTypes::RenderPoints );
601  markerLayer->setStrokeWidthUnit( QgsUnitTypes::RenderPoints );
602  markerLayer->setStrokeStyle( penStyle );
603  markerLayer->setStrokeWidth( penWidthInPoints );
604  markerLayer->setOffset( QPointF( xOffset, yOffset ) );
605  markerLayer->setOffsetUnit( QgsUnitTypes::RenderPoints );
606  layers.append( markerLayer.release() );
607 
608  std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
609  return symbol;
610 }
611 
612 std::unique_ptr<QgsMarkerSymbol> QgsArcGisRestUtils::parseEsriPictureMarkerSymbolJson( const QVariantMap &symbolData )
613 {
614  bool ok = false;
615  const double widthInPixels = symbolData.value( QStringLiteral( "width" ) ).toInt( &ok );
616  if ( !ok )
617  return nullptr;
618  const double heightInPixels = symbolData.value( QStringLiteral( "height" ) ).toInt( &ok );
619  if ( !ok )
620  return nullptr;
621 
622  const double angleCCW = symbolData.value( QStringLiteral( "angle" ) ).toDouble( &ok );
623  double angleCW = 0;
624  if ( ok )
625  angleCW = -angleCCW;
626 
627  const double xOffset = symbolData.value( QStringLiteral( "xoffset" ) ).toDouble();
628  const double yOffset = symbolData.value( QStringLiteral( "yoffset" ) ).toDouble();
629 
630  //const QString contentType = symbolData.value( QStringLiteral( "contentType" ) ).toString();
631 
632  QString symbolPath( symbolData.value( QStringLiteral( "imageData" ) ).toString() );
633  symbolPath.prepend( QLatin1String( "base64:" ) );
634 
635  QgsSymbolLayerList layers;
636  std::unique_ptr< QgsRasterMarkerSymbolLayer > markerLayer = std::make_unique< QgsRasterMarkerSymbolLayer >( symbolPath, widthInPixels, angleCW, Qgis::ScaleMethod::ScaleArea );
637  markerLayer->setSizeUnit( QgsUnitTypes::RenderPoints );
638 
639  // only change the default aspect ratio if the server height setting requires this
640  if ( !qgsDoubleNear( static_cast< double >( heightInPixels ) / widthInPixels, markerLayer->defaultAspectRatio() ) )
641  markerLayer->setFixedAspectRatio( static_cast< double >( heightInPixels ) / widthInPixels );
642 
643  markerLayer->setOffset( QPointF( xOffset, yOffset ) );
644  markerLayer->setOffsetUnit( QgsUnitTypes::RenderPoints );
645  layers.append( markerLayer.release() );
646 
647  std::unique_ptr< QgsMarkerSymbol > symbol = std::make_unique< QgsMarkerSymbol >( layers );
648  return symbol;
649 }
650 
652 {
653  if ( labelingData.empty() )
654  return nullptr;
655 
656  QgsRuleBasedLabeling::Rule *root = new QgsRuleBasedLabeling::Rule( new QgsPalLayerSettings(), 0, 0, QString(), QString(), false );
657  root->setActive( true );
658 
659  int i = 1;
660  for ( const QVariant &lbl : labelingData )
661  {
662  const QVariantMap labeling = lbl.toMap();
663 
664  QgsPalLayerSettings *settings = new QgsPalLayerSettings();
665  QgsTextFormat format;
666 
667  const QString placement = labeling.value( QStringLiteral( "labelPlacement" ) ).toString();
668  if ( placement == QLatin1String( "esriServerPointLabelPlacementAboveCenter" ) )
669  {
671  settings->quadOffset = Qgis::LabelQuadrantPosition::Above;
672  }
673  else if ( placement == QLatin1String( "esriServerPointLabelPlacementBelowCenter" ) )
674  {
676  settings->quadOffset = Qgis::LabelQuadrantPosition::Below;
677  }
678  else if ( placement == QLatin1String( "esriServerPointLabelPlacementCenterCenter" ) )
679  {
681  settings->quadOffset = Qgis::LabelQuadrantPosition::Over;
682  }
683  else if ( placement == QLatin1String( "esriServerPointLabelPlacementAboveLeft" ) )
684  {
686  settings->quadOffset = Qgis::LabelQuadrantPosition::AboveLeft;
687  }
688  else if ( placement == QLatin1String( "esriServerPointLabelPlacementBelowLeft" ) )
689  {
691  settings->quadOffset = Qgis::LabelQuadrantPosition::BelowLeft;
692  }
693  else if ( placement == QLatin1String( "esriServerPointLabelPlacementCenterLeft" ) )
694  {
696  settings->quadOffset = Qgis::LabelQuadrantPosition::Left;
697  }
698  else if ( placement == QLatin1String( "esriServerPointLabelPlacementAboveRight" ) )
699  {
701  settings->quadOffset = Qgis::LabelQuadrantPosition::AboveRight;
702  }
703  else if ( placement == QLatin1String( "esriServerPointLabelPlacementBelowRight" ) )
704  {
706  settings->quadOffset = Qgis::LabelQuadrantPosition::BelowRight;
707  }
708  else if ( placement == QLatin1String( "esriServerPointLabelPlacementCenterRight" ) )
709  {
711  settings->quadOffset = Qgis::LabelQuadrantPosition::Right;
712  }
713  else if ( placement == QLatin1String( "esriServerLinePlacementAboveAfter" ) ||
714  placement == QLatin1String( "esriServerLinePlacementAboveStart" ) ||
715  placement == QLatin1String( "esriServerLinePlacementAboveAlong" ) )
716  {
718  settings->lineSettings().setPlacementFlags( QgsLabeling::LinePlacementFlag::AboveLine | QgsLabeling::LinePlacementFlag::MapOrientation );
719  }
720  else if ( placement == QLatin1String( "esriServerLinePlacementBelowAfter" ) ||
721  placement == QLatin1String( "esriServerLinePlacementBelowStart" ) ||
722  placement == QLatin1String( "esriServerLinePlacementBelowAlong" ) )
723  {
725  settings->lineSettings().setPlacementFlags( QgsLabeling::LinePlacementFlag::BelowLine | QgsLabeling::LinePlacementFlag::MapOrientation );
726  }
727  else if ( placement == QLatin1String( "esriServerLinePlacementCenterAfter" ) ||
728  placement == QLatin1String( "esriServerLinePlacementCenterStart" ) ||
729  placement == QLatin1String( "esriServerLinePlacementCenterAlong" ) )
730  {
732  settings->lineSettings().setPlacementFlags( QgsLabeling::LinePlacementFlag::OnLine | QgsLabeling::LinePlacementFlag::MapOrientation );
733  }
734  else if ( placement == QLatin1String( "esriServerPolygonPlacementAlwaysHorizontal" ) )
735  {
737  }
738 
739  const double minScale = labeling.value( QStringLiteral( "minScale" ) ).toDouble();
740  const double maxScale = labeling.value( QStringLiteral( "maxScale" ) ).toDouble();
741 
742  QVariantMap symbol = labeling.value( QStringLiteral( "symbol" ) ).toMap();
743  format.setColor( convertColor( symbol.value( QStringLiteral( "color" ) ) ) );
744  const double haloSize = symbol.value( QStringLiteral( "haloSize" ) ).toDouble();
745  if ( !qgsDoubleNear( haloSize, 0.0 ) )
746  {
747  QgsTextBufferSettings buffer;
748  buffer.setEnabled( true );
749  buffer.setSize( haloSize );
751  buffer.setColor( convertColor( symbol.value( QStringLiteral( "haloColor" ) ) ) );
752  format.setBuffer( buffer );
753  }
754 
755  const QString fontFamily = symbol.value( QStringLiteral( "font" ) ).toMap().value( QStringLiteral( "family" ) ).toString();
756  const QString fontStyle = symbol.value( QStringLiteral( "font" ) ).toMap().value( QStringLiteral( "style" ) ).toString();
757  const QString fontWeight = symbol.value( QStringLiteral( "font" ) ).toMap().value( QStringLiteral( "weight" ) ).toString();
758  const int fontSize = symbol.value( QStringLiteral( "font" ) ).toMap().value( QStringLiteral( "size" ) ).toInt();
759  QFont font( fontFamily, fontSize );
760  font.setStyleName( fontStyle );
761  font.setWeight( fontWeight == QLatin1String( "bold" ) ? QFont::Bold : QFont::Normal );
762 
763  format.setFont( font );
764  format.setSize( fontSize );
766 
767  settings->setFormat( format );
768 
769  QString where = labeling.value( QStringLiteral( "where" ) ).toString();
770  QgsExpression exp( where );
771  // If the where clause isn't parsed as valid, don't use its
772  if ( !exp.isValid() )
773  where.clear();
774 
775  settings->fieldName = convertLabelingExpression( labeling.value( QStringLiteral( "labelExpression" ) ).toString() );
776  settings->isExpression = true;
777 
778  QgsRuleBasedLabeling::Rule *child = new QgsRuleBasedLabeling::Rule( settings, maxScale, minScale, where, QObject::tr( "ASF label %1" ).arg( i++ ), false );
779  child->setActive( true );
780  root->appendChild( child );
781  }
782 
783  return new QgsRuleBasedLabeling( root );
784 }
785 
786 QgsFeatureRenderer *QgsArcGisRestUtils::convertRenderer( const QVariantMap &rendererData )
787 {
788  const QString type = rendererData.value( QStringLiteral( "type" ) ).toString();
789  if ( type == QLatin1String( "simple" ) )
790  {
791  const QVariantMap symbolProps = rendererData.value( QStringLiteral( "symbol" ) ).toMap();
792  std::unique_ptr< QgsSymbol > symbol( convertSymbol( symbolProps ) );
793  if ( symbol )
794  return new QgsSingleSymbolRenderer( symbol.release() );
795  else
796  return nullptr;
797  }
798  else if ( type == QLatin1String( "uniqueValue" ) )
799  {
800  const QString field1 = rendererData.value( QStringLiteral( "field1" ) ).toString();
801  const QString field2 = rendererData.value( QStringLiteral( "field2" ) ).toString();
802  const QString field3 = rendererData.value( QStringLiteral( "field3" ) ).toString();
803  QString attribute;
804  if ( !field2.isEmpty() || !field3.isEmpty() )
805  {
806  const QString delimiter = rendererData.value( QStringLiteral( "fieldDelimiter" ) ).toString();
807  if ( !field3.isEmpty() )
808  {
809  attribute = QStringLiteral( "concat(\"%1\",'%2',\"%3\",'%4',\"%5\")" ).arg( field1, delimiter, field2, delimiter, field3 );
810  }
811  else
812  {
813  attribute = QStringLiteral( "concat(\"%1\",'%2',\"%3\")" ).arg( field1, delimiter, field2 );
814  }
815  }
816  else
817  {
818  attribute = field1;
819  }
820 
821  const QVariantList categories = rendererData.value( QStringLiteral( "uniqueValueInfos" ) ).toList();
822  QgsCategoryList categoryList;
823  for ( const QVariant &category : categories )
824  {
825  const QVariantMap categoryData = category.toMap();
826  const QString value = categoryData.value( QStringLiteral( "value" ) ).toString();
827  const QString label = categoryData.value( QStringLiteral( "label" ) ).toString();
828  std::unique_ptr< QgsSymbol > symbol( QgsArcGisRestUtils::convertSymbol( categoryData.value( QStringLiteral( "symbol" ) ).toMap() ) );
829  if ( symbol )
830  {
831  categoryList.append( QgsRendererCategory( value, symbol.release(), label ) );
832  }
833  }
834 
835  std::unique_ptr< QgsSymbol > defaultSymbol( convertSymbol( rendererData.value( QStringLiteral( "defaultSymbol" ) ).toMap() ) );
836  if ( defaultSymbol )
837  {
838  categoryList.append( QgsRendererCategory( QVariant(), defaultSymbol.release(), rendererData.value( QStringLiteral( "defaultLabel" ) ).toString() ) );
839  }
840 
841  if ( categoryList.empty() )
842  return nullptr;
843 
844  return new QgsCategorizedSymbolRenderer( attribute, categoryList );
845  }
846  else if ( type == QLatin1String( "classBreaks" ) )
847  {
848  // currently unsupported
849  return nullptr;
850  }
851  else if ( type == QLatin1String( "heatmap" ) )
852  {
853  // currently unsupported
854  return nullptr;
855  }
856  else if ( type == QLatin1String( "vectorField" ) )
857  {
858  // currently unsupported
859  return nullptr;
860  }
861  return nullptr;
862 }
863 
864 QString QgsArcGisRestUtils::convertLabelingExpression( const QString &string )
865 {
866  QString expression = string;
867 
868  // Replace a few ArcGIS token to QGIS equivalents
869  expression = expression.replace( QRegularExpression( "(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)CONCAT(\\s|$)" ), QStringLiteral( "\\4||\\5" ) );
870  expression = expression.replace( QRegularExpression( "(?=([^\"\\\\]*(\\\\.|\"([^\"\\\\]*\\\\.)*[^\"\\\\]*\"))*[^\"]*$)(\\s|^)NEWLINE(\\s|$)" ), QStringLiteral( "\\4'\\n'\\5" ) );
871 
872  // ArcGIS's double quotes are single quotes in QGIS
873  expression = expression.replace( QRegularExpression( "\"(.*?(?<!\\\\))\"" ), QStringLiteral( "'\\1'" ) );
874  expression = expression.replace( QRegularExpression( "\\\\\"" ), QStringLiteral( "\"" ) );
875 
876  // ArcGIS's square brakets are double quotes in QGIS
877  expression = expression.replace( QRegularExpression( "\\[([^]]*)\\]" ), QStringLiteral( "\"\\1\"" ) );
878 
879  return expression;
880 }
881 
882 QColor QgsArcGisRestUtils::convertColor( const QVariant &colorData )
883 {
884  const QVariantList colorParts = colorData.toList();
885  if ( colorParts.count() < 4 )
886  return QColor();
887 
888  int red = colorParts.at( 0 ).toInt();
889  int green = colorParts.at( 1 ).toInt();
890  int blue = colorParts.at( 2 ).toInt();
891  int alpha = colorParts.at( 3 ).toInt();
892  return QColor( red, green, blue, alpha );
893 }
894 
895 Qt::PenStyle QgsArcGisRestUtils::convertLineStyle( const QString &style )
896 {
897  if ( style == QLatin1String( "esriSLSSolid" ) )
898  return Qt::SolidLine;
899  else if ( style == QLatin1String( "esriSLSDash" ) )
900  return Qt::DashLine;
901  else if ( style == QLatin1String( "esriSLSDashDot" ) )
902  return Qt::DashDotLine;
903  else if ( style == QLatin1String( "esriSLSDashDotDot" ) )
904  return Qt::DashDotDotLine;
905  else if ( style == QLatin1String( "esriSLSDot" ) )
906  return Qt::DotLine;
907  else if ( style == QLatin1String( "esriSLSNull" ) )
908  return Qt::NoPen;
909  else
910  return Qt::SolidLine;
911 }
912 
913 Qt::BrushStyle QgsArcGisRestUtils::convertFillStyle( const QString &style )
914 {
915  if ( style == QLatin1String( "esriSFSBackwardDiagonal" ) )
916  return Qt::BDiagPattern;
917  else if ( style == QLatin1String( "esriSFSCross" ) )
918  return Qt::CrossPattern;
919  else if ( style == QLatin1String( "esriSFSDiagonalCross" ) )
920  return Qt::DiagCrossPattern;
921  else if ( style == QLatin1String( "esriSFSForwardDiagonal" ) )
922  return Qt::FDiagPattern;
923  else if ( style == QLatin1String( "esriSFSHorizontal" ) )
924  return Qt::HorPattern;
925  else if ( style == QLatin1String( "esriSFSNull" ) )
926  return Qt::NoBrush;
927  else if ( style == QLatin1String( "esriSFSSolid" ) )
928  return Qt::SolidPattern;
929  else if ( style == QLatin1String( "esriSFSVertical" ) )
930  return Qt::VerPattern;
931  else
932  return Qt::SolidPattern;
933 }
934 
935 QDateTime QgsArcGisRestUtils::convertDateTime( const QVariant &value )
936 {
937  if ( value.isNull() )
938  return QDateTime();
939  bool ok = false;
940  QDateTime dt = QDateTime::fromMSecsSinceEpoch( value.toLongLong( &ok ) );
941  if ( !ok )
942  {
943  QgsDebugMsg( QStringLiteral( "Invalid value %1 for datetime" ).arg( value.toString() ) );
944  return QDateTime();
945  }
946  else
947  return dt;
948 }
QgsArcGisRestUtils::convertFillStyle
static Qt::BrushStyle convertFillStyle(const QString &style)
Converts an ESRI fill style to a Qt brush style.
Definition: qgsarcgisrestutils.cpp:913
QgsRectangle::intersects
bool intersects(const QgsRectangle &rect) const SIP_HOLDGIL
Returns true when rectangle intersects with other rectangle.
Definition: qgsrectangle.h:349
QgsCurve
Abstract base class for curved geometry type.
Definition: qgscurve.h:35
qgspolygon.h
QgsTextBufferSettings::setSizeUnit
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units used for the buffer size.
Definition: qgstextbuffersettings.cpp:97
QgsCoordinateReferenceSystem::createFromWkt
bool createFromWkt(const QString &wkt)
Sets this CRS using a WKT definition.
Definition: qgscoordinatereferencesystem.cpp:899
qgsfields.h
QgsPalLayerSettings::placement
Qgis::LabelPlacement placement
Label placement mode.
Definition: qgspallabeling.h:434
qgspallabeling.h
QgsTextFormat::setFont
void setFont(const QFont &font)
Sets the font used for rendering text.
Definition: qgstextformat.cpp:207
QgsRuleBasedLabeling::Rule
A child rule for QgsRuleBasedLabeling.
Definition: qgsrulebasedlabeling.h:55
QgsWkbTypes::Point
@ Point
Definition: qgswkbtypes.h:72
qgslinestring.h
qgscategorizedsymbolrenderer.h
qgsrectangle.h
QgsWkbTypes::MultiPolygon
@ MultiPolygon
Definition: qgswkbtypes.h:78
QgsPoint
Point geometry type, with support for z-dimension and m-values.
Definition: qgspoint.h:48
qgssinglesymbolrenderer.h
QgsPalLayerSettings
Contains settings for how a map layer will be labeled.
Definition: qgspallabeling.h:86
QgsTextBufferSettings::setEnabled
void setEnabled(bool enabled)
Sets whether the text buffer will be drawn.
Definition: qgstextbuffersettings.cpp:77
QgsCurvePolygon::setExteriorRing
virtual void setExteriorRing(QgsCurve *ring)
Sets the exterior ring of the polygon.
Definition: qgscurvepolygon.cpp:698
crs
const QgsCoordinateReferenceSystem & crs
Definition: qgswfsgetfeature.cpp:105
QgsCurvePolygon
Curve polygon geometry type.
Definition: qgscurvepolygon.h:34
Qgis::MarkerShape::Cross2
@ Cross2
Rotated cross (lines only), 'x' shape.
QgsRuleBasedLabeling::Rule::setActive
void setActive(bool state)
Sets if this rule is active.
Definition: qgsrulebasedlabeling.h:176
QgsUnitTypes::RenderPoints
@ RenderPoints
Points (e.g., for font sizes)
Definition: qgsunittypes.h:173
QgsExpression::isValid
bool isValid() const
Checks if this expression is valid.
Definition: qgsexpression.cpp:201
qgsmultipoint.h
Qgis::MarkerShape::Square
@ Square
Square.
QgsRendererCategory
Represents an individual category (class) from a QgsCategorizedSymbolRenderer.
Definition: qgscategorizedsymbolrenderer.h:35
QgsArcGisRestUtils::convertSpatialReference
static QgsCoordinateReferenceSystem convertSpatialReference(const QVariantMap &spatialReferenceMap)
Converts a spatial reference JSON definition to a QgsCoordinateReferenceSystem value.
Definition: qgsarcgisrestutils.cpp:403
QgsArcGisRestUtils::convertLineStyle
static Qt::PenStyle convertLineStyle(const QString &style)
Converts an ESRI line style to a Qt pen style.
Definition: qgsarcgisrestutils.cpp:895
QgsSingleSymbolRenderer
Definition: qgssinglesymbolrenderer.h:29
QgsWkbTypes::Type
Type
The WKB type describes the number of dimensions a geometry has.
Definition: qgswkbtypes.h:69
QgsPalLayerSettings::quadOffset
Qgis::LabelQuadrantPosition quadOffset
Sets the quadrant in which to offset labels from feature.
Definition: qgspallabeling.h:526
QgsWkbTypes::MultiCurve
@ MultiCurve
Definition: qgswkbtypes.h:83
QgsSymbol
Abstract base class for all rendered symbols.
Definition: qgssymbol.h:92
QgsDebugMsg
#define QgsDebugMsg(str)
Definition: qgslogger.h:38
QgsRectangle
A rectangle specified with double values.
Definition: qgsrectangle.h:41
QgsRuleBasedLabeling
Rule based labeling for a vector layer.
Definition: qgsrulebasedlabeling.h:42
QgsCompoundCurve::startPoint
QgsPoint startPoint() const override SIP_HOLDGIL
Returns the starting point of the curve.
Definition: qgscompoundcurve.cpp:380
QgsArcGisRestUtils::convertSymbol
static QgsSymbol * convertSymbol(const QVariantMap &definition)
Converts a symbol JSON definition to a QgsSymbol.
Definition: qgsarcgisrestutils.cpp:437
QgsTextFormat
Container for all settings relating to text rendering.
Definition: qgstextformat.h:40
QgsTextFormat::setColor
void setColor(const QColor &color)
Sets the color that text will be rendered in.
Definition: qgstextformat.cpp:302
qgsgeometryengine.h
qgsrulebasedlabeling.h
QgsCurve::endPoint
virtual QgsPoint endPoint() const =0
Returns the end point of the curve.
Qgis::LabelPlacement::Horizontal
@ Horizontal
Arranges horizontal candidates scattered throughout a polygon feature. Applies to polygon layers only...
QgsWkbTypes::Unknown
@ Unknown
Definition: qgswkbtypes.h:71
QgsArcGisRestUtils::convertFieldType
static QVariant::Type convertFieldType(const QString &type)
Converts an ESRI REST field type to a QVariant type.
Definition: qgsarcgisrestutils.cpp:44
QgsArcGisRestUtils::convertColor
static QColor convertColor(const QVariant &data)
Converts ESRI JSON color data to a QColor object.
Definition: qgsarcgisrestutils.cpp:882
QgsCategoryList
QList< QgsRendererCategory > QgsCategoryList
Definition: qgscategorizedsymbolrenderer.h:158
Qgis::MarkerShape::Diamond
@ Diamond
Diamond.
QgsCurvePolygon::addInteriorRing
virtual void addInteriorRing(QgsCurve *ring)
Adds an interior ring to the geometry (takes ownership)
Definition: qgscurvepolygon.cpp:745
qgsDoubleNear
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:2265
QgsPalLayerSettings::setFormat
void setFormat(const QgsTextFormat &format)
Sets the label text formatting settings, e.g., font settings, buffer settings, etc.
Definition: qgspallabeling.h:849
QgsArcGisRestUtils::convertLabeling
static QgsAbstractVectorLayerLabeling * convertLabeling(const QVariantList &data)
Converts labeling JSON data to an equivalent QGIS vector labeling.
Definition: qgsarcgisrestutils.cpp:651
QgsWkbTypes::hasM
static bool hasM(Type type) SIP_HOLDGIL
Tests whether a WKB type contains m values.
Definition: qgswkbtypes.h:1130
QgsCoordinateReferenceSystem::isValid
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Definition: qgscoordinatereferencesystem.cpp:977
Qgis::LabelPlacement::OverPoint
@ OverPoint
Arranges candidates over a point (or centroid of a polygon), or at a preset offset from the point....
QgsPalLayerSettings::lineSettings
const QgsLabelLineSettings & lineSettings() const
Returns the label line settings, which contain settings related to how the label engine places and fo...
Definition: qgspallabeling.h:879
qgssymbollayer.h
QgsWkbTypes::zmType
static Type zmType(Type type, bool hasZ, bool hasM) SIP_HOLDGIL
Returns the modified input geometry type according to hasZ / hasM.
Definition: qgswkbtypes.h:831
QgsArcGisRestUtils::convertGeometryType
static QgsWkbTypes::Type convertGeometryType(const QString &type)
Converts an ESRI REST geometry type to a WKB type.
Definition: qgsarcgisrestutils.cpp:75
qgsrenderer.h
qgsfillsymbollayer.h
QgsTextBufferSettings
Container for settings relating to a text buffer.
Definition: qgstextbuffersettings.h:42
QgsArcGisRestUtils::convertGeometry
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.
Definition: qgsarcgisrestutils.cpp:364
qgscircularstring.h
QgsCoordinateReferenceSystem
This class represents a coordinate reference system (CRS).
Definition: qgscoordinatereferencesystem.h:211
QgsAbstractGeometry
Abstract base class for all geometries.
Definition: qgsabstractgeometry.h:79
QgsAbstractVectorLayerLabeling
Abstract base class - its implementations define different approaches to the labeling of a vector lay...
Definition: qgsvectorlayerlabeling.h:41
QgsCoordinateReferenceSystem::createFromString
bool createFromString(const QString &definition)
Set up this CRS from a string definition.
Definition: qgscoordinatereferencesystem.cpp:269
QgsArcGisRestUtils::convertLabelingExpression
static QString convertLabelingExpression(const QString &string)
Converts an ESRI labeling expression to a QGIS expression string.
Definition: qgsarcgisrestutils.cpp:864
QgsGeometry::createGeometryEngine
static QgsGeometryEngine * createGeometryEngine(const QgsAbstractGeometry *geometry)
Creates and returns a new geometry engine representing the specified geometry.
Definition: qgsgeometry.cpp:3972
QgsTextFormat::setBuffer
void setBuffer(const QgsTextBufferSettings &bufferSettings)
Sets the text's buffer settings.
Definition: qgstextformat.cpp:118
QgsPalLayerSettings::fieldName
QString fieldName
Name of field (or an expression) to use for label text.
Definition: qgspallabeling.h:354
qgslinesymbollayer.h
QgsFeatureRenderer
Definition: qgsrenderer.h:101
qgsarcgisrestutils.h
qgscurve.h
QgsRuleBasedLabeling::Rule::appendChild
void appendChild(QgsRuleBasedLabeling::Rule *rule)
add child rule, take ownership, sets this as parent
Definition: qgsrulebasedlabeling.cpp:180
QgsSymbolLayerList
QList< QgsSymbolLayer * > QgsSymbolLayerList
Definition: qgssymbol.h:27
qgsmarkersymbol.h
QgsWkbTypes::Polygon
@ Polygon
Definition: qgswkbtypes.h:74
Qgis::MarkerShape::Circle
@ Circle
Circle.
QgsWkbTypes::MultiPoint
@ MultiPoint
Definition: qgswkbtypes.h:76
QgsArcGisRestUtils::convertDateTime
static QDateTime convertDateTime(const QVariant &value)
Converts a date time value to a QDateTime.
Definition: qgsarcgisrestutils.cpp:935
QgsArcGisRestUtils::convertRenderer
static QgsFeatureRenderer * convertRenderer(const QVariantMap &rendererData)
Converts renderer JSON data to an equivalent QgsFeatureRenderer.
Definition: qgsarcgisrestutils.cpp:786
QgsCurve::boundingBox
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Definition: qgscurve.cpp:238
QgsTextBufferSettings::setSize
void setSize(double size)
Sets the size of the buffer.
Definition: qgstextbuffersettings.cpp:87
Qgis::ScaleMethod::ScaleArea
@ ScaleArea
Calculate scale by the area.
QgsPalLayerSettings::isExpression
bool isExpression
true if this label is made from a expression string, e.g., FieldName || 'mm'
Definition: qgspallabeling.h:360
QgsTextBufferSettings::setColor
void setColor(const QColor &color)
Sets the color for the buffer.
Definition: qgstextbuffersettings.cpp:117
QgsTextFormat::setSizeUnit
void setSizeUnit(QgsUnitTypes::RenderUnit unit)
Sets the units for the size of rendered text.
Definition: qgstextformat.cpp:269
QgsWkbTypes::hasZ
static bool hasZ(Type type) SIP_HOLDGIL
Tests whether a WKB type contains the z-dimension.
Definition: qgswkbtypes.h:1080
qgsmulticurve.h
QgsCategorizedSymbolRenderer
Definition: qgscategorizedsymbolrenderer.h:164
qgsvectorlayerlabeling.h
Qgis::MarkerShape
MarkerShape
Marker shapes.
Definition: qgis.h:1370
qgslogger.h
QgsTextFormat::setSize
void setSize(double size)
Sets the size for rendered text.
Definition: qgstextformat.cpp:291
Qgis::LabelPlacement::Line
@ Line
Arranges candidates parallel to a generalised line representing the feature or parallel to a polygon'...
QgsExpression
Class for parsing and evaluation of expressions (formerly called "search strings")....
Definition: qgsexpression.h:102
qgsfillsymbol.h
QgsLabelLineSettings::setPlacementFlags
void setPlacementFlags(QgsLabeling::LinePlacementFlags flags)
Returns the line placement flags, which dictate how line labels can be placed above or below the line...
Definition: qgslabellinesettings.h:106
qgssymbol.h
qgsmultisurface.h
QgsSurface::boundingBox
QgsRectangle boundingBox() const override
Returns the minimal bounding box for the geometry.
Definition: qgssurface.h:43
QgsCompoundCurve
Compound curve geometry type.
Definition: qgscompoundcurve.h:31
Qgis::MarkerShape::Cross
@ Cross
Cross (lines only)
qgslinesymbol.h
Qgis::MarkerShape::Triangle
@ Triangle
Triangle.