1 /***************************************************************************
2                          qgswkbtypes.h
3                          -----------------------
4     begin                : January 2015
5     copyright            : (C) 2015 by Marco Hugentobler
6     email                : marco at sourcepole dot ch
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #ifndef QGSWKBTYPES_H
19 #define QGSWKBTYPES_H
20 
21 #include <QObject>
22 #include <QMap>
23 #include <QString>
24 
25 #include "qgis_core.h"
26 #include "qgis_sip.h"
27 
28 /***************************************************************************
29  * This class is considered CRITICAL and any change MUST be accompanied with
30  * full unit tests in testqgsstatisticalsummary.cpp.
31  * See details in QEP #17
32  ****************************************************************************/
33 
34 /**
35  * \ingroup core
36  * \class QgsWkbTypes
37  * \brief Handles storage of information regarding WKB types and their properties.
38  * \since QGIS 2.10
39  */
40 
41 class CORE_EXPORT QgsWkbTypes
42 {
43     Q_GADGET
44   public:
45 
46     /**
47      * The WKB type describes the number of dimensions a geometry has
48      *
49      * - Point
50      * - LineString
51      * - Polygon
52      *
53      * as well as the number of dimensions for each individual vertex
54      *
55      * - X (always)
56      * - Y (always)
57      * - Z (optional)
58      * - M (measurement value, optional)
59      *
60      * it also has values for multi types, collections, unknown geometry,
61      * null geometry, no geometry and curve support.
62      *
63      * These classes of geometry are often used for data sources to
64      * communicate what kind of geometry should be expected for a given
65      * geometry field. It is also used for tools or algorithms to decide
66      * if they should be available for a given geometry type or act in
67      * a different mode.
68      */
69     enum Type
70     {
71       Unknown = 0,
72       Point = 1,
73       LineString = 2,
74       Polygon = 3,
75       Triangle = 17,
76       MultiPoint = 4,
77       MultiLineString = 5,
78       MultiPolygon = 6,
79       GeometryCollection = 7,
80       CircularString = 8,
81       CompoundCurve = 9,
82       CurvePolygon = 10, //13, //should be 10. Seems to be correct in newer PostGIS versions
83       MultiCurve = 11,
84       MultiSurface = 12,
85       NoGeometry = 100, //attributes only
86       PointZ = 1001,
87       LineStringZ = 1002,
88       PolygonZ = 1003,
89       TriangleZ = 1017,
90       MultiPointZ = 1004,
91       MultiLineStringZ = 1005,
92       MultiPolygonZ = 1006,
93       GeometryCollectionZ = 1007,
94       CircularStringZ = 1008,
95       CompoundCurveZ = 1009,
96       CurvePolygonZ = 1010,
97       MultiCurveZ = 1011,
98       MultiSurfaceZ = 1012,
99       PointM = 2001,
100       LineStringM = 2002,
101       PolygonM = 2003,
102       TriangleM = 2017,
103       MultiPointM = 2004,
104       MultiLineStringM = 2005,
105       MultiPolygonM = 2006,
106       GeometryCollectionM = 2007,
107       CircularStringM = 2008,
108       CompoundCurveM = 2009,
109       CurvePolygonM = 2010,
110       MultiCurveM = 2011,
111       MultiSurfaceM = 2012,
112       PointZM = 3001,
113       LineStringZM = 3002,
114       PolygonZM = 3003,
115       MultiPointZM = 3004,
116       MultiLineStringZM = 3005,
117       MultiPolygonZM = 3006,
118       GeometryCollectionZM = 3007,
119       CircularStringZM = 3008,
120       CompoundCurveZM = 3009,
121       CurvePolygonZM = 3010,
122       MultiCurveZM = 3011,
123       MultiSurfaceZM = 3012,
124       TriangleZM = 3017,
125       Point25D = 0x80000001,
126       LineString25D,
127       Polygon25D,
128       MultiPoint25D,
129       MultiLineString25D,
130       MultiPolygon25D
131     };
132     Q_ENUM( Type )
133 
134     /**
135      * The geometry types are used to group QgsWkbTypes::Type in a
136      * coarse way.
137      *
138      * \see geometryType( QgsWkbTypes::Type )
139      */
140     enum GeometryType
141     {
142       PointGeometry,
143       LineGeometry,
144       PolygonGeometry,
145       UnknownGeometry,
146       NullGeometry
147     };
Q_ENUM(GeometryType)148     Q_ENUM( GeometryType )
149 
150     /**
151      * Returns the single type for a WKB type. For example, for MultiPolygon WKB types the single type would be Polygon.
152      * \see isSingleType()
153      * \see multiType()
154      * \see curveType()
155      * \see flatType()
156      */
157     static Type singleType( Type type ) SIP_HOLDGIL
158     {
159       switch ( type )
160       {
161         case Unknown:
162         case GeometryCollection:
163         case GeometryCollectionZ:
164         case GeometryCollectionM:
165         case GeometryCollectionZM:
166           return Unknown;
167 
168         case Point:
169         case MultiPoint:
170           return Point;
171 
172         case PointZ:
173         case MultiPointZ:
174           return PointZ;
175 
176         case PointM:
177         case MultiPointM:
178           return PointM;
179 
180         case PointZM:
181         case MultiPointZM:
182           return PointZM;
183 
184         case LineString:
185         case MultiLineString:
186           return LineString;
187 
188         case LineStringZ:
189         case MultiLineStringZ:
190           return LineStringZ;
191 
192         case LineStringM:
193         case MultiLineStringM:
194           return LineStringM;
195 
196         case LineStringZM:
197         case MultiLineStringZM:
198           return LineStringZM;
199 
200         case Polygon:
201         case MultiPolygon:
202           return Polygon;
203 
204         case PolygonZ:
205         case MultiPolygonZ:
206           return PolygonZ;
207 
208         case PolygonM:
209         case MultiPolygonM:
210           return PolygonM;
211 
212         case PolygonZM:
213         case MultiPolygonZM:
214           return PolygonZM;
215 
216         case Triangle:
217           // case MultiTriangle:
218           return Triangle;
219 
220         case TriangleZ:
221           // case MultiTriangleZ:
222           return TriangleZ;
223 
224         case TriangleM:
225           // case MultiTriangleM:
226           return TriangleM;
227 
228         case TriangleZM:
229           // case MultiTriangleZM:
230           return TriangleZM;
231 
232         case CircularString:
233           return CircularString;
234 
235         case CircularStringZ:
236           return CircularStringZ;
237 
238         case CircularStringM:
239           return CircularStringM;
240 
241         case CircularStringZM:
242           return CircularStringZM;
243 
244         case CompoundCurve:
245         case MultiCurve:
246           return CompoundCurve;
247 
248         case CompoundCurveZ:
249         case MultiCurveZ:
250           return CompoundCurveZ;
251 
252         case CompoundCurveM:
253         case MultiCurveM:
254           return CompoundCurveM;
255 
256         case CompoundCurveZM:
257         case MultiCurveZM:
258           return CompoundCurveZM;
259 
260         case CurvePolygon:
261         case MultiSurface:
262           return CurvePolygon;
263 
264         case CurvePolygonZ:
265         case MultiSurfaceZ:
266           return CurvePolygonZ;
267 
268         case CurvePolygonM:
269         case MultiSurfaceM:
270           return CurvePolygonM;
271 
272         case CurvePolygonZM:
273         case MultiSurfaceZM:
274           return CurvePolygonZM;
275 
276         case NoGeometry:
277           return NoGeometry;
278 
279         case Point25D:
280         case MultiPoint25D:
281           return Point25D;
282 
283         case LineString25D:
284         case MultiLineString25D:
285           return LineString25D;
286 
287         case Polygon25D:
288         case MultiPolygon25D:
289           return Polygon25D;
290 
291       }
292       return Unknown;
293     }
294 
295     /**
296      * Returns the multi type for a WKB type. For example, for Polygon WKB types the multi type would be MultiPolygon.
297      *
298      * \see promoteNonPointTypesToMulti()
299      * \see isMultiType()
300      * \see singleType()
301      * \see curveType()
302      * \see flatType()
303      */
multiType(Type type)304     static Type multiType( Type type ) SIP_HOLDGIL
305     {
306       switch ( type )
307       {
308         case Unknown:
309           return Unknown;
310 
311         // until we support TIN types, use multipolygon
312         case Triangle:
313           return MultiPolygon;
314 
315         case TriangleZ:
316           return MultiPolygonZ;
317 
318         case TriangleM:
319           return MultiPolygonM;
320 
321         case TriangleZM:
322           return MultiPolygonZM;
323 
324         case GeometryCollection:
325           return GeometryCollection;
326 
327         case GeometryCollectionZ:
328           return GeometryCollectionZ;
329 
330         case GeometryCollectionM:
331           return GeometryCollectionM;
332 
333         case GeometryCollectionZM:
334           return GeometryCollectionZM;
335 
336         case Point:
337         case MultiPoint:
338           return MultiPoint;
339 
340         case PointZ:
341         case MultiPointZ:
342           return MultiPointZ;
343 
344         case PointM:
345         case MultiPointM:
346           return MultiPointM;
347 
348         case PointZM:
349         case MultiPointZM:
350           return MultiPointZM;
351 
352         case LineString:
353         case MultiLineString:
354           return MultiLineString;
355 
356         case LineStringZ:
357         case MultiLineStringZ:
358           return MultiLineStringZ;
359 
360         case LineStringM:
361         case MultiLineStringM:
362           return MultiLineStringM;
363 
364         case LineStringZM:
365         case MultiLineStringZM:
366           return MultiLineStringZM;
367 
368         case Polygon:
369         case MultiPolygon:
370           return MultiPolygon;
371 
372         case PolygonZ:
373         case MultiPolygonZ:
374           return MultiPolygonZ;
375 
376         case PolygonM:
377         case MultiPolygonM:
378           return MultiPolygonM;
379 
380         case PolygonZM:
381         case MultiPolygonZM:
382           return MultiPolygonZM;
383 
384         case CompoundCurve:
385         case CircularString:
386         case MultiCurve:
387           return MultiCurve;
388 
389         case CompoundCurveZ:
390         case CircularStringZ:
391         case MultiCurveZ:
392           return MultiCurveZ;
393 
394         case CompoundCurveM:
395         case CircularStringM:
396         case MultiCurveM:
397           return MultiCurveM;
398 
399         case CompoundCurveZM:
400         case CircularStringZM:
401         case MultiCurveZM:
402           return MultiCurveZM;
403 
404         case CurvePolygon:
405         case MultiSurface:
406           return MultiSurface;
407 
408         case CurvePolygonZ:
409         case MultiSurfaceZ:
410           return MultiSurfaceZ;
411 
412         case CurvePolygonM:
413         case MultiSurfaceM:
414           return MultiSurfaceM;
415 
416         case CurvePolygonZM:
417         case MultiSurfaceZM:
418           return MultiSurfaceZM;
419 
420         case NoGeometry:
421           return NoGeometry;
422 
423         case Point25D:
424         case MultiPoint25D:
425           return MultiPoint25D;
426 
427         case LineString25D:
428         case MultiLineString25D:
429           return MultiLineString25D;
430 
431         case Polygon25D:
432         case MultiPolygon25D:
433           return MultiPolygon25D;
434       }
435       return Unknown;
436     }
437 
438 
439     /**
440      * Promotes a WKB geometry type to its multi-type equivalent, with the exception of point geometry types.
441      *
442      * Specifically, this method should be used to determine the most-permissive possible resultant WKB type which can result
443      * from subtracting parts of a geometry. A single-point geometry type can never become a multi-point geometry type as
444      * a result of a subtraction, but a single-line or single-polygon geometry CAN become a multipart geometry as a result of subtracting
445      * portions of the geometry.
446      *
447      * \see multiType()
448      * \see singleType()
449      * \since QGIS 3.24
450      */
promoteNonPointTypesToMulti(Type type)451     static Type promoteNonPointTypesToMulti( Type type ) SIP_HOLDGIL
452     {
453       switch ( geometryType( type ) )
454       {
455         case QgsWkbTypes::PointGeometry:
456         case QgsWkbTypes::UnknownGeometry:
457         case QgsWkbTypes::NullGeometry:
458           return type;
459 
460         case QgsWkbTypes::LineGeometry:
461         case QgsWkbTypes::PolygonGeometry:
462           return multiType( type );
463       }
464       return Unknown;
465     }
466 
467     /**
468      * Returns the curve type for a WKB type. For example, for Polygon WKB types the curve type would be CurvePolygon.
469      *
470      * \note Returns `CompoundCurve` for `CircularString` (and its Z/M variants)
471      *
472      * \see linearType()
473      * \see isMultiType()
474      * \see isCurvedType()
475      * \see singleType()
476      * \see flatType()
477      * \see multiType()
478      *
479      * \since QGIS 3.10
480      */
curveType(Type type)481     static Type curveType( Type type ) SIP_HOLDGIL
482     {
483       switch ( type )
484       {
485         case Unknown:
486         case Triangle:
487         case TriangleZ:
488         case TriangleM:
489         case TriangleZM:
490           return Unknown;
491 
492         case GeometryCollection:
493           return GeometryCollection;
494 
495         case GeometryCollectionZ:
496           return GeometryCollectionZ;
497 
498         case GeometryCollectionM:
499           return GeometryCollectionM;
500 
501         case GeometryCollectionZM:
502           return GeometryCollectionZM;
503 
504         case Point:
505           return Point;
506 
507         case MultiPoint:
508           return MultiPoint;
509 
510         case PointZ:
511           return PointZ;
512 
513         case MultiPointZ:
514           return MultiPointZ;
515 
516         case PointM:
517           return PointM;
518 
519         case MultiPointM:
520           return MultiPointM;
521 
522         case PointZM:
523           return PointZM;
524 
525         case MultiPointZM:
526           return MultiPointZM;
527 
528         case LineString:
529         case CompoundCurve:
530         case CircularString:
531           return CompoundCurve;
532 
533         case MultiLineString:
534         case MultiCurve:
535           return MultiCurve;
536 
537         case LineStringZ:
538         case CompoundCurveZ:
539         case CircularStringZ:
540         case LineString25D:
541           return CompoundCurveZ;
542 
543         case MultiLineStringZ:
544         case MultiCurveZ:
545         case MultiLineString25D:
546           return MultiCurveZ;
547 
548         case LineStringM:
549         case CompoundCurveM:
550         case CircularStringM:
551           return CompoundCurveM;
552 
553         case MultiLineStringM:
554         case MultiCurveM:
555           return MultiCurveM;
556 
557         case LineStringZM:
558         case CompoundCurveZM:
559         case CircularStringZM:
560           return CompoundCurveZM;
561 
562         case MultiLineStringZM:
563         case MultiCurveZM:
564           return MultiCurveZM;
565 
566         case Polygon:
567         case CurvePolygon:
568           return CurvePolygon;
569 
570         case MultiPolygon:
571         case MultiSurface:
572           return MultiSurface;
573 
574         case PolygonZ:
575         case CurvePolygonZ:
576         case Polygon25D:
577           return CurvePolygonZ;
578 
579         case MultiPolygonZ:
580         case MultiSurfaceZ:
581         case MultiPolygon25D:
582           return MultiSurfaceZ;
583 
584         case PolygonM:
585         case CurvePolygonM:
586           return CurvePolygonM;
587 
588         case MultiPolygonM:
589         case MultiSurfaceM:
590           return MultiSurfaceM;
591 
592         case PolygonZM:
593         case CurvePolygonZM:
594           return CurvePolygonZM;
595 
596         case MultiPolygonZM:
597         case MultiSurfaceZM:
598           return MultiSurfaceZM;
599 
600         case NoGeometry:
601           return NoGeometry;
602 
603         case Point25D:
604         case MultiPoint25D:
605           return MultiPoint25D;
606       }
607       return Unknown;
608     }
609 
610     /**
611      * Returns the linear type for a WKB type. For example, for a CompoundCurve, the linear type would be LineString.
612      *
613      * \see curveType()
614      * \see isMultiType()
615      * \see isCurvedType()
616      * \see singleType()
617      * \see flatType()
618      * \see multiType()
619      *
620      * \since QGIS 3.14
621      */
linearType(Type type)622     static Type linearType( Type type ) SIP_HOLDGIL
623     {
624       switch ( type )
625       {
626 
627         case CircularString:
628         case CompoundCurve:
629           return LineString;
630 
631         case CircularStringM:
632         case CompoundCurveM:
633           return LineStringM;
634 
635         case CircularStringZ:
636         case CompoundCurveZ:
637           return LineStringZ;
638 
639         case CircularStringZM:
640         case CompoundCurveZM:
641           return LineStringZM;
642 
643         case MultiCurve:
644           return MultiLineString;
645 
646         case MultiCurveM:
647           return MultiLineStringM;
648 
649         case MultiCurveZ:
650           return MultiLineStringZ;
651 
652         case MultiCurveZM:
653           return MultiLineStringZM;
654 
655         case CurvePolygon:
656           return Polygon;
657 
658         case CurvePolygonM:
659           return PolygonM;
660 
661         case CurvePolygonZ:
662           return PolygonZ;
663 
664         case CurvePolygonZM:
665           return PolygonZM;
666 
667         case MultiSurface:
668           return MultiPolygon;
669 
670         case MultiSurfaceM:
671           return MultiPolygonM;
672 
673         case MultiSurfaceZ:
674           return MultiPolygonZ;
675 
676         case MultiSurfaceZM:
677           return MultiPolygonZM;
678 
679         case GeometryCollection:
680         case GeometryCollectionM:
681         case GeometryCollectionZ:
682         case GeometryCollectionZM:
683         case LineString:
684         case LineString25D:
685         case LineStringM:
686         case LineStringZ:
687         case LineStringZM:
688         case MultiLineString:
689         case MultiLineString25D:
690         case MultiLineStringM:
691         case MultiLineStringZ:
692         case MultiLineStringZM:
693         case MultiPoint:
694         case MultiPoint25D:
695         case MultiPointM:
696         case MultiPointZ:
697         case MultiPointZM:
698         case MultiPolygon:
699         case MultiPolygon25D:
700         case MultiPolygonM:
701         case MultiPolygonZ:
702         case MultiPolygonZM:
703         case NoGeometry:
704         case Point:
705         case Point25D:
706         case PointM:
707         case PointZ:
708         case PointZM:
709         case Polygon:
710         case Polygon25D:
711         case PolygonM:
712         case PolygonZ:
713         case PolygonZM:
714         case Triangle:
715         case TriangleM:
716         case TriangleZ:
717         case TriangleZM:
718         case Unknown:
719           return type;
720 
721       }
722       return Unknown;
723     }
724 
725     /**
726      * Returns the flat type for a WKB type. This is the WKB type minus any Z or M dimensions.
727      * For example, for PolygonZM WKB types the single type would be Polygon.
728      * \see singleType()
729      * \see multiType()
730      * \see curveType()
731      */
flatType(Type type)732     static Type flatType( Type type ) SIP_HOLDGIL
733     {
734       switch ( type )
735       {
736         case Unknown:
737           return Unknown;
738 
739         case Point:
740         case PointZ:
741         case PointM:
742         case PointZM:
743         case Point25D:
744           return Point;
745 
746         case LineString:
747         case LineStringZ:
748         case LineStringM:
749         case LineStringZM:
750         case LineString25D:
751           return LineString;
752 
753         case Polygon:
754         case PolygonZ:
755         case PolygonM:
756         case PolygonZM:
757         case Polygon25D:
758           return Polygon;
759 
760         case Triangle:
761         case TriangleZ:
762         case TriangleM:
763         case TriangleZM:
764           return Triangle;
765 
766         case MultiPoint:
767         case MultiPointZ:
768         case MultiPointM:
769         case MultiPointZM:
770         case MultiPoint25D:
771           return MultiPoint;
772 
773         case MultiLineString:
774         case MultiLineStringZ:
775         case MultiLineStringM:
776         case MultiLineStringZM:
777         case MultiLineString25D:
778           return MultiLineString;
779 
780         case MultiPolygon:
781         case MultiPolygonZ:
782         case MultiPolygonM:
783         case MultiPolygonZM:
784         case MultiPolygon25D:
785           return MultiPolygon;
786 
787         case GeometryCollection:
788         case GeometryCollectionZ:
789         case GeometryCollectionM:
790         case GeometryCollectionZM:
791           return GeometryCollection;
792 
793         case CircularString:
794         case CircularStringZ:
795         case CircularStringM:
796         case CircularStringZM:
797           return CircularString;
798 
799         case CompoundCurve:
800         case CompoundCurveZ:
801         case CompoundCurveM:
802         case CompoundCurveZM:
803           return CompoundCurve;
804 
805         case MultiCurve:
806         case MultiCurveZ:
807         case MultiCurveM:
808         case MultiCurveZM:
809           return MultiCurve;
810 
811         case CurvePolygon:
812         case CurvePolygonZ:
813         case CurvePolygonM:
814         case CurvePolygonZM:
815           return CurvePolygon;
816 
817         case MultiSurface:
818         case MultiSurfaceZ:
819         case MultiSurfaceM:
820         case MultiSurfaceZM:
821           return MultiSurface;
822 
823         case NoGeometry:
824           return NoGeometry;
825 
826       }
827       return Unknown;
828     }
829 
830     //! Returns the modified input geometry type according to hasZ / hasM
zmType(Type type,bool hasZ,bool hasM)831     static Type zmType( Type type, bool hasZ, bool hasM ) SIP_HOLDGIL
832     {
833       type = flatType( type );
834       if ( hasZ )
835         type = static_cast<QgsWkbTypes::Type>( static_cast<quint32>( type ) + 1000 );
836       if ( hasM )
837         type = static_cast<QgsWkbTypes::Type>( static_cast<quint32>( type ) + 2000 );
838       return type;
839     }
840 
841     /**
842      * Attempts to extract the WKB type from a WKT string.
843      * \param wktStr a valid WKT string
844      */
845     static Type parseType( const QString &wktStr );
846 
847     /**
848      * Returns TRUE if the WKB type is a single type.
849      * \see isMultiType()
850      * \see singleType()
851      */
isSingleType(Type type)852     static bool isSingleType( Type type ) SIP_HOLDGIL
853     {
854       return ( type != Unknown && !isMultiType( type ) );
855     }
856 
857     /**
858      * Returns TRUE if the WKB type is a multi type.
859      * \see isSingleType()
860      * \see multiType()
861      */
isMultiType(Type type)862     static bool isMultiType( Type type ) SIP_HOLDGIL
863     {
864       switch ( type )
865       {
866         case Unknown:
867         case Point:
868         case LineString:
869         case Polygon:
870         case Triangle:
871         case CircularString:
872         case CompoundCurve:
873         case CurvePolygon:
874         case NoGeometry:
875         case PointZ:
876         case LineStringZ:
877         case PolygonZ:
878         case TriangleZ:
879         case CircularStringZ:
880         case CompoundCurveZ:
881         case CurvePolygonZ:
882         case PointM:
883         case LineStringM:
884         case PolygonM:
885         case TriangleM:
886         case CircularStringM:
887         case CompoundCurveM:
888         case CurvePolygonM:
889         case PointZM:
890         case LineStringZM:
891         case PolygonZM:
892         case TriangleZM:
893         case CircularStringZM:
894         case CompoundCurveZM:
895         case CurvePolygonZM:
896         case Point25D:
897         case LineString25D:
898         case Polygon25D:
899           return false;
900 
901         default:
902           return true;
903 
904       }
905     }
906 
907     /**
908      * Returns TRUE if the WKB type is a curved type or can contain curved geometries.
909      * \since QGIS 2.14
910      */
isCurvedType(Type type)911     static bool isCurvedType( Type type ) SIP_HOLDGIL
912     {
913       switch ( flatType( type ) )
914       {
915         case CircularString:
916         case CompoundCurve:
917         case CurvePolygon:
918         case MultiCurve:
919         case MultiSurface:
920           return true;
921 
922         default:
923           return false;
924       }
925     }
926 
927     /**
928      * Returns the inherent dimension of the geometry type as an integer. Returned value will
929      * always be less than or equal to the coordinate dimension.
930      * \returns 0 for point geometries, 1 for line geometries, 2 for polygon geometries
931      * Invalid geometry types will return a dimension of 0.
932      * \see coordDimensions()
933      */
wkbDimensions(Type type)934     static int wkbDimensions( Type type ) SIP_HOLDGIL
935     {
936       const GeometryType gtype = geometryType( type );
937       switch ( gtype )
938       {
939         case LineGeometry:
940           return 1;
941         case PolygonGeometry:
942           return 2;
943         default: //point, no geometry, unknown geometry
944           return 0;
945       }
946     }
947 
948     /**
949      * Returns the coordinate dimension of the geometry type as an integer. Returned value will
950      * be between 2-4, depending on whether the geometry type contains the Z or M dimensions.
951      * Invalid geometry types will return a dimension of 0.
952      * \see wkbDimensions()
953      * \since QGIS 2.14
954      */
coordDimensions(Type type)955     static int coordDimensions( Type type ) SIP_HOLDGIL
956     {
957       if ( type == Unknown || type == NoGeometry )
958         return 0;
959 
960       return 2 + hasZ( type ) + hasM( type );
961     }
962 
963     /**
964      * Returns the geometry type for a WKB type, e.g., both MultiPolygon and CurvePolygon would have a
965      * PolygonGeometry geometry type.
966      * GeometryCollections are reported as QgsWkbTypes::UnknownGeometry.
967      */
geometryType(Type type)968     static GeometryType geometryType( Type type ) SIP_HOLDGIL
969     {
970       switch ( type )
971       {
972         case Unknown:
973         case GeometryCollection:
974         case GeometryCollectionZ:
975         case GeometryCollectionM:
976         case GeometryCollectionZM:
977           return UnknownGeometry;
978 
979         case Point:
980         case MultiPoint:
981         case PointZ:
982         case MultiPointZ:
983         case PointM:
984         case MultiPointM:
985         case PointZM:
986         case MultiPointZM:
987         case Point25D:
988         case MultiPoint25D:
989           return PointGeometry;
990 
991         case LineString:
992         case MultiLineString:
993         case LineStringZ:
994         case MultiLineStringZ:
995         case LineStringM:
996         case MultiLineStringM:
997         case LineStringZM:
998         case MultiLineStringZM:
999         case LineString25D:
1000         case MultiLineString25D:
1001         case CircularString:
1002         case CompoundCurve:
1003         case MultiCurve:
1004         case CircularStringZ:
1005         case CompoundCurveZ:
1006         case MultiCurveZ:
1007         case CircularStringM:
1008         case CompoundCurveM:
1009         case MultiCurveM:
1010         case CircularStringZM:
1011         case CompoundCurveZM:
1012         case MultiCurveZM:
1013           return LineGeometry;
1014 
1015         case Polygon:
1016         case MultiPolygon:
1017         case Triangle:
1018         case PolygonZ:
1019         case TriangleZ:
1020         case MultiPolygonZ:
1021         case PolygonM:
1022         case TriangleM:
1023         case MultiPolygonM:
1024         case PolygonZM:
1025         case MultiPolygonZM:
1026         case TriangleZM:
1027         case Polygon25D:
1028         case MultiPolygon25D:
1029         case CurvePolygon:
1030         case MultiSurface:
1031         case CurvePolygonZ:
1032         case MultiSurfaceZ:
1033         case CurvePolygonM:
1034         case MultiSurfaceM:
1035         case CurvePolygonZM:
1036         case MultiSurfaceZM:
1037           return PolygonGeometry;
1038 
1039         case NoGeometry:
1040           return NullGeometry;
1041       }
1042 
1043       return UnknownGeometry;
1044     }
1045 
1046     /**
1047      * Returns a non-translated display string type for a WKB type, e.g., the geometry name used in WKT geometry representations.
1048      */
1049     static QString displayString( Type type ) SIP_HOLDGIL;
1050 
1051     /**
1052      * Returns a translated display string type for a WKB type, e.g., the geometry name used in WKT geometry representations.
1053      *
1054      * \since QGIS 3.18
1055      */
1056     static QString translatedDisplayString( Type type ) SIP_HOLDGIL;
1057 
1058     /**
1059      * Returns a display string for a geometry type.
1060      *
1061      * This will return one of the following strings:
1062      *
1063      * - Point
1064      * - Line
1065      * - Polygon
1066      * - Unknown Geometry
1067      * - No Geometry
1068      * - Invalid Geometry
1069      *
1070      * \since QGIS 3.0
1071      */
1072     static QString geometryDisplayString( GeometryType type ) SIP_HOLDGIL;
1073 
1074     /**
1075      * Tests whether a WKB type contains the z-dimension.
1076      * \returns TRUE if type has z values
1077      * \see addZ()
1078      * \see hasM()
1079      */
hasZ(Type type)1080     static bool hasZ( Type type ) SIP_HOLDGIL
1081     {
1082       switch ( type )
1083       {
1084         case PointZ:
1085         case LineStringZ:
1086         case PolygonZ:
1087         case TriangleZ:
1088         case MultiPointZ:
1089         case MultiLineStringZ:
1090         case MultiPolygonZ:
1091         case GeometryCollectionZ:
1092         case CircularStringZ:
1093         case CompoundCurveZ:
1094         case CurvePolygonZ:
1095         case MultiCurveZ:
1096         case MultiSurfaceZ:
1097         case PointZM:
1098         case LineStringZM:
1099         case PolygonZM:
1100         case TriangleZM:
1101         case MultiPointZM:
1102         case MultiLineStringZM:
1103         case MultiPolygonZM:
1104         case GeometryCollectionZM:
1105         case CircularStringZM:
1106         case CompoundCurveZM:
1107         case CurvePolygonZM:
1108         case MultiCurveZM:
1109         case MultiSurfaceZM:
1110         case Point25D:
1111         case LineString25D:
1112         case Polygon25D:
1113         case MultiPoint25D:
1114         case MultiLineString25D:
1115         case MultiPolygon25D:
1116           return true;
1117 
1118         default:
1119           return false;
1120 
1121       }
1122     }
1123 
1124     /**
1125      * Tests whether a WKB type contains m values.
1126      * \returns TRUE if type has m values
1127      * \see addM()
1128      * \see hasZ()
1129      */
hasM(Type type)1130     static bool hasM( Type type ) SIP_HOLDGIL
1131     {
1132       switch ( type )
1133       {
1134         case PointM:
1135         case LineStringM:
1136         case PolygonM:
1137         case TriangleM:
1138         case MultiPointM:
1139         case MultiLineStringM:
1140         case MultiPolygonM:
1141         case GeometryCollectionM:
1142         case CircularStringM:
1143         case CompoundCurveM:
1144         case CurvePolygonM:
1145         case MultiCurveM:
1146         case MultiSurfaceM:
1147         case PointZM:
1148         case LineStringZM:
1149         case PolygonZM:
1150         case TriangleZM:
1151         case MultiPointZM:
1152         case MultiLineStringZM:
1153         case MultiPolygonZM:
1154         case GeometryCollectionZM:
1155         case CircularStringZM:
1156         case CompoundCurveZM:
1157         case CurvePolygonZM:
1158         case MultiCurveZM:
1159         case MultiSurfaceZM:
1160           return true;
1161 
1162         default:
1163           return false;
1164 
1165       }
1166     }
1167 
1168     /**
1169      * Adds the z dimension to a WKB type and returns the new type
1170      * \param type original type
1171      * \see addM()
1172      * \see dropZ()
1173      * \see hasZ()
1174      * \since QGIS 2.12
1175      */
addZ(Type type)1176     static Type addZ( Type type ) SIP_HOLDGIL
1177     {
1178       if ( hasZ( type ) )
1179         return type;
1180       else if ( type == Unknown )
1181         return Unknown;
1182       else if ( type == NoGeometry )
1183         return NoGeometry;
1184 
1185       //upgrade with z dimension
1186       const Type flat = flatType( type );
1187       if ( hasM( type ) )
1188         return static_cast< QgsWkbTypes::Type >( flat + 3000 );
1189       else
1190         return static_cast< QgsWkbTypes::Type >( flat + 1000 );
1191     }
1192 
1193     /**
1194      * Adds the m dimension to a WKB type and returns the new type
1195      * \param type original type
1196      * \see addZ()
1197      * \see dropM()
1198      * \see hasM()
1199      * \since QGIS 2.12
1200      */
addM(Type type)1201     static Type addM( Type type ) SIP_HOLDGIL
1202     {
1203       if ( hasM( type ) )
1204         return type;
1205       else if ( type == Unknown )
1206         return Unknown;
1207       else if ( type == NoGeometry )
1208         return NoGeometry;
1209       else if ( type == Point25D )
1210         return PointZM;
1211       else if ( type == LineString25D )
1212         return LineStringZM;
1213       else if ( type == Polygon25D )
1214         return PolygonZM;
1215       else if ( type == MultiPoint25D )
1216         return MultiPointZM;
1217       else if ( type == MultiLineString25D )
1218         return MultiLineStringZM;
1219       else if ( type == MultiPolygon25D )
1220         return MultiPolygonZM;
1221 
1222       //upgrade with m dimension
1223       const Type flat = flatType( type );
1224       if ( hasZ( type ) )
1225         return static_cast< QgsWkbTypes::Type >( flat + 3000 );
1226       else
1227         return static_cast< QgsWkbTypes::Type >( flat + 2000 );
1228     }
1229 
1230     /**
1231      * Drops the z dimension (if present) for a WKB type and returns the new type.
1232      * \param type original type
1233      * \see dropM()
1234      * \see addZ()
1235      * \since QGIS 2.14
1236      */
dropZ(Type type)1237     static Type dropZ( Type type ) SIP_HOLDGIL
1238     {
1239       if ( !hasZ( type ) )
1240         return type;
1241 
1242       QgsWkbTypes::Type returnType = flatType( type );
1243       if ( hasM( type ) )
1244         returnType = addM( returnType );
1245       return returnType;
1246     }
1247 
1248     /**
1249      * Drops the m dimension (if present) for a WKB type and returns the new type.
1250      * \param type original type
1251      * \see dropZ()
1252      * \see addM()
1253      * \since QGIS 2.14
1254      */
dropM(Type type)1255     static Type dropM( Type type ) SIP_HOLDGIL
1256     {
1257       if ( !hasM( type ) )
1258         return type;
1259 
1260       QgsWkbTypes::Type returnType = flatType( type );
1261       if ( hasZ( type ) )
1262         returnType = addZ( returnType );
1263       return returnType;
1264     }
1265 
1266     /**
1267      * Will convert the 25D version of the flat type if supported or Unknown if not supported.
1268      * \param type The type to convert
1269      * \returns the 25D version of the type or Unknown
1270      */
to25D(Type type)1271     static Type to25D( Type type ) SIP_HOLDGIL
1272     {
1273       const QgsWkbTypes::Type flat = flatType( type );
1274 
1275       if ( flat >= Point && flat <= MultiPolygon )
1276         return static_cast< QgsWkbTypes::Type >( static_cast<unsigned>( flat ) + 0x80000000U );
1277       else if ( type == QgsWkbTypes::NoGeometry )
1278         return QgsWkbTypes::NoGeometry;
1279       else
1280         return Unknown;
1281     }
1282 
1283 };
1284 
1285 #endif // QGSWKBTYPES_H
1286