1 /*************************************************************************** 2 qgscoordinatetransformcontext.h 3 ------------------------------- 4 begin : November 2017 5 copyright : (C) 2017 by Nyall Dawson 6 email : nyall dot dawson at gmail dot com 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 QGSCOORDINATETRANSFORMCONTEXT_H 19 #define QGSCOORDINATETRANSFORMCONTEXT_H 20 21 #include "qgis_core.h" 22 #include "qgis_sip.h" 23 #include "qgsdatumtransform.h" 24 25 #include <QMetaType> 26 #include <QExplicitlySharedDataPointer> 27 class QgsCoordinateReferenceSystem; 28 class QgsReadWriteContext; 29 class QgsCoordinateTransformContextPrivate; 30 class QDomElement; 31 32 /*************************************************************************** 33 * This class is considered CRITICAL and any change MUST be accompanied with 34 * full unit tests in testqgsfeature.cpp. 35 * See details in QEP #17 36 ****************************************************************************/ 37 38 /** 39 * \class QgsCoordinateTransformContext 40 * \ingroup core 41 * \brief Contains information about the context in which a coordinate transform is executed. 42 * 43 * The context stores various information regarding which coordinate operations should 44 * be used when transforming points from a source to destination coordinate reference 45 * system. 46 * 47 * \note QgsCoordinateTransformContext objects are thread safe for read and write. 48 * 49 * \note QgsCoordinateTransformContext objects are implicitly shared. 50 * 51 * \see QgsDatumTransform 52 * \see QgsCoordinateTransform 53 * 54 * \since QGIS 3.0 55 */ 56 57 class CORE_EXPORT QgsCoordinateTransformContext 58 { 59 public: 60 61 /** 62 * Constructor for QgsCoordinateTransformContext. 63 */ 64 QgsCoordinateTransformContext(); 65 66 ~QgsCoordinateTransformContext() ; 67 68 /** 69 * Copy constructor 70 */ 71 QgsCoordinateTransformContext( const QgsCoordinateTransformContext &rhs ); 72 73 /** 74 * Assignment operator 75 */ 76 QgsCoordinateTransformContext &operator=( const QgsCoordinateTransformContext &rhs ) SIP_SKIP; 77 78 bool operator==( const QgsCoordinateTransformContext &rhs ) const ; 79 80 /** 81 * Clears all stored transform information from the context. 82 */ 83 void clear(); 84 85 /** 86 * Returns the stored mapping for source to destination CRS pairs to associated datum transforms to use. 87 * The map keys will be QgsCoordinateReferenceSystems::authid()s. 88 * 89 * If either the source transform ID or destination transform ID is -1, then no datum transform is 90 * required for transformations for that source or destination. 91 * 92 * \warning This method should not be used to calculate the corresponding datum transforms 93 * to use for a coordinate transform. Instead, always use calculateDatumTransforms() 94 * to determine this. 95 * 96 * \see addSourceDestinationDatumTransform() 97 * 98 * \deprecated Has no effect on builds based on Proj 6.0 or later, use coordinateOperations() instead. 99 */ 100 Q_DECL_DEPRECATED QMap< QPair< QString, QString>, QgsDatumTransform::TransformPair > sourceDestinationDatumTransforms() const SIP_DEPRECATED; 101 102 /** 103 * Returns the stored mapping for source to destination CRS pairs to associated coordinate operation to use 104 * (as a proj string). The map keys will be QgsCoordinateReferenceSystems::authid()s. 105 * 106 * \warning This method should not be used to calculate the corresponding coordinate operation 107 * to use for a coordinate transform. Instead, always use calculateCoordinateOperation() 108 * to determine this. 109 * 110 * \see addCoordinateOperation() 111 * 112 * \note Requires Proj 6.0 or later. Builds based on earlier Proj versions will always return an empty list, 113 * and the deprecated sourceDestinationDatumTransforms() method must be used instead. 114 * 115 * \since QGIS 3.8 116 */ 117 QMap< QPair< QString, QString>, QString > coordinateOperations() const; 118 119 /** 120 * Adds a new \a sourceTransform and \a destinationTransform to use when projecting coordinates 121 * from the specified \a sourceCrs to the specified \a destinationCrs. 122 * 123 * If either \a sourceTransformId or \a destinationTransformId is -1, then no datum transform is 124 * required for transformations for that source or destination. 125 * 126 * Returns TRUE if the new transform pair was added successfully. 127 * 128 * \see sourceDestinationDatumTransforms() 129 * \see removeSourceDestinationDatumTransform() 130 * 131 * \deprecated Has no effect on builds based on Proj 6.0 or later, use addCoordinateOperation() instead. 132 */ 133 Q_DECL_DEPRECATED bool addSourceDestinationDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, int sourceTransformId, int destinationTransformId ) SIP_DEPRECATED; 134 135 /** 136 * Adds a new \a coordinateOperationProjString to use when projecting coordinates 137 * from the specified \a sourceCrs to the specified \a destinationCrs. 138 * 139 * \a coordinateOperationProjString should be set to a valid Proj coordinate operation 140 * string. If \a coordinateOperationProjString is empty, then the default Proj operation 141 * will be used when transforming between the coordinate reference systems. 142 * 143 * If \a allowFallback is TRUE (since QGIS 3.12), then "ballpark" fallback transformations 144 * will be used in the case that the specified coordinate operation fails (such as when 145 * coordinates from outside a required grid shift file are transformed). See 146 * QgsCoordinateTransform::fallbackOperationOccurred() for further details. Note that if an 147 * existing \a sourceCrs and \a destinationCrs pair are added with a different \a allowFallback 148 * value, that value will replace the existing one (i.e. each combination of \a sourceCrs and 149 * \a destinationCrs must be unique). 150 * 151 * \warning coordinateOperationProjString MUST be a proj string which has been normalized for 152 * visualization, and must be constructed so that coordinates are always input and output 153 * with x/y coordinate ordering. (Proj strings output by utilities such as projinfo will NOT 154 * automatically normalize the axis order!). 155 * 156 * Returns TRUE if the new coordinate operation was added successfully. 157 * 158 * \see coordinateOperations() 159 * \see removeCoordinateOperation() 160 * 161 * \note Requires Proj 6.0 or later. Builds based on earlier Proj versions will ignore this setting, 162 * and the deprecated addSourceDestinationDatumTransform() method must be used instead. 163 * 164 * \since QGIS 3.8 165 */ 166 bool addCoordinateOperation( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs, const QString &coordinateOperationProjString, bool allowFallback = true ); 167 168 /** 169 * Removes the source to destination datum transform pair for the specified \a sourceCrs and 170 * \a destinationCrs. 171 * \see addSourceDestinationDatumTransform() 172 * 173 * \deprecated Use removeCoordinateOperation() instead 174 */ 175 Q_DECL_DEPRECATED void removeSourceDestinationDatumTransform( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs ) SIP_DEPRECATED ; 176 177 /** 178 * Removes the coordinate operation for the specified \a sourceCrs and \a destinationCrs. 179 * 180 * \since QGIS 3.8 181 */ 182 void removeCoordinateOperation( const QgsCoordinateReferenceSystem &sourceCrs, const QgsCoordinateReferenceSystem &destinationCrs ); 183 184 /** 185 * Returns TRUE if the context has a valid coordinate operation to use 186 * when transforming from the specified \a source CRS to \a destination CRS. 187 * \note source and destination are reversible. 188 */ 189 bool hasTransform( const QgsCoordinateReferenceSystem &source, 190 const QgsCoordinateReferenceSystem &destination ) const; 191 192 /** 193 * Returns the pair of source and destination datum transforms to use 194 * for a transform from the specified \a source CRS to \a destination CRS. 195 * 196 * Returns an ID of -1 if a datum transform should not be used for the source or 197 * destination. 198 * 199 * \note source and destination are reversible. 200 * \deprecated Has no effect on builds based on Proj 6.0 or later. Use calculateCoordinateOperation() instead. 201 */ 202 Q_DECL_DEPRECATED QgsDatumTransform::TransformPair calculateDatumTransforms( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const SIP_DEPRECATED; 203 204 /** 205 * Returns the Proj coordinate operation string to use when transforming 206 * from the specified \a source CRS to \a destination CRS. 207 * 208 * Returns an empty string if no specific coordinate operation is set for the source to 209 * destination pair, in which case the default Proj coordinate operation should 210 * be used. 211 * 212 * \note source and destination are reversible. 213 * 214 * \note Requires Proj 6.0 or later. Builds based on earlier Proj versions will always return 215 * an empty string, and the deprecated calculateDatumTransforms() method should be used instead. 216 * 217 * \warning Always check the result of mustReverseCoordinateOperation() in order to determine if the 218 * proj coordinate operation string returned by this method corresponds to the reverse operation, and 219 * must be manually flipped when calculating coordinate transforms. 220 * 221 * \since QGIS 3.8 222 */ 223 QString calculateCoordinateOperation( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const; 224 225 /** 226 * Returns TRUE if approximate "ballpark" transforms may be used when transforming 227 * between a \a source and \a destination CRS pair, in the case that the preferred 228 * coordinate operation fails (such as when 229 * coordinates from outside a required grid shift file are transformed). See 230 * QgsCoordinateTransform::fallbackOperationOccurred() for further details. 231 * 232 * \since QGIS 3.12 233 */ 234 bool allowFallbackTransform( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const; 235 236 /** 237 * Returns TRUE if the coordinate operation returned by calculateCoordinateOperation() for the \a source to \a destination pair 238 * must be inverted. 239 * 240 * \since QGIS 3.10.2 241 */ 242 bool mustReverseCoordinateOperation( const QgsCoordinateReferenceSystem &source, const QgsCoordinateReferenceSystem &destination ) const; 243 244 // TODO QGIS 4.0 - remove missingTransforms, not used for Proj >= 6.0 builds 245 246 /** 247 * Reads the context's state from a DOM \a element. 248 * 249 * Returns FALSE if transforms stored in the XML are not available. In this case \a missingTransforms will be 250 * filled with missing datum transform strings. 251 * 252 * \see writeXml() 253 */ 254 bool readXml( const QDomElement &element, const QgsReadWriteContext &context, QStringList &missingTransforms SIP_OUT ); 255 256 /** 257 * Writes the context's state to a DOM \a element. 258 * \see readXml() 259 */ 260 void writeXml( QDomElement &element, const QgsReadWriteContext &context ) const; 261 262 263 /** 264 * Reads the context's state from application settings. 265 * \see readSettings() 266 */ 267 void readSettings(); 268 269 /** 270 * Write the context's state to application settings. 271 * \see writeSettings() 272 */ 273 void writeSettings(); 274 275 276 private: 277 278 QExplicitlySharedDataPointer<QgsCoordinateTransformContextPrivate> d; 279 280 }; 281 282 Q_DECLARE_METATYPE( QgsCoordinateTransformContext ) 283 284 #endif // QGSCOORDINATETRANSFORMCONTEXT_H 285 286 287 288 289