LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/generic - ogrwarpedlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 189 244 77.5 %
Date: 2024-11-21 22:18:42 Functions: 22 26 84.6 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  OpenGIS Simple Features Reference Implementation
       4             :  * Purpose:  Implements OGRWarpedLayer class
       5             :  * Author:   Even Rouault, even dot rouault at spatialys.com
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2012-2014, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #ifndef DOXYGEN_SKIP
      14             : 
      15             : #include <cmath>
      16             : 
      17             : #include "ogrwarpedlayer.h"
      18             : 
      19             : /************************************************************************/
      20             : /*                          OGRWarpedLayer()                            */
      21             : /************************************************************************/
      22             : 
      23          17 : OGRWarpedLayer::OGRWarpedLayer(OGRLayer *poDecoratedLayer, int iGeomField,
      24             :                                int bTakeOwnership,
      25             :                                OGRCoordinateTransformation *poCT,
      26          17 :                                OGRCoordinateTransformation *poReversedCT)
      27             :     : OGRLayerDecorator(poDecoratedLayer, bTakeOwnership),
      28             :       m_poFeatureDefn(nullptr), m_iGeomField(iGeomField), m_poCT(poCT),
      29             :       m_poReversedCT(poReversedCT),
      30          17 :       m_poSRS(const_cast<OGRSpatialReference *>(m_poCT->GetTargetCS()))
      31             : {
      32          17 :     CPLAssert(poCT != nullptr);
      33          17 :     SetDescription(poDecoratedLayer->GetDescription());
      34             : 
      35          17 :     if (m_poSRS != nullptr)
      36             :     {
      37          17 :         m_poSRS->Reference();
      38             :     }
      39          17 : }
      40             : 
      41             : /************************************************************************/
      42             : /*                         ~OGRWarpedLayer()                            */
      43             : /************************************************************************/
      44             : 
      45          34 : OGRWarpedLayer::~OGRWarpedLayer()
      46             : {
      47          17 :     if (m_poFeatureDefn != nullptr)
      48          14 :         m_poFeatureDefn->Release();
      49          17 :     if (m_poSRS != nullptr)
      50          17 :         m_poSRS->Release();
      51          17 :     delete m_poCT;
      52          17 :     delete m_poReversedCT;
      53          34 : }
      54             : 
      55             : /************************************************************************/
      56             : /*                         SetSpatialFilter()                           */
      57             : /************************************************************************/
      58             : 
      59          15 : void OGRWarpedLayer::SetSpatialFilter(OGRGeometry *poGeom)
      60             : {
      61          15 :     SetSpatialFilter(0, poGeom);
      62          15 : }
      63             : 
      64             : /************************************************************************/
      65             : /*                          SetSpatialFilterRect()                      */
      66             : /************************************************************************/
      67             : 
      68           1 : void OGRWarpedLayer::SetSpatialFilterRect(double dfMinX, double dfMinY,
      69             :                                           double dfMaxX, double dfMaxY)
      70             : {
      71           1 :     OGRLayer::SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX, dfMaxY);
      72           1 : }
      73             : 
      74             : /************************************************************************/
      75             : /*                         SetSpatialFilter()                           */
      76             : /************************************************************************/
      77             : 
      78         221 : void OGRWarpedLayer::SetSpatialFilter(int iGeomField, OGRGeometry *poGeom)
      79             : {
      80         221 :     if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount())
      81             :     {
      82           2 :         CPLError(CE_Failure, CPLE_AppDefined,
      83             :                  "Invalid geometry field index : %d", iGeomField);
      84           2 :         return;
      85             :     }
      86             : 
      87         219 :     m_iGeomFieldFilter = iGeomField;
      88         219 :     if (InstallFilter(poGeom))
      89          99 :         ResetReading();
      90             : 
      91         219 :     if (m_iGeomFieldFilter == m_iGeomField)
      92             :     {
      93          63 :         if (poGeom == nullptr || m_poReversedCT == nullptr)
      94             :         {
      95          19 :             m_poDecoratedLayer->SetSpatialFilter(m_iGeomFieldFilter, nullptr);
      96             :         }
      97             :         else
      98             :         {
      99          44 :             OGREnvelope sEnvelope;
     100          44 :             poGeom->getEnvelope(&sEnvelope);
     101          54 :             if (std::isinf(sEnvelope.MinX) && std::isinf(sEnvelope.MinY) &&
     102          54 :                 std::isinf(sEnvelope.MaxX) && std::isinf(sEnvelope.MaxY))
     103             :             {
     104           5 :                 m_poDecoratedLayer->SetSpatialFilterRect(
     105             :                     m_iGeomFieldFilter, sEnvelope.MinX, sEnvelope.MinY,
     106           5 :                     sEnvelope.MaxX, sEnvelope.MaxY);
     107             :             }
     108          39 :             else if (ReprojectEnvelope(&sEnvelope, m_poReversedCT))
     109             :             {
     110          39 :                 m_poDecoratedLayer->SetSpatialFilterRect(
     111             :                     m_iGeomFieldFilter, sEnvelope.MinX, sEnvelope.MinY,
     112          39 :                     sEnvelope.MaxX, sEnvelope.MaxY);
     113             :             }
     114             :             else
     115             :             {
     116           0 :                 m_poDecoratedLayer->SetSpatialFilter(m_iGeomFieldFilter,
     117           0 :                                                      nullptr);
     118             :             }
     119             :         }
     120             :     }
     121             :     else
     122             :     {
     123         156 :         m_poDecoratedLayer->SetSpatialFilter(m_iGeomFieldFilter, poGeom);
     124             :     }
     125             : }
     126             : 
     127             : /************************************************************************/
     128             : /*                        SetSpatialFilterRect()                        */
     129             : /************************************************************************/
     130             : 
     131           1 : void OGRWarpedLayer::SetSpatialFilterRect(int iGeomField, double dfMinX,
     132             :                                           double dfMinY, double dfMaxX,
     133             :                                           double dfMaxY)
     134             : {
     135           1 :     OGRLayer::SetSpatialFilterRect(iGeomField, dfMinX, dfMinY, dfMaxX, dfMaxY);
     136           1 : }
     137             : 
     138             : /************************************************************************/
     139             : /*                     SrcFeatureToWarpedFeature()                      */
     140             : /************************************************************************/
     141             : 
     142             : std::unique_ptr<OGRFeature>
     143         398 : OGRWarpedLayer::SrcFeatureToWarpedFeature(std::unique_ptr<OGRFeature> poFeature)
     144             : {
     145             :     // This is safe to do here as they have matching attribute and geometry
     146             :     // fields
     147         398 :     poFeature->SetFDefnUnsafe(GetLayerDefn());
     148             : 
     149         398 :     OGRGeometry *poGeom = poFeature->GetGeomFieldRef(m_iGeomField);
     150         398 :     if (poGeom && poGeom->transform(m_poCT) != OGRERR_NONE)
     151             :     {
     152           2 :         delete poFeature->StealGeometry(m_iGeomField);
     153             :     }
     154             : 
     155         398 :     return poFeature;
     156             : }
     157             : 
     158             : /************************************************************************/
     159             : /*                     WarpedFeatureToSrcFeature()                      */
     160             : /************************************************************************/
     161             : 
     162             : std::unique_ptr<OGRFeature>
     163           9 : OGRWarpedLayer::WarpedFeatureToSrcFeature(std::unique_ptr<OGRFeature> poFeature)
     164             : {
     165             :     // This is safe to do here as they have matching attribute and geometry
     166             :     // fields
     167           9 :     poFeature->SetFDefnUnsafe(m_poDecoratedLayer->GetLayerDefn());
     168             : 
     169           9 :     OGRGeometry *poGeom = poFeature->GetGeomFieldRef(m_iGeomField);
     170          16 :     if (poGeom &&
     171           7 :         (!m_poReversedCT || poGeom->transform(m_poReversedCT) != OGRERR_NONE))
     172             :     {
     173           2 :         return nullptr;
     174             :     }
     175             : 
     176           7 :     return poFeature;
     177             : }
     178             : 
     179             : /************************************************************************/
     180             : /*                          GetNextFeature()                            */
     181             : /************************************************************************/
     182             : 
     183         487 : OGRFeature *OGRWarpedLayer::GetNextFeature()
     184             : {
     185             :     while (true)
     186             :     {
     187             :         auto poFeature =
     188         487 :             std::unique_ptr<OGRFeature>(m_poDecoratedLayer->GetNextFeature());
     189         487 :         if (!poFeature)
     190          95 :             return nullptr;
     191             : 
     192         392 :         auto poFeatureNew = SrcFeatureToWarpedFeature(std::move(poFeature));
     193         392 :         const OGRGeometry *poGeom = poFeatureNew->GetGeomFieldRef(m_iGeomField);
     194         392 :         if (m_poFilterGeom != nullptr && !FilterGeometry(poGeom))
     195             :         {
     196           0 :             continue;
     197             :         }
     198             : 
     199         392 :         return poFeatureNew.release();
     200           0 :     }
     201             : }
     202             : 
     203             : /************************************************************************/
     204             : /*                             GetFeature()                             */
     205             : /************************************************************************/
     206             : 
     207           9 : OGRFeature *OGRWarpedLayer::GetFeature(GIntBig nFID)
     208             : {
     209             :     auto poFeature =
     210          18 :         std::unique_ptr<OGRFeature>(m_poDecoratedLayer->GetFeature(nFID));
     211           9 :     if (poFeature)
     212             :     {
     213           6 :         poFeature = SrcFeatureToWarpedFeature(std::move(poFeature));
     214             :     }
     215          18 :     return poFeature.release();
     216             : }
     217             : 
     218             : /************************************************************************/
     219             : /*                             ISetFeature()                             */
     220             : /************************************************************************/
     221             : 
     222           5 : OGRErr OGRWarpedLayer::ISetFeature(OGRFeature *poFeature)
     223             : {
     224             :     auto poFeatureNew = WarpedFeatureToSrcFeature(
     225          10 :         std::unique_ptr<OGRFeature>(poFeature->Clone()));
     226           5 :     if (!poFeatureNew)
     227           1 :         return OGRERR_FAILURE;
     228             : 
     229           4 :     return m_poDecoratedLayer->SetFeature(poFeatureNew.get());
     230             : }
     231             : 
     232             : /************************************************************************/
     233             : /*                            ICreateFeature()                           */
     234             : /************************************************************************/
     235             : 
     236           4 : OGRErr OGRWarpedLayer::ICreateFeature(OGRFeature *poFeature)
     237             : {
     238             :     auto poFeatureNew = WarpedFeatureToSrcFeature(
     239           8 :         std::unique_ptr<OGRFeature>(poFeature->Clone()));
     240           4 :     if (!poFeatureNew)
     241           1 :         return OGRERR_FAILURE;
     242             : 
     243           3 :     return m_poDecoratedLayer->CreateFeature(poFeatureNew.get());
     244             : }
     245             : 
     246             : /************************************************************************/
     247             : /*                            IUpsertFeature()                          */
     248             : /************************************************************************/
     249             : 
     250           0 : OGRErr OGRWarpedLayer::IUpsertFeature(OGRFeature *poFeature)
     251             : {
     252             :     auto poFeatureNew = WarpedFeatureToSrcFeature(
     253           0 :         std::unique_ptr<OGRFeature>(poFeature->Clone()));
     254           0 :     if (poFeatureNew == nullptr)
     255           0 :         return OGRERR_FAILURE;
     256             : 
     257           0 :     return m_poDecoratedLayer->UpsertFeature(poFeatureNew.get());
     258             : }
     259             : 
     260             : /************************************************************************/
     261             : /*                            IUpdateFeature()                          */
     262             : /************************************************************************/
     263             : 
     264           0 : OGRErr OGRWarpedLayer::IUpdateFeature(OGRFeature *poFeature,
     265             :                                       int nUpdatedFieldsCount,
     266             :                                       const int *panUpdatedFieldsIdx,
     267             :                                       int nUpdatedGeomFieldsCount,
     268             :                                       const int *panUpdatedGeomFieldsIdx,
     269             :                                       bool bUpdateStyleString)
     270             : {
     271             :     auto poFeatureNew = WarpedFeatureToSrcFeature(
     272           0 :         std::unique_ptr<OGRFeature>(poFeature->Clone()));
     273           0 :     if (!poFeatureNew)
     274           0 :         return OGRERR_FAILURE;
     275             : 
     276           0 :     return m_poDecoratedLayer->UpdateFeature(
     277             :         poFeatureNew.get(), nUpdatedFieldsCount, panUpdatedFieldsIdx,
     278           0 :         nUpdatedGeomFieldsCount, panUpdatedGeomFieldsIdx, bUpdateStyleString);
     279             : }
     280             : 
     281             : /************************************************************************/
     282             : /*                            GetLayerDefn()                           */
     283             : /************************************************************************/
     284             : 
     285        1100 : OGRFeatureDefn *OGRWarpedLayer::GetLayerDefn()
     286             : {
     287        1100 :     if (m_poFeatureDefn != nullptr)
     288        1086 :         return m_poFeatureDefn;
     289             : 
     290          14 :     m_poFeatureDefn = m_poDecoratedLayer->GetLayerDefn()->Clone();
     291          14 :     m_poFeatureDefn->Reference();
     292          14 :     if (m_poFeatureDefn->GetGeomFieldCount() > 0)
     293          14 :         m_poFeatureDefn->GetGeomFieldDefn(m_iGeomField)->SetSpatialRef(m_poSRS);
     294             : 
     295          14 :     return m_poFeatureDefn;
     296             : }
     297             : 
     298             : /************************************************************************/
     299             : /*                            GetSpatialRef()                           */
     300             : /************************************************************************/
     301             : 
     302           5 : OGRSpatialReference *OGRWarpedLayer::GetSpatialRef()
     303             : {
     304           5 :     if (m_iGeomField == 0)
     305           5 :         return m_poSRS;
     306             :     else
     307           0 :         return OGRLayer::GetSpatialRef();
     308             : }
     309             : 
     310             : /************************************************************************/
     311             : /*                           GetFeatureCount()                          */
     312             : /************************************************************************/
     313             : 
     314          45 : GIntBig OGRWarpedLayer::GetFeatureCount(int bForce)
     315             : {
     316          45 :     if (m_poFilterGeom == nullptr)
     317          25 :         return m_poDecoratedLayer->GetFeatureCount(bForce);
     318             : 
     319          20 :     return OGRLayer::GetFeatureCount(bForce);
     320             : }
     321             : 
     322             : /************************************************************************/
     323             : /*                              GetExtent()                             */
     324             : /************************************************************************/
     325             : 
     326           3 : OGRErr OGRWarpedLayer::GetExtent(OGREnvelope *psExtent, int bForce)
     327             : {
     328           3 :     return GetExtent(0, psExtent, bForce);
     329             : }
     330             : 
     331             : /************************************************************************/
     332             : /*                              GetExtent()                             */
     333             : /************************************************************************/
     334             : 
     335          13 : OGRErr OGRWarpedLayer::GetExtent(int iGeomField, OGREnvelope *psExtent,
     336             :                                  int bForce)
     337             : {
     338          13 :     if (iGeomField == m_iGeomField)
     339             :     {
     340           7 :         if (sStaticEnvelope.IsInit())
     341             :         {
     342           1 :             *psExtent = sStaticEnvelope;
     343           1 :             return OGRERR_NONE;
     344             :         }
     345             : 
     346           6 :         OGREnvelope sExtent;
     347             :         OGRErr eErr =
     348           6 :             m_poDecoratedLayer->GetExtent(m_iGeomField, &sExtent, bForce);
     349           6 :         if (eErr != OGRERR_NONE)
     350           0 :             return eErr;
     351             : 
     352           6 :         if (ReprojectEnvelope(&sExtent, m_poCT))
     353             :         {
     354           6 :             *psExtent = sExtent;
     355           6 :             return OGRERR_NONE;
     356             :         }
     357             :         else
     358           0 :             return OGRERR_FAILURE;
     359             :     }
     360             :     else
     361           6 :         return m_poDecoratedLayer->GetExtent(iGeomField, psExtent, bForce);
     362             : }
     363             : 
     364             : /************************************************************************/
     365             : /*                    TransformAndUpdateBBAndReturnX()                  */
     366             : /************************************************************************/
     367             : 
     368           0 : static double TransformAndUpdateBBAndReturnX(OGRCoordinateTransformation *poCT,
     369             :                                              double dfX, double dfY,
     370             :                                              double &dfMinX, double &dfMinY,
     371             :                                              double &dfMaxX, double &dfMaxY)
     372             : {
     373           0 :     int bSuccess = FALSE;
     374           0 :     poCT->Transform(1, &dfX, &dfY, nullptr, nullptr, &bSuccess);
     375           0 :     if (bSuccess)
     376             :     {
     377           0 :         if (dfX < dfMinX)
     378           0 :             dfMinX = dfX;
     379           0 :         if (dfY < dfMinY)
     380           0 :             dfMinY = dfY;
     381           0 :         if (dfX > dfMaxX)
     382           0 :             dfMaxX = dfX;
     383           0 :         if (dfY > dfMaxY)
     384           0 :             dfMaxY = dfY;
     385           0 :         return dfX;
     386             :     }
     387             : 
     388           0 :     return 0.0;
     389             : }
     390             : 
     391             : /************************************************************************/
     392             : /*                            FindXDiscontinuity()                      */
     393             : /************************************************************************/
     394             : 
     395           0 : static void FindXDiscontinuity(OGRCoordinateTransformation *poCT, double dfX1,
     396             :                                double dfX2, double dfY, double &dfMinX,
     397             :                                double &dfMinY, double &dfMaxX, double &dfMaxY,
     398             :                                int nRecLevel = 0)
     399             : {
     400           0 :     double dfXMid = (dfX1 + dfX2) / 2;
     401             : 
     402           0 :     double dfWrkX1 = TransformAndUpdateBBAndReturnX(poCT, dfX1, dfY, dfMinX,
     403             :                                                     dfMinY, dfMaxX, dfMaxY);
     404           0 :     double dfWrkXMid = TransformAndUpdateBBAndReturnX(poCT, dfXMid, dfY, dfMinX,
     405             :                                                       dfMinY, dfMaxX, dfMaxY);
     406           0 :     double dfWrkX2 = TransformAndUpdateBBAndReturnX(poCT, dfX2, dfY, dfMinX,
     407             :                                                     dfMinY, dfMaxX, dfMaxY);
     408             : 
     409           0 :     double dfDX1 = dfWrkXMid - dfWrkX1;
     410           0 :     double dfDX2 = dfWrkX2 - dfWrkXMid;
     411             : 
     412           0 :     if (dfDX1 * dfDX2 < 0 && nRecLevel < 30)
     413             :     {
     414           0 :         FindXDiscontinuity(poCT, dfX1, dfXMid, dfY, dfMinX, dfMinY, dfMaxX,
     415             :                            dfMaxY, nRecLevel + 1);
     416           0 :         FindXDiscontinuity(poCT, dfXMid, dfX2, dfY, dfMinX, dfMinY, dfMaxX,
     417             :                            dfMaxY, nRecLevel + 1);
     418             :     }
     419           0 : }
     420             : 
     421             : /************************************************************************/
     422             : /*                            ReprojectEnvelope()                       */
     423             : /************************************************************************/
     424             : 
     425          45 : int OGRWarpedLayer::ReprojectEnvelope(OGREnvelope *psEnvelope,
     426             :                                       OGRCoordinateTransformation *poCT)
     427             : {
     428          45 :     const int NSTEP = 20;
     429          45 :     double dfXStep = (psEnvelope->MaxX - psEnvelope->MinX) / NSTEP;
     430          45 :     double dfYStep = (psEnvelope->MaxY - psEnvelope->MinY) / NSTEP;
     431             : 
     432             :     double *padfX = static_cast<double *>(
     433          45 :         VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(double)));
     434             :     double *padfY = static_cast<double *>(
     435          45 :         VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(double)));
     436             :     int *pabSuccess = static_cast<int *>(
     437          45 :         VSI_MALLOC_VERBOSE((NSTEP + 1) * (NSTEP + 1) * sizeof(int)));
     438          45 :     if (padfX == nullptr || padfY == nullptr || pabSuccess == nullptr)
     439             :     {
     440           0 :         VSIFree(padfX);
     441           0 :         VSIFree(padfY);
     442           0 :         VSIFree(pabSuccess);
     443           0 :         return FALSE;
     444             :     }
     445             : 
     446         990 :     for (int j = 0; j <= NSTEP; j++)
     447             :     {
     448       20790 :         for (int i = 0; i <= NSTEP; i++)
     449             :         {
     450       19845 :             padfX[j * (NSTEP + 1) + i] = psEnvelope->MinX + i * dfXStep;
     451       19845 :             padfY[j * (NSTEP + 1) + i] = psEnvelope->MinY + j * dfYStep;
     452             :         }
     453             :     }
     454             : 
     455          45 :     int bRet = FALSE;
     456             : 
     457          90 :     if (poCT->Transform((NSTEP + 1) * (NSTEP + 1), padfX, padfY, nullptr,
     458          45 :                         nullptr, pabSuccess))
     459             :     {
     460          45 :         double dfMinX = 0.0;
     461          45 :         double dfMinY = 0.0;
     462          45 :         double dfMaxX = 0.0;
     463          45 :         double dfMaxY = 0.0;
     464          45 :         int bSet = FALSE;
     465         990 :         for (int j = 0; j <= NSTEP; j++)
     466             :         {
     467         945 :             double dfXOld = 0.0;
     468         945 :             double dfDXOld = 0.0;
     469         945 :             int iOld = -1;
     470         945 :             int iOldOld = -1;
     471       20790 :             for (int i = 0; i <= NSTEP; i++)
     472             :             {
     473       19845 :                 if (pabSuccess[j * (NSTEP + 1) + i])
     474             :                 {
     475       17665 :                     double dfX = padfX[j * (NSTEP + 1) + i];
     476       17665 :                     double dfY = padfY[j * (NSTEP + 1) + i];
     477             : 
     478       17665 :                     if (!bSet)
     479             :                     {
     480          45 :                         dfMinX = dfX;
     481          45 :                         dfMaxX = dfX;
     482          45 :                         dfMinY = dfY;
     483          45 :                         dfMaxY = dfY;
     484          45 :                         bSet = TRUE;
     485             :                     }
     486             :                     else
     487             :                     {
     488       17620 :                         if (dfX < dfMinX)
     489         124 :                             dfMinX = dfX;
     490       17620 :                         if (dfY < dfMinY)
     491          81 :                             dfMinY = dfY;
     492       17620 :                         if (dfX > dfMaxX)
     493         890 :                             dfMaxX = dfX;
     494       17620 :                         if (dfY > dfMaxY)
     495        3393 :                             dfMaxY = dfY;
     496             :                     }
     497             : 
     498       17665 :                     if (iOld >= 0)
     499             :                     {
     500       16800 :                         double dfDXNew = dfX - dfXOld;
     501       16800 :                         if (iOldOld >= 0 && dfDXNew * dfDXOld < 0)
     502             :                         {
     503           0 :                             FindXDiscontinuity(
     504           0 :                                 poCT, psEnvelope->MinX + iOldOld * dfXStep,
     505           0 :                                 psEnvelope->MinX + i * dfXStep,
     506           0 :                                 psEnvelope->MinY + j * dfYStep, dfMinX, dfMinY,
     507             :                                 dfMaxX, dfMaxY);
     508             :                         }
     509       16800 :                         dfDXOld = dfDXNew;
     510             :                     }
     511             : 
     512       17665 :                     dfXOld = dfX;
     513       17665 :                     iOldOld = iOld;
     514       17665 :                     iOld = i;
     515             :                 }
     516             :             }
     517             :         }
     518          45 :         if (bSet)
     519             :         {
     520          45 :             psEnvelope->MinX = dfMinX;
     521          45 :             psEnvelope->MinY = dfMinY;
     522          45 :             psEnvelope->MaxX = dfMaxX;
     523          45 :             psEnvelope->MaxY = dfMaxY;
     524          45 :             bRet = TRUE;
     525             :         }
     526             :     }
     527             : 
     528          45 :     VSIFree(padfX);
     529          45 :     VSIFree(padfY);
     530          45 :     VSIFree(pabSuccess);
     531             : 
     532          45 :     return bRet;
     533             : }
     534             : 
     535             : /************************************************************************/
     536             : /*                             TestCapability()                         */
     537             : /************************************************************************/
     538             : 
     539         174 : int OGRWarpedLayer::TestCapability(const char *pszCapability)
     540             : {
     541         174 :     if (EQUAL(pszCapability, OLCFastGetExtent) && sStaticEnvelope.IsInit())
     542           0 :         return TRUE;
     543             : 
     544         174 :     int bVal = m_poDecoratedLayer->TestCapability(pszCapability);
     545             : 
     546         174 :     if (EQUAL(pszCapability, OLCFastGetArrowStream))
     547           1 :         return false;
     548             : 
     549         173 :     if (EQUAL(pszCapability, OLCFastSpatialFilter) ||
     550         173 :         EQUAL(pszCapability, OLCRandomWrite) ||
     551         172 :         EQUAL(pszCapability, OLCSequentialWrite))
     552             :     {
     553           2 :         if (bVal)
     554           0 :             bVal = m_poReversedCT != nullptr;
     555             :     }
     556         171 :     else if (EQUAL(pszCapability, OLCFastFeatureCount))
     557             :     {
     558           0 :         if (bVal)
     559           0 :             bVal = m_poFilterGeom == nullptr;
     560             :     }
     561             : 
     562         173 :     return bVal;
     563             : }
     564             : 
     565             : /************************************************************************/
     566             : /*                              SetExtent()                             */
     567             : /************************************************************************/
     568             : 
     569           1 : void OGRWarpedLayer::SetExtent(double dfXMin, double dfYMin, double dfXMax,
     570             :                                double dfYMax)
     571             : {
     572           1 :     sStaticEnvelope.MinX = dfXMin;
     573           1 :     sStaticEnvelope.MinY = dfYMin;
     574           1 :     sStaticEnvelope.MaxX = dfXMax;
     575           1 :     sStaticEnvelope.MaxY = dfYMax;
     576           1 : }
     577             : 
     578             : /************************************************************************/
     579             : /*                            GetArrowStream()                          */
     580             : /************************************************************************/
     581             : 
     582           7 : bool OGRWarpedLayer::GetArrowStream(struct ArrowArrayStream *out_stream,
     583             :                                     CSLConstList papszOptions)
     584             : {
     585           7 :     return OGRLayer::GetArrowStream(out_stream, papszOptions);
     586             : }
     587             : 
     588             : #endif /* #ifndef DOXYGEN_SKIP */

Generated by: LCOV version 1.14