LCOV - code coverage report
Current view: top level - core - qgscoordinatereferencesystem_p.h (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 75 88 85.2 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :                              qgscoordinatereferencesystem_p.h
       3                 :            : 
       4                 :            :                              --------------------------------
       5                 :            :     begin                : 2016
       6                 :            :     copyright            : (C) 2016 by Nyall Dawson
       7                 :            :     email                : nyall dot dawson at gmail dot com
       8                 :            : ***************************************************************************/
       9                 :            : 
      10                 :            : /***************************************************************************
      11                 :            :  *                                                                         *
      12                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      13                 :            :  *   it under the terms of the GNU General Public License as published by  *
      14                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      15                 :            :  *   (at your option) any later version.                                   *
      16                 :            :  *                                                                         *
      17                 :            :  ***************************************************************************/
      18                 :            : #ifndef QGSCOORDINATEREFERENCESYSTEM_PRIVATE_H
      19                 :            : #define QGSCOORDINATEREFERENCESYSTEM_PRIVATE_H
      20                 :            : 
      21                 :            : /// @cond PRIVATE
      22                 :            : 
      23                 :            : //
      24                 :            : //  W A R N I N G
      25                 :            : //  -------------
      26                 :            : //
      27                 :            : // This file is not part of the QGIS API.  It exists purely as an
      28                 :            : // implementation detail.  This header file may change from version to
      29                 :            : // version without notice, or even be removed.
      30                 :            : //
      31                 :            : 
      32                 :            : #include "qgscoordinatereferencesystem.h"
      33                 :            : 
      34                 :            : #include <proj.h>
      35                 :            : #include "qgsprojutils.h"
      36                 :            : #include "qgsreadwritelocker.h"
      37                 :            : 
      38                 :            : #ifdef DEBUG
      39                 :            : typedef struct OGRSpatialReferenceHS *OGRSpatialReferenceH;
      40                 :            : #else
      41                 :            : typedef void *OGRSpatialReferenceH;
      42                 :            : #endif
      43                 :            : 
      44                 :            : class QgsCoordinateReferenceSystemPrivate : public QSharedData
      45                 :            : {
      46                 :            :   public:
      47                 :            : 
      48                 :         58 :     explicit QgsCoordinateReferenceSystemPrivate()
      49                 :         58 :     {
      50                 :         58 :     }
      51                 :            : 
      52                 :          5 :     QgsCoordinateReferenceSystemPrivate( const QgsCoordinateReferenceSystemPrivate &other )
      53                 :          5 :       : QSharedData( other )
      54                 :          5 :       , mSrsId( other.mSrsId )
      55                 :          5 :       , mDescription( other.mDescription )
      56                 :          5 :       , mProjectionAcronym( other.mProjectionAcronym )
      57                 :          5 :       , mEllipsoidAcronym( other.mEllipsoidAcronym )
      58                 :          5 :       , mIsGeographic( other.mIsGeographic )
      59                 :          5 :       , mMapUnits( other.mMapUnits )
      60                 :          5 :       , mSRID( other.mSRID )
      61                 :          5 :       , mAuthId( other.mAuthId )
      62                 :          5 :       , mIsValid( other.mIsValid )
      63                 :          5 :       , mPj()
      64                 :          5 :       , mProj4( other.mProj4 )
      65                 :          5 :       , mWktPreferred( other.mWktPreferred )
      66                 :          5 :       , mAxisInvertedDirty( other.mAxisInvertedDirty )
      67                 :          5 :       , mAxisInverted( other.mAxisInverted )
      68                 :          5 :       , mProjObjects()
      69                 :          5 :     {
      70                 :          5 :     }
      71                 :            : 
      72                 :         57 :     ~QgsCoordinateReferenceSystemPrivate()
      73                 :            :     {
      74                 :         57 :       QgsReadWriteLocker locker( mProjLock, QgsReadWriteLocker::Read );
      75                 :         57 :       if ( !mProjObjects.empty() || mPj )
      76                 :            :       {
      77                 :          8 :         locker.changeMode( QgsReadWriteLocker::Write );
      78                 :          8 :         cleanPjObjects();
      79                 :          8 :       }
      80                 :         57 :     }
      81                 :            : 
      82                 :            :     //! The internal sqlite3 srs.db primary key for this CRS
      83                 :         58 :     long mSrsId = 0;
      84                 :            : 
      85                 :            :     //! A textual description of the CRS
      86                 :            :     QString mDescription;
      87                 :            : 
      88                 :            :     //! The official proj4 acronym for the projection family
      89                 :            :     QString mProjectionAcronym;
      90                 :            : 
      91                 :            :     //! The official proj4 acronym for the ellipsoid
      92                 :            :     QString mEllipsoidAcronym;
      93                 :            : 
      94                 :            :     //! Whether this is a geographic or projected coordinate system
      95                 :         58 :     bool mIsGeographic = false;
      96                 :            : 
      97                 :            :     //! The map units for the CRS
      98                 :         58 :     QgsUnitTypes::DistanceUnit mMapUnits = QgsUnitTypes::DistanceUnknownUnit;
      99                 :            : 
     100                 :            :     //! If available, the PostGIS spatial_ref_sys identifier for this CRS (defaults to 0)
     101                 :         58 :     long mSRID = 0;
     102                 :            : 
     103                 :            :     //! If available the authority identifier for this CRS
     104                 :            :     QString mAuthId;
     105                 :            : 
     106                 :            :     //! Whether this CRS is properly defined and valid
     107                 :         58 :     bool mIsValid = false;
     108                 :            : 
     109                 :            :     // this is the "master" proj object, to be used as a template for new proj objects created on different threads ONLY.
     110                 :            :     // Always use threadLocalProjObject() instead of this.
     111                 :            : 
     112                 :            :   private:
     113                 :            :     QgsProjUtils::proj_pj_unique_ptr mPj;
     114                 :         63 :     PJ_CONTEXT *mPjParentContext = nullptr;
     115                 :            : 
     116                 :         19 :     void cleanPjObjects()
     117                 :            :     {
     118                 :            : 
     119                 :            :       // During destruction of PJ* objects, the errno is set in the underlying
     120                 :            :       // context. Consequently the context attached to the PJ* must still exist !
     121                 :            :       // Which is not necessarily the case currently unfortunately. So
     122                 :            :       // create a temporary dummy context, and attach it to the PJ* before destroying
     123                 :            :       // it
     124                 :         19 :       PJ_CONTEXT *tmpContext = proj_context_create();
     125                 :         28 :       for ( auto it = mProjObjects.begin(); it != mProjObjects.end(); ++it )
     126                 :            :       {
     127                 :          9 :         proj_assign_context( it.value(), tmpContext );
     128                 :          9 :         proj_destroy( it.value() );
     129                 :          9 :       }
     130                 :         19 :       mProjObjects.clear();
     131                 :         19 :       if ( mPj )
     132                 :            :       {
     133                 :          9 :         proj_assign_context( mPj.get(), tmpContext );
     134                 :          9 :         mPj.reset();
     135                 :          9 :       }
     136                 :         19 :       proj_context_destroy( tmpContext );
     137                 :         19 :     }
     138                 :            : 
     139                 :            :   public:
     140                 :            : 
     141                 :         11 :     void setPj( QgsProjUtils::proj_pj_unique_ptr obj )
     142                 :            :     {
     143                 :         11 :       QgsReadWriteLocker locker( mProjLock, QgsReadWriteLocker::Write );
     144                 :         11 :       cleanPjObjects();
     145                 :            : 
     146                 :         11 :       mPj = std::move( obj );
     147                 :         11 :       mPjParentContext = QgsProjContext::get();
     148                 :         11 :     }
     149                 :            : 
     150                 :         12 :     bool hasPj() const
     151                 :            :     {
     152                 :         12 :       QgsReadWriteLocker locker( mProjLock, QgsReadWriteLocker::Read );
     153                 :         12 :       return static_cast< bool >( mPj );
     154                 :         12 :     }
     155                 :            : 
     156                 :            :     mutable QString mProj4;
     157                 :            : 
     158                 :            :     mutable QString mWktPreferred;
     159                 :            : 
     160                 :            :     //! True if presence of an inverted axis needs to be recalculated
     161                 :         58 :     mutable bool mAxisInvertedDirty = false;
     162                 :            : 
     163                 :            :     //! Whether this is a coordinate system has inverted axis
     164                 :         58 :     mutable bool mAxisInverted = false;
     165                 :            : 
     166                 :            :   private:
     167                 :         63 :     mutable QReadWriteLock mProjLock{};
     168                 :         58 :     mutable QMap < PJ_CONTEXT *, PJ * > mProjObjects{};
     169                 :            : 
     170                 :            :   public:
     171                 :            : 
     172                 :         18 :     PJ *threadLocalProjObject() const
     173                 :            :     {
     174                 :         18 :       QgsReadWriteLocker locker( mProjLock, QgsReadWriteLocker::Read );
     175                 :         18 :       if ( !mPj )
     176                 :          2 :         return nullptr;
     177                 :            : 
     178                 :         16 :       PJ_CONTEXT *context = QgsProjContext::get();
     179                 :         16 :       QMap < PJ_CONTEXT *, PJ * >::const_iterator it = mProjObjects.constFind( context );
     180                 :            : 
     181                 :         16 :       if ( it != mProjObjects.constEnd() )
     182                 :            :       {
     183                 :          5 :         return it.value();
     184                 :            :       }
     185                 :            : 
     186                 :            :       // proj object doesn't exist yet, so we need to create
     187                 :         11 :       locker.changeMode( QgsReadWriteLocker::Write );
     188                 :            : 
     189                 :         11 :       PJ *res = proj_clone( context, mPj.get() );
     190                 :         11 :       mProjObjects.insert( context, res );
     191                 :         11 :       return res;
     192                 :         18 :     }
     193                 :            : 
     194                 :            :     // Only meant to be called by QgsCoordinateReferenceSystem::removeFromCacheObjectsBelongingToCurrentThread()
     195                 :          0 :     bool removeObjectsBelongingToCurrentThread( PJ_CONTEXT *pj_context )
     196                 :            :     {
     197                 :          0 :       QgsReadWriteLocker locker( mProjLock, QgsReadWriteLocker::Write );
     198                 :            : 
     199                 :          0 :       QMap < PJ_CONTEXT *, PJ * >::iterator it = mProjObjects.find( pj_context );
     200                 :          0 :       if ( it != mProjObjects.end() )
     201                 :            :       {
     202                 :          0 :         proj_destroy( it.value() );
     203                 :          0 :         mProjObjects.erase( it );
     204                 :          0 :       }
     205                 :            : 
     206                 :          0 :       if ( mPjParentContext == pj_context )
     207                 :            :       {
     208                 :          0 :         mPj.reset();
     209                 :          0 :         mPjParentContext = nullptr;
     210                 :          0 :       }
     211                 :            : 
     212                 :          0 :       return mProjObjects.isEmpty();
     213                 :          0 :     }
     214                 :            : 
     215                 :            :   private:
     216                 :            :     QgsCoordinateReferenceSystemPrivate &operator= ( const QgsCoordinateReferenceSystemPrivate & ) = delete;
     217                 :            : 
     218                 :            : };
     219                 :            : 
     220                 :            : /// @endcond
     221                 :            : 
     222                 :            : #endif //QGSCOORDINATEREFERENCESYSTEM_PRIVATE_H

Generated by: LCOV version 1.14