QGIS/python/core/qgscoordinatereferencesystem.sip
Nyall Dawson ac36cb5dd2 Make QgsCoordinateReferenceSystem use an internal cache
for initializing CRS objects.

This avoids the need for the separate QgsCRSCache class,
and means that the caching benefits are available without the
need for calling methods from QgsCrsCache.
2016-07-25 10:14:19 +10:00

523 lines
23 KiB
Plaintext

/** \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.4 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 proj4 library for all the math behind coordinate transformations, so in case
* of any troubles with projections it is best to examine the PROJ.4 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(), toProj4(), 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:
*
* ~~~{.py}
* crs = QgsCoordinateReferenceSystem("EPSG:27700")
* if crs.isValid():
* print("CRS Description: {}".format(crs.description()))
* print("CRS PROJ.4 text: {}".format(crs.toProj4()))
* else:
* print("Invalid CRS!")
* ~~~
*
* This will produce the following output:
*
* ~~~
* CRS Description: OSGB 1936 / British National Grid
* CRS PROJ.4 text: +proj=tmerc +lat_0=49 +lon_0=-2 +k=0.9996012717 +x_0=400000 +y_0=-100000 [output trimmed]
* ~~~
*
* 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.4 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 proj4 library. For example, the definition of WGS84 looks like this:
*
* +proj=longlat +datum=WGS84 +no_defs
*
* See toProj4() and createFromProj4() 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::srsDbFilePath())
* 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 databse (in user's home directory, see QgsApplication::qgisUserDbFilePath()).
* 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 flavours 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 flavours.
*
* \see QgsCoordinateTransform
*/
class QgsCoordinateReferenceSystem
{
%TypeHeaderCode
#include <qgscoordinatereferencesystem.h>
%End
public:
// typedef void (*CUSTOM_CRS_VALIDATION)(QgsCoordinateReferenceSystem*);
//! 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
EpsgCrsId //!< EPSG code
};
/** Constructs an invalid CRS object */
QgsCoordinateReferenceSystem();
~QgsCoordinateReferenceSystem();
/*!
* 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 createFromProj4()
* - "WKT:<wkt>" - handled with createFromWkt()
*
* If no prefix is specified, WKT definition is assumed.
* @param theDefinition A String containing a coordinate reference system definition.
* @see createFromString()
*/
// TODO QGIS 3: remove "POSTGIS" and "INTERNAL", allow PROJ4 without the prefix
explicit QgsCoordinateReferenceSystem( const QString& theDefinition );
/** 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, WKT or Proj4 to describe CRS's in your code
* wherever possible. Internal QGIS CRS IDs are not guaranteed to be permanent / involatile.
* @param theId The ID valid for the chosen CRS ID type
* @param theType One of the types described in CrsType
*/
// TODO QGIS 3: remove theType and always use EPSG code
QgsCoordinateReferenceSystem( const long theId, CrsType theType = PostgisCrsId );
// static creators
/** Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
* @param ogcCrs OGR compliant CRS definition, eg "EPSG:4326"
* @returns matching CRS, or an invalid CRS if string could not be matched
* @note added in QGIS 3.0
* @see createFromOgcWmsCrs()
*/
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
* @note added in QGIS 3.0
*/
static QgsCoordinateReferenceSystem fromEpsgId( long epsg );
/** Creates a CRS from a proj4 style formatted string.
* @param proj4 proj4 format string
* @returns matching CRS, or an invalid CRS if string could not be matched
* @note added in QGIS 3.0
* @see createFromProj4()
*/
static QgsCoordinateReferenceSystem fromProj4( const QString& proj4 );
/** 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
* @note added in QGIS 3.0
* @see createFromWkt()
*/
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
* @note added in QGIS 3.0
* @see createFromSrsId()
*/
static QgsCoordinateReferenceSystem fromSrsId( long srsId );
// Misc helper functions -----------------------
/**
* Sets this CRS by lookup of the given ID in the CRS database.
* @note We encourage you to use EPSG code, WKT or Proj4 to describe CRS's in your code
* wherever possible. Internal QGIS CRS IDs are not guaranteed to be permanent / involatile.
* @return True on success else false
*/
// TODO QGIS 3: remove theType and always use EPSG code, rename to createFromEpsg
bool createFromId( const long theId, CrsType theType = PostgisCrsId );
/**
* 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.
* @note this method uses an internal cache. Call invalidateCache() to clear the cache.
* @return True on success else false
*/
// TODO QGIS 3: remove "QGIS" and "CUSTOM", only support "USER" (also returned by authid())
bool createFromOgcWmsCrs( const QString& theCrs );
/** Sets this CRS by lookup of the given PostGIS SRID in the CRS database.
* @param theSrid The postgis SRID for the desired spatial reference system.
* @return True on success else false
*/
// TODO QGIS 3: remove unless really necessary - let's use EPSG codes instead
bool createFromSrid( const long theSrid );
/** 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.
* Otherwise the WKT will be converted to a proj4 string and createFromProj4()
* set up the object.
* @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.
* @param theWkt The WKT for the desired spatial reference system.
* @return True on success else false
*/
bool createFromWkt( const QString &theWkt );
/** 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.
* @note this method uses an internal cache. Call invalidateCache() to clear the cache.
* @param theSrsId The internal QGIS CRS ID for the desired spatial reference system.
* @return True on success else false
*/
bool createFromSrsId( const long theSrsId );
/** Sets this CRS by passing it a PROJ.4 style formatted string.
*
* The string will be parsed and the projection and ellipsoid
* members set and the remainder of the proj4 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 proj4 string to internal QGIS CRS ID using the following logic:
*
* - perform a whole text search on proj4 string (if not null)
* - if not match is found, split proj4 into individual parameters and try to find
* a match where the parameters are in a different order
* - if none of the above match, use findMatchingProj()
*
* @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.
* @param theProjString A proj4 format string
* @return True on success else false
*/
bool createFromProj4( const QString &theProjString );
/** 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 createFromProj4()
* - "WKT:<wkt>" - handled with createFromWkt()
*
* If no prefix is specified, WKT definition is assumed.
* @param theDefinition A String containing a coordinate reference system definition.
* @return True on success else false
*/
bool createFromString( const QString &theDefinition );
/** 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.4 string, filename (with WKT, XML or PROJ.4 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 )
* @note this function generates a WKT string using OSRSetFromUserInput() and
* passes it to createFromWkt() function.
* @param theDefinition A String containing a coordinate reference system definition.
* @return True on success else false
*/
// TODO QGIS3: rename to createFromStringOGR so it is clear it's similar to createFromString, just different backend
bool createFromUserInput( const QString &theDefinition );
/** 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() .
*/
static void setupESRIWktFix();
/** 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 behaviour 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();
/** Walks the CRS databases (both system and user database) trying to match
* stored PROJ.4 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 proj4string!
* @return long the SrsId of the matched CRS, zero if no match was found
*/
// TODO QGIS 3: seems completely obsolete now (only compares proj4 - already done in createFromProj4)
long findMatchingProj();
/** Overloaded == operator used to compare to CRS's.
*
* Internally it will use authid() for comparison.
*/
bool operator==( const QgsCoordinateReferenceSystem &theSrs ) const;
/** Overloaded != operator used to compare to CRS's.
*
* Returns opposite bool value to operator ==
*/
bool operator!=( const QgsCoordinateReferenceSystem &theSrs ) const;
/** Restores state from the given DOM node.
* @param theNode The node from which state will be restored
* @return bool True on success, False on failure
*/
bool readXml( const QDomNode & theNode );
/** Stores state to the given Dom node in the given document.
* @param theNode The node in which state will be restored
* @param theDoc The document in which state will be stored
* @return bool True on success, False on failure
*/
bool writeXml( QDomNode & theNode, QDomDocument & theDoc ) const;
/** Sets custom function to force valid CRS
* QGIS uses implementation in QgisGui::customCrsValidation
* @note not available in python bindings
*/
// static void setCustomCrsValidation( CUSTOM_CRS_VALIDATION f );
/** Gets custom function
* @note not available in python bindings
*/
// static CUSTOM_CRS_VALIDATION customSrsValidation();
// Accessors -----------------------------------
/** Returns the internal CRS ID, if available.
* @return the internal sqlite3 srs.db primary key for this CRS
*/
long srsid() const;
/** Returns PostGIS SRID for the CRS.
* @return the PostGIS spatial_ref_sys identifier for this CRS (defaults to 0)
*/
// TODO QGIS 3: remove unless really necessary - let's use EPSG codes instead
long postgisSrid() const;
/** Returns the authority identifier for the CRS.
*
* The identifier includes both the authority (eg EPSG) and the CRS number (eg 4326).
* This is the best method to use when showing a very short CRS identifier to a user,
* eg "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, eg "WGS 84" or "GDA 94 / Vicgrid94". In most
* cases this is the best method to use when showing a friendly identifier for the CRS to a
* user.
* @returns descriptive name of the CRS
* @note an empty string will be returned if the description is not available for the CRS
* @see authid()
*/
QString description() const;
/** Returns the projection acronym for the projection used by the CRS.
* @returns the official proj4 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 proj4 acronym for the ellipoid
* @note an empty string will be returned if the ellipsoidAcronym is not available for the CRS
* @see projectionAcronym()
*/
QString ellipsoidAcronym() const;
/** Returns a WKT representation of this CRS.
* @return string containing WKT of the CRS
* @see toProj4()
*/
QString toWkt() const;
/** Returns a Proj4 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.
* @return Proj4 format string that defines this CRS.
* @note an empty string will be returned if the CRS could not be represented by a Proj4 string
* @see toWkt()
*/
QString toProj4() 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 (eg. 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.
*/
Qgis::UnitType mapUnits() const;
// Mutators -----------------------------------
/** Set user hint for validation
*/
void setValidationHint( const QString& html );
/** Get 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 syncDb();
/** Save the proj4-string as a custom CRS
* @returns bool true if success else false
*/
bool saveAsUserCrs( const QString& name );
/** Returns auth id of related geographic CRS*/
QString geographicCrsAuthId() const;
/** Returns a list of recently used projections
* @returns list of srsid for recently used projections
* @note added in QGIS 2.7
*/
static QStringList recentProjections();
/** Clears the internal cache used to initialise QgsCoordinateReferenceSystem objects.
* This should be called whenever the srs database has been modified in order to ensure
* that outdated CRS objects are not created.
* @note added in QGIS 3.0
*/
static void invalidateCache();
};