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

Generated by: LCOV version 1.14