Coverage Report

Created: 2026-07-25 06:50

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