25 #include <QDomElement>
26 #include <QApplication>
28 #include <QStringList>
42 , mShortCircuit( false )
43 , mInitialisedFlag( false )
44 , mSourceProjection( 0 )
45 , mDestinationProjection( 0 )
46 , mSourceDatumTransform( -1 )
47 , mDestinationDatumTransform( -1 )
54 , mShortCircuit( false )
55 , mInitialisedFlag( false )
56 , mSourceProjection( 0 )
57 , mDestinationProjection( 0 )
58 , mSourceDatumTransform( -1 )
59 , mDestinationDatumTransform( -1 )
69 , mInitialisedFlag( false )
72 , mSourceProjection( 0 )
73 , mDestinationProjection( 0 )
74 , mSourceDatumTransform( -1 )
75 , mDestinationDatumTransform( -1 )
82 , mInitialisedFlag( false )
83 , mSourceProjection( 0 )
84 , mDestinationProjection( 0 )
85 , mSourceDatumTransform( -1 )
86 , mDestinationDatumTransform( -1 )
102 , mInitialisedFlag( false )
103 , mSourceProjection( 0 )
104 , mDestinationProjection( 0 )
105 , mSourceDatumTransform( -1 )
106 , mDestinationDatumTransform( -1 )
110 mSourceCRS.
createFromId( theSourceSrid, theSourceCRSType );
122 if ( mSourceProjection )
124 pj_free( mSourceProjection );
126 if ( mDestinationProjection )
128 pj_free( mDestinationProjection );
169 mShortCircuit =
true;
181 bool useDefaultDatumTransform = ( mSourceDatumTransform == - 1 && mDestinationDatumTransform == -1 );
185 pj_free( mSourceProjection );
187 if ( !useDefaultDatumTransform )
189 sourceProjString = stripDatumTransform( sourceProjString );
191 if ( mSourceDatumTransform != -1 )
196 pj_free( mDestinationProjection );
198 if ( !useDefaultDatumTransform )
200 destProjString = stripDatumTransform( destProjString );
202 if ( mDestinationDatumTransform != -1 )
207 if ( !useDefaultDatumTransform )
209 addNullGridShifts( sourceProjString, destProjString );
212 mSourceProjection = pj_init_plus( sourceProjString.
toUtf8() );
213 mDestinationProjection = pj_init_plus( destProjString.
toUtf8() );
215 #ifdef COORDINATE_TRANSFORM_VERBOSE
220 mInitialisedFlag =
true;
221 if ( !mDestinationProjection )
223 mInitialisedFlag =
false;
225 if ( !mSourceProjection )
227 mInitialisedFlag =
false;
229 #ifdef COORDINATE_TRANSFORM_VERBOSE
230 if ( mInitialisedFlag )
232 QgsDebugMsg(
"------------------------------------------------------------" );
233 QgsDebugMsg(
"The OGR Coordinate transformation for this layer was set to" );
234 QgsLogger::debug<QgsCoordinateReferenceSystem>(
"Input", mSourceCRS, __FILE__, __FUNCTION__, __LINE__ );
235 QgsLogger::debug<QgsCoordinateReferenceSystem>(
"Output", mDestCRS, __FILE__, __FUNCTION__, __LINE__ );
236 QgsDebugMsg(
"------------------------------------------------------------" );
240 QgsDebugMsg(
"------------------------------------------------------------" );
241 QgsDebugMsg(
"The OGR Coordinate transformation FAILED TO INITIALISE!" );
242 QgsDebugMsg(
"------------------------------------------------------------" );
245 if ( !mInitialisedFlag )
247 QgsDebugMsg(
"Coordinate transformation failed to initialize!" );
254 if ( mSourceCRS == mDestCRS )
258 mShortCircuit =
true;
264 mShortCircuit =
false;
280 if ( mShortCircuit || !mInitialisedFlag )
283 double x = thePoint.
x();
284 double y = thePoint.
y();
317 if ( mShortCircuit || !mInitialisedFlag )
341 #ifdef COORDINATE_TRANSFORM_VERBOSE
354 if ( mShortCircuit || !mInitialisedFlag )
374 if ( mShortCircuit || !mInitialisedFlag )
380 int nVertices = poly.
size();
386 for (
int i = 0; i < nVertices; ++i )
405 for (
int i = 0; i < nVertices; ++i )
417 if ( mShortCircuit || !mInitialisedFlag )
441 TransformDirection direction )
const
443 double xd = ( double ) x, yd = (
double ) y;
452 TransformDirection direction )
const
454 if ( mShortCircuit || !mInitialisedFlag )
480 TransformDirection direction )
const
482 if ( mShortCircuit || !mInitialisedFlag )
495 int vectorSize = x.
size();
499 for (
int i = 0; i < vectorSize; ++i )
508 for (
int i = 0; i < vectorSize; ++i )
532 if ( mShortCircuit || !mInitialisedFlag )
541 static const int numP = 8;
549 double x[numP * numP];
550 double y[numP * numP];
551 double z[numP * numP];
557 double dx = rect.
width() / ( double )( numP - 1 );
558 double dy = rect.
height() / ( double )( numP - 1 );
562 for (
int i = 0; i < numP ; i++ )
568 for (
int j = 0; j < numP; j++ )
570 x[( i*numP ) + j] = pointX;
571 y[( i*numP ) + j] = pointY;
573 z[( i*numP ) + j] = 0.0;
595 for (
int i = 0; i < numP * numP; i++ )
597 if ( !qIsFinite( x[i] ) || !qIsFinite( y[i] ) )
602 if ( handle180Crossover )
613 if ( handle180Crossover )
638 "The coordinates can not be reprojected. The CRS is: %1" )
639 .arg( mSourceCRS.
toProj4() ),
tr(
"CRS" ) );
645 "The coordinates can not be reprojected. The CRS is: %1" ).arg( mDestCRS.
toProj4() ),
tr(
"CRS" ) );
649 #ifdef COORDINATE_TRANSFORM_VERBOSE
652 QgsDebugMsg(
QString(
"[[[[[[ Number of points to transform: %1 ]]]]]]" ).arg( numPoints ) );
659 if (( pj_is_latlong( mDestinationProjection ) && ( direction ==
ReverseTransform ) )
660 || ( pj_is_latlong( mSourceProjection ) && ( direction ==
ForwardTransform ) ) )
662 for (
int i = 0; i < numPoints; ++i )
673 projResult = pj_transform( mDestinationProjection, mSourceProjection, numPoints, 0, x, y, z );
677 Q_ASSERT( mSourceProjection != 0 );
678 Q_ASSERT( mDestinationProjection != 0 );
679 projResult = pj_transform( mSourceProjection, mDestinationProjection, numPoints, 0, x, y, z );
682 if ( projResult != 0 )
687 for (
int i = 0; i < numPoints; ++i )
691 points +=
QString(
"(%1, %2)\n" ).
arg( x[i], 0,
'f' ).
arg( y[i], 0,
'f' );
695 points +=
QString(
"(%1, %2)\n" ).
arg( x[i] * RAD_TO_DEG, 0,
'f' ).
arg( y[i] * RAD_TO_DEG, 0,
'f' );
699 dir = ( direction ==
ForwardTransform ) ?
tr(
"forward transform" ) :
tr(
"inverse transform" );
701 char *srcdef = pj_get_def( mSourceProjection, 0 );
702 char *dstdef = pj_get_def( mDestinationProjection, 0 );
706 "PROJ.4: %3 +to %4\n"
710 .
arg( srcdef ).
arg( dstdef )
716 QgsDebugMsg(
"Projection failed emitting invalid transform signal: " + msg );
727 if (( pj_is_latlong( mDestinationProjection ) && ( direction ==
ForwardTransform ) )
728 || ( pj_is_latlong( mSourceProjection ) && ( direction ==
ReverseTransform ) ) )
730 for (
int i = 0; i < numPoints; ++i )
737 #ifdef COORDINATE_TRANSFORM_VERBOSE
739 .arg( xorg, 0,
'g', 15 ).arg( yorg, 0,
'g', 15 )
740 .arg( *x, 0,
'g', 15 ).arg( *y, 0,
'g', 15 ) );
747 QgsDebugMsg(
"Reading Coordinate Transform from xml ------------------------!" );
750 mSourceCRS.
readXML( mySrcNode );
753 mDestCRS.
readXML( myDestNode );
771 mSourceCRS.
writeXML( mySourceElement, theDoc );
775 mDestCRS.
writeXML( myDestElement, theDoc );
788 +
"/share/proj/" +
QString( name );
795 void QgsCoordinateTransform::setFinder()
820 return transformations;
826 if ( srcSplit.
size() < 2 || destSplit.
size() < 2 )
828 return transformations;
831 int srcAuthCode = srcSplit.
at( 1 ).toInt();
832 int destAuthCode = destSplit.
at( 1 ).toInt();
834 if ( srcAuthCode == destAuthCode )
836 return transformations;
840 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 ),
843 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 ),
844 reverseDirectTransforms );
846 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 ),
849 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 ),
854 for ( ; directIt != directTransforms.
constEnd(); ++directIt )
860 directIt = reverseDirectTransforms.
constBegin();
861 for ( ; directIt != reverseDirectTransforms.
constEnd(); ++directIt )
867 for ( ; srcWgsIt != srcToWgs84.
constEnd(); ++srcWgsIt )
870 for ( ; dstWgsIt != destToWgs84.
constEnd(); ++dstWgsIt )
876 return transformations;
879 QString QgsCoordinateTransform::stripDatumTransform(
const QString& proj4 )
885 for (
int i = 0; i < parameterSplit.
size(); ++i )
887 currentParameter = parameterSplit.
at( i );
888 if ( !currentParameter.
startsWith(
"towgs84", Qt::CaseInsensitive )
889 && !currentParameter.
startsWith(
"nadgrids", Qt::CaseInsensitive ) )
891 newProjString.
append(
"+" );
892 newProjString.
append( currentParameter );
893 newProjString.
append(
" " );
896 return newProjString;
899 void QgsCoordinateTransform::searchDatumTransform(
const QString& sql,
QList< int >& transforms )
903 if ( openResult != SQLITE_OK )
910 int prepareRes = sqlite3_prepare( db, sql.
toAscii(), sql.
size(), &stmt, NULL );
911 if ( prepareRes != SQLITE_OK )
913 sqlite3_finalize( stmt ); sqlite3_close( db );
918 while ( sqlite3_step( stmt ) == SQLITE_ROW )
920 cOpCode = (
const char * ) sqlite3_column_text( stmt, 0 );
923 sqlite3_finalize( stmt ); sqlite3_close( db );
932 if ( openResult != SQLITE_OK )
935 return transformString;
939 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 );
940 int prepareRes = sqlite3_prepare( db, sql.
toAscii(), sql.
size(), &stmt, NULL );
941 if ( prepareRes != SQLITE_OK )
943 sqlite3_finalize( stmt ); sqlite3_close( db );
944 return transformString;
947 if ( sqlite3_step( stmt ) == SQLITE_ROW )
950 int methodCode = sqlite3_column_int( stmt, 0 );
951 if ( methodCode == 9615 )
953 transformString =
"+nadgrids=" +
QString((
const char * )sqlite3_column_text( stmt, 1 ) );
955 else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 )
957 transformString +=
"+towgs84=";
958 double p1 = sqlite3_column_double( stmt, 1 );
959 double p2 = sqlite3_column_double( stmt, 2 );
960 double p3 = sqlite3_column_double( stmt, 3 );
961 double p4 = sqlite3_column_double( stmt, 4 );
962 double p5 = sqlite3_column_double( stmt, 5 );
963 double p6 = sqlite3_column_double( stmt, 6 );
964 double p7 = sqlite3_column_double( stmt, 7 );
965 if ( methodCode == 9603 )
976 sqlite3_finalize( stmt ); sqlite3_close( db );
977 return transformString;
984 if ( openResult != SQLITE_OK )
991 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 );
992 int prepareRes = sqlite3_prepare( db, sql.
toAscii(), sql.
size(), &stmt, NULL );
993 if ( prepareRes != SQLITE_OK )
995 sqlite3_finalize( stmt ); sqlite3_close( db );
999 int srcCrsId, destCrsId;
1000 if ( sqlite3_step( stmt ) != SQLITE_ROW )
1002 sqlite3_finalize( stmt );
1003 sqlite3_close( db );
1007 epsgNr = sqlite3_column_int( stmt, 0 );
1008 srcCrsId = sqlite3_column_int( stmt, 1 );
1009 destCrsId = sqlite3_column_int( stmt, 2 );
1012 preferred = sqlite3_column_int( stmt, 5 ) != 0;
1013 deprecated = sqlite3_column_int( stmt, 6 ) != 0;
1022 sqlite3_finalize( stmt );
1023 sqlite3_close( db );
1027 void QgsCoordinateTransform::addNullGridShifts(
QString& srcProjString,
QString& destProjString )
1030 if ( mDestinationDatumTransform == -1 && srcProjString.
contains(
"+nadgrids" ) )
1032 destProjString +=
" +nadgrids=@null";
1035 if ( mSourceDatumTransform == -1 && destProjString.
contains(
"+nadgrids" ) )
1037 srcProjString +=
" +nadgrids=@null";
1043 if ( mSourceCRS.
authid().
compare(
"EPSG:3857", Qt::CaseInsensitive ) == 0 && mSourceDatumTransform == -1 )
1045 srcProjString +=
" +nadgrids=@null";
1047 if ( mDestCRS.
authid().
compare(
"EPSG:3857", Qt::CaseInsensitive ) == 0 && mDestinationDatumTransform == -1 )
1049 destProjString +=
" +nadgrids=@null";
A rectangle specified with double values.
QString & append(QChar ch)
const QgsCoordinateReferenceSystem & crsByAuthId(const QString &authid)
Returns the CRS for authid, e.g.
bool isEmpty() const
test if rectangle is empty.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
bool createFromWkt(const QString &theWkt)
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
double yMaximum() const
Get the y maximum value (top side of rectangle)
QString geographicCRSAuthId() const
Returns auth id of related geographic CRS.
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
const T & at(int i) const
bool createFromId(const long theId, CrsType theType=PostgisCrsId)
QString tr(const char *sourceText, const char *disambiguation, int n)
static void logMessage(QString message, QString tag=QString::null, MessageLevel level=WARNING)
add a message to the instance (and create it if necessary)
QDomElement toElement() const
bool createFromOgcWmsCrs(QString theCrs)
Set up this CRS from the given OGC CRS.
QString number(int n, int base)
void combineExtentWith(QgsRectangle *rect)
expand the rectangle so that covers both the original rectangle and the given rectangle ...
bool createFromSrsId(const long theSrsId)
QString fromUtf8(const char *str, int size)
double yMinimum() const
Get the y minimum value (bottom side of rectangle)
double xMaximum() const
Get the x maximum value (right side of rectangle)
#define QgsDebugMsgLevel(str, level)
void setAttribute(const QString &name, const QString &value)
int toInt(bool *ok, int base) const
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
A class to represent a point.
QDomNode namedItem(const QString &name) const
bool contains(QChar ch, Qt::CaseSensitivity cs) const
const T & at(int i) const
bool writeXML(QDomNode &theNode, QDomDocument &theDoc) const
Class for storing a coordinate reference system (CRS)
static const QString srsDbFilePath()
Returns the path to the srs.db file.
bool readXML(QDomNode &theNode)
QString description() const
Custom exception class for Coordinate Reference System related exceptions.
const_iterator constEnd() const
QDomElement createElement(const QString &tagName)
const_iterator constBegin() const
double width() const
Width of the rectangle.
QString applicationDirPath()
int compare(const QString &other) const
QString toString(bool automaticPrecision=false) const
returns string representation of form xmin,ymin xmax,ymax
QString arg(qlonglong a, int fieldWidth, int base, const QChar &fillChar) const
double xMinimum() const
Get the x minimum value (left side of rectangle)
static QgsCRSCache * instance()
void setXMinimum(double x)
Set the minimum x value.
QByteArray toAscii() const
double height() const
Height of the rectangle.
QString toProj4() const
Get the Proj Proj4 string representation of this srs.
QByteArray toUtf8() const