29 #include <QDomElement> 30 #include <QApplication> 32 #include <QStringList> 37 #ifndef ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 38 #define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H 47 QReadWriteLock QgsCoordinateTransform::sCacheLock;
52 d =
new QgsCoordinateTransformPrivate();
59 if ( !d->checkValidity() )
62 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
72 d =
new QgsCoordinateTransformPrivate( source, destination, mContext );
77 if ( !d->checkValidity() )
80 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
90 d =
new QgsCoordinateTransformPrivate( source, destination, mContext );
96 if ( !d->checkValidity() )
99 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
108 d =
new QgsCoordinateTransformPrivate( source, destination, sourceDatumTransform, destinationDatumTransform );
113 if ( !d->checkValidity() )
116 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
124 : mContext( o.mContext )
126 , mHasContext( o.mHasContext )
136 mHasContext = o.mHasContext;
138 mContext = o.mContext;
148 if ( !d->checkValidity() )
151 d->calculateTransforms( mContext );
152 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
162 if ( !d->checkValidity() )
165 d->calculateTransforms( mContext );
166 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
180 if ( !d->checkValidity() )
183 d->calculateTransforms( mContext );
184 if ( !setFromCache( d->mSourceCRS, d->mDestCRS, d->mSourceDatumTransform, d->mDestinationDatumTransform ) )
198 return d->mSourceCRS;
208 if ( !d->mIsValid || d->mShortCircuit )
212 double x = point.
x();
213 double y = point.
y();
222 QgsDebugMsg( QStringLiteral(
"rethrowing exception" ) );
239 QgsDebugMsg( QStringLiteral(
"rethrowing exception" ) );
246 if ( !d->mIsValid || d->mShortCircuit )
266 QgsDebugMsg( QStringLiteral(
"rethrowing exception" ) );
270 #ifdef COORDINATE_TRANSFORM_VERBOSE 271 QgsDebugMsg( QStringLiteral(
"Rect projection..." ) );
283 if ( !d->mIsValid || d->mShortCircuit )
296 QgsDebugMsg( QStringLiteral(
"rethrowing exception" ) );
304 double xd =
static_cast< double >( x ), yd = static_cast< double >( y );
313 if ( !d->mIsValid || d->mShortCircuit )
332 QgsDebugMsg( QStringLiteral(
"rethrowing exception" ) );
339 if ( !d->mIsValid || d->mShortCircuit )
345 int nVertices = poly.size();
347 QVector<double> x( nVertices );
348 QVector<double> y( nVertices );
349 QVector<double> z( nVertices );
350 double *destX = x.data();
351 double *destY = y.data();
352 double *destZ = z.data();
354 const QPointF *polyData = poly.constData();
355 for (
int i = 0; i < nVertices; ++i )
357 *destX++ = polyData->x();
358 *destY++ = polyData->y();
370 QgsDebugMsg( QStringLiteral(
"rethrowing exception" ) );
374 QPointF *destPoint = poly.data();
375 const double *srcX = x.constData();
376 const double *srcY = y.constData();
377 for (
int i = 0; i < nVertices; ++i )
379 destPoint->rx() = *srcX++;
380 destPoint->ry() = *srcY++;
386 QVector<double> &x, QVector<double> &y, QVector<double> &z,
390 if ( !d->mIsValid || d->mShortCircuit )
393 Q_ASSERT( x.size() == y.size() );
407 QgsDebugMsg( QStringLiteral(
"rethrowing exception" ) );
414 QVector<float> &x, QVector<float> &y, QVector<float> &z,
417 if ( !d->mIsValid || d->mShortCircuit )
420 Q_ASSERT( x.size() == y.size() );
430 int vectorSize = x.size();
431 QVector<double> xd( x.size() );
432 QVector<double> yd( y.size() );
433 QVector<double> zd( z.size() );
435 double *destX = xd.data();
436 double *destY = yd.data();
437 double *destZ = zd.data();
439 const float *srcX = x.constData();
440 const float *srcY = y.constData();
441 const float *srcZ = z.constData();
443 for (
int i = 0; i < vectorSize; ++i )
445 *destX++ =
static_cast< double >( *srcX++ );
446 *destY++ =
static_cast< double >( *srcY++ );
447 *destZ++ =
static_cast< double >( *srcZ++ );
453 float *destFX = x.data();
454 float *destFY = y.data();
455 float *destFZ = z.data();
456 const double *srcXD = xd.constData();
457 const double *srcYD = yd.constData();
458 const double *srcZD = zd.constData();
459 for (
int i = 0; i < vectorSize; ++i )
461 *destFX++ =
static_cast< float >( *srcXD++ );
462 *destFY++ =
static_cast< float >( *srcYD++ );
463 *destFZ++ =
static_cast< float >( *srcZD++ );
469 QgsDebugMsg( QStringLiteral(
"rethrowing exception" ) );
481 if ( !d->mIsValid || d->mShortCircuit )
494 const int nPoints = 1000;
495 double d = std::sqrt( ( rect.
width() * rect.
height() ) / std::pow( std::sqrt( static_cast< double >( nPoints ) ) - 1, 2.0 ) );
496 int nXPoints =
static_cast< int >( std::ceil( rect.
width() / d ) ) + 1;
497 int nYPoints =
static_cast< int >( std::ceil( rect.
height() / d ) ) + 1;
505 QVector<double> x( nXPoints * nYPoints );
506 QVector<double> y( nXPoints * nYPoints );
507 QVector<double> z( nXPoints * nYPoints );
509 QgsDebugMsgLevel( QStringLiteral(
"Entering transformBoundingBox..." ), 4 );
513 double dx = rect.
width() /
static_cast< double >( nXPoints - 1 );
514 double dy = rect.
height() /
static_cast< double >( nYPoints - 1 );
518 for (
int i = 0; i < nYPoints ; i++ )
524 for (
int j = 0; j < nXPoints; j++ )
526 x[( i * nXPoints ) + j] = pointX;
527 y[( i * nXPoints ) + j] = pointY;
529 z[( i * nXPoints ) + j] = 0.0;
540 transformCoords( nXPoints * nYPoints, x.data(), y.data(), z.data(), direction );
545 QgsDebugMsg( QStringLiteral(
"rethrowing exception" ) );
551 for (
int i = 0; i < nXPoints * nYPoints; i++ )
553 if ( !std::isfinite( x[i] ) || !std::isfinite( y[i] ) )
558 if ( handle180Crossover )
572 throw QgsCsException( QObject::tr(
"Could not transform bounding box to target CRS" ) );
575 if ( handle180Crossover )
596 if ( !d->mIsValid || d->mShortCircuit )
599 if ( !d->mSourceCRS.isValid() )
602 "The coordinates can not be reprojected. The CRS is: %1" )
603 .arg( d->mSourceCRS.toProj4() ), QObject::tr(
"CRS" ) );
606 if ( !d->mDestCRS.isValid() )
609 "The coordinates can not be reprojected. The CRS is: %1" ).arg( d->mDestCRS.toProj4() ), QObject::tr(
"CRS" ) );
613 #ifdef COORDINATE_TRANSFORM_VERBOSE 616 QgsDebugMsg( QStringLiteral(
"[[[[[[ Number of points to transform: %1 ]]]]]]" ).arg( numPoints ) );
621 QgsDebugMsgLevel( QStringLiteral(
"No QgsCoordinateTransformContext context set for transform" ), 4 );
628 QPair<projPJ, projPJ> projData = d->threadLocalProjData();
629 projPJ sourceProj = projData.first;
630 projPJ destProj = projData.second;
635 for (
int i = 0; i < numPoints; ++i )
645 projResult = pj_transform( destProj, sourceProj, numPoints, 0, x, y, z );
649 Q_ASSERT( sourceProj );
650 Q_ASSERT( destProj );
651 projResult = pj_transform( sourceProj, destProj, numPoints, 0, x, y, z );
654 if ( projResult != 0 )
659 for (
int i = 0; i < numPoints; ++i )
663 points += QStringLiteral(
"(%1, %2)\n" ).arg( x[i], 0,
'f' ).arg( y[i], 0,
'f' );
667 points += QStringLiteral(
"(%1, %2)\n" ).arg( x[i] * RAD_TO_DEG, 0,
'f' ).arg( y[i] * RAD_TO_DEG, 0,
'f' );
671 QString dir = ( direction ==
ForwardTransform ) ? QObject::tr(
"forward transform" ) : QObject::tr(
"inverse transform" );
673 char *srcdef = pj_get_def( sourceProj, 0 );
674 char *dstdef = pj_get_def( destProj, 0 );
676 QString msg = QObject::tr(
"%1 of\n" 683 QString::fromUtf8( pj_strerrno( projResult ) ) );
688 QgsDebugMsg(
"Projection failed emitting invalid transform signal: " + msg );
689 QgsDebugMsg( QStringLiteral(
"throwing exception" ) );
699 for (
int i = 0; i < numPoints; ++i )
705 #ifdef COORDINATE_TRANSFORM_VERBOSE 706 QgsDebugMsg( QStringLiteral(
"[[[[[[ Projected %1, %2 to %3, %4 ]]]]]]" )
707 .arg( xorg, 0,
'g', 15 ).arg( yorg, 0,
'g', 15 )
708 .arg( *x, 0,
'g', 15 ).arg( *y, 0,
'g', 15 ) );
719 return !d->mIsValid || d->mShortCircuit;
726 proj = QApplication::applicationDirPath()
727 +
"/share/proj/" + QString( name );
731 return proj.toUtf8();
739 sCacheLock.lockForRead();
740 const QList< QgsCoordinateTransform > values = sTransforms.values( qMakePair( src.
authid(), dest.
authid() ) );
741 for (
auto valIt = values.constBegin(); valIt != values.constEnd(); ++valIt )
743 if ( ( *valIt ).sourceDatumTransformId() == srcDatumTransform &&
744 ( *valIt ).destinationDatumTransformId() == destDatumTransform )
749 bool hasContext = mHasContext;
756 mHasContext = hasContext;
766 void QgsCoordinateTransform::addToCache()
768 if ( !d->mSourceCRS.isValid() || !d->mDestCRS.isValid() )
771 sCacheLock.lockForWrite();
772 sTransforms.insertMulti( qMakePair( d->mSourceCRS.authid(), d->mDestCRS.authid() ), *
this );
778 return d->mSourceDatumTransform;
784 d->mSourceDatumTransform = dt;
789 return d->mDestinationDatumTransform;
795 d->mDestinationDatumTransform = dt;
800 sCacheLock.lockForWrite();
809 double distSourceUnits = std::sqrt( source1.sqrDist( source2 ) );
812 double distDestUnits = std::sqrt( dest1.sqrDist( dest2 ) );
813 return distDestUnits / distSourceUnits;
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.
const QgsCoordinateReferenceSystem & crs
#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).
QgsCoordinateTransformContext transformContext
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.