-
-
Notifications
You must be signed in to change notification settings - Fork 3k
/
qgscoordinatereferencesystem.h
1029 lines (904 loc) · 40.1 KB
/
qgscoordinatereferencesystem.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/***************************************************************************
qgscoordinatereferencesystem.h
-------------------
begin : 2007
copyright : (C) 2007 by Gary E. Sherman
email : sherman@mrcc.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSCOORDINATEREFERENCESYSTEM_H
#define QGSCOORDINATEREFERENCESYSTEM_H
//Standard includes
#include "qgis_core.h"
#include <ostream>
//qt includes
#include <QString>
#include <QMap>
#include <QHash>
#include <QReadWriteLock>
#include <QExplicitlySharedDataPointer>
#include <QObject>
//qgis includes
#include "qgis_sip.h"
#include "qgsunittypes.h"
#include "qgsrectangle.h"
#include "qgssqliteutils.h"
class QDomNode;
class QDomDocument;
class QgsCoordinateReferenceSystemPrivate;
#if PROJ_VERSION_MAJOR>=6
#ifndef SIP_RUN
struct PJconsts;
typedef struct PJconsts PJ;
#endif
#endif
// forward declaration for sqlite3
typedef struct sqlite3 sqlite3 SIP_SKIP;
#ifdef DEBUG
typedef struct OGRSpatialReferenceHS *OGRSpatialReferenceH SIP_SKIP;
#else
typedef void *OGRSpatialReferenceH SIP_SKIP;
#endif
class QgsCoordinateReferenceSystem;
typedef void ( *CUSTOM_CRS_VALIDATION )( QgsCoordinateReferenceSystem & ) SIP_SKIP;
/**
* \ingroup core
* This class represents a coordinate reference system (CRS).
*
* Coordinate reference system object defines a specific map projection, as well as transformations
* between different coordinate reference systems. There are various ways how a CRS can be defined:
* using well-known text (WKT), PROJ string or combination of authority and code (e.g. EPSG:4326).
* QGIS comes with its internal database of coordinate reference systems (stored in SQLite) that
* allows lookups of CRS and seamless conversions between the various definitions.
*
* Most commonly one comes across two types of coordinate systems:
*
* 1. **Geographic coordinate systems** - based on a geodetic datum, normally with coordinates being
* latitude/longitude in degrees. The most common one is World Geodetic System 84 (WGS84).
* 2. **Projected coordinate systems** - based on a geodetic datum with coordinates projected to a plane,
* typically using meters or feet as units. Common projected coordinate systems are Universal
* Transverse Mercator or Albers Equal Area.
*
* Internally QGIS uses proj library for all the math behind coordinate transformations, so in case
* of any troubles with projections it is best to examine the PROJ representation within the object,
* as that is the representation that will be ultimately used.
*
* Methods that allow inspection of CRS instances include isValid(), authid(), description(),
* toWkt(), toProj(), mapUnits() and others.
* Creation of CRS instances is further described in \ref crs_construct_and_copy section below.
* Transformations between coordinate reference systems are done using QgsCoordinateTransform class.
*
* For example, the following code will create and inspect "British national grid" CRS:
*
* \code{.py}
* crs = QgsCoordinateReferenceSystem("EPSG:27700")
* if crs.isValid():
* print("CRS Description: {}".format(crs.description()))
* print("CRS PROJ text: {}".format(crs.toProj()))
* else:
* print("Invalid CRS!")
* \endcode
*
* This will produce the following output:
*
* \code
* CRS Description: OSGB 1936 / British National Grid
* CRS PROJ text: +proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 [output trimmed]
* \endcode
*
* CRS Definition Formats
* ======================
*
* This section gives an overview of various supported CRS definition formats:
*
* 1. **Authority and Code.** Also referred to as OGC WMS format within QGIS as they have been widely
* used in OGC standards. These are encoded as `<auth>:<code>`, for example `EPSG:4326` refers
* to WGS84 system. EPSG is the most commonly used authority that covers a wide range
* of coordinate systems around the world.
*
* An extended variant of this format is OGC URN. Syntax of URN for CRS definition is
* `urn:ogc:def:crs:<auth>:[<version>]:<code>`. This class can also parse URNs (versions
* are currently ignored). For example, WGS84 may be encoded as `urn:ogc:def:crs:OGC:1.3:CRS84`.
*
* QGIS adds support for "USER" authority that refers to IDs used internally in QGIS. This variant
* is best avoided or used with caution as the IDs are not permanent and they refer to different CRS
* on different machines or user profiles.
*
* See authid() and createFromOgcWmsCrs() methods.
*
* 2. **PROJ string.** This is a string consisting of a series of key/value pairs in the following
* format: `+param1=value1 +param2=value2 [...]`. This is the format natively used by the
* underlying proj library. For example, the definition of WGS84 looks like this:
*
* +proj=longlat +datum=WGS84 +no_defs
*
* See toProj() and createFromProj() methods.
*
* 3. **Well-known text (WKT).** Defined by Open Geospatial Consortium (OGC), this is another common
* format to define CRS. For WGS84 the OGC WKT definition is the following:
*
* GEOGCS["WGS 84",
* DATUM["WGS_1984",
* SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],
* AUTHORITY["EPSG","6326"]],
* PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],
* UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],
* AUTHORITY["EPSG","4326"]]
*
* See toWkt() and createFromWkt() methods.
*
* CRS Database and Custom CRS
* ===========================
*
* The database of CRS shipped with QGIS is stored in a SQLite database (see QgsApplication::srsDatabaseFilePath())
* and it is based on the data files maintained by GDAL project (a variety of .csv and .wkt files).
*
* Sometimes it happens that users need to use a CRS definition that is not well known
* or that has been only created with a specific purpose (and thus its definition is not
* available in our database of CRS). Whenever a new CRS definition is seen, it will
* be added to the local database (in user's home directory, see QgsApplication::qgisUserDatabaseFilePath()).
* QGIS also features a GUI for management of local custom CRS definitions.
*
* There are therefore two databases: one for shipped CRS definitions and one for custom CRS definitions.
* Custom CRS have internal IDs (accessible with srsid()) greater or equal to \ref USER_CRS_START_ID.
* The local CRS databases should never be accessed directly with SQLite functions, instead
* you should use QgsCoordinateReferenceSystem API for CRS lookups and for managements of custom CRS.
*
* Validation
* ==========
*
* In some cases (most prominently when loading a map layer), QGIS will try to ensure
* that the given map layer CRS is valid using validate() call. If not, a custom
* validation function will be called - such function may for example show a GUI
* for manual CRS selection. The validation function is configured using setCustomCrsValidation().
* If validation fails or no validation function is set, the default CRS is assigned
* (WGS84). QGIS application registers its validation function that will act according
* to user's settings (either show CRS selector dialog or use project/custom CRS).
*
* Object Construction and Copying {#crs_construct_and_copy}
* ===============================
*
* The easiest way of creating CRS instances is to use QgsCoordinateReferenceSystem(const QString&)
* constructor that automatically recognizes definition format from the given string.
*
* Creation of CRS object involves some queries in a local SQLite database, which may
* be potentially expensive. Consequently, CRS creation methods use an internal cache to avoid
* unnecessary database lookups. If the CRS database is modified, then it is necessary to call
* invalidateCache() to ensure that outdated records are not being returned from the cache.
*
* Since QGIS 2.16 QgsCoordinateReferenceSystem objects are implicitly shared.
*
* Caveats
* =======
*
* There are two different flavors of WKT: one is defined by OGC, the other is the standard
* used by ESRI. They look very similar, but they are not the same. QGIS is able to consume
* both flavors.
*
* \see QgsCoordinateTransform
*/
class CORE_EXPORT QgsCoordinateReferenceSystem
{
Q_GADGET
Q_PROPERTY( QgsUnitTypes::DistanceUnit mapUnits READ mapUnits )
Q_PROPERTY( bool isGeographic READ isGeographic )
public:
//! Enumeration of types of IDs accepted in createFromId() method
enum CrsType
{
InternalCrsId, //!< Internal ID used by QGIS in the local SQLite database
PostgisCrsId, //!< SRID used in PostGIS. DEPRECATED -- DO NOT USE
EpsgCrsId //!< EPSG code
};
//! Projection definition formats
enum Format
{
FormatWkt = 0, //!< WKT format (always recommended over proj string format)
FormatProj, //!< Proj string format
};
//! Constructs an invalid CRS object
QgsCoordinateReferenceSystem();
~QgsCoordinateReferenceSystem();
// TODO QGIS 4: remove "POSTGIS" and "INTERNAL", allow PROJ4 without the prefix
/**
* Constructs a CRS object from a string definition using createFromString()
*
* It supports the following formats:
* - "EPSG:<code>" - handled with createFromOgcWms()
* - "POSTGIS:<srid>" - handled with createFromSrid()
* - "INTERNAL:<srsid>" - handled with createFromSrsId()
* - "PROJ4:<proj4>" - handled with createFromProj()
* - "WKT:<wkt>" - handled with createFromWkt()
*
* If no prefix is specified, WKT definition is assumed.
* \param definition A String containing a coordinate reference system definition.
* \see createFromString()
*/
explicit QgsCoordinateReferenceSystem( const QString &definition );
// TODO QGIS 4: remove type and always use EPSG code
/**
* Constructor a CRS object using a PostGIS SRID, an EPSG code or an internal QGIS CRS ID.
* \note We encourage you to use EPSG code or WKT to describe CRSes in your code
* wherever possible. Internal QGIS CRS IDs are not guaranteed to be permanent / involatile,
* and proj strings are a lossy format.
* \param id The ID valid for the chosen CRS ID type
* \param type One of the types described in CrsType
* \deprecated We encourage you to use EPSG codes or WKT to describe CRSes in your code
* wherever possible. Internal QGIS CRS IDs are not guaranteed to be permanent / involatile,
* and Proj strings are a lossy format.
*/
Q_DECL_DEPRECATED explicit QgsCoordinateReferenceSystem( long id, CrsType type = PostgisCrsId ) SIP_DEPRECATED;
//! Copy constructor
QgsCoordinateReferenceSystem( const QgsCoordinateReferenceSystem &srs );
//! Assignment operator
QgsCoordinateReferenceSystem &operator=( const QgsCoordinateReferenceSystem &srs );
//! Allows direct construction of QVariants from QgsCoordinateReferenceSystem.
operator QVariant() const
{
return QVariant::fromValue( *this );
}
/**
* Returns a list of all valid SRS IDs present in the CRS database. Any of the
* returned values can be safely passed to fromSrsId() to create a new, valid
* QgsCoordinateReferenceSystem object.
* \see fromSrsId()
* \since QGIS 3.0
*/
static QList< long > validSrsIds();
// static creators
/**
* Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
* \param ogcCrs OGR compliant CRS definition, e.g., "EPSG:4326"
* \returns matching CRS, or an invalid CRS if string could not be matched
* \see createFromOgcWmsCrs()
* \since QGIS 3.0
*/
static QgsCoordinateReferenceSystem fromOgcWmsCrs( const QString &ogcCrs );
/**
* Creates a CRS from a given EPSG ID.
* \param epsg epsg CRS ID
* \returns matching CRS, or an invalid CRS if string could not be matched
* \since QGIS 3.0
*/
Q_INVOKABLE static QgsCoordinateReferenceSystem fromEpsgId( long epsg );
/**
* Creates a CRS from a proj style formatted string.
* \param proj proj format string
* \returns matching CRS, or an invalid CRS if string could not be matched
* \see createFromProj()
* \deprecated Use fromProj() instead.
*/
Q_DECL_DEPRECATED static QgsCoordinateReferenceSystem fromProj4( const QString &proj4 ) SIP_DEPRECATED;
/**
* Creates a CRS from a proj style formatted string.
* \param proj proj format string
* \returns matching CRS, or an invalid CRS if string could not be matched
* \see createFromProj()
* \since QGIS 3.10.3
*/
static QgsCoordinateReferenceSystem fromProj( const QString &proj );
/**
* Creates a CRS from a WKT spatial ref sys definition string.
* \param wkt WKT for the desired spatial reference system.
* \returns matching CRS, or an invalid CRS if string could not be matched
* \see createFromWkt()
* \since QGIS 3.0
*/
static QgsCoordinateReferenceSystem fromWkt( const QString &wkt );
/**
* Creates a CRS from a specified QGIS SRS ID.
* \param srsId internal QGIS SRS ID
* \returns matching CRS, or an invalid CRS if ID could not be found
* \see createFromSrsId()
* \see validSrsIds()
* \since QGIS 3.0
*/
static QgsCoordinateReferenceSystem fromSrsId( long srsId );
// Misc helper functions -----------------------
// TODO QGIS 4: remove type and always use EPSG code, rename to createFromEpsg
/**
* Sets this CRS by lookup of the given ID in the CRS database.
* \returns TRUE on success else FALSE
* \deprecated We encourage you to use EPSG code or WKT to describe CRSes in your code
* wherever possible. Internal QGIS CRS IDs are not guaranteed to be permanent / involatile,
* and Proj strings are a lossy format.
*/
Q_DECL_DEPRECATED bool createFromId( long id, CrsType type = PostgisCrsId ) SIP_DEPRECATED;
// TODO QGIS 4: remove "QGIS" and "CUSTOM", only support "USER" (also returned by authid())
/**
* Sets this CRS to the given OGC WMS-format Coordinate Reference Systems.
*
* Accepts both "<auth>:<code>" format and OGC URN "urn:ogc:def:crs:<auth>:[<version>]:<code>".
* It also recognizes "QGIS", "USER", "CUSTOM" authorities, which all have the same meaning
* and refer to QGIS internal CRS IDs.
* \returns TRUE on success else FALSE
* \note this method uses an internal cache. Call invalidateCache() to clear the cache.
* \see fromOgcWmsCrs()
*/
bool createFromOgcWmsCrs( const QString &crs );
// TODO QGIS 4: remove unless really necessary - let's use EPSG codes instead
/**
* Sets this CRS by lookup of the given PostGIS SRID in the CRS database.
* \param srid The PostGIS SRID for the desired spatial reference system.
* \returns TRUE on success else FALSE
*
* \deprecated Use alternative methods for SRS construction instead -- this
* method was specifically created for use by the postgres provider alone,
* and using it elsewhere will lead to subtle bugs.
*/
Q_DECL_DEPRECATED bool createFromSrid( long srid ) SIP_DEPRECATED;
/**
* Sets this CRS using a WKT definition.
*
* If EPSG code of the WKT definition can be determined, it is extracted
* and createFromOgcWmsCrs() is used to initialize the object.
*
* \param wkt The WKT for the desired spatial reference system.
* \returns TRUE on success else FALSE
* \note Some members may be left blank if no match can be found in CRS database.
* \note this method uses an internal cache. Call invalidateCache() to clear the cache.
* \see fromWkt()
*/
bool createFromWkt( const QString &wkt );
/**
* Sets this CRS by lookup of internal QGIS CRS ID in the CRS database.
*
* If the srsid is < USER_CRS_START_ID, system CRS database is used, otherwise
* user's local CRS database from home directory is used.
* \param srsId The internal QGIS CRS ID for the desired spatial reference system.
* \returns TRUE on success else FALSE
* \note this method uses an internal cache. Call invalidateCache() to clear the cache.
* \see fromSrsId()
* \warning This method is highly discouraged, and CRS objects should instead be constructed
* using auth:id codes or WKT strings
*/
bool createFromSrsId( long srsId );
/**
* Sets this CRS by passing it a PROJ style formatted string.
*
* The string will be parsed and the projection and ellipsoid
* members set and the remainder of the Proj string will be stored
* in the parameters member. The reason for this is so that we
* can easily present the user with 'natural language' representation
* of the projection and ellipsoid by looking them up in the srs.db sqlite
* database.
*
* We try to match the Proj string to internal QGIS CRS ID using the following logic:
*
* - ask the Proj library to identify the CRS to a standard registered CRS (e.g. EPSG codes)
* - if no match is found, compare the CRS to all user CRSes, using the Proj library
* to determine CRS equivalence (hence making the match parameter order insensitive)
* - if none of the above match, use the Proj string to create the CRS and do not
* associated an internal CRS ID to it.
*
* \param projString A Proj format string
* \returns TRUE on success else FALSE
* \note Some members may be left blank if no match can be found in CRS database.
* \note this method uses an internal cache. Call invalidateCache() to clear the cache.
* \see fromProj()
* \deprecated Use createFromProj() instead
*/
Q_DECL_DEPRECATED bool createFromProj4( const QString &projString ) SIP_DEPRECATED;
/**
* Sets this CRS by passing it a PROJ style formatted string.
*
* The string will be parsed and the projection and ellipsoid
* members set and the remainder of the Proj string will be stored
* in the parameters member. The reason for this is so that we
* can easily present the user with 'natural language' representation
* of the projection and ellipsoid by looking them up in the srs.db sqlite
* database.
*
* We try to match the Proj string to internal QGIS CRS ID using the following logic:
*
* - ask the Proj library to identify the CRS to a standard registered CRS (e.g. EPSG codes)
* - if no match is found, compare the CRS to all user CRSes, using the Proj library
* to determine CRS equivalence (hence making the match parameter order insensitive)
* - if none of the above match, use the Proj string to create the CRS and do not
* associated an internal CRS ID to it.
*
* \param projString A Proj format string
* \returns TRUE on success else FALSE
* \note Some members may be left blank if no match can be found in CRS database.
* \note this method uses an internal cache. Call invalidateCache() to clear the cache.
* \see fromProj()
* \since QGIS 3.10.3
*/
bool createFromProj( const QString &projString );
/**
* Set up this CRS from a string definition.
*
* It supports the following formats:
* - "EPSG:<code>" - handled with createFromOgcWms()
* - "POSTGIS:<srid>" - handled with createFromSrid()
* - "INTERNAL:<srsid>" - handled with createFromSrsId()
* - "PROJ4:<proj4>" - handled with createFromProj()
* - "WKT:<wkt>" - handled with createFromWkt()
*
* If no prefix is specified, WKT definition is assumed.
* \param definition A String containing a coordinate reference system definition.
* \returns TRUE on success else FALSE
*/
bool createFromString( const QString &definition );
/**
* Set up this CRS from various text formats.
*
* Valid formats: WKT string, "EPSG:n", "EPSGA:n", "AUTO:proj_id,unit_id,lon0,lat0",
* "urn:ogc:def:crs:EPSG::n", PROJ string, filename (with WKT, XML or PROJ string),
* well known name (such as NAD27, NAD83, WGS84 or WGS72),
* ESRI::[WKT string] (directly or in a file), "IGNF:xxx"
*
* For more details on supported formats see OGRSpatialReference::SetFromUserInput()
* ( http://www.gdal.org/ogr/classOGRSpatialReference.html#aec3c6a49533fe457ddc763d699ff8796 )
* \param definition A String containing a coordinate reference system definition.
* \returns TRUE on success else FALSE
* \note this function generates a WKT string using OSRSetFromUserInput() and
* passes it to createFromWkt() function.
*/ // TODO QGIS3: rename to createFromStringOGR so it is clear it's similar to createFromString, just different backend
bool createFromUserInput( const QString &definition );
/**
* Make sure that ESRI WKT import is done properly.
* This is required for proper shapefile CRS import when using gdal>= 1.9.
* \note This function is called by createFromUserInput() and QgsOgrProvider::crs(), there is usually
* no need to call it from elsewhere.
* \note This function sets CPL config option GDAL_FIX_ESRI_WKT to a proper value,
* unless it has been set by the user through the commandline or an environment variable.
* For more details refer to OGRSpatialReference::morphFromESRI() .
* \deprecated Not used on builds based on Proj version 6 or later
*/
Q_DECL_DEPRECATED static void setupESRIWktFix() SIP_DEPRECATED;
//! Returns whether this CRS is correctly initialized and usable
bool isValid() const;
/**
* Perform some validation on this CRS. If the CRS doesn't validate the
* default behavior settings for layers with unknown CRS will be
* consulted and acted on accordingly. By hell or high water this
* method will do its best to make sure that this CRS is valid - even
* if that involves resorting to a hard coded default of geocs:wgs84.
*
* \note It is not usually necessary to use this function, unless you
* are trying to force this CRS to be valid.
* \see setCustomCrsValidation(), customCrsValidation()
*/
void validate();
// TODO QGIS 4: seems completely obsolete now (only compares proj4 - already done in createFromProj4)
/**
* Walks the CRS databases (both system and user database) trying to match
* stored PROJ string to a database entry in order to fill in further
* pieces of information about CRS.
* \note The ellipsoid and projection acronyms must be set as well as the proj string!
* \returns long the SrsId of the matched CRS, zero if no match was found
* \deprecated Not used in Proj >= 6 based builds
*/
Q_DECL_DEPRECATED long findMatchingProj() SIP_DEPRECATED;
/**
* Overloaded == operator used to compare to CRS's.
*
* Internally it will use authid() for comparison.
*/
bool operator==( const QgsCoordinateReferenceSystem &srs ) const;
/**
* Overloaded != operator used to compare to CRS's.
*
* Returns opposite bool value to operator ==
*/
bool operator!=( const QgsCoordinateReferenceSystem &srs ) const;
/**
* Restores state from the given DOM node.
* If it fails or if the node is empty, a default empty CRS will be returned.
* \param node The node from which state will be restored
* \returns bool TRUE on success, FALSE on failure
*/
bool readXml( const QDomNode &node );
/**
* Stores state to the given Dom node in the given document.
* \param node The node in which state will be restored
* \param doc The document in which state will be stored
* \returns bool TRUE on success, FALSE on failure
*/
bool writeXml( QDomNode &node, QDomDocument &doc ) const;
/**
* Sets custom function to force valid CRS
* \note not available in Python bindings
*/
static void setCustomCrsValidation( CUSTOM_CRS_VALIDATION f ) SIP_SKIP;
/**
* Gets custom function
* \note not available in Python bindings
*/
static CUSTOM_CRS_VALIDATION customCrsValidation() SIP_SKIP;
// Accessors -----------------------------------
/**
* Returns the internal CRS ID, if available.
* \returns the internal sqlite3 srs.db primary key for this CRS
*/
long srsid() const;
// TODO QGIS 4: remove unless really necessary - let's use EPSG codes instead
/**
* Returns PostGIS SRID for the CRS.
* \returns the PostGIS spatial_ref_sys identifier for this CRS (defaults to 0)
*/
long postgisSrid() const;
/**
* Returns the authority identifier for the CRS.
*
* The identifier includes both the authority (e.g., EPSG) and the CRS number (e.g., 4326).
* This is the best method to use when showing a very short CRS identifier to a user,
* e.g., "EPSG:4326".
*
* If CRS object is a custom CRS (not found in database), the method will return
* internal QGIS CRS ID with "QGIS" authority, for example "QGIS:100005"
* \returns the authority identifier for this CRS
* \see description()
*/
QString authid() const;
/**
* Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".
* \note an empty string will be returned if the description is not available for the CRS
* \see authid()
* \see userFriendlyIdentifier()
*/
QString description() const;
/**
* Returns a user friendly identifier for the CRS.
*
* Depending on the format of the CRS, this may reflect the CRSes registered name, or for
* CRSes not saved in the database it may reflect the underlying WKT or Proj string definition
* of the CRS.
*
* In most cases this is the best method to use when showing a friendly identifier for the CRS to a
* user.
*
* If \a shortString is TRUE than an abbreviated identifier will be returned.
*
* \see description()
* \since QGIS 3.10.3
*/
QString userFriendlyIdentifier( bool shortString = false ) const;
/**
* Returns the projection acronym for the projection used by the CRS.
* \returns the official Proj acronym for the projection family
* \note an empty string will be returned if the projectionAcronym is not available for the CRS
* \see ellipsoidAcronym()
*/
QString projectionAcronym() const;
/**
* Returns the ellipsoid acronym for the ellipsoid used by the CRS.
* \returns the official authority:code identifier for the ellipoid, or PARAMETER:MAJOR:MINOR for custom ellipsoids
* \note an empty string will be returned if the ellipsoidAcronym is not available for the CRS
* \see projectionAcronym()
*/
QString ellipsoidAcronym() const;
//! WKT formatting variants, only used for builds based on Proj >= 6
enum WktVariant
{
WKT1_GDAL, //!< WKT1 as traditionally output by GDAL, deriving from OGC 01-009. A notable departure from WKT1_GDAL with respect to OGC 01-009 is that in WKT1_GDAL, the unit of the PRIMEM value is always degrees.
WKT1_ESRI, //!< WKT1 as traditionally output by ESRI software, deriving from OGC 99-049.
WKT2_2015, //!< Full WKT2 string, conforming to ISO 19162:2015(E) / OGC 12-063r5 with all possible nodes and new keyword names.
WKT2_2015_SIMPLIFIED, //!< Same as WKT2_2015 with the following exceptions: UNIT keyword used. ID node only on top element. No ORDER element in AXIS element. PRIMEM node omitted if it is Greenwich. ELLIPSOID.UNIT node omitted if it is UnitOfMeasure::METRE. PARAMETER.UNIT / PRIMEM.UNIT omitted if same as AXIS. AXIS.UNIT omitted and replaced by a common GEODCRS.UNIT if they are all the same on all axis.
WKT2_2018, //!< Full WKT2 string, conforming to ISO 19162:2018 / OGC 18-010, with all possible nodes and new keyword names. Non-normative list of differences: WKT2_2018 uses GEOGCRS / BASEGEOGCRS keywords for GeographicCRS.
WKT2_2018_SIMPLIFIED, //!< WKT2_2018 with the simplification rule of WKT2_SIMPLIFIED
};
/**
* Returns a WKT representation of this CRS.
*
* The \a variant argument specifies the formatting variant to use when creating the WKT string. This is
* only used on builds based on Proj >= 6, with earlier versions always using WKT1_GDAL.
*
* If \a multiline is TRUE then a formatted multiline string will be returned, using the specified \a indentationWidth.
* This is only used on builds based on Proj >= 6.
*
* \see toProj()
*/
QString toWkt( WktVariant variant = WKT1_GDAL, bool multiline = false, int indentationWidth = 4 ) const;
/**
* Returns a Proj string representation of this CRS.
*
* If proj and ellps keys are found in the parameters,
* they will be stripped out and the projection and ellipsoid acronyms will be
* overridden with these.
* \returns Proj format string that defines this CRS.
* \warning Not all CRS definitions can be represented by Proj strings. An empty
* string will be returned if the CRS could not be represented by a Proj string.
* \see toWkt()
* \deprecated use toProj() instead.
*/
Q_DECL_DEPRECATED QString toProj4() const SIP_DEPRECATED;
/**
* Returns a Proj string representation of this CRS.
*
* If proj and ellps keys are found in the parameters,
* they will be stripped out and the projection and ellipsoid acronyms will be
* overridden with these.
* \returns Proj format string that defines this CRS.
* \warning Not all CRS definitions can be represented by Proj strings. An empty
* string will be returned if the CRS could not be represented by a Proj string.
* \see toWkt()
* \since QGIS 3.10.3
*/
QString toProj() const;
/**
* Returns whether the CRS is a geographic CRS (using lat/lon coordinates)
* \returns TRUE if CRS is geographic, or FALSE if it is a projected CRS
*/
bool isGeographic() const;
/**
* Returns whether axis is inverted (e.g., for WMS 1.3) for the CRS.
* \returns TRUE if CRS axis is inverted
*/
bool hasAxisInverted() const;
/**
* Returns the units for the projection used by the CRS.
*/
QgsUnitTypes::DistanceUnit mapUnits() const;
/**
* Returns the approximate bounds for the region the CRS is usable within.
*
* The returned bounds represent the latitude and longitude extent for the
* projection in the WGS 84 CRS.
*
* \since QGIS 3.0
*/
QgsRectangle bounds() const;
// Mutators -----------------------------------
/**
* Set user hint for validation
*/
void setValidationHint( const QString &html );
/**
* Gets user hint for validation
*/
QString validationHint();
/**
* Update proj.4 parameters in our database from proj.4
* \returns number of updated CRS on success and
* negative number of failed updates in case of errors.
* \note This is used internally and should not be necessary to call in client code
*/
static int syncDatabase();
/**
* Saves the CRS as a custom ("USER") CRS.
*
* Returns the new CRS srsid(), or -1 if the CRS could not be saved.
*
* The \a nativeFormat argument specifies the format to use when saving the CRS
* definition. FormatWkt is recommended as it is a lossless format.
*
* \warning Not all CRS definitions can be represented as a Proj string, so
* take care when using the FormatProj option.
*/
long saveAsUserCrs( const QString &name, Format nativeFormat = FormatWkt );
//! Returns auth id of related geographic CRS
QString geographicCrsAuthId() const;
#ifdef SIP_RUN
SIP_PYOBJECT __repr__();
% MethodCode
QString str = QStringLiteral( "<QgsCoordinateReferenceSystem: %1>" ).arg( sipCpp->authid() );
sipRes = PyUnicode_FromString( str.toUtf8().constData() );
% End
#endif
#ifndef SIP_RUN
#if PROJ_VERSION_MAJOR>=6
/**
* Returns the underlying PROJ PJ object corresponding to the CRS, or NULLPTR
* if the CRS is invalid.
*
* This object is only valid for the lifetime of the QgsCoordinateReferenceSystem.
*
* \note Not available in Python bindings.
* \since QGIS 3.8
*/
PJ *projObject() const;
#endif
#endif
/**
* Returns a list of recently used projections
* \returns list of srsid for recently used projections
* \deprecated use recentCoordinateReferenceSystems() instead.
*/
Q_DECL_DEPRECATED static QStringList recentProjections() SIP_DEPRECATED;
/**
* Returns a list of recently used CRS.
* \since QGIS 3.10.3
*/
static QList< QgsCoordinateReferenceSystem > recentCoordinateReferenceSystems();
/**
* Pushes a recently used CRS to the top of the recent CRS list.
* \since QGIS 3.10.3
*/
static void pushRecentCoordinateReferenceSystem( const QgsCoordinateReferenceSystem &crs );
#ifndef SIP_RUN
/**
* Clears the internal cache used to initialize QgsCoordinateReferenceSystem objects.
* This should be called whenever the srs database has been modified in order to ensure
* that outdated CRS objects are not created.
*
* If \a disableCache is TRUE then the inbuilt cache will be completely disabled. This
* argument is for internal use only.
*
* \since QGIS 3.0
*/
static void invalidateCache( bool disableCache = false );
#else
/**
* Clears the internal cache used to initialize QgsCoordinateReferenceSystem objects.
* This should be called whenever the srs database has been modified in order to ensure
* that outdated CRS objects are not created.
*
* \since QGIS 3.0
*/
static void invalidateCache( bool disableCache SIP_PYARGREMOVE = false );
#endif
// Mutators -----------------------------------
// We don't want to expose these to the public api since they won't create
// a fully valid crs. Programmers should use the createFrom* methods rather
private:
/**
* A static helper function to find out the proj string for a srsid
* \param srsId The srsid used for the lookup
* \returns QString The proj string
*/
static QString projFromSrsId( int srsId );
/**
* Set the QGIS SrsId
* \param srsId The internal sqlite3 srs.db primary key for this CRS
*/
void setInternalId( long srsId );
/**
* Set the PostGIS srid
* \param srid The PostGIS spatial_ref_sys key for this CRS
*/
void setSrid( long srid );
/**
* Set the Description
* \param description A textual description of the CRS.
*/
void setDescription( const QString &description );
/**
* Set the Proj string.
* \param projString Proj format specifies
* (excluding proj and ellips) that define this CRS.
*/
void setProjString( const QString &projString );
/**
* Set the WKT string
*/
bool setWktString( const QString &wkt, bool allowProjFallback = true );
/**
* Set this Geographic? flag
* \param geoFlag Whether this is a geographic or projected coordinate system
*/
void setGeographicFlag( bool geoFlag );
/**
* Set the EpsgCrsId identifier for this CRS
* \param epsg the EPSG identifier for this CRS (defaults to 0)
*/
void setEpsg( long epsg );
/**
* Set the authority identifier for this CRS
* \param theID the authority identifier for this CRS (defaults to 0)
*/
void setAuthId( const QString &theID );
/**
* Set the projection acronym
* \param projectionAcronym the acronym (must be a valid Proj projection acronym)
*/
void setProjectionAcronym( const QString &projectionAcronym );
/**
* Set the ellipsoid acronym
* \param ellipsoidAcronym the acronym (must be a valid Proj ellipsoid acronym or
* authority:code identifier on Proj version 6+ builds)
*/
void setEllipsoidAcronym( const QString &ellipsoidAcronym );
/**
* Print the description if debugging
*/
void debugPrint();
//! A string based associative array used for passing records around
typedef QMap<QString, QString> RecordMap;
/**
* Gets a record from the srs.db or qgis.db backends, given an sql statement.
* \param sql The sql query to execute
* \returns An associative array of field name <-> value pairs
* \note only handles queries that return a single record.
* \note it will first try the system srs.db then the users qgis.db!
*/
RecordMap getRecord( const QString &sql );
/**
* Open SQLite db and show message if cannot be opened
* \returns the same code as sqlite3_open
*/
static int openDatabase( const QString &path, sqlite3_database_unique_ptr &database, bool readonly = true );
//! Work out the projection units and set the appropriate local variable
void setMapUnits();
//! Helper for getting number of user CRS already in db
long getRecordCount();
#if PROJ_VERSION_MAJOR>=6
bool loadFromAuthCode( const QString &auth, const QString &code );
#endif
/**
* Initialize the CRS object by looking up CRS database in path given in db argument,
* using first CRS entry where expression = 'value'
*/
bool loadFromDatabase( const QString &db, const QString &expression, const QString &value );
#if PROJ_VERSION_MAJOR<6 // not used for proj >= 6.0
static bool loadIds( QHash<int, QString> &wkts );
static bool loadWkts( QHash<int, QString> &wkts, const char *filename );
//! Update datum shift definitions from GDAL data. Used by syncDb()
static bool syncDatumTransform( const QString &dbPath );
#endif
QExplicitlySharedDataPointer<QgsCoordinateReferenceSystemPrivate> d;
//! Function for CRS validation. May be NULLPTR.
static CUSTOM_CRS_VALIDATION sCustomSrsValidation;
// cache
static bool sDisableSrIdCache;
static bool sDisableOgcCache;
static bool sDisableProjCache;
static bool sDisableWktCache;
static bool sDisableSrsIdCache;
static bool sDisableStringCache;
// for tests
static const QHash< QString, QgsCoordinateReferenceSystem > &stringCache();
static const QHash< QString, QgsCoordinateReferenceSystem > &projCache();
static const QHash< QString, QgsCoordinateReferenceSystem > &ogcCache();
static const QHash< QString, QgsCoordinateReferenceSystem > &wktCache();
static const QHash< long, QgsCoordinateReferenceSystem > &srsIdCache();
static const QHash< long, QgsCoordinateReferenceSystem > &srIdCache();
friend class TestQgsCoordinateReferenceSystem;
friend class QgsPostgresProvider;
bool createFromPostgisSrid( const long id );
};
Q_DECLARE_METATYPE( QgsCoordinateReferenceSystem )
//! Output stream operator
#ifndef SIP_RUN
inline std::ostream &operator << ( std::ostream &os, const QgsCoordinateReferenceSystem &r )
{
QString mySummary( QStringLiteral( "\n\tSpatial Reference System:" ) );
mySummary += QLatin1String( "\n\t\tDescription : " );
if ( !r.description().isNull() )
{
mySummary += r.description();
}
else
{
mySummary += QLatin1String( "Undefined" );
}
mySummary += QLatin1String( "\n\t\tProjection : " );
if ( !r.projectionAcronym().isNull() )
{
mySummary += r.projectionAcronym();
}
else