25 #include <QDomElement> 26 #include <QApplication> 28 #include <QStringList> 44 , mShortCircuit( false )
45 , mInitialisedFlag( false )
46 , mSourceDatumTransform( -1 )
47 , mDestinationDatumTransform( -1 )
54 , mShortCircuit( false )
55 , mInitialisedFlag( false )
56 , mSourceDatumTransform( -1 )
57 , mDestinationDatumTransform( -1 )
67 , mInitialisedFlag( false )
68 , mSourceCRS(
QgsCRSCache::instance()->crsBySrsId( theSourceSrsId ) )
69 , mDestCRS(
QgsCRSCache::instance()->crsBySrsId( theDestSrsId ) )
70 , mSourceDatumTransform( -1 )
71 , mDestinationDatumTransform( -1 )
78 , mInitialisedFlag( false )
79 , mSourceDatumTransform( -1 )
80 , mDestinationDatumTransform( -1 )
96 , mInitialisedFlag( false )
97 , mSourceDatumTransform( -1 )
98 , mDestinationDatumTransform( -1 )
102 mSourceCRS.
createFromId( theSourceSrid, theSourceCRSType );
153 mShortCircuit =
true;
165 bool useDefaultDatumTransform = ( mSourceDatumTransform == - 1 && mDestinationDatumTransform == -1 );
169 mSourceProjString = mSourceCRS.
toProj4();
170 if ( !useDefaultDatumTransform )
172 mSourceProjString = stripDatumTransform( mSourceProjString );
174 if ( mSourceDatumTransform != -1 )
179 mDestProjString = mDestCRS.
toProj4();
180 if ( !useDefaultDatumTransform )
182 mDestProjString = stripDatumTransform( mDestProjString );
184 if ( mDestinationDatumTransform != -1 )
189 if ( !useDefaultDatumTransform )
191 addNullGridShifts( mSourceProjString, mDestProjString );
197 #ifdef COORDINATE_TRANSFORM_VERBOSE 202 mInitialisedFlag =
true;
205 mInitialisedFlag =
false;
209 mInitialisedFlag =
false;
211 #ifdef COORDINATE_TRANSFORM_VERBOSE 212 if ( mInitialisedFlag )
214 QgsDebugMsg(
"------------------------------------------------------------" );
215 QgsDebugMsg(
"The OGR Coordinate transformation for this layer was set to" );
216 QgsLogger::debug<QgsCoordinateReferenceSystem>(
"Input", mSourceCRS, __FILE__, __FUNCTION__, __LINE__ );
217 QgsLogger::debug<QgsCoordinateReferenceSystem>(
"Output", mDestCRS, __FILE__, __FUNCTION__, __LINE__ );
218 QgsDebugMsg(
"------------------------------------------------------------" );
222 QgsDebugMsg(
"------------------------------------------------------------" );
223 QgsDebugMsg(
"The OGR Coordinate transformation FAILED TO INITIALISE!" );
224 QgsDebugMsg(
"------------------------------------------------------------" );
227 if ( !mInitialisedFlag )
229 QgsDebugMsg(
"Coordinate transformation failed to initialize!" );
236 if ( mSourceCRS == mDestCRS )
240 mShortCircuit =
true;
246 mShortCircuit =
false;
262 if ( mShortCircuit || !mInitialisedFlag )
265 double x = thePoint.
x();
266 double y = thePoint.
y();
299 if ( mShortCircuit || !mInitialisedFlag )
323 #ifdef COORDINATE_TRANSFORM_VERBOSE 336 if ( mShortCircuit || !mInitialisedFlag )
357 double xd =
static_cast< double >( x ), yd = static_cast< double >( y );
366 if ( mShortCircuit || !mInitialisedFlag )
392 if ( mShortCircuit || !mInitialisedFlag )
398 int nVertices = poly.
size();
404 for (
int i = 0; i < nVertices; ++i )
423 for (
int i = 0; i < nVertices; ++i )
435 if ( mShortCircuit || !mInitialisedFlag )
462 if ( mShortCircuit || !mInitialisedFlag )
475 int vectorSize = x.
size();
479 for (
int i = 0; i < vectorSize; ++i )
488 for (
int i = 0; i < vectorSize; ++i )
510 if ( mShortCircuit || !mInitialisedFlag )
523 const int nPoints = 1000;
524 double d = sqrt(( rect.
width() * rect.
height() ) / pow( sqrt( static_cast< double >( nPoints ) ) - 1, 2.0 ) );
525 int nXPoints =
static_cast< int >( ceil( rect.
width() / d ) ) + 1;
526 int nYPoints =
static_cast< int >( ceil( rect.
height() / d ) ) + 1;
542 double dx = rect.
width() /
static_cast< double >( nXPoints - 1 );
543 double dy = rect.
height() /
static_cast< double >( nYPoints - 1 );
547 for (
int i = 0; i < nYPoints ; i++ )
553 for (
int j = 0; j < nXPoints; j++ )
555 x[( i*nXPoints ) + j] = pointX;
556 y[( i*nXPoints ) + j] = pointY;
558 z[( i*nXPoints ) + j] = 0.0;
580 for (
int i = 0; i < nXPoints * nYPoints; i++ )
582 if ( !qIsFinite( x[i] ) || !qIsFinite( y[i] ) )
587 if ( handle180Crossover )
598 if ( handle180Crossover )
619 if ( mShortCircuit || !mInitialisedFlag )
625 "The coordinates can not be reprojected. The CRS is: %1" )
626 .arg( mSourceCRS.
toProj4() ),
tr(
"CRS" ) );
632 "The coordinates can not be reprojected. The CRS is: %1" ).arg( mDestCRS.
toProj4() ),
tr(
"CRS" ) );
636 #ifdef COORDINATE_TRANSFORM_VERBOSE 639 QgsDebugMsg(
QString(
"[[[[[[ Number of points to transform: %1 ]]]]]]" ).arg( numPoints ) );
647 projPJ sourceProj = projData.first;
648 projPJ destProj = projData.second;
653 for (
int i = 0; i < numPoints; ++i )
663 projResult = pj_transform( destProj, sourceProj, numPoints, 0, x, y, z );
667 Q_ASSERT( sourceProj );
668 Q_ASSERT( destProj );
669 projResult = pj_transform( sourceProj, destProj, numPoints, 0, x, y, z );
672 if ( projResult != 0 )
677 for (
int i = 0; i < numPoints; ++i )
681 points +=
QString(
"(%1, %2)\n" ).
arg( x[i], 0,
'f' ).
arg( y[i], 0,
'f' );
685 points +=
QString(
"(%1, %2)\n" ).
arg( x[i] * RAD_TO_DEG, 0,
'f' ).
arg( y[i] * RAD_TO_DEG, 0,
'f' );
689 dir = ( direction ==
ForwardTransform ) ?
tr(
"forward transform" ) :
tr(
"inverse transform" );
691 char *srcdef = pj_get_def( sourceProj, 0 );
692 char *dstdef = pj_get_def( destProj, 0 );
696 "PROJ.4: %3 +to %4\n" 706 QgsDebugMsg(
"Projection failed emitting invalid transform signal: " + msg );
720 for (
int i = 0; i < numPoints; ++i )
726 #ifdef COORDINATE_TRANSFORM_VERBOSE 728 .arg( xorg, 0,
'g', 15 ).arg( yorg, 0,
'g', 15 )
729 .arg( *x, 0,
'g', 15 ).arg( *y, 0,
'g', 15 ) );
736 QgsDebugMsg(
"Reading Coordinate Transform from xml ------------------------!" );
739 mSourceCRS.
readXML( mySrcNode );
742 mDestCRS.
readXML( myDestNode );
760 mSourceCRS.
writeXML( mySourceElement, theDoc );
764 mDestCRS.
writeXML( myDestElement, theDoc );
777 +
"/share/proj/" +
QString( name );
784 void QgsCoordinateTransform::setFinder()
809 return transformations;
815 if ( srcSplit.
size() < 2 || destSplit.
size() < 2 )
817 return transformations;
820 int srcAuthCode = srcSplit.
at( 1 ).toInt();
821 int destAuthCode = destSplit.
at( 1 ).toInt();
823 if ( srcAuthCode == destAuthCode )
825 return transformations;
829 searchDatumTransform(
QString(
"SELECT coord_op_code FROM tbl_datum_transform WHERE source_crs_code=%1 AND target_crs_code=%2 ORDER BY deprecated ASC,preferred DESC" ).arg( srcAuthCode ).arg( destAuthCode ),
832 searchDatumTransform(
QString(
"SELECT coord_op_code FROM tbl_datum_transform WHERE source_crs_code = %1 AND target_crs_code=%2 ORDER BY deprecated ASC,preferred DESC" ).arg( destAuthCode ).arg( srcAuthCode ),
833 reverseDirectTransforms );
835 searchDatumTransform(
QString(
"SELECT coord_op_code FROM tbl_datum_transform WHERE (source_crs_code=%1 AND target_crs_code=%2) OR (source_crs_code=%2 AND target_crs_code=%1) ORDER BY deprecated ASC,preferred DESC" ).arg( srcAuthCode ).arg( 4326 ),
838 searchDatumTransform(
QString(
"SELECT coord_op_code FROM tbl_datum_transform WHERE (source_crs_code=%1 AND target_crs_code=%2) OR (source_crs_code=%2 AND target_crs_code=%1) ORDER BY deprecated ASC,preferred DESC" ).arg( destAuthCode ).arg( 4326 ),
843 for ( ; directIt != directTransforms.
constEnd(); ++directIt )
849 directIt = reverseDirectTransforms.
constBegin();
850 for ( ; directIt != reverseDirectTransforms.
constEnd(); ++directIt )
856 for ( ; srcWgsIt != srcToWgs84.
constEnd(); ++srcWgsIt )
859 for ( ; dstWgsIt != destToWgs84.
constEnd(); ++dstWgsIt )
865 return transformations;
868 QString QgsCoordinateTransform::stripDatumTransform(
const QString& proj4 )
874 for (
int i = 0; i < parameterSplit.
size(); ++i )
876 currentParameter = parameterSplit.
at( i );
877 if ( !currentParameter.
startsWith(
"towgs84", Qt::CaseInsensitive )
878 && !currentParameter.
startsWith(
"nadgrids", Qt::CaseInsensitive ) )
880 newProjString.
append(
'+' );
881 newProjString.
append( currentParameter );
882 newProjString.
append(
' ' );
885 return newProjString;
888 void QgsCoordinateTransform::searchDatumTransform(
const QString& sql,
QList< int >& transforms )
892 if ( openResult != SQLITE_OK )
899 int prepareRes = sqlite3_prepare( db, sql.
toAscii(), sql.
size(), &stmt, nullptr );
900 if ( prepareRes != SQLITE_OK )
902 sqlite3_finalize( stmt );
908 while ( sqlite3_step( stmt ) == SQLITE_ROW )
910 cOpCode =
reinterpret_cast< const char *
>( sqlite3_column_text( stmt, 0 ) );
913 sqlite3_finalize( stmt );
923 if ( openResult != SQLITE_OK )
926 return transformString;
930 QString sql =
QString(
"SELECT coord_op_method_code,p1,p2,p3,p4,p5,p6,p7 FROM tbl_datum_transform WHERE coord_op_code=%1" ).
arg( datumTransform );
931 int prepareRes = sqlite3_prepare( db, sql.
toAscii(), sql.
size(), &stmt, nullptr );
932 if ( prepareRes != SQLITE_OK )
934 sqlite3_finalize( stmt );
936 return transformString;
939 if ( sqlite3_step( stmt ) == SQLITE_ROW )
942 int methodCode = sqlite3_column_int( stmt, 0 );
943 if ( methodCode == 9615 )
945 transformString =
"+nadgrids=" +
QString( reinterpret_cast< const char * >( sqlite3_column_text( stmt, 1 ) ) );
947 else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 )
949 transformString +=
"+towgs84=";
950 double p1 = sqlite3_column_double( stmt, 1 );
951 double p2 = sqlite3_column_double( stmt, 2 );
952 double p3 = sqlite3_column_double( stmt, 3 );
953 double p4 = sqlite3_column_double( stmt, 4 );
954 double p5 = sqlite3_column_double( stmt, 5 );
955 double p6 = sqlite3_column_double( stmt, 6 );
956 double p7 = sqlite3_column_double( stmt, 7 );
957 if ( methodCode == 9603 )
968 sqlite3_finalize( stmt );
970 return transformString;
977 if ( openResult != SQLITE_OK )
984 QString sql =
QString(
"SELECT epsg_nr,source_crs_code,target_crs_code,remarks,scope,preferred,deprecated FROM tbl_datum_transform WHERE coord_op_code=%1" ).
arg( datumTransform );
985 int prepareRes = sqlite3_prepare( db, sql.
toAscii(), sql.
size(), &stmt, nullptr );
986 if ( prepareRes != SQLITE_OK )
988 sqlite3_finalize( stmt );
993 int srcCrsId, destCrsId;
994 if ( sqlite3_step( stmt ) != SQLITE_ROW )
996 sqlite3_finalize( stmt );
1001 epsgNr = sqlite3_column_int( stmt, 0 );
1002 srcCrsId = sqlite3_column_int( stmt, 1 );
1003 destCrsId = sqlite3_column_int( stmt, 2 );
1004 remarks =
QString::fromUtf8( reinterpret_cast< const char * >( sqlite3_column_text( stmt, 3 ) ) );
1005 scope =
QString::fromUtf8( reinterpret_cast< const char * >( sqlite3_column_text( stmt, 4 ) ) );
1006 preferred = sqlite3_column_int( stmt, 5 ) != 0;
1007 deprecated = sqlite3_column_int( stmt, 6 ) != 0;
1014 sqlite3_finalize( stmt );
1015 sqlite3_close( db );
1019 void QgsCoordinateTransform::addNullGridShifts(
QString& srcProjString,
QString& destProjString )
1022 if ( mDestinationDatumTransform == -1 && srcProjString.
contains(
"+nadgrids" ) )
1024 destProjString +=
" +nadgrids=@null";
1027 if ( mSourceDatumTransform == -1 && destProjString.
contains(
"+nadgrids" ) )
1029 srcProjString +=
" +nadgrids=@null";
1035 if ( mSourceCRS.
authid().
compare(
"EPSG:3857", Qt::CaseInsensitive ) == 0 && mSourceDatumTransform == -1 )
1037 srcProjString +=
" +nadgrids=@null";
1039 if ( mDestCRS.
authid().
compare(
"EPSG:3857", Qt::CaseInsensitive ) == 0 && mDestinationDatumTransform == -1 )
1041 destProjString +=
" +nadgrids=@null";
1050 pContext = mProjContext.
localData()->get();
1053 mProjContext.
setLocalData(
new QgsProjContextStore() );
1054 pContext = mProjContext.
localData()->get();
1058 if ( it != mProjProjections.
constEnd() )
1069 pj_init_plus_ctx( pContext, mDestProjString.
toUtf8() ) );
1070 mProjProjections.
insert( reinterpret_cast< uintptr_t >( pContext ), res );
1075 void QgsCoordinateTransform::freeProj()
1079 for ( ; it != mProjProjections.
constEnd(); ++it )
1081 pj_free( it.
value().first );
1082 pj_free( it.
value().second );
1084 mProjProjections.
clear();
1088 QgsCoordinateTransform::QgsProjContextStore::QgsProjContextStore()
1090 context = pj_ctx_alloc();
1093 QgsCoordinateTransform::QgsProjContextStore::~QgsProjContextStore()
1095 pj_ctx_free( context );
A rectangle specified with double values.
QString & append(QChar ch)
QgsCoordinateReferenceSystem crsByOgcWmsCrs(const QString &ogcCrs) const
Returns the CRS from a given OGC WMS-format Coordinate Reference System string.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
QDomNode appendChild(const QDomNode &newChild)
void setXMaximum(double x)
Set the maximum x value.
void push_back(const T &value)
QString attribute(const QString &name, const QString &defValue) const
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
const_iterator constBegin() const
const T & at(int i) const
QString toProj4() const
Returns a Proj4 string representation of this CRS.
bool createFromId(const long theId, CrsType theType=PostgisCrsId)
QgsCoordinateReferenceSystem crsByWkt(const QString &wkt) const
Returns the CRS from a WKT spatial ref sys definition string.
const_iterator constFind(const Key &key) const
QString tr(const char *sourceText, const char *disambiguation, int n)
QgsCoordinateReferenceSystem crsBySrsId(long srsId) const
Returns the CRS from a specified QGIS SRS ID.
double y() const
Get the y value of the point.
void setLocalData(T data)
QDomElement toElement() const
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
const char * name() const
QString number(int n, int base)
bool hasLocalData() const
QString fromUtf8(const char *str, int size)
QString geographicCRSAuthId() const
Returns auth id of related geographic CRS.
#define QgsDebugMsgLevel(str, level)
bool isEmpty() const
test if rectangle is empty.
bool readXML(const QDomNode &theNode)
Restores state from the given Dom node.
void setAttribute(const QString &name, const QString &value)
double width() const
Width of the rectangle.
int toInt(bool *ok, int base) const
const_iterator constEnd() const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
static void logMessage(const QString &message, const QString &tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
QString description() const
Returns the descriptive name of the CRS, eg "WGS 84" or "GDA 94 / Vicgrid94".
A class to represent a point.
Caches QgsCoordinateReferenceSystem construction, which may be expensive.
QDomNode namedItem(const QString &name) const
bool contains(QChar ch, Qt::CaseSensitivity cs) const
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
double xMaximum() const
Get the x maximum value (right side of rectangle)
void combineExtentWith(const QgsRectangle &rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
const T & at(int i) const
Class for storing a coordinate reference system (CRS)
double xMinimum() const
Get the x minimum value (left side of rectangle)
double yMaximum() const
Get the y maximum value (top side of rectangle)
iterator insert(const Key &key, const T &value)
static QString srsDbFilePath()
Returns the path to the srs.db file.
Custom exception class for Coordinate Reference System related exceptions.
const_iterator constEnd() const
bool writeXML(QDomNode &theNode, QDomDocument &theDoc) const
Stores state to the given Dom node in the given document.
QDomElement createElement(const QString &tagName)
const_iterator constBegin() const
QString applicationDirPath()
int compare(const QString &other) const
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
static QgsCRSCache * instance()
Returns a pointer to the QgsCRSCache singleton.
QString authid() const
Returns the authority identifier for the CRS, which includes both the authority (eg EPSG) and the CRS...
double x() const
Get the x value of the point.
void setXMinimum(double x)
Set the minimum x value.
QByteArray toAscii() const
double height() const
Height of the rectangle.
const T value(const Key &key) const
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
QByteArray toUtf8() const