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 )
375 double xd = ( double )x, yd = (
double )y;
384 if ( mShortCircuit || !mInitialisedFlag )
410 if ( mShortCircuit || !mInitialisedFlag )
416 int nVertices = poly.
size();
422 for (
int i = 0; i < nVertices; ++i )
441 for (
int i = 0; i < nVertices; ++i )
453 if ( mShortCircuit || !mInitialisedFlag )
480 if ( mShortCircuit || !mInitialisedFlag )
493 int vectorSize = x.
size();
497 for (
int i = 0; i < vectorSize; ++i )
506 for (
int i = 0; i < vectorSize; ++i )
528 if ( mShortCircuit || !mInitialisedFlag )
537 static const int numP = 8;
545 double x[numP * numP];
546 double y[numP * numP];
547 double z[numP * numP];
553 double dx = rect.
width() / ( double )( numP - 1 );
554 double dy = rect.
height() / ( double )( numP - 1 );
558 for (
int i = 0; i < numP ; i++ )
564 for (
int j = 0; j < numP; j++ )
566 x[( i*numP ) + j] = pointX;
567 y[( i*numP ) + j] = pointY;
569 z[( i*numP ) + j] = 0.0;
591 for (
int i = 0; i < numP * numP; i++ )
593 if ( !qIsFinite( x[i] ) || !qIsFinite( y[i] ) )
598 if ( handle180Crossover )
609 if ( handle180Crossover )
634 "The coordinates can not be reprojected. The CRS is: %1" )
635 .arg( mSourceCRS.
toProj4() ),
tr(
"CRS" ) );
641 "The coordinates can not be reprojected. The CRS is: %1" ).arg( mDestCRS.
toProj4() ),
tr(
"CRS" ) );
645 #ifdef COORDINATE_TRANSFORM_VERBOSE
648 QgsDebugMsg(
QString(
"[[[[[[ Number of points to transform: %1 ]]]]]]" ).arg( numPoints ) );
655 if (( pj_is_latlong( mDestinationProjection ) && ( direction ==
ReverseTransform ) )
656 || ( pj_is_latlong( mSourceProjection ) && ( direction ==
ForwardTransform ) ) )
658 for (
int i = 0; i < numPoints; ++i )
669 projResult = pj_transform( mDestinationProjection, mSourceProjection, numPoints, 0, x, y, z );
673 Q_ASSERT( mSourceProjection != 0 );
674 Q_ASSERT( mDestinationProjection != 0 );
675 projResult = pj_transform( mSourceProjection, mDestinationProjection, numPoints, 0, x, y, z );
678 if ( projResult != 0 )
683 for (
int i = 0; i < numPoints; ++i )
687 points +=
QString(
"(%1, %2)\n" ).
arg( x[i], 0,
'f' ).
arg( y[i], 0,
'f' );
691 points +=
QString(
"(%1, %2)\n" ).
arg( x[i] * RAD_TO_DEG, 0,
'f' ).
arg( y[i] * RAD_TO_DEG, 0,
'f' );
695 dir = ( direction ==
ForwardTransform ) ?
tr(
"forward transform" ) :
tr(
"inverse transform" );
697 char *srcdef = pj_get_def( mSourceProjection, 0 );
698 char *dstdef = pj_get_def( mDestinationProjection, 0 );
702 "PROJ.4: %3 +to %4\n"
712 QgsDebugMsg(
"Projection failed emitting invalid transform signal: " + msg );
723 if (( pj_is_latlong( mDestinationProjection ) && ( direction ==
ForwardTransform ) )
724 || ( pj_is_latlong( mSourceProjection ) && ( direction ==
ReverseTransform ) ) )
726 for (
int i = 0; i < numPoints; ++i )
733 #ifdef COORDINATE_TRANSFORM_VERBOSE
735 .arg( xorg, 0,
'g', 15 ).arg( yorg, 0,
'g', 15 )
736 .arg( *x, 0,
'g', 15 ).arg( *y, 0,
'g', 15 ) );
743 QgsDebugMsg(
"Reading Coordinate Transform from xml ------------------------!" );
746 mSourceCRS.
readXML( mySrcNode );
749 mDestCRS.
readXML( myDestNode );
767 mSourceCRS.
writeXML( mySourceElement, theDoc );
771 mDestCRS.
writeXML( myDestElement, theDoc );
784 +
"/share/proj/" +
QString( name );
791 void QgsCoordinateTransform::setFinder()
816 return transformations;
822 if ( srcSplit.
size() < 2 || destSplit.
size() < 2 )
824 return transformations;
827 int srcAuthCode = srcSplit.
at( 1 ).toInt();
828 int destAuthCode = destSplit.
at( 1 ).toInt();
830 if ( srcAuthCode == destAuthCode )
832 return transformations;
836 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 ),
839 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 ),
840 reverseDirectTransforms );
842 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 ),
845 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 ),
850 for ( ; directIt != directTransforms.
constEnd(); ++directIt )
856 directIt = reverseDirectTransforms.
constBegin();
857 for ( ; directIt != reverseDirectTransforms.
constEnd(); ++directIt )
863 for ( ; srcWgsIt != srcToWgs84.
constEnd(); ++srcWgsIt )
866 for ( ; dstWgsIt != destToWgs84.
constEnd(); ++dstWgsIt )
872 return transformations;
875 QString QgsCoordinateTransform::stripDatumTransform(
const QString& proj4 )
881 for (
int i = 0; i < parameterSplit.
size(); ++i )
883 currentParameter = parameterSplit.
at( i );
884 if ( !currentParameter.
startsWith(
"towgs84", Qt::CaseInsensitive )
885 && !currentParameter.
startsWith(
"nadgrids", Qt::CaseInsensitive ) )
887 newProjString.
append(
"+" );
888 newProjString.
append( currentParameter );
889 newProjString.
append(
" " );
892 return newProjString;
895 void QgsCoordinateTransform::searchDatumTransform(
const QString& sql,
QList< int >& transforms )
899 if ( openResult != SQLITE_OK )
906 int prepareRes = sqlite3_prepare( db, sql.
toAscii(), sql.
size(), &stmt, NULL );
907 if ( prepareRes != SQLITE_OK )
909 sqlite3_finalize( stmt ); sqlite3_close( db );
914 while ( sqlite3_step( stmt ) == SQLITE_ROW )
916 cOpCode = (
const char * ) sqlite3_column_text( stmt, 0 );
919 sqlite3_finalize( stmt ); sqlite3_close( db );
928 if ( openResult != SQLITE_OK )
931 return transformString;
935 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 );
936 int prepareRes = sqlite3_prepare( db, sql.
toAscii(), sql.
size(), &stmt, NULL );
937 if ( prepareRes != SQLITE_OK )
939 sqlite3_finalize( stmt ); sqlite3_close( db );
940 return transformString;
943 if ( sqlite3_step( stmt ) == SQLITE_ROW )
946 int methodCode = sqlite3_column_int( stmt, 0 );
947 if ( methodCode == 9615 )
949 transformString =
"+nadgrids=" +
QString((
const char * )sqlite3_column_text( stmt, 1 ) );
951 else if ( methodCode == 9603 || methodCode == 9606 || methodCode == 9607 )
953 transformString +=
"+towgs84=";
954 double p1 = sqlite3_column_double( stmt, 1 );
955 double p2 = sqlite3_column_double( stmt, 2 );
956 double p3 = sqlite3_column_double( stmt, 3 );
957 double p4 = sqlite3_column_double( stmt, 4 );
958 double p5 = sqlite3_column_double( stmt, 5 );
959 double p6 = sqlite3_column_double( stmt, 6 );
960 double p7 = sqlite3_column_double( stmt, 7 );
961 if ( methodCode == 9603 )
972 sqlite3_finalize( stmt ); sqlite3_close( db );
973 return transformString;
980 if ( openResult != SQLITE_OK )
987 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 );
988 int prepareRes = sqlite3_prepare( db, sql.
toAscii(), sql.
size(), &stmt, NULL );
989 if ( prepareRes != SQLITE_OK )
991 sqlite3_finalize( stmt ); sqlite3_close( db );
995 int srcCrsId, destCrsId;
996 if ( sqlite3_step( stmt ) != SQLITE_ROW )
998 sqlite3_finalize( stmt );
1003 epsgNr = sqlite3_column_int( stmt, 0 );
1004 srcCrsId = sqlite3_column_int( stmt, 1 );
1005 destCrsId = sqlite3_column_int( stmt, 2 );
1008 preferred = sqlite3_column_int( stmt, 5 ) != 0;
1009 deprecated = sqlite3_column_int( stmt, 6 ) != 0;
1018 sqlite3_finalize( stmt );
1019 sqlite3_close( db );
1023 void QgsCoordinateTransform::addNullGridShifts(
QString& srcProjString,
QString& destProjString )
1026 if ( mDestinationDatumTransform == -1 && srcProjString.
contains(
"+nadgrids" ) )
1028 destProjString +=
" +nadgrids=@null";
1031 if ( mSourceDatumTransform == -1 && destProjString.
contains(
"+nadgrids" ) )
1033 srcProjString +=
" +nadgrids=@null";
1039 if ( mSourceCRS.
authid().
compare(
"EPSG:3857", Qt::CaseInsensitive ) == 0 && mSourceDatumTransform == -1 )
1041 srcProjString +=
" +nadgrids=@null";
1043 if ( mDestCRS.
authid().
compare(
"EPSG:3857", Qt::CaseInsensitive ) == 0 && mDestinationDatumTransform == -1 )
1045 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)
Set up this srs using a Wkt spatial ref sys definition.
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)
TransformDirection
Enum used to indicate the direction (forward or inverse) of the transform.
QString tr(const char *sourceText, const char *disambiguation, int n)
double x() const
Get the x value of the point.
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)
Set up this srs by fetching the appropriate information from the sqlite backend.
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
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)
A class to represent a point.
QDomNode namedItem(const QString &name) const
bool contains(QChar ch, Qt::CaseSensitivity cs) const
bool isValid() const
Find out whether this CRS is correctly initialised and usable.
const T & at(int i) const
bool writeXML(QDomNode &theNode, QDomDocument &theDoc) const
Stores state to the given Dom node in the given document.
Class for storing a coordinate reference system (CRS)
QString authid() const
Get the authority identifier for this srs.
double y() const
Get the y value of the point.
bool readXML(QDomNode &theNode)
Restores state from the given Dom node.
static QString srsDbFilePath()
Returns the path to the srs.db file.
QString description() const
Get the Description.
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