LCOV - code coverage report
Current view: top level - ogr/ogrsf_frmts/generic - ogrwarpedlayer.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 184 235 78.3 %
Date: 2025-02-20 10:14:44 Functions: 19 25 76.0 %

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

Generated by: LCOV version 1.14