29 #include <QDomElement> 30 #include <QApplication> 32 #include <QStringList> 44 QReadWriteLock QgsCoordinateTransform::sCacheLock;
49 d =
new QgsCoordinateTransformPrivate();
56 if ( !d->checkValidity() )
59 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
69 d =
new QgsCoordinateTransformPrivate( source, destination, mContext );
74 if ( !d->checkValidity() )
77 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
87 d =
new QgsCoordinateTransformPrivate( source, destination, mContext );
93 if ( !d->checkValidity() )
96 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
105 d =
new QgsCoordinateTransformPrivate( source, destination, sourceDatumTransform, destinationDatumTransform );
110 if ( !d->checkValidity() )
113 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
121 : mContext( o.mContext )
123 , mHasContext( o.mHasContext )
133 mHasContext = o.mHasContext;
135 mContext = o.mContext;
145 if ( !d->checkValidity() )
148 d->calculateTransforms( mContext );
149 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
159 if ( !d->checkValidity() )
162 d->calculateTransforms( mContext );
163 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
177 if ( !d->checkValidity() )
180 d->calculateTransforms( mContext );
181 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
190 return d->mSourceCRS;
200 if ( !d->mIsValid || d->mShortCircuit )
204 double x = point.
x();
205 double y = point.
y();
238 if ( !d->mIsValid || d->mShortCircuit )
262 #ifdef COORDINATE_TRANSFORM_VERBOSE 275 if ( !d->mIsValid || d->mShortCircuit )
296 double xd =
static_cast< double >( x ), yd = static_cast< double >( y );
305 if ( !d->mIsValid || d->mShortCircuit )
331 if ( !d->mIsValid || d->mShortCircuit )
337 int nVertices = poly.size();
339 QVector<double> x( nVertices );
340 QVector<double> y( nVertices );
341 QVector<double> z( nVertices );
342 double *destX = x.data();
343 double *destY = y.data();
344 double *destZ = z.data();
346 const QPointF *polyData = poly.constData();
347 for (
int i = 0; i < nVertices; ++i )
349 *destX++ = polyData->x();
350 *destY++ = polyData->y();
366 QPointF *destPoint = poly.data();
367 const double *srcX = x.constData();
368 const double *srcY = y.constData();
369 for (
int i = 0; i < nVertices; ++i )
371 destPoint->rx() = *srcX++;
372 destPoint->ry() = *srcY++;
378 QVector<double> &x, QVector<double> &y, QVector<double> &z,
382 if ( !d->mIsValid || d->mShortCircuit )
385 Q_ASSERT( x.size() == y.size() );
406 QVector<float> &x, QVector<float> &y, QVector<float> &z,
409 if ( !d->mIsValid || d->mShortCircuit )
412 Q_ASSERT( x.size() == y.size() );
422 int vectorSize = x.size();
423 QVector<double> xd( x.size() );
424 QVector<double> yd( y.size() );
425 QVector<double> zd( z.size() );
427 double *destX = xd.data();
428 double *destY = yd.data();
429 double *destZ = zd.data();
431 const float *srcX = x.constData();
432 const float *srcY = y.constData();
433 const float *srcZ = z.constData();
435 for (
int i = 0; i < vectorSize; ++i )
437 *destX++ =
static_cast< double >( *srcX++ );
438 *destY++ =
static_cast< double >( *srcY++ );
439 *destZ++ =
static_cast< double >( *srcZ++ );
445 float *destFX = x.data();
446 float *destFY = y.data();
447 float *destFZ = z.data();
448 const double *srcXD = xd.constData();
449 const double *srcYD = yd.constData();
450 const double *srcZD = zd.constData();
451 for (
int i = 0; i < vectorSize; ++i )
453 *destFX++ =
static_cast< float >( *srcXD++ );
454 *destFY++ =
static_cast< float >( *srcYD++ );
455 *destFZ++ =
static_cast< float >( *srcZD++ );
473 if ( !d->mIsValid || d->mShortCircuit )
486 const int nPoints = 1000;
487 double d = std::sqrt( ( rect.
width() * rect.
height() ) / std::pow( std::sqrt( static_cast< double >( nPoints ) ) - 1, 2.0 ) );
488 int nXPoints =
static_cast< int >( std::ceil( rect.
width() / d ) ) + 1;
489 int nYPoints =
static_cast< int >( std::ceil( rect.
height() / d ) ) + 1;
497 QVector<double> x( nXPoints * nYPoints );
498 QVector<double> y( nXPoints * nYPoints );
499 QVector<double> z( nXPoints * nYPoints );
505 double dx = rect.
width() /
static_cast< double >( nXPoints - 1 );
506 double dy = rect.
height() /
static_cast< double >( nYPoints - 1 );
510 for (
int i = 0; i < nYPoints ; i++ )
516 for (
int j = 0; j < nXPoints; j++ )
518 x[( i * nXPoints ) + j] = pointX;
519 y[( i * nXPoints ) + j] = pointY;
521 z[( i * nXPoints ) + j] = 0.0;
532 transformCoords( nXPoints * nYPoints, x.data(), y.data(), z.data(), direction );
543 for (
int i = 0; i < nXPoints * nYPoints; i++ )
545 if ( !std::isfinite( x[i] ) || !std::isfinite( y[i] ) )
550 if ( handle180Crossover )
564 throw QgsCsException( QObject::tr(
"Could not transform bounding box to target CRS" ) );
567 if ( handle180Crossover )
588 if ( !d->mIsValid || d->mShortCircuit )
591 if ( !d->mSourceCRS.isValid() )
594 "The coordinates can not be reprojected. The CRS is: %1" )
595 .arg( d->mSourceCRS.toProj4() ), QObject::tr(
"CRS" ) );
598 if ( !d->mDestCRS.isValid() )
601 "The coordinates can not be reprojected. The CRS is: %1" ).arg( d->mDestCRS.toProj4() ), QObject::tr(
"CRS" ) );
605 #ifdef COORDINATE_TRANSFORM_VERBOSE 608 QgsDebugMsg( QString(
"[[[[[[ Number of points to transform: %1 ]]]]]]" ).arg( numPoints ) );
613 qWarning(
"No QgsCoordinateTransformContext context set for transform" );
620 QPair<projPJ, projPJ> projData = d->threadLocalProjData();
621 projPJ sourceProj = projData.first;
622 projPJ destProj = projData.second;
627 for (
int i = 0; i < numPoints; ++i )
637 projResult = pj_transform( destProj, sourceProj, numPoints, 0, x, y, z );
641 Q_ASSERT( sourceProj );
642 Q_ASSERT( destProj );
643 projResult = pj_transform( sourceProj, destProj, numPoints, 0, x, y, z );
646 if ( projResult != 0 )
651 for (
int i = 0; i < numPoints; ++i )
655 points += QStringLiteral(
"(%1, %2)\n" ).arg( x[i], 0,
'f' ).arg( y[i], 0,
'f' );
659 points += QStringLiteral(
"(%1, %2)\n" ).arg( x[i] * RAD_TO_DEG, 0,
'f' ).arg( y[i] * RAD_TO_DEG, 0,
'f' );
663 QString dir = ( direction ==
ForwardTransform ) ? QObject::tr(
"forward transform" ) : QObject::tr(
"inverse transform" );
665 char *srcdef = pj_get_def( sourceProj, 0 );
666 char *dstdef = pj_get_def( destProj, 0 );
668 QString msg = QObject::tr(
"%1 of\n" 675 QString::fromUtf8( pj_strerrno( projResult ) ) );
680 QgsDebugMsg(
"Projection failed emitting invalid transform signal: " + msg );
691 for (
int i = 0; i < numPoints; ++i )
697 #ifdef COORDINATE_TRANSFORM_VERBOSE 698 QgsDebugMsg( QString(
"[[[[[[ Projected %1, %2 to %3, %4 ]]]]]]" )
699 .arg( xorg, 0,
'g', 15 ).arg( yorg, 0,
'g', 15 )
700 .arg( *x, 0,
'g', 15 ).arg( *y, 0,
'g', 15 ) );
711 return !d->mIsValid || d->mShortCircuit;
718 proj = QApplication::applicationDirPath()
719 +
"/share/proj/" + QString( name );
723 return proj.toUtf8();
731 sCacheLock.lockForRead();
732 const QList< QgsCoordinateTransform > values = sTransforms.values( qMakePair( src.
authid(), dest.
authid() ) );
733 for (
auto valIt = values.constBegin(); valIt != values.constEnd(); ++valIt )
735 if ( ( *valIt ).sourceDatumTransformId() == srcDatumTransform &&
736 ( *valIt ).destinationDatumTransformId() == destDatumTransform )
741 bool hasContext = mHasContext;
748 mHasContext = hasContext;
758 void QgsCoordinateTransform::addToCache()
760 if ( !d->mSourceCRS.isValid() || !d->mDestCRS.isValid() )
763 sCacheLock.lockForWrite();
764 sTransforms.insertMulti( qMakePair( d->mSourceCRS.authid(), d->mDestCRS.authid() ), *
this );
770 return d->mSourceDatumTransform;
776 d->mSourceDatumTransform = dt;
781 return d->mDestinationDatumTransform;
787 d->mDestinationDatumTransform = dt;
792 sCacheLock.lockForWrite();
A rectangle specified with double values.
void setMinimal()
Set a rectangle so that min corner is at max and max corner is at min.
void setXMaximum(double x)
Set the maximum x value.
A class to represent a 2D point.
QgsCoordinateTransformContext transformContext() const
Returns a copy of the project's coordinate transform context, which stores various information regard...
#define QgsDebugMsgLevel(str, level)
bool isEmpty() const
Returns true if the rectangle is empty.
double width() const
Returns the width of the rectangle.
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
QString toString(int precision=16) const
Returns a string representation of form xmin,ymin : xmax,ymax Coordinates will be truncated to the sp...
Reads and writes project states.
Contains information about the context in which a coordinate transform is executed.
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
void combineExtentWith(const QgsRectangle &rect)
Expands the rectangle so that it covers both the original rectangle and the given rectangle...
This class represents a coordinate reference system (CRS).
bool isNull() const
Test if the rectangle is null (all coordinates zero or after call to setMinimal()).
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Custom exception class for Coordinate Reference System related exceptions.
QString authid() const
Returns the authority identifier for the CRS.
void setXMinimum(double x)
Set the minimum x value.
double height() const
Returns the height of the rectangle.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.