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 );
186 QString sourceProjString = mSourceCRS.
toProj4();
187 if ( !useDefaultDatumTransform )
189 sourceProjString = stripDatumTransform( sourceProjString );
191 if ( mSourceDatumTransform != -1 )
196 pj_free( mDestinationProjection );
197 QString destProjString = mDestCRS.
toProj4();
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();
382 QVector<double> x( nVertices );
383 QVector<double> y( nVertices );
384 QVector<double> z( nVertices );
386 for (
int i = 0; i < nVertices; ++i )
388 const QPointF& pt = poly.at( i );
405 for (
int i = 0; i < nVertices; ++i )
407 QPointF& pt = poly[i];
414 QVector<double>& x, QVector<double>& y, QVector<double>& z,
417 if ( mShortCircuit || !mInitialisedFlag )
420 Q_ASSERT( x.size() == y.size() );
441 TransformDirection direction )
const
443 double xd = ( double ) x, yd = (
double ) y;
452 TransformDirection direction )
const
454 if ( mShortCircuit || !mInitialisedFlag )
479 QVector<float>& x, QVector<float>& y, QVector<float>& z,
480 TransformDirection direction )
const
482 if ( mShortCircuit || !mInitialisedFlag )
485 Q_ASSERT( x.size() == y.size() );
495 int vectorSize = x.size();
496 QVector<double> xd( x.size() );
497 QVector<double> yd( y.size() );
498 QVector<double> zd( z.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 );
704 QString msg =
tr(
"%1 of\n"
706 "PROJ.4: %3 +to %4\n"
710 .arg( srcdef ).arg( dstdef )
711 .arg( QString::fromUtf8( pj_strerrno( projResult ) ) );
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
738 QgsDebugMsg( QString(
"[[[[[[ Projected %1, %2 to %3, %4 ]]]]]]" )
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 ------------------------!" );
749 QDomNode mySrcNode = theNode.namedItem(
"sourcesrs" );
750 mSourceCRS.
readXML( mySrcNode );
752 QDomNode myDestNode = theNode.namedItem(
"destinationsrs" );
753 mDestCRS.
readXML( myDestNode );
755 mSourceDatumTransform = theNode.toElement().attribute(
"sourceDatumTransform",
"-1" ).toInt();
756 mDestinationDatumTransform = theNode.toElement().attribute(
"destinationDatumTransform",
"-1" ).toInt();
765 QDomElement myNodeElement = theNode.toElement();
766 QDomElement myTransformElement = theDoc.createElement(
"coordinatetransform" );
767 myTransformElement.setAttribute(
"sourceDatumTransform", QString::number( mSourceDatumTransform ) );
768 myTransformElement.setAttribute(
"destinationDatumTransform", QString::number( mDestinationDatumTransform ) );
770 QDomElement mySourceElement = theDoc.createElement(
"sourcesrs" );
771 mSourceCRS.
writeXML( mySourceElement, theDoc );
772 myTransformElement.appendChild( mySourceElement );
774 QDomElement myDestElement = theDoc.createElement(
"destinationsrs" );
775 mDestCRS.
writeXML( myDestElement, theDoc );
776 myTransformElement.appendChild( myDestElement );
778 myNodeElement.appendChild( myTransformElement );
787 proj = QApplication::applicationDirPath()
788 +
"/share/proj/" + QString( name );
792 return proj.toUtf8();
795 void QgsCoordinateTransform::setFinder()
813 QList< QList< int > > transformations;
818 if ( srcGeoId.isEmpty() || destGeoId.isEmpty() )
820 return transformations;
823 QStringList srcSplit = srcGeoId.split(
":" );
824 QStringList destSplit = destGeoId.split(
":" );
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;
839 QList<int> directTransforms;
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 ),
842 QList<int> reverseDirectTransforms;
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 );
845 QList<int> srcToWgs84;
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 ),
848 QList<int> destToWgs84;
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 ),
853 QList<int>::const_iterator directIt = directTransforms.constBegin();
854 for ( ; directIt != directTransforms.constEnd(); ++directIt )
856 transformations.push_back( QList<int>() << *directIt << -1 );
860 directIt = reverseDirectTransforms.constBegin();
861 for ( ; directIt != reverseDirectTransforms.constEnd(); ++directIt )
863 transformations.push_back( QList<int>() << -1 << *directIt );
866 QList<int>::const_iterator srcWgsIt = srcToWgs84.constBegin();
867 for ( ; srcWgsIt != srcToWgs84.constEnd(); ++srcWgsIt )
869 QList<int>::const_iterator dstWgsIt = destToWgs84.constBegin();
870 for ( ; dstWgsIt != destToWgs84.constEnd(); ++dstWgsIt )
872 transformations.push_back( QList<int>() << *srcWgsIt << *dstWgsIt );
876 return transformations;
879 QString QgsCoordinateTransform::stripDatumTransform(
const QString& proj4 )
881 QStringList parameterSplit = proj4.split(
"+", QString::SkipEmptyParts );
882 QString currentParameter;
883 QString newProjString;
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 );
921 transforms.push_back( cOpCode.toInt() );
923 sqlite3_finalize( stmt ); sqlite3_close( db );
928 QString transformString;
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 )
967 transformString += QString(
"%1,%2,%3" ).arg( p1 ).arg( p2 ).arg( p3 );
971 transformString += QString(
"%1,%2,%3,%4,%5,%6,%7" ).arg( p1 ).arg( p2 ).arg( p3 ).arg( p4 ).arg( p5 ).arg( p6 ).arg( p7 );
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 );
1010 remarks = QString::fromUtf8((
const char * ) sqlite3_column_text( stmt, 3 ) );
1011 scope = QString::fromUtf8((
const char * ) sqlite3_column_text( stmt, 4 ) );
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";