34#include <QRegularExpression>
37#include <netinet/in.h>
43#define GML_NAMESPACE QStringLiteral( "http://www.opengis.net/gml" )
44#define GML32_NAMESPACE QStringLiteral( "http://www.opengis.net/gml/3.2" )
45#define OGC_NAMESPACE QStringLiteral( "http://www.opengis.net/ogc" )
46#define FES_NAMESPACE QStringLiteral( "http://www.opengis.net/fes/2.0" )
53 bool honourAxisOrientation,
54 bool invertAxisOrientation )
57 , mGMLVersion( gmlVersion )
58 , mFilterVersion( filterVersion )
61 , mInvertAxisOrientation( invertAxisOrientation )
62 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
63 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
67 if ( !mSrsName.isEmpty() )
73 mInvertAxisOrientation = !mInvertAxisOrientation;
80 QDomElement geometryTypeElement = geometryNode.toElement();
81 QString geomType = geometryTypeElement.tagName();
84 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
85 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
86 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
88 const QDomNode geometryChild = geometryNode.firstChild();
89 if ( geometryChild.isNull() )
93 geometryTypeElement = geometryChild.toElement();
94 geomType = geometryTypeElement.tagName();
97 if ( !( geomType == QLatin1String(
"Point" ) || geomType == QLatin1String(
"LineString" ) || geomType == QLatin1String(
"Polygon" ) ||
98 geomType == QLatin1String(
"MultiPoint" ) || geomType == QLatin1String(
"MultiLineString" ) || geomType == QLatin1String(
"MultiPolygon" ) ||
99 geomType == QLatin1String(
"Box" ) || geomType == QLatin1String(
"Envelope" ) ) )
102 if ( geomType == QLatin1String(
"Point" ) )
104 geometry = geometryFromGMLPoint( geometryTypeElement );
106 else if ( geomType == QLatin1String(
"LineString" ) )
108 geometry = geometryFromGMLLineString( geometryTypeElement );
110 else if ( geomType == QLatin1String(
"Polygon" ) )
112 geometry = geometryFromGMLPolygon( geometryTypeElement );
114 else if ( geomType == QLatin1String(
"MultiPoint" ) )
116 geometry = geometryFromGMLMultiPoint( geometryTypeElement );
118 else if ( geomType == QLatin1String(
"MultiLineString" ) )
120 geometry = geometryFromGMLMultiLineString( geometryTypeElement );
122 else if ( geomType == QLatin1String(
"MultiPolygon" ) )
124 geometry = geometryFromGMLMultiPolygon( geometryTypeElement );
126 else if ( geomType == QLatin1String(
"Box" ) )
130 else if ( geomType == QLatin1String(
"Envelope" ) )
144 if ( geometryTypeElement.hasAttribute( QStringLiteral(
"srsName" ) ) )
146 QString
srsName { geometryTypeElement.attribute( QStringLiteral(
"srsName" ) ) };
149 const bool ignoreAxisOrientation {
srsName.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) ||
srsName.startsWith( QLatin1String(
"EPSG:" ) ) };
153 if (
srsName.startsWith( QLatin1String(
"http://www.opengis.net/gml/srs/" ) ) )
155 const auto parts {
srsName.split( QRegularExpression( QStringLiteral( R
"raw(/|#|\.)raw" ) ) ) };
156 if ( parts.length() == 10 )
158 srsName = QStringLiteral(
"http://www.opengis.net/def/crs/%1/0/%2" ).arg( parts[ 7 ].toUpper(), parts[ 9 ] );
191 const QString xml = QStringLiteral(
"<tmp xmlns=\"%1\" xmlns:gml=\"%1\">%2</tmp>" ).arg(
GML_NAMESPACE, xmlString );
193 if ( !doc.setContent( xml,
true ) )
196 return geometryFromGML( doc.documentElement().firstChildElement(), context );
200QgsGeometry QgsOgcUtils::geometryFromGMLPoint(
const QDomElement &geometryElement )
204 const QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
205 if ( !coordList.isEmpty() )
207 const QDomElement coordElement = coordList.at( 0 ).toElement();
208 if ( readGMLCoordinates( pointCoordinate, coordElement ) != 0 )
215 const QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
216 if ( posList.size() < 1 )
220 const QDomElement posElement = posList.at( 0 ).toElement();
221 if ( readGMLPositions( pointCoordinate, posElement ) != 0 )
227 if ( pointCoordinate.empty() )
232 QgsPolylineXY::const_iterator point_it = pointCoordinate.constBegin();
233 char e = htonl( 1 ) != 1;
234 double x = point_it->x();
235 double y = point_it->y();
236 const int size = 1 +
sizeof( int ) + 2 *
sizeof(
double );
239 unsigned char *wkb =
new unsigned char[size];
242 memcpy( &( wkb )[wkbPosition], &e, 1 );
244 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
245 wkbPosition +=
sizeof( int );
246 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
247 wkbPosition +=
sizeof( double );
248 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
255QgsGeometry QgsOgcUtils::geometryFromGMLLineString(
const QDomElement &geometryElement )
259 const QDomNodeList coordList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
260 if ( !coordList.isEmpty() )
262 const QDomElement coordElement = coordList.at( 0 ).toElement();
263 if ( readGMLCoordinates( lineCoordinates, coordElement ) != 0 )
270 const QDomNodeList posList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
271 if ( posList.size() < 1 )
275 const QDomElement posElement = posList.at( 0 ).toElement();
276 if ( readGMLPositions( lineCoordinates, posElement ) != 0 )
282 char e = htonl( 1 ) != 1;
283 const int size = 1 + 2 *
sizeof( int ) + lineCoordinates.size() * 2 *
sizeof( double );
286 unsigned char *wkb =
new unsigned char[size];
290 int nPoints = lineCoordinates.size();
293 memcpy( &( wkb )[wkbPosition], &e, 1 );
295 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
296 wkbPosition +=
sizeof( int );
297 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
298 wkbPosition +=
sizeof( int );
300 QgsPolylineXY::const_iterator iter;
301 for ( iter = lineCoordinates.constBegin(); iter != lineCoordinates.constEnd(); ++iter )
305 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
306 wkbPosition +=
sizeof( double );
307 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
308 wkbPosition +=
sizeof( double );
316QgsGeometry QgsOgcUtils::geometryFromGMLPolygon(
const QDomElement &geometryElement )
323 const QDomNodeList outerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
324 if ( !outerBoundaryList.isEmpty() )
326 QDomElement coordinatesElement = outerBoundaryList.at( 0 ).firstChild().firstChild().toElement();
327 if ( coordinatesElement.isNull() )
331 if ( readGMLCoordinates( exteriorPointList, coordinatesElement ) != 0 )
335 ringCoordinates.push_back( exteriorPointList );
338 const QDomNodeList innerBoundaryList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
339 for (
int i = 0; i < innerBoundaryList.size(); ++i )
342 coordinatesElement = innerBoundaryList.at( i ).firstChild().firstChild().toElement();
343 if ( coordinatesElement.isNull() )
347 if ( readGMLCoordinates( interiorPointList, coordinatesElement ) != 0 )
351 ringCoordinates.push_back( interiorPointList );
357 const QDomNodeList exteriorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
358 if ( exteriorList.size() < 1 )
362 const QDomElement posElement = exteriorList.at( 0 ).firstChild().firstChild().toElement();
363 if ( posElement.isNull() )
367 if ( readGMLPositions( exteriorPointList, posElement ) != 0 )
371 ringCoordinates.push_back( exteriorPointList );
374 const QDomNodeList interiorList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
375 for (
int i = 0; i < interiorList.size(); ++i )
378 const QDomElement posElement = interiorList.at( i ).firstChild().firstChild().toElement();
379 if ( posElement.isNull() )
384 if ( readGMLPositions( interiorPointList, posElement ) )
388 ringCoordinates.push_back( interiorPointList );
393 int nrings = ringCoordinates.size();
398 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
400 npoints += it->size();
402 const int size = 1 + 2 *
sizeof( int ) + nrings *
sizeof(
int ) + 2 * npoints *
sizeof( double );
405 unsigned char *wkb =
new unsigned char[size];
408 char e = htonl( 1 ) != 1;
410 int nPointsInRing = 0;
414 memcpy( &( wkb )[wkbPosition], &e, 1 );
416 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
417 wkbPosition +=
sizeof( int );
418 memcpy( &( wkb )[wkbPosition], &nrings,
sizeof(
int ) );
419 wkbPosition +=
sizeof( int );
420 for ( QgsMultiPolylineXY::const_iterator it = ringCoordinates.constBegin(); it != ringCoordinates.constEnd(); ++it )
422 nPointsInRing = it->size();
423 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
424 wkbPosition +=
sizeof( int );
426 QgsPolylineXY::const_iterator iter;
427 for ( iter = it->begin(); iter != it->end(); ++iter )
432 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
433 wkbPosition +=
sizeof( double );
434 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
435 wkbPosition +=
sizeof( double );
444QgsGeometry QgsOgcUtils::geometryFromGMLMultiPoint(
const QDomElement &geometryElement )
448 const QDomNodeList pointMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pointMember" ) );
449 if ( pointMemberList.size() < 1 )
453 QDomNodeList pointNodeList;
455 QDomNodeList coordinatesList;
456 QDomNodeList posList;
457 for (
int i = 0; i < pointMemberList.size(); ++i )
460 pointNodeList = pointMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Point" ) );
461 if ( pointNodeList.size() < 1 )
466 coordinatesList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
467 if ( !coordinatesList.isEmpty() )
469 currentPoint.clear();
470 if ( readGMLCoordinates( currentPoint, coordinatesList.at( 0 ).toElement() ) != 0 )
474 if ( currentPoint.empty() )
478 pointList.push_back( ( *currentPoint.begin() ) );
484 posList = pointNodeList.at( 0 ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"pos" ) );
485 if ( posList.size() < 1 )
489 currentPoint.clear();
490 if ( readGMLPositions( currentPoint, posList.at( 0 ).toElement() ) != 0 )
494 if ( currentPoint.empty() )
498 pointList.push_back( ( *currentPoint.begin() ) );
502 int nPoints = pointList.size();
507 const int size = 1 + 2 *
sizeof( int ) + pointList.size() * ( 2 *
sizeof( double ) + 1 +
sizeof(
int ) );
510 unsigned char *wkb =
new unsigned char[size];
513 char e = htonl( 1 ) != 1;
516 memcpy( &( wkb )[wkbPosition], &e, 1 );
518 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
519 wkbPosition +=
sizeof( int );
520 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
521 wkbPosition +=
sizeof( int );
523 for ( QgsPolylineXY::const_iterator it = pointList.constBegin(); it != pointList.constEnd(); ++it )
525 memcpy( &( wkb )[wkbPosition], &e, 1 );
527 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
528 wkbPosition +=
sizeof( int );
530 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
531 wkbPosition +=
sizeof( double );
533 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
534 wkbPosition +=
sizeof( double );
542QgsGeometry QgsOgcUtils::geometryFromGMLMultiLineString(
const QDomElement &geometryElement )
553 QList< QgsPolylineXY > lineCoordinates;
554 QDomElement currentLineStringElement;
555 QDomNodeList currentCoordList;
556 QDomNodeList currentPosList;
558 const QDomNodeList lineStringMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lineStringMember" ) );
559 if ( !lineStringMemberList.isEmpty() )
561 for (
int i = 0; i < lineStringMemberList.size(); ++i )
563 const QDomNodeList lineStringNodeList = lineStringMemberList.at( i ).toElement().elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
564 if ( lineStringNodeList.size() < 1 )
568 currentLineStringElement = lineStringNodeList.at( 0 ).toElement();
569 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
570 if ( !currentCoordList.isEmpty() )
573 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
577 lineCoordinates.push_back( currentPointList );
581 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
582 if ( currentPosList.size() < 1 )
587 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
591 lineCoordinates.push_back( currentPointList );
597 const QDomNodeList lineStringList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LineString" ) );
598 if ( !lineStringList.isEmpty() )
600 for (
int i = 0; i < lineStringList.size(); ++i )
602 currentLineStringElement = lineStringList.at( i ).toElement();
603 currentCoordList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
604 if ( !currentCoordList.isEmpty() )
607 if ( readGMLCoordinates( currentPointList, currentCoordList.at( 0 ).toElement() ) != 0 )
611 lineCoordinates.push_back( currentPointList );
616 currentPosList = currentLineStringElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
617 if ( currentPosList.size() < 1 )
622 if ( readGMLPositions( currentPointList, currentPosList.at( 0 ).toElement() ) != 0 )
626 lineCoordinates.push_back( currentPointList );
636 int nLines = lineCoordinates.size();
641 int size = ( lineCoordinates.size() + 1 ) * ( 1 + 2 *
sizeof(
int ) );
642 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
644 size += it->size() * 2 *
sizeof( double );
648 unsigned char *wkb =
new unsigned char[size];
651 char e = htonl( 1 ) != 1;
655 memcpy( &( wkb )[wkbPosition], &e, 1 );
657 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
658 wkbPosition +=
sizeof( int );
659 memcpy( &( wkb )[wkbPosition], &nLines,
sizeof(
int ) );
660 wkbPosition +=
sizeof( int );
662 for ( QList< QgsPolylineXY >::const_iterator it = lineCoordinates.constBegin(); it != lineCoordinates.constEnd(); ++it )
664 memcpy( &( wkb )[wkbPosition], &e, 1 );
666 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
667 wkbPosition +=
sizeof( int );
668 nPoints = it->size();
669 memcpy( &( wkb )[wkbPosition], &nPoints,
sizeof(
int ) );
670 wkbPosition +=
sizeof( int );
671 for ( QgsPolylineXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
676 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
677 wkbPosition +=
sizeof( double );
678 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
679 wkbPosition +=
sizeof( double );
688QgsGeometry QgsOgcUtils::geometryFromGMLMultiPolygon(
const QDomElement &geometryElement )
692 QDomElement currentPolygonMemberElement;
693 QDomNodeList polygonList;
694 QDomElement currentPolygonElement;
696 QDomNodeList outerBoundaryList;
697 QDomElement currentOuterBoundaryElement;
698 const QDomNodeList innerBoundaryList;
699 QDomElement currentInnerBoundaryElement;
701 QDomNodeList exteriorList;
702 QDomElement currentExteriorElement;
703 QDomElement currentInteriorElement;
704 const QDomNodeList interiorList;
706 QDomNodeList linearRingNodeList;
707 QDomElement currentLinearRingElement;
709 QDomNodeList currentCoordinateList;
710 QDomNodeList currentPosList;
712 const QDomNodeList polygonMemberList = geometryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"polygonMember" ) );
714 for (
int i = 0; i < polygonMemberList.size(); ++i )
716 currentPolygonList.resize( 0 );
717 currentPolygonMemberElement = polygonMemberList.at( i ).toElement();
718 polygonList = currentPolygonMemberElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"Polygon" ) );
719 if ( polygonList.size() < 1 )
723 currentPolygonElement = polygonList.at( 0 ).toElement();
726 outerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"outerBoundaryIs" ) );
727 if ( !outerBoundaryList.isEmpty() )
729 currentOuterBoundaryElement = outerBoundaryList.at( 0 ).toElement();
732 linearRingNodeList = currentOuterBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
733 if ( linearRingNodeList.size() < 1 )
737 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
738 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
739 if ( currentCoordinateList.size() < 1 )
743 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
747 currentPolygonList.push_back( ringCoordinates );
750 const QDomNodeList innerBoundaryList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"innerBoundaryIs" ) );
751 for (
int j = 0; j < innerBoundaryList.size(); ++j )
754 currentInnerBoundaryElement = innerBoundaryList.at( j ).toElement();
755 linearRingNodeList = currentInnerBoundaryElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
756 if ( linearRingNodeList.size() < 1 )
760 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
761 currentCoordinateList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"coordinates" ) );
762 if ( currentCoordinateList.size() < 1 )
766 if ( readGMLCoordinates( ringCoordinates, currentCoordinateList.at( 0 ).toElement() ) != 0 )
770 currentPolygonList.push_back( ringCoordinates );
776 exteriorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"exterior" ) );
777 if ( exteriorList.size() < 1 )
782 currentExteriorElement = exteriorList.at( 0 ).toElement();
785 linearRingNodeList = currentExteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
786 if ( linearRingNodeList.size() < 1 )
790 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
791 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
792 if ( currentPosList.size() < 1 )
796 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
800 currentPolygonList.push_back( ringPositions );
803 const QDomNodeList interiorList = currentPolygonElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"interior" ) );
804 for (
int j = 0; j < interiorList.size(); ++j )
807 currentInteriorElement = interiorList.at( j ).toElement();
808 linearRingNodeList = currentInteriorElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"LinearRing" ) );
809 if ( linearRingNodeList.size() < 1 )
813 currentLinearRingElement = linearRingNodeList.at( 0 ).toElement();
814 currentPosList = currentLinearRingElement.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"posList" ) );
815 if ( currentPosList.size() < 1 )
819 if ( readGMLPositions( ringPositions, currentPosList.at( 0 ).toElement() ) != 0 )
823 currentPolygonList.push_back( ringPositions );
826 multiPolygonPoints.push_back( currentPolygonList );
829 int nPolygons = multiPolygonPoints.size();
833 int size = 1 + 2 *
sizeof( int );
835 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
837 size += 1 + 2 *
sizeof( int );
838 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
840 size +=
sizeof( int ) + 2 * iter->size() *
sizeof( double );
845 unsigned char *wkb =
new unsigned char[size];
847 char e = htonl( 1 ) != 1;
854 memcpy( &( wkb )[wkbPosition], &e, 1 );
856 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
857 wkbPosition +=
sizeof( int );
858 memcpy( &( wkb )[wkbPosition], &nPolygons,
sizeof(
int ) );
859 wkbPosition +=
sizeof( int );
863 for ( QgsMultiPolygonXY::const_iterator it = multiPolygonPoints.constBegin(); it != multiPolygonPoints.constEnd(); ++it )
865 memcpy( &( wkb )[wkbPosition], &e, 1 );
867 memcpy( &( wkb )[wkbPosition], &type,
sizeof(
int ) );
868 wkbPosition +=
sizeof( int );
870 memcpy( &( wkb )[wkbPosition], &nRings,
sizeof(
int ) );
871 wkbPosition +=
sizeof( int );
872 for ( QgsPolygonXY::const_iterator iter = it->begin(); iter != it->end(); ++iter )
874 nPointsInRing = iter->size();
875 memcpy( &( wkb )[wkbPosition], &nPointsInRing,
sizeof(
int ) );
876 wkbPosition +=
sizeof( int );
877 for ( QgsPolylineXY::const_iterator iterator = iter->begin(); iterator != iter->end(); ++iterator )
881 memcpy( &( wkb )[wkbPosition], &x,
sizeof(
double ) );
882 wkbPosition +=
sizeof( double );
883 memcpy( &( wkb )[wkbPosition], &y,
sizeof(
double ) );
884 wkbPosition +=
sizeof( double );
894QDomElement QgsOgcUtils::filterElement( QDomDocument &doc, GMLVersion gmlVersion, FilterVersion filterVersion,
bool GMLUsed )
896 QDomElement filterElem =
898 doc.createElementNS(
FES_NAMESPACE, QStringLiteral(
"fes:Filter" ) ) :
899 doc.createElementNS(
OGC_NAMESPACE, QStringLiteral(
"ogc:Filter" ) );
903 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:gml" ) );
908 filterElem.setAttributeNode( attr );
914bool QgsOgcUtils::readGMLCoordinates(
QgsPolylineXY &coords,
const QDomElement &elem )
916 QString coordSeparator = QStringLiteral(
"," );
917 QString tupelSeparator = QStringLiteral(
" " );
922 if ( elem.hasAttribute( QStringLiteral(
"cs" ) ) )
924 coordSeparator = elem.attribute( QStringLiteral(
"cs" ) );
926 if ( elem.hasAttribute( QStringLiteral(
"ts" ) ) )
928 tupelSeparator = elem.attribute( QStringLiteral(
"ts" ) );
931#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
932 QStringList tupels = elem.text().split( tupelSeparator, QString::SkipEmptyParts );
934 const QStringList tupels = elem.text().split( tupelSeparator, Qt::SkipEmptyParts );
936 QStringList tuple_coords;
938 bool conversionSuccess;
940 QStringList::const_iterator it;
941 for ( it = tupels.constBegin(); it != tupels.constEnd(); ++it )
943#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
944 tuple_coords = ( *it ).split( coordSeparator, QString::SkipEmptyParts );
946 tuple_coords = ( *it ).split( coordSeparator, Qt::SkipEmptyParts );
948 if ( tuple_coords.size() < 2 )
952 x = tuple_coords.at( 0 ).toDouble( &conversionSuccess );
953 if ( !conversionSuccess )
957 y = tuple_coords.at( 1 ).toDouble( &conversionSuccess );
958 if ( !conversionSuccess )
971 const QDomElement boxElem = boxNode.toElement();
972 if ( boxElem.tagName() != QLatin1String(
"Box" ) )
975 const QDomElement bElem = boxElem.firstChild().toElement();
976 QString coordSeparator = QStringLiteral(
"," );
977 QString tupelSeparator = QStringLiteral(
" " );
978 if ( bElem.hasAttribute( QStringLiteral(
"cs" ) ) )
980 coordSeparator = bElem.attribute( QStringLiteral(
"cs" ) );
982 if ( bElem.hasAttribute( QStringLiteral(
"ts" ) ) )
984 tupelSeparator = bElem.attribute( QStringLiteral(
"ts" ) );
987 const QString bString = bElem.text();
988 bool ok1, ok2, ok3, ok4;
989 const double xmin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 0, 0 ).toDouble( &ok1 );
990 const double ymin = bString.section( tupelSeparator, 0, 0 ).section( coordSeparator, 1, 1 ).toDouble( &ok2 );
991 const double xmax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 0, 0 ).toDouble( &ok3 );
992 const double ymax = bString.section( tupelSeparator, 1, 1 ).section( coordSeparator, 1, 1 ).toDouble( &ok4 );
994 if ( ok1 && ok2 && ok3 && ok4 )
1003bool QgsOgcUtils::readGMLPositions(
QgsPolylineXY &coords,
const QDomElement &elem )
1007#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1008 QStringList pos = elem.text().split(
' ', QString::SkipEmptyParts );
1010 const QStringList pos = elem.text().split(
' ', Qt::SkipEmptyParts );
1013 bool conversionSuccess;
1014 const int posSize = pos.size();
1016 int srsDimension = 2;
1017 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1019 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1020 if ( !conversionSuccess )
1025 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1027 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1028 if ( !conversionSuccess )
1034 for (
int i = 0; i < posSize / srsDimension; i++ )
1036 x = pos.at( i * srsDimension ).toDouble( &conversionSuccess );
1037 if ( !conversionSuccess )
1041 y = pos.at( i * srsDimension + 1 ).toDouble( &conversionSuccess );
1042 if ( !conversionSuccess )
1056 const QDomElement envelopeElem = envelopeNode.toElement();
1057 if ( envelopeElem.tagName() != QLatin1String(
"Envelope" ) )
1060 const QDomNodeList lowerCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"lowerCorner" ) );
1061 if ( lowerCornerList.size() < 1 )
1064 const QDomNodeList upperCornerList = envelopeElem.elementsByTagNameNS(
GML_NAMESPACE, QStringLiteral(
"upperCorner" ) );
1065 if ( upperCornerList.size() < 1 )
1068 bool conversionSuccess;
1069 int srsDimension = 2;
1071 QDomElement elem = lowerCornerList.at( 0 ).toElement();
1072 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1074 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1075 if ( !conversionSuccess )
1080 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1082 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1083 if ( !conversionSuccess )
1088 QString bString = elem.text();
1090 const double xmin = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1091 if ( !conversionSuccess )
1093 const double ymin = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1094 if ( !conversionSuccess )
1097 elem = upperCornerList.at( 0 ).toElement();
1098 if ( elem.hasAttribute( QStringLiteral(
"srsDimension" ) ) )
1100 srsDimension = elem.attribute( QStringLiteral(
"srsDimension" ) ).toInt( &conversionSuccess );
1101 if ( !conversionSuccess )
1106 else if ( elem.hasAttribute( QStringLiteral(
"dimension" ) ) )
1108 srsDimension = elem.attribute( QStringLiteral(
"dimension" ) ).toInt( &conversionSuccess );
1109 if ( !conversionSuccess )
1115 Q_UNUSED( srsDimension )
1117 bString = elem.text();
1118 const double xmax = bString.section(
' ', 0, 0 ).toDouble( &conversionSuccess );
1119 if ( !conversionSuccess )
1121 const double ymax = bString.section(
' ', 1, 1 ).toDouble( &conversionSuccess );
1122 if ( !conversionSuccess )
1138 bool invertAxisOrientation,
1143 return QDomElement();
1146 QDomElement boxElem = doc.createElement( QStringLiteral(
"gml:Box" ) );
1149 boxElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1151 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1152 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1153 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1155 QString coordString;
1164 const QDomText coordText = doc.createTextNode( coordString );
1165 coordElem.appendChild( coordText );
1166 boxElem.appendChild( coordElem );
1178 bool invertAxisOrientation,
1183 return QDomElement();
1186 QDomElement envElem = doc.createElement( QStringLiteral(
"gml:Envelope" ) );
1189 envElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1193 QDomElement lowerCornerElem = doc.createElement( QStringLiteral(
"gml:lowerCorner" ) );
1197 const QDomText lowerCornerText = doc.createTextNode( posList );
1198 lowerCornerElem.appendChild( lowerCornerText );
1199 envElem.appendChild( lowerCornerElem );
1201 QDomElement upperCornerElem = doc.createElement( QStringLiteral(
"gml:upperCorner" ) );
1205 const QDomText upperCornerText = doc.createTextNode( posList );
1206 upperCornerElem.appendChild( upperCornerText );
1207 envElem.appendChild( upperCornerElem );
1221 bool invertAxisOrientation,
1222 const QString &gmlIdBase,
1226 return QDomElement();
1229 QString cs = QStringLiteral(
"," );
1231 const QString ts = QStringLiteral(
" " );
1233 QDomElement baseCoordElem;
1235 bool hasZValue =
false;
1237 const QByteArray wkb( geometry.
asWkb() );
1247 return QDomElement();
1258 baseCoordElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1261 baseCoordElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1264 baseCoordElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1269 baseCoordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1270 baseCoordElem.setAttribute( QStringLiteral(
"cs" ), cs );
1271 baseCoordElem.setAttribute( QStringLiteral(
"ts" ), ts );
1281 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1282 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1283 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1285 pointElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1286 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1290 if ( invertAxisOrientation )
1296 coordElem.appendChild( coordText );
1297 pointElem.appendChild( coordElem );
1306 QDomElement multiPointElem = doc.createElement( QStringLiteral(
"gml:MultiPoint" ) );
1307 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1308 multiPointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1310 multiPointElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1315 for (
int idx = 0; idx < nPoints; ++idx )
1317 QDomElement pointMemberElem = doc.createElement( QStringLiteral(
"gml:pointMember" ) );
1318 QDomElement pointElem = doc.createElement( QStringLiteral(
"gml:Point" ) );
1319 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1320 pointElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( idx + 1 ) );
1321 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1327 if ( invertAxisOrientation )
1333 coordElem.appendChild( coordText );
1334 pointElem.appendChild( coordElem );
1338 wkbPtr +=
sizeof( double );
1340 pointMemberElem.appendChild( pointElem );
1341 multiPointElem.appendChild( pointMemberElem );
1343 return multiPointElem;
1351 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1352 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1353 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1355 lineStringElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1361 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1362 QString coordString;
1363 for (
int idx = 0; idx < nPoints; ++idx )
1372 if ( invertAxisOrientation )
1380 wkbPtr +=
sizeof( double );
1383 const QDomText coordText = doc.createTextNode( coordString );
1384 coordElem.appendChild( coordText );
1385 lineStringElem.appendChild( coordElem );
1386 return lineStringElem;
1394 QDomElement multiLineStringElem = doc.createElement( QStringLiteral(
"gml:MultiLineString" ) );
1395 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1396 multiLineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1398 multiLineStringElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1403 for (
int jdx = 0; jdx < nLines; jdx++ )
1405 QDomElement lineStringMemberElem = doc.createElement( QStringLiteral(
"gml:lineStringMember" ) );
1406 QDomElement lineStringElem = doc.createElement( QStringLiteral(
"gml:LineString" ) );
1407 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1408 lineStringElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( jdx + 1 ) );
1415 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1416 QString coordString;
1417 for (
int idx = 0; idx < nPoints; idx++ )
1426 if ( invertAxisOrientation )
1435 wkbPtr +=
sizeof( double );
1438 const QDomText coordText = doc.createTextNode( coordString );
1439 coordElem.appendChild( coordText );
1440 lineStringElem.appendChild( coordElem );
1441 lineStringMemberElem.appendChild( lineStringElem );
1442 multiLineStringElem.appendChild( lineStringMemberElem );
1444 return multiLineStringElem;
1452 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1453 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1454 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1456 polygonElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1462 if ( numRings == 0 )
1463 return QDomElement();
1465 for (
int idx = 0; idx < numRings; idx++ )
1467 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1470 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1472 QDomElement boundaryElem = doc.createElement( boundaryName );
1473 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1478 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1479 QString coordString;
1480 for (
int jdx = 0; jdx < nPoints; jdx++ )
1489 if ( invertAxisOrientation )
1497 wkbPtr +=
sizeof( double );
1500 const QDomText coordText = doc.createTextNode( coordString );
1501 coordElem.appendChild( coordText );
1502 ringElem.appendChild( coordElem );
1503 boundaryElem.appendChild( ringElem );
1504 polygonElem.appendChild( boundaryElem );
1514 QDomElement multiPolygonElem = doc.createElement( QStringLiteral(
"gml:MultiPolygon" ) );
1515 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1516 multiPolygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase );
1518 multiPolygonElem.setAttribute( QStringLiteral(
"srsName" ),
srsName );
1521 wkbPtr >> numPolygons;
1523 for (
int kdx = 0; kdx < numPolygons; kdx++ )
1525 QDomElement polygonMemberElem = doc.createElement( QStringLiteral(
"gml:polygonMember" ) );
1526 QDomElement polygonElem = doc.createElement( QStringLiteral(
"gml:Polygon" ) );
1527 if ( gmlVersion ==
GML_3_2_1 && !gmlIdBase.isEmpty() )
1528 polygonElem.setAttribute( QStringLiteral(
"gml:id" ), gmlIdBase + QStringLiteral(
".%1" ).arg( kdx + 1 ) );
1535 for (
int idx = 0; idx < numRings; idx++ )
1537 QString boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:outerBoundaryIs" :
"gml:exterior";
1540 boundaryName = ( gmlVersion ==
GML_2_1_2 ) ?
"gml:innerBoundaryIs" :
"gml:interior";
1542 QDomElement boundaryElem = doc.createElement( boundaryName );
1543 QDomElement ringElem = doc.createElement( QStringLiteral(
"gml:LinearRing" ) );
1548 QDomElement coordElem = baseCoordElem.cloneNode().toElement();
1549 QString coordString;
1550 for (
int jdx = 0; jdx < nPoints; jdx++ )
1559 if ( invertAxisOrientation )
1568 wkbPtr +=
sizeof( double );
1571 const QDomText coordText = doc.createTextNode( coordString );
1572 coordElem.appendChild( coordText );
1573 ringElem.appendChild( coordElem );
1574 boundaryElem.appendChild( ringElem );
1575 polygonElem.appendChild( boundaryElem );
1576 polygonMemberElem.appendChild( polygonElem );
1577 multiPolygonElem.appendChild( polygonMemberElem );
1580 return multiPolygonElem;
1583 return QDomElement();
1589 return QDomElement();
1598QDomElement QgsOgcUtils::createGMLCoordinates(
const QgsPolylineXY &points, QDomDocument &doc )
1600 QDomElement coordElem = doc.createElement( QStringLiteral(
"gml:coordinates" ) );
1601 coordElem.setAttribute( QStringLiteral(
"cs" ), QStringLiteral(
"," ) );
1602 coordElem.setAttribute( QStringLiteral(
"ts" ), QStringLiteral(
" " ) );
1604 QString coordString;
1605 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1606 for ( ; pointIt != points.constEnd(); ++pointIt )
1608 if ( pointIt != points.constBegin() )
1617 const QDomText coordText = doc.createTextNode( coordString );
1618 coordElem.appendChild( coordText );
1622QDomElement QgsOgcUtils::createGMLPositions(
const QgsPolylineXY &points, QDomDocument &doc )
1624 QDomElement posElem = doc.createElement( QStringLiteral(
"gml:pos" ) );
1625 if ( points.size() > 1 )
1626 posElem = doc.createElement( QStringLiteral(
"gml:posList" ) );
1627 posElem.setAttribute( QStringLiteral(
"srsDimension" ), QStringLiteral(
"2" ) );
1629 QString coordString;
1630 QVector<QgsPointXY>::const_iterator pointIt = points.constBegin();
1631 for ( ; pointIt != points.constEnd(); ++pointIt )
1633 if ( pointIt != points.constBegin() )
1642 const QDomText coordText = doc.createTextNode( coordString );
1643 posElem.appendChild( coordText );
1653 if ( fillElement.isNull() || !fillElement.hasChildNodes() )
1661 QDomElement cssElem = fillElement.firstChildElement( QStringLiteral(
"CssParameter" ) );
1662 while ( !cssElem.isNull() )
1664 cssName = cssElem.attribute( QStringLiteral(
"name" ), QStringLiteral(
"not_found" ) );
1665 if ( cssName != QLatin1String(
"not_found" ) )
1667 elemText = cssElem.text();
1668 if ( cssName == QLatin1String(
"fill" ) )
1670 color.setNamedColor( elemText );
1672 else if ( cssName == QLatin1String(
"fill-opacity" ) )
1675 const double opacity = elemText.toDouble( &ok );
1678 color.setAlphaF( opacity );
1683 cssElem = cssElem.nextSiblingElement( QStringLiteral(
"CssParameter" ) );
1697 if ( element.isNull() || !element.hasChildNodes() )
1704 if ( element.firstChild().nodeType() == QDomNode::TextNode )
1714 QDomElement childElem = element.firstChildElement();
1715 while ( !childElem.isNull() )
1727 if ( !expr->d->mRootNode )
1729 expr->d->mRootNode = node;
1736 childElem = childElem.nextSiblingElement();
1740 expr->d->mExp = expr->
dump();
1766static
int binaryOperatorFromTagName( const QString &tagName )
1769 return BINARY_OPERATORS_TAG_NAMES_MAP()->value( tagName, -1 );
1776 return QStringLiteral(
"PropertyIsLike" );
1778 return BINARY_OPERATORS_TAG_NAMES_MAP()->key( op, QString() );
1781static bool isBinaryOperator(
const QString &tagName )
1783 return binaryOperatorFromTagName( tagName ) >= 0;
1787static bool isSpatialOperator(
const QString &tagName )
1789 static QStringList spatialOps;
1790 if ( spatialOps.isEmpty() )
1792 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
1793 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
1796 return spatialOps.contains( tagName );
1803 errorMessage = utils.errorMessage();
1811 errorMessage = utils.errorMessage();
1819 errorMessage = utils.errorMessage();
1827 errorMessage = utils.errorMessage();
1835 errorMessage = utils.errorMessage();
1843 errorMessage = utils.errorMessage();
1851 errorMessage = utils.errorMessage();
1855QgsExpressionNode *QgsOgcUtils::nodeIsBetweenFromOgcFilter( QDomElement &element, QString &errorMessage )
1859 errorMessage = utils.errorMessage();
1867 errorMessage = utils.errorMessage();
1878 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage );
1884 QStringLiteral(
"geometry" ), QString(),
false,
false, errorMessage, requiresFilterElement );
1894 bool honourAxisOrientation,
1895 bool invertAxisOrientation,
1896 QString *errorMessage )
1899 return QDomElement();
1909 if ( exprRootElem.isNull() )
1910 return QDomElement();
1912 QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
1913 filterElem.appendChild( exprRootElem );
1923 bool honourAxisOrientation,
1924 bool invertAxisOrientation,
1925 QString *errorMessage,
1926 bool requiresFilterElement )
1935 return QDomElement();
1949 if ( !exprRootElem.isNull() )
1951 if ( requiresFilterElement )
1953 QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
1955 filterElem.appendChild( exprRootElem );
1958 return exprRootElem;
1965 *errorMessage = QObject::tr(
"Node type not supported in expression translation: %1" ).arg( node->
nodeType() );
1969 return QDomElement();
1976 const QList<LayerProperties> &layerProperties,
1977 bool honourAxisOrientation,
1978 bool invertAxisOrientation,
1979 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename,
1980 QString *errorMessage )
1983 return QDomElement();
1986 layerProperties, honourAxisOrientation, invertAxisOrientation,
1987 mapUnprefixedTypenameToPrefixedTypename );
1991 if ( exprRootElem.isNull() )
1992 return QDomElement();
1994 QDomElement filterElem = filterElement( doc, gmlVersion, filterVersion, utils.
GMLNamespaceUsed() );
1996 QSet<QString> setNamespaceURI;
1999 if ( !props.mNamespacePrefix.isEmpty() && !props.mNamespaceURI.isEmpty() &&
2000 !setNamespaceURI.contains( props.mNamespaceURI ) )
2002 setNamespaceURI.insert( props.mNamespaceURI );
2003 QDomAttr attr = doc.createAttribute( QStringLiteral(
"xmlns:" ) + props.mNamespacePrefix );
2004 attr.setValue( props.mNamespaceURI );
2005 filterElem.setAttributeNode( attr );
2008 filterElem.appendChild( exprRootElem );
2033 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2034 return QDomElement();
2041 if ( !mErrorMessage.isEmpty() )
2042 return QDomElement();
2045 switch ( node->
op() )
2048 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2053 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2054 mDoc.removeChild( operandElem );
2058 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2059 return QDomElement();
2063 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2064 uoElem.appendChild( operandElem );
2068 mErrorMessage = QObject::tr(
"Unary operator '%1' not implemented yet" ).arg( node->
text() );
2069 return QDomElement();
2079 if ( !mErrorMessage.isEmpty() )
2080 return QDomElement();
2090 if ( rightLit->
value().isNull() )
2093 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2094 elem.appendChild( leftElem );
2098 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2099 notElem.appendChild( elem );
2113 if ( !mErrorMessage.isEmpty() )
2114 return QDomElement();
2117 const QString opText = binaryOperatorToTagName( op );
2118 if ( opText.isEmpty() )
2122 mErrorMessage = QObject::tr(
"Binary operator %1 not implemented yet" ).arg( node->
text() );
2123 return QDomElement();
2126 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2131 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2134 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2135 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2137 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2139 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2142 boElem.appendChild( leftElem );
2143 boElem.appendChild( rightElem );
2150 Q_UNUSED( expression )
2153 switch ( node->
value().type() )
2156 value = QString::number( node->
value().toInt() );
2158 case QVariant::Double:
2161 case QVariant::String:
2162 value = node->
value().toString();
2164 case QVariant::Date:
2165 value = node->
value().toDate().toString( Qt::ISODate );
2167 case QVariant::DateTime:
2168 value = node->
value().toDateTime().toString( Qt::ISODate );
2172 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2173 return QDomElement();
2176 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2177 litElem.appendChild( mDoc.createTextNode( value ) );
2184 Q_UNUSED( expression )
2186 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2187 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2195 if ( node->
list()->
list().size() == 1 )
2198 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2201 const auto constList = node->
list()->
list();
2205 if ( !mErrorMessage.isEmpty() )
2206 return QDomElement();
2208 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2209 eqElem.appendChild( leftNode.cloneNode() );
2210 eqElem.appendChild( listNode );
2212 orElem.appendChild( eqElem );
2217 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2218 notElem.appendChild( orElem );
2227 { QLatin1String(
"disjoint" ), QLatin1String(
"Disjoint" ) },
2228 { QLatin1String(
"intersects" ), QLatin1String(
"Intersects" )},
2229 { QLatin1String(
"touches" ), QLatin1String(
"Touches" ) },
2230 { QLatin1String(
"crosses" ), QLatin1String(
"Crosses" ) },
2231 { QLatin1String(
"contains" ), QLatin1String(
"Contains" ) },
2232 { QLatin1String(
"overlaps" ), QLatin1String(
"Overlaps" ) },
2233 { QLatin1String(
"within" ), QLatin1String(
"Within" ) }
2236static
bool isBinarySpatialOperator( const QString &fnName )
2238 return BINARY_SPATIAL_OPS_MAP()->contains( fnName );
2241static QString tagNameForSpatialOperator(
const QString &fnName )
2243 return BINARY_SPATIAL_OPS_MAP()->value( fnName );
2253 return fd->
name() == QLatin1String(
"$geometry" );
2265 if ( fnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2267 const QList<QgsExpressionNode *> &args = fnNode->
args()->
list();
2283 if ( fd->
name() == QLatin1String(
"intersects_bbox" ) )
2285 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2286 Q_ASSERT( argNodes.count() == 2 );
2288 const QgsGeometry geom = geometryFromConstExpr( argNodes[1] );
2289 if ( !geom.
isNull() && isGeometryColumn( argNodes[0] ) )
2299 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2300 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2302 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":BBOX" );
2303 funcElem.appendChild( geomProperty );
2304 funcElem.appendChild( elemBox );
2309 mErrorMessage = QObject::tr(
"<BBOX> is currently supported only in form: bbox($geometry, geomFromWKT('…'))" );
2310 return QDomElement();
2314 if ( isBinarySpatialOperator( fd->
name() ) )
2316 QList<QgsExpressionNode *> argNodes = node->
args()->
list();
2317 Q_ASSERT( argNodes.count() == 2 );
2320 if ( isGeometryColumn( argNodes[0] ) )
2321 otherNode = argNodes[1];
2322 else if ( isGeometryColumn( argNodes[1] ) )
2323 otherNode = argNodes[0];
2326 mErrorMessage = QObject::tr(
"Unable to translate spatial operator: at least one must refer to geometry." );
2327 return QDomElement();
2330 QDomElement otherGeomElem;
2335 mErrorMessage = QObject::tr(
"spatial operator: the other operator must be a geometry constructor function" );
2336 return QDomElement();
2341 if ( otherFnDef->
name() == QLatin1String(
"geom_from_wkt" ) )
2346 mErrorMessage = QObject::tr(
"geom_from_wkt: argument must be string literal" );
2347 return QDomElement();
2352 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2353 if ( otherGeomElem.isNull() )
2355 mErrorMessage = QObject::tr(
"geom_from_wkt: unable to generate GML from wkt geometry" );
2356 return QDomElement();
2360 else if ( otherFnDef->
name() == QLatin1String(
"geom_from_gml" ) )
2365 mErrorMessage = QObject::tr(
"geom_from_gml: argument must be string literal" );
2366 return QDomElement();
2369 QDomDocument geomDoc;
2371 if ( !geomDoc.setContent( gml,
true ) )
2373 mErrorMessage = QObject::tr(
"geom_from_gml: unable to parse XML" );
2374 return QDomElement();
2377 const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2378 otherGeomElem = geomNode.toElement();
2384 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2385 if ( otherGeomElem.
isNull() )
2387 mErrorMessage = QObject::tr(
"geom from static value: unable to generate GML from static variable" );
2388 return QDomElement();
2394 mErrorMessage = QObject::tr(
"spatial operator: unknown geometry constructor function" );
2395 return QDomElement();
2400 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + tagNameForSpatialOperator( fd->
name() ) );
2401 QDomElement geomProperty = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2402 geomProperty.appendChild( mDoc.createTextNode( mGeometryName ) );
2403 funcElem.appendChild( geomProperty );
2404 funcElem.appendChild( otherGeomElem );
2408 if ( fd->
isStatic( node, expression, context ) )
2410 const QVariant result = fd->
run( node->
args(), context, expression, node );
2412 return expressionLiteralToOgcFilter( &literal, expression, context );
2417 mErrorMessage = QObject::tr(
"Special columns/constants are not supported." );
2418 return QDomElement();
2422 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
2423 funcElem.setAttribute( QStringLiteral(
"name" ), fd->
name() );
2424 const auto constList = node->
args()->
list();
2428 if ( !mErrorMessage.isEmpty() )
2429 return QDomElement();
2431 funcElem.appendChild( childElem );
2442 const QList<QgsOgcUtils::LayerProperties> &layerProperties,
2443 bool honourAxisOrientation,
2444 bool invertAxisOrientation,
2445 const QMap< QString, QString> &mapUnprefixedTypenameToPrefixedTypename )
2448 , mGMLVersion( gmlVersion )
2449 , mFilterVersion( filterVersion )
2450 , mLayerProperties( layerProperties )
2451 , mHonourAxisOrientation( honourAxisOrientation )
2452 , mInvertAxisOrientation( invertAxisOrientation )
2453 , mFilterPrefix( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"fes" :
"ogc" )
2454 , mPropertyName( ( filterVersion ==
QgsOgcUtils::FILTER_FES_2_0 ) ?
"ValueReference" :
"PropertyName" )
2456 , mMapUnprefixedTypenameToPrefixedTypename( mapUnprefixedTypenameToPrefixedTypename )
2482 mErrorMessage = QObject::tr(
"Node type not supported: %1" ).arg( node->
nodeType() );
2483 return QDomElement();
2492 if ( !mErrorMessage.isEmpty() )
2493 return QDomElement();
2496 switch ( node->
op() )
2499 uoElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2504 uoElem.appendChild( mDoc.createTextNode(
"-" + operandElem.text() ) );
2505 mDoc.removeChild( operandElem );
2509 mErrorMessage = QObject::tr(
"This use of unary operator not implemented yet" );
2510 return QDomElement();
2514 uoElem = mDoc.createElement( mFilterPrefix +
":Not" );
2515 uoElem.appendChild( operandElem );
2520 return QDomElement();
2530 if ( !mErrorMessage.isEmpty() )
2531 return QDomElement();
2541 if ( rightLit->
value().isNull() )
2544 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsNull" );
2545 elem.appendChild( leftElem );
2549 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2550 notElem.appendChild( elem );
2564 if ( !mErrorMessage.isEmpty() )
2565 return QDomElement();
2570 opText = QStringLiteral(
"Or" );
2572 opText = QStringLiteral(
"And" );
2574 opText = QStringLiteral(
"PropertyIsEqualTo" );
2576 opText = QStringLiteral(
"PropertyIsNotEqualTo" );
2578 opText = QStringLiteral(
"PropertyIsLessThanOrEqualTo" );
2580 opText = QStringLiteral(
"PropertyIsGreaterThanOrEqualTo" );
2582 opText = QStringLiteral(
"PropertyIsLessThan" );
2584 opText = QStringLiteral(
"PropertyIsGreaterThan" );
2586 opText = QStringLiteral(
"PropertyIsLike" );
2588 opText = QStringLiteral(
"PropertyIsLike" );
2590 if ( opText.isEmpty() )
2594 return QDomElement();
2597 QDomElement boElem = mDoc.createElement( mFilterPrefix +
":" + opText );
2602 boElem.setAttribute( QStringLiteral(
"matchCase" ), QStringLiteral(
"false" ) );
2605 boElem.setAttribute( QStringLiteral(
"wildCard" ), QStringLiteral(
"%" ) );
2606 boElem.setAttribute( QStringLiteral(
"singleChar" ), QStringLiteral(
"_" ) );
2608 boElem.setAttribute( QStringLiteral(
"escape" ), QStringLiteral(
"\\" ) );
2610 boElem.setAttribute( QStringLiteral(
"escapeChar" ), QStringLiteral(
"\\" ) );
2613 boElem.appendChild( leftElem );
2614 boElem.appendChild( rightElem );
2622 switch ( node->
value().type() )
2625 value = QString::number( node->
value().toInt() );
2627 case QVariant::LongLong:
2628 value = QString::number( node->
value().toLongLong() );
2630 case QVariant::Double:
2633 case QVariant::String:
2634 value = node->
value().toString();
2638 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( node->
value().type() );
2639 return QDomElement();
2642 QDomElement litElem = mDoc.createElement( mFilterPrefix +
":Literal" );
2643 litElem.appendChild( mDoc.createTextNode( value ) );
2650 QDomElement propElem = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
2651 if ( node->
tableName().isEmpty() || mLayerProperties.size() == 1 )
2653 if ( mLayerProperties.size() == 1 && !mLayerProperties[0].mNamespacePrefix.isEmpty() )
2654 propElem.appendChild( mDoc.createTextNode(
2655 mLayerProperties[0].mNamespacePrefix + QStringLiteral(
":" ) + node->
name() ) );
2657 propElem.appendChild( mDoc.createTextNode( node->
name() ) );
2661 QString tableName( mMapTableAliasToNames[node->
tableName()] );
2662 if ( mMapUnprefixedTypenameToPrefixedTypename.contains( tableName ) )
2663 tableName = mMapUnprefixedTypenameToPrefixedTypename[tableName];
2664 propElem.appendChild( mDoc.createTextNode( tableName +
"/" + node->
name() ) );
2671 if ( node->
list()->
list().size() == 1 )
2674 QDomElement orElem = mDoc.createElement( mFilterPrefix +
":Or" );
2677 const auto constList = node->
list()->
list();
2681 if ( !mErrorMessage.isEmpty() )
2682 return QDomElement();
2684 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
2685 eqElem.appendChild( leftNode.cloneNode() );
2686 eqElem.appendChild( listNode );
2688 orElem.appendChild( eqElem );
2693 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2694 notElem.appendChild( orElem );
2703 QDomElement elem = mDoc.createElement( mFilterPrefix +
":PropertyIsBetween" );
2705 QDomElement lowerBoundary = mDoc.createElement( mFilterPrefix +
":LowerBoundary" );
2707 elem.appendChild( lowerBoundary );
2708 QDomElement upperBoundary = mDoc.createElement( mFilterPrefix +
":UpperBoundary" );
2710 elem.appendChild( upperBoundary );
2714 QDomElement notElem = mDoc.createElement( mFilterPrefix +
":Not" );
2715 notElem.appendChild( elem );
2722static QString mapBinarySpatialToOgc(
const QString &name )
2724 QString nameCompare( name );
2725#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2726 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2727 nameCompare = name.mid( 3 );
2729 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).toString().compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2730 nameCompare = name.mid( 3 );
2732 QStringList spatialOps;
2733 spatialOps << QStringLiteral(
"BBOX" ) << QStringLiteral(
"Intersects" ) << QStringLiteral(
"Contains" ) << QStringLiteral(
"Crosses" ) << QStringLiteral(
"Equals" )
2734 << QStringLiteral(
"Disjoint" ) << QStringLiteral(
"Overlaps" ) << QStringLiteral(
"Touches" ) << QStringLiteral(
"Within" );
2735 const auto constSpatialOps = spatialOps;
2736 for ( QString op : constSpatialOps )
2738 if ( nameCompare.compare( op, Qt::CaseInsensitive ) == 0 )
2744static QString mapTernarySpatialToOgc(
const QString &name )
2746 QString nameCompare( name );
2747#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
2748 if ( name.size() > 3 && name.midRef( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2749 nameCompare = name.mid( 3 );
2751 if ( name.size() > 3 && QStringView {name}.mid( 0, 3 ).compare( QLatin1String(
"ST_" ), Qt::CaseInsensitive ) == 0 )
2752 nameCompare = name.mid( 3 );
2754 if ( nameCompare.compare( QLatin1String(
"DWithin" ), Qt::CaseInsensitive ) == 0 )
2755 return QStringLiteral(
"DWithin" );
2756 if ( nameCompare.compare( QLatin1String(
"Beyond" ), Qt::CaseInsensitive ) == 0 )
2757 return QStringLiteral(
"Beyond" );
2761QString QgsOgcUtilsSQLStatementToFilter::getGeometryColumnSRSName(
const QgsSQLStatement::Node *node )
2769 const auto constMLayerProperties = mLayerProperties;
2772 if ( prop.mName.compare( mMapTableAliasToNames[col->
tableName()], Qt::CaseInsensitive ) == 0 &&
2773 prop.mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2775 return prop.mSRSName;
2779 if ( !mLayerProperties.empty() &&
2780 mLayerProperties.at( 0 ).mGeometryAttribute.compare( col->
name(), Qt::CaseInsensitive ) == 0 )
2782 return mLayerProperties.at( 0 ).mSRSName;
2788 QList<QgsSQLStatement::Node *> args,
2789 bool lastArgIsSRSName,
2791 bool &axisInversion )
2794 axisInversion = mInvertAxisOrientation;
2796 if ( lastArgIsSRSName )
2801 mErrorMessage = QObject::tr(
"%1: Last argument must be string or integer literal" ).arg( mainNode->
name() );
2805 if ( lit->
value().type() == QVariant::Int )
2809 srsName =
"EPSG:" + QString::number( lit->
value().toInt() );
2813 srsName =
"urn:ogc:def:crs:EPSG::" + QString::number( lit->
value().toInt() );
2819 if (
srsName.startsWith( QLatin1String(
"EPSG:" ), Qt::CaseInsensitive ) )
2831 axisInversion = !axisInversion;
2841 if ( node->
name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 )
2843 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2844 if ( args.size() != 1 && args.size() != 2 )
2846 mErrorMessage = QObject::tr(
"Function %1 should have 1 or 2 arguments" ).arg( node->
name() );
2847 return QDomElement();
2853 mErrorMessage = QObject::tr(
"%1: First argument must be string literal" ).arg( node->
name() );
2854 return QDomElement();
2859 if ( ! processSRSName( node, args, args.size() == 2,
srsName, axisInversion ) )
2861 return QDomElement();
2867 QStringLiteral(
"qgis_id_geom_%1" ).arg( mGeomId ) );
2869 if ( geomElem.isNull() )
2871 mErrorMessage = QObject::tr(
"%1: invalid WKT" ).arg( node->
name() );
2872 return QDomElement();
2879 if ( node->
name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 )
2881 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2882 if ( args.size() != 4 && args.size() != 5 )
2884 mErrorMessage = QObject::tr(
"Function %1 should have 4 or 5 arguments" ).arg( node->
name() );
2885 return QDomElement();
2890 for (
int i = 0; i < 4; i++ )
2895 mErrorMessage = QObject::tr(
"%1: Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2896 return QDomElement();
2900 if ( lit->
value().type() == QVariant::Int )
2901 val = lit->
value().toInt();
2902 else if ( lit->
value().type() == QVariant::LongLong )
2903 val = lit->
value().toLongLong();
2904 else if ( lit->
value().type() == QVariant::Double )
2905 val = lit->
value().toDouble();
2908 mErrorMessage = QObject::tr(
"%1 Argument %2 must be numeric literal" ).arg( node->
name() ).arg( i + 1 );
2909 return QDomElement();
2923 if ( ! processSRSName( node, args, args.size() == 5,
srsName, axisInversion ) )
2925 return QDomElement();
2936 if ( node->
name().compare( QLatin1String(
"ST_GeomFromGML" ), Qt::CaseInsensitive ) == 0 )
2938 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2939 if ( args.size() != 1 )
2941 mErrorMessage = QObject::tr(
"Function %1 should have 1 argument" ).arg( node->
name() );
2942 return QDomElement();
2948 mErrorMessage = QObject::tr(
"%1: Argument must be string literal" ).arg( node->
name() );
2949 return QDomElement();
2952 QDomDocument geomDoc;
2954 if ( !geomDoc.setContent( gml,
true ) )
2956 mErrorMessage = QObject::tr(
"ST_GeomFromGML: unable to parse XML" );
2957 return QDomElement();
2960 const QDomNode geomNode = mDoc.importNode( geomDoc.documentElement(),
true );
2962 return geomNode.toElement();
2966 QString ogcName( mapBinarySpatialToOgc( node->
name() ) );
2967 if ( !ogcName.isEmpty() )
2969 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
2970 if ( args.size() != 2 )
2972 mErrorMessage = QObject::tr(
"Function %1 should have 2 arguments" ).arg( node->
name() );
2973 return QDomElement();
2976 for (
int i = 0; i < 2; i ++ )
2979 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
2980 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
2982 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
2989 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + ogcName );
2990 const auto constArgs = args;
2994 if ( !mErrorMessage.isEmpty() )
2996 mCurrentSRSName.clear();
2997 return QDomElement();
3000 funcElem.appendChild( childElem );
3003 mCurrentSRSName.clear();
3007 ogcName = mapTernarySpatialToOgc( node->
name() );
3008 if ( !ogcName.isEmpty() )
3010 QList<QgsSQLStatement::Node *> args = node->
args()->
list();
3011 if ( args.size() != 3 )
3013 mErrorMessage = QObject::tr(
"Function %1 should have 3 arguments" ).arg( node->
name() );
3014 return QDomElement();
3017 for (
int i = 0; i < 2; i ++ )
3020 (
static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_GeometryFromText" ), Qt::CaseInsensitive ) == 0 ||
3021 static_cast<const QgsSQLStatement::NodeFunction *
>( args[i] )->name().compare( QLatin1String(
"ST_MakeEnvelope" ), Qt::CaseInsensitive ) == 0 ) )
3023 mCurrentSRSName = getGeometryColumnSRSName( args[1 - i] );
3028 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":" + node->
name().mid( 3 ) );
3029 for (
int i = 0; i < 2; i++ )
3031 const QDomElement childElem =
toOgcFilter( args[i] );
3032 if ( !mErrorMessage.isEmpty() )
3034 mCurrentSRSName.clear();
3035 return QDomElement();
3038 funcElem.appendChild( childElem );
3040 mCurrentSRSName.clear();
3045 mErrorMessage = QObject::tr(
"Function %1 3rd argument should be a numeric value or a string made of a numeric value followed by a string" ).arg( node->
name() );
3046 return QDomElement();
3049 if ( lit->
value().isNull() )
3051 mErrorMessage = QObject::tr(
"Function %1 3rd argument should be a numeric value or a string made of a numeric value followed by a string" ).arg( node->
name() );
3052 return QDomElement();
3055 QString unit( QStringLiteral(
"m" ) );
3056 switch ( lit->
value().type() )
3059 distance = QString::number( lit->
value().toInt() );
3061 case QVariant::LongLong:
3062 distance = QString::number( lit->
value().toLongLong() );
3064 case QVariant::Double:
3067 case QVariant::String:
3069 distance = lit->
value().toString();
3070 for (
int i = 0; i < distance.size(); i++ )
3072 if ( !( ( distance[i] >=
'0' && distance[i] <=
'9' ) || distance[i] ==
'-' || distance[i] ==
'.' || distance[i] ==
'e' || distance[i] ==
'E' ) )
3074 unit = distance.mid( i ).trimmed();
3075 distance = distance.mid( 0, i );
3083 mErrorMessage = QObject::tr(
"Literal type not supported: %1" ).arg( lit->
value().type() );
3084 return QDomElement();
3087 QDomElement distanceElem = mDoc.createElement( mFilterPrefix +
":Distance" );
3089 distanceElem.setAttribute( QStringLiteral(
"uom" ), unit );
3091 distanceElem.setAttribute( QStringLiteral(
"unit" ), unit );
3092 distanceElem.appendChild( mDoc.createTextNode( distance ) );
3093 funcElem.appendChild( distanceElem );
3098 QDomElement funcElem = mDoc.createElement( mFilterPrefix +
":Function" );
3099 funcElem.setAttribute( QStringLiteral(
"name" ), node->
name() );
3100 const auto constList = node->
args()->
list();
3104 if ( !mErrorMessage.isEmpty() )
3105 return QDomElement();
3107 funcElem.appendChild( childElem );
3113 const QString &leftTable )
3121 QList<QDomElement> listElem;
3123 for (
const QString &columnName : constUsingColumns )
3125 QDomElement eqElem = mDoc.createElement( mFilterPrefix +
":PropertyIsEqualTo" );
3126 QDomElement propElem1 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3127 propElem1.appendChild( mDoc.createTextNode( leftTable +
"/" + columnName ) );
3128 eqElem.appendChild( propElem1 );
3129 QDomElement propElem2 = mDoc.createElement( mFilterPrefix +
":" + mPropertyName );
3130 propElem2.appendChild( mDoc.createTextNode( node->
tableDef()->
name() +
"/" + columnName ) );
3131 eqElem.appendChild( propElem2 );
3132 listElem.append( eqElem );
3135 if ( listElem.size() == 1 )
3139 else if ( listElem.size() > 1 )
3141 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3142 const auto constListElem = listElem;
3143 for (
const QDomElement &elem : constListElem )
3145 andElem.appendChild( elem );
3150 return QDomElement();
3155 if ( node->
alias().isEmpty() )
3157 mMapTableAliasToNames[ node->
name()] = node->
name();
3161 mMapTableAliasToNames[ node->
alias()] = node->
name();
3167 QList<QDomElement> listElem;
3170 ( node->
tables().size() != 1 || !node->
joins().empty() ) )
3172 mErrorMessage = QObject::tr(
"Joins are only supported with WFS 2.0" );
3173 return QDomElement();
3177 const auto constTables = node->
tables();
3182 const auto constJoins = node->
joins();
3185 visit( join->tableDef() );
3189 const QList< QgsSQLStatement::NodeTableDef *> nodeTables = node->
tables();
3190 QString leftTable = nodeTables.at( nodeTables.length() - 1 )->name();
3193 const QDomElement joinElem =
toOgcFilter( join, leftTable );
3194 if ( !mErrorMessage.isEmpty() )
3195 return QDomElement();
3196 listElem.append( joinElem );
3197 leftTable = join->tableDef()->name();
3201 if ( node->
where() )
3204 if ( !mErrorMessage.isEmpty() )
3205 return QDomElement();
3206 listElem.append( whereElem );
3210 if ( listElem.size() == 1 )
3214 else if ( listElem.size() > 1 )
3216 QDomElement andElem = mDoc.createElement( mFilterPrefix +
":And" );
3217 const auto constListElem = listElem;
3218 for (
const QDomElement &elem : constListElem )
3220 andElem.appendChild( elem );
3225 return QDomElement();
3231 mPropertyName = QStringLiteral(
"PropertyName" );
3232 mPrefix = QStringLiteral(
"ogc" );
3236 mPropertyName = QStringLiteral(
"ValueReference" );
3237 mPrefix = QStringLiteral(
"fes" );
3243 if ( element.isNull() )
3247 if ( isBinaryOperator( element.tagName() ) )
3253 if ( isSpatialOperator( element.tagName() ) )
3259 if ( element.tagName() == QLatin1String(
"Not" ) )
3263 else if ( element.tagName() == QLatin1String(
"PropertyIsNull" ) )
3267 else if ( element.tagName() == QLatin1String(
"Literal" ) )
3271 else if ( element.tagName() == QLatin1String(
"Function" ) )
3275 else if ( element.tagName() == mPropertyName )
3279 else if ( element.tagName() == QLatin1String(
"PropertyIsBetween" ) )
3284 mErrorMessage += QObject::tr(
"unable to convert '%1' element to a valid expression: it is not supported yet or it has invalid arguments" ).arg( element.tagName() );
3290 if ( element.isNull() )
3293 int op = binaryOperatorFromTagName( element.tagName() );
3296 mErrorMessage = QObject::tr(
"'%1' binary operator not supported." ).arg( element.tagName() );
3300 if ( op ==
QgsExpressionNodeBinaryOperator::boLike && element.hasAttribute( QStringLiteral(
"matchCase" ) ) && element.attribute( QStringLiteral(
"matchCase" ) ) == QLatin1String(
"false" ) )
3305 QDomElement operandElem = element.firstChildElement();
3310 mErrorMessage = QObject::tr(
"invalid left operand for '%1' binary operator" ).arg( element.tagName() );
3314 const std::unique_ptr<QgsExpressionNode> leftOp( expr->clone() );
3315 for ( operandElem = operandElem.nextSiblingElement(); !operandElem.isNull(); operandElem = operandElem.nextSiblingElement() )
3320 mErrorMessage = QObject::tr(
"invalid right operand for '%1' binary operator" ).arg( element.tagName() );
3327 if ( element.hasAttribute( QStringLiteral(
"wildCard" ) ) )
3329 wildCard = element.attribute( QStringLiteral(
"wildCard" ) );
3332 if ( element.hasAttribute( QStringLiteral(
"singleChar" ) ) )
3334 singleChar = element.attribute( QStringLiteral(
"singleChar" ) );
3336 QString escape = QStringLiteral(
"\\" );
3337 if ( element.hasAttribute( QStringLiteral(
"escape" ) ) )
3339 escape = element.attribute( QStringLiteral(
"escape" ) );
3341 if ( element.hasAttribute( QStringLiteral(
"escapeChar" ) ) )
3343 escape = element.attribute( QStringLiteral(
"escapeChar" ) );
3347 if ( !wildCard.isEmpty() && wildCard != QLatin1String(
"%" ) )
3349 oprValue.replace(
'%', QLatin1String(
"\\%" ) );
3350 if ( oprValue.startsWith( wildCard ) )
3352 oprValue.replace( 0, 1, QStringLiteral(
"%" ) );
3355 QRegularExpressionMatch match = rx.match( oprValue );
3357 while ( match.hasMatch() )
3359 pos = match.capturedStart();
3360 oprValue.replace( pos + 1, 1, QStringLiteral(
"%" ) );
3362 match = rx.match( oprValue, pos );
3364 oprValue.replace( escape + wildCard, wildCard );
3366 if ( !singleChar.isEmpty() && singleChar != QLatin1String(
"_" ) )
3368 oprValue.replace(
'_', QLatin1String(
"\\_" ) );
3369 if ( oprValue.startsWith( singleChar ) )
3371 oprValue.replace( 0, 1, QStringLiteral(
"_" ) );
3374 QRegularExpressionMatch match = rx.match( oprValue );
3376 while ( match.hasMatch() )
3378 pos = match.capturedStart();
3379 oprValue.replace( pos + 1, 1, QStringLiteral(
"_" ) );
3381 match = rx.match( oprValue, pos );
3383 oprValue.replace( escape + singleChar, singleChar );
3385 if ( !escape.isEmpty() && escape != QLatin1String(
"\\" ) )
3387 oprValue.replace( escape + escape, escape );
3395 if ( expr == leftOp )
3397 mErrorMessage = QObject::tr(
"only one operand for '%1' binary operator" ).arg( element.tagName() );
3411 QDomElement childElem = element.firstChildElement();
3413 while ( !childElem.isNull() && gml2Str.isEmpty() )
3415 if ( childElem.tagName() != mPropertyName )
3417 QTextStream gml2Stream( &gml2Str );
3418 childElem.save( gml2Stream, 0 );
3420 childElem = childElem.nextSiblingElement();
3422 if ( !gml2Str.isEmpty() )
3428 mErrorMessage = QObject::tr(
"No OGC Geometry found" );
3441 if ( element.isNull() || element.tagName() != mPropertyName )
3443 mErrorMessage = QObject::tr(
"%1:PropertyName expected, got %2" ).arg( mPrefix, element.tagName() );
3452 if ( element.isNull() || element.tagName() != QLatin1String(
"Literal" ) )
3454 mErrorMessage = QObject::tr(
"%1:Literal expected, got %2" ).arg( mPrefix, element.tagName() );
3458 std::unique_ptr<QgsExpressionNode> root;
3461 QDomNode childNode = element.firstChild();
3462 while ( !childNode.isNull() )
3464 std::unique_ptr<QgsExpressionNode> operand;
3466 if ( childNode.nodeType() == QDomNode::ElementNode )
3469 const QDomElement operandElem = childNode.toElement();
3473 mErrorMessage = QObject::tr(
"'%1' is an invalid or not supported content for %2:Literal" ).arg( operandElem.tagName(), mPrefix );
3480 QVariant value = childNode.nodeValue();
3482 bool converted =
false;
3487 QDomElement propertyNameElement = element.previousSiblingElement( mPropertyName );
3488 if ( propertyNameElement.isNull() || propertyNameElement.tagName() != mPropertyName )
3490 propertyNameElement = element.nextSiblingElement( mPropertyName );
3492 if ( !propertyNameElement.isNull() || propertyNameElement.tagName() == mPropertyName )
3494 const int fieldIndex = mLayer->
fields().
indexOf( propertyNameElement.firstChild().nodeValue() );
3495 if ( fieldIndex != -1 )
3508 const double d = value.toDouble( &ok );
3521 root = std::move( operand );
3528 childNode = childNode.nextSibling();
3532 return root.release();
3539 if ( element.tagName() != QLatin1String(
"Not" ) )
3542 const QDomElement operandElem = element.firstChildElement();
3546 mErrorMessage = QObject::tr(
"invalid operand for '%1' unary operator" ).arg( element.tagName() );
3556 if ( element.tagName() != QLatin1String(
"PropertyIsNull" ) )
3561 const QDomElement operandElem = element.firstChildElement();
3572 if ( element.isNull() || element.tagName() != QLatin1String(
"Function" ) )
3574 mErrorMessage = QObject::tr(
"%1:Function expected, got %2" ).arg( mPrefix, element.tagName() );
3582 if ( element.attribute( QStringLiteral(
"name" ) ) != funcDef->
name() )
3587 QDomElement operandElem = element.firstChildElement();
3588 while ( !operandElem.isNull() )
3595 args->append( op.release() );
3597 operandElem = operandElem.nextSiblingElement();
3609 std::unique_ptr<QgsExpressionNode> operand;
3610 std::unique_ptr<QgsExpressionNode> lowerBound;
3611 std::unique_ptr<QgsExpressionNode> upperBound;
3613 QDomElement operandElem = element.firstChildElement();
3614 while ( !operandElem.isNull() )
3616 if ( operandElem.tagName() == QLatin1String(
"LowerBoundary" ) )
3618 const QDomElement lowerBoundElem = operandElem.firstChildElement();
3621 else if ( operandElem.tagName() == QLatin1String(
"UpperBoundary" ) )
3623 const QDomElement upperBoundElem = operandElem.firstChildElement();
3632 if ( operand && lowerBound && upperBound )
3635 operandElem = operandElem.nextSiblingElement();
3638 if ( !operand || !lowerBound || !upperBound )
3640 mErrorMessage = QObject::tr(
"missing some required sub-elements in %1:PropertyIsBetween" ).arg( mPrefix );
3651 return mErrorMessage;
GeometryOperationResult
Success or failure of a geometry operation.
@ Success
Operation succeeded.
virtual void swapXy()=0
Swaps the x and y coordinates from the geometry.
QgsWkbTypes::Type readHeader() const
readHeader
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
bool createFromUserInput(const QString &definition)
Set up this CRS from various text formats.
bool hasAxisInverted() const
Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS.
Custom exception class for Coordinate Reference System related exceptions.
static QgsExpressionContextScope * globalScope()
Creates a new scope which contains variables and functions relating to the global QGIS context.
Expression contexts are used to encapsulate the parameters around which a QgsExpression should be eva...
A abstract base class for defining QgsExpression functions.
int params() const
The number of parameters this function takes.
virtual bool isStatic(const QgsExpressionNodeFunction *node, QgsExpression *parent, const QgsExpressionContext *context) const
Will be called during prepare to determine if the function is static.
QString name() const
The name of the function.
virtual QVariant run(QgsExpressionNode::NodeList *args, const QgsExpressionContext *context, QgsExpression *parent, const QgsExpressionNodeFunction *node)
Evaluates the function, first evaluating all required arguments before passing them to the function's...
A binary expression operator, which operates on two values.
QgsExpressionNode * opLeft() const
Returns the node to the left of the operator.
QgsExpressionNode * opRight() const
Returns the node to the right of the operator.
QgsExpressionNodeBinaryOperator::BinaryOperator op() const
Returns the binary operator.
QString text() const
Returns a the name of this operator without the operands.
BinaryOperator
list of binary operators
An expression node which takes it value from a feature's field.
QString name() const
The name of the column.
An expression node for expression functions.
int fnIndex() const
Returns the index of the node's function.
QgsExpressionNode::NodeList * args() const
Returns a list of arguments specified for the function.
An expression node for value IN or NOT IN clauses.
QgsExpressionNode * node() const
Returns the expression node.
QgsExpressionNode::NodeList * list() const
Returns the list of nodes to search for matching values within.
bool isNotIn() const
Returns true if this node is a "NOT IN" operator, or false if the node is a normal "IN" operator.
An expression node for literal values.
QVariant value() const
The value of the literal.
A unary node is either negative as in boolean (not) or as in numbers (minus).
QgsExpressionNodeUnaryOperator::UnaryOperator op() const
Returns the unary operator.
QString text() const
Returns a the name of this operator without the operands.
QgsExpressionNode * operand() const
Returns the node the operator will operate upon.
A list of expression nodes.
QList< QgsExpressionNode * > list()
Gets a list of all the nodes.
Abstract base class for all nodes that can appear in an expression.
bool hasCachedStaticValue() const
Returns true if the node can be replaced by a static cached value.
virtual QgsExpressionNode::NodeType nodeType() const =0
Gets the type of this node.
QVariant cachedStaticValue() const
Returns the node's static cached value.
Class for parsing and evaluation of expressions (formerly called "search strings").
static const QList< QgsExpressionFunction * > & Functions()
void setExpression(const QString &expression)
Set the expression string, will reset the whole internal structure.
static int functionIndex(const QString &name)
Returns index of the function in Functions array.
QString dump() const
Returns an expression string, constructed from the internal abstract syntax tree.
const QgsExpressionNode * rootNode() const
Returns the root node of the expression.
Encapsulate a field in an attribute table or data source.
bool convertCompatible(QVariant &v, QString *errorMessage=nullptr) const
Converts the provided variant to a compatible format.
int indexOf(const QString &fieldName) const
Gets the field index from the field name.
QgsField field(int fieldIdx) const
Returns the field at particular index (must be in range 0..N-1).
A geometry is the spatial representation of a feature.
QgsWkbTypes::Type wkbType() const SIP_HOLDGIL
Returns type of the geometry as a WKB type (point / linestring / polygon etc.)
Qgis::GeometryOperationResult transform(const QgsCoordinateTransform &ct, Qgis::TransformDirection direction=Qgis::TransformDirection::Forward, bool transformZ=false) SIP_THROW(QgsCsException)
Transforms this geometry as described by the coordinate transform ct.
QgsAbstractGeometry * get()
Returns a modifiable (non-const) reference to the underlying abstract geometry primitive.
static QgsGeometry fromRect(const QgsRectangle &rect) SIP_HOLDGIL
Creates a new geometry from a QgsRectangle.
void fromWkb(unsigned char *wkb, int length)
Set the geometry, feeding in the buffer containing OGC Well-Known Binary and the buffer's length.
static QgsGeometry fromWkt(const QString &wkt)
Creates a new geometry from a WKT string.
QByteArray asWkb(QgsAbstractGeometry::WkbFlags flags=QgsAbstractGeometry::WkbFlags()) const
Export the geometry to WKB.
QgsRectangle boundingBox() const
Returns the bounding box of the geometry.
QgsCoordinateReferenceSystem crs
Internal use by QgsOgcUtils.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
QgsOgcUtilsExprToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QString &geometryName, const QString &srsName, bool honourAxisOrientation, bool invertAxisOrientation)
Constructor.
QDomElement expressionNodeToOgcFilter(const QgsExpressionNode *node, QgsExpression *expression, const QgsExpressionContext *context)
Convert an expression to a OGC filter.
QString errorMessage() const
Returns the error message.
Internal use by QgsOgcUtils.
QgsExpressionNodeFunction * nodeSpatialOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with spatial operators.
QgsExpressionNodeUnaryOperator * nodeNotFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with Not operator.
QgsExpressionNodeColumnRef * nodeColumnRefFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with column references.
QgsExpressionNode * nodeIsBetweenFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with boudnaries operator.
QgsOgcUtilsExpressionFromFilter(QgsOgcUtils::FilterVersion version=QgsOgcUtils::FILTER_OGC_1_0, const QgsVectorLayer *layer=nullptr)
Constructor for QgsOgcUtilsExpressionFromFilter.
QgsExpressionNodeBinaryOperator * nodeBinaryOperatorFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with binary operators.
QgsExpressionNodeFunction * nodeFunctionFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with functions.
QgsExpressionNode * nodeFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document element.
QgsExpressionNodeBinaryOperator * nodePropertyIsNullFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with IsNull operator.
QString errorMessage() const
Returns the underlying error message, or an empty string in case of no error.
QgsExpressionNode * nodeLiteralFromOgcFilter(const QDomElement &element)
Returns an expression node from a WFS filter embedded in a document with literal tag.
Internal use by QgsOgcUtils.
QgsOgcUtilsSQLStatementToFilter(QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, QgsOgcUtils::FilterVersion filterVersion, const QList< QgsOgcUtils::LayerProperties > &layerProperties, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &mapUnprefixedTypenameToPrefixedTypename)
Constructor.
QDomElement toOgcFilter(const QgsSQLStatement::Node *node)
Convert a SQL statement to a OGC filter.
bool GMLNamespaceUsed() const
Returns whether the gml: namespace is used.
QString errorMessage() const
Returns the error message.
The QgsOgcUtils class provides various utility functions for conversion between OGC (Open Geospatial ...
static QgsRectangle rectangleFromGMLBox(const QDomNode &boxNode)
Read rectangle from GML2 Box.
static QDomElement expressionToOgcExpression(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr, bool requiresFilterElement=false)
Creates an OGC expression XML element from the exp expression with default values for the geometry na...
static QColor colorFromOgcFill(const QDomElement &fillElement)
Parse XML with OGC fill into QColor.
static QDomElement expressionToOgcFilter(const QgsExpression &exp, QDomDocument &doc, QString *errorMessage=nullptr)
Creates OGC filter XML element.
FilterVersion
OGC filter version.
static QDomElement SQLStatementToOgcFilter(const QgsSQLStatement &statement, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, FilterVersion filterVersion, const QList< LayerProperties > &layerProperties, bool honourAxisOrientation, bool invertAxisOrientation, const QMap< QString, QString > &mapUnprefixedTypenameToPrefixedTypename, QString *errorMessage=nullptr)
Creates OGC filter XML element from the WHERE and JOIN clauses of a SQL statement.
static QgsRectangle rectangleFromGMLEnvelope(const QDomNode &envelopeNode)
Read rectangle from GML3 Envelope.
static QDomElement geometryToGML(const QgsGeometry &geometry, QDomDocument &doc, QgsOgcUtils::GMLVersion gmlVersion, const QString &srsName, bool invertAxisOrientation, const QString &gmlIdBase, int precision=17)
Exports the geometry to GML.
static QgsGeometry geometryFromGML(const QString &xmlString, const QgsOgcUtils::Context &context=QgsOgcUtils::Context())
Static method that creates geometry from GML.
static QDomElement rectangleToGMLEnvelope(QgsRectangle *env, QDomDocument &doc, int precision=17)
Exports the rectangle to GML3 Envelope.
static QgsExpression * expressionFromOgcFilter(const QDomElement &element, QgsVectorLayer *layer=nullptr)
Parse XML with OGC filter into QGIS expression.
static QDomElement rectangleToGMLBox(QgsRectangle *box, QDomDocument &doc, int precision=17)
Exports the rectangle to GML2 Box.
A class to represent a 2D point.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
void normalize()
Normalize the rectangle so it has non-negative width/height.
'X BETWEEN y and z' operator
QgsSQLStatement::Node * node() const
Variable at the left of BETWEEN.
QgsSQLStatement::Node * minVal() const
Minimum bound.
bool isNotBetween() const
Whether this is a NOT BETWEEN operator.
QgsSQLStatement::Node * maxVal() const
Maximum bound.
Binary logical/arithmetical operator (AND, OR, =, +, ...)
QgsSQLStatement::Node * opLeft() const
Left operand.
QgsSQLStatement::BinaryOperator op() const
Operator.
QgsSQLStatement::Node * opRight() const
Right operand.
QString name() const
The name of the column.
QString tableName() const
The name of the table. May be empty.
Function with a name and arguments node.
QgsSQLStatement::NodeList * args() const
Returns arguments.
QString name() const
Returns function name.
bool isNotIn() const
Whether this is a NOT IN operator.
QgsSQLStatement::Node * node() const
Variable at the left of IN.
QgsSQLStatement::NodeList * list() const
Values list.
QgsSQLStatement::NodeTableDef * tableDef() const
Table definition.
QgsSQLStatement::Node * onExpr() const
On expression. Will be nullptr if usingColumns() is not empty.
QList< QString > usingColumns() const
Columns referenced by USING.
QList< QgsSQLStatement::Node * > list()
Returns list.
Literal value (integer, integer64, double, string)
QVariant value() const
The value of the literal.
QList< QgsSQLStatement::NodeJoin * > joins() const
Returns the list of joins.
QgsSQLStatement::Node * where() const
Returns the where clause.
QList< QgsSQLStatement::NodeTableDef * > tables() const
Returns the list of tables.
QString name() const
Table name.
QString alias() const
Table alias.
Unary logicial/arithmetical operator ( NOT, - )
QgsSQLStatement::UnaryOperator op() const
Operator.
QgsSQLStatement::Node * operand() const
Operand.
virtual QgsSQLStatement::NodeType nodeType() const =0
Abstract virtual that returns the type of this node.
Class for parsing SQL statements.
BinaryOperator
list of binary operators
static const char * BINARY_OPERATOR_TEXT[]
const QgsSQLStatement::Node * rootNode() const
Returns the root node of the statement.
static const char * UNARY_OPERATOR_TEXT[]
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
Represents a vector layer which manages a vector based data sets.
QgsFields fields() const FINAL
Returns the list of fields of this layer.
Custom exception class for Wkb related exceptions.
Type
The WKB type describes the number of dimensions a geometry has.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
QMap< QString, QString > QgsStringMap
QVector< QgsPolylineXY > QgsPolygonXY
Polygon: first item of the list is outer ring, inner rings (if any) start from second item.
QVector< QgsPolylineXY > QgsMultiPolylineXY
A collection of QgsPolylines that share a common collection of attributes.
QVector< QgsPointXY > QgsPolylineXY
Polyline as represented as a vector of two-dimensional points.
QVector< QgsPolygonXY > QgsMultiPolygonXY
A collection of QgsPolygons that share a common collection of attributes.
#define QgsDebugMsgLevel(str, level)
Q_GLOBAL_STATIC_WITH_ARGS(IntMap, BINARY_OPERATORS_TAG_NAMES_MAP,({ { QLatin1String("Or"), QgsExpressionNodeBinaryOperator::boOr }, { QLatin1String("And"), QgsExpressionNodeBinaryOperator::boAnd }, { QLatin1String("PropertyIsEqualTo"), QgsExpressionNodeBinaryOperator::boEQ }, { QLatin1String("PropertyIsNotEqualTo"), QgsExpressionNodeBinaryOperator::boNE }, { QLatin1String("PropertyIsLessThanOrEqualTo"), QgsExpressionNodeBinaryOperator::boLE }, { QLatin1String("PropertyIsGreaterThanOrEqualTo"), QgsExpressionNodeBinaryOperator::boGE }, { QLatin1String("PropertyIsLessThan"), QgsExpressionNodeBinaryOperator::boLT }, { QLatin1String("PropertyIsGreaterThan"), QgsExpressionNodeBinaryOperator::boGT }, { QLatin1String("PropertyIsLike"), QgsExpressionNodeBinaryOperator::boLike }, { QLatin1String("Add"), QgsExpressionNodeBinaryOperator::boPlus }, { QLatin1String("Sub"), QgsExpressionNodeBinaryOperator::boMinus }, { QLatin1String("Mul"), QgsExpressionNodeBinaryOperator::boMul }, { QLatin1String("Div"), QgsExpressionNodeBinaryOperator::boDiv }, })) static int binaryOperatorFromTagName(const QString &tagName)
QMap< QString, int > IntMap
const QString & geometryName
const QgsCoordinateReferenceSystem & crs
The Context struct stores the current layer and coordinate transform context.
const QgsMapLayer * layer
QgsCoordinateTransformContext transformContext