Coverage Report

Created: 2026-09-14 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/gdal/ogr/ogrsf_frmts/generic/ogrlayer.cpp
Line
Count
Source
1
/******************************************************************************
2
 *
3
 * Project:  OpenGIS Simple Features Reference Implementation
4
 * Purpose:  The generic portions of the OGRSFLayer class.
5
 * Author:   Frank Warmerdam, warmerdam@pobox.com
6
 *
7
 ******************************************************************************
8
 * Copyright (c) 1999,  Les Technologies SoftMap Inc.
9
 * Copyright (c) 2008-2014, Even Rouault <even dot rouault at spatialys.com>
10
 *
11
 * SPDX-License-Identifier: MIT
12
 ****************************************************************************/
13
14
#include "ogrsf_frmts.h"
15
#include "ogr_api.h"
16
#include "ogr_p.h"
17
#include "ogr_attrind.h"
18
#include "ogr_swq.h"
19
#include "ograpispy.h"
20
#include "ogr_wkb.h"
21
#include "ogrlayer_private.h"
22
23
#include "cpl_time.h"
24
#include <cassert>
25
#include <cmath>
26
#include <limits>
27
#include <memory>
28
#include <set>
29
30
/************************************************************************/
31
/*                              OGRLayer()                              */
32
/************************************************************************/
33
34
OGRLayer::OGRLayer()
35
0
    : m_poPrivate(new Private()), m_bFilterIsEnvelope(FALSE),
36
0
      m_poFilterGeom(nullptr), m_pPreparedFilterGeom(nullptr),
37
0
      m_sFilterEnvelope{}, m_iGeomFieldFilter(0), m_poStyleTable(nullptr),
38
0
      m_poAttrQuery(nullptr), m_pszAttrQueryString(nullptr),
39
0
      m_poAttrIndex(nullptr), m_nRefCount(0), m_nFeaturesRead(0)
40
0
{
41
0
}
42
43
/************************************************************************/
44
/*                             ~OGRLayer()                              */
45
/************************************************************************/
46
47
OGRLayer::~OGRLayer()
48
49
0
{
50
0
    if (m_poStyleTable)
51
0
    {
52
0
        delete m_poStyleTable;
53
0
        m_poStyleTable = nullptr;
54
0
    }
55
56
0
    if (m_poAttrIndex != nullptr)
57
0
    {
58
0
        delete m_poAttrIndex;
59
0
        m_poAttrIndex = nullptr;
60
0
    }
61
62
0
    if (m_poAttrQuery != nullptr)
63
0
    {
64
0
        delete m_poAttrQuery;
65
0
        m_poAttrQuery = nullptr;
66
0
    }
67
68
0
    CPLFree(m_pszAttrQueryString);
69
70
0
    if (m_poFilterGeom)
71
0
    {
72
0
        delete m_poFilterGeom;
73
0
        m_poFilterGeom = nullptr;
74
0
    }
75
76
0
    if (m_pPreparedFilterGeom != nullptr)
77
0
    {
78
0
        OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
79
0
        m_pPreparedFilterGeom = nullptr;
80
0
    }
81
82
0
    if (m_poSharedArrowArrayStreamPrivateData != nullptr)
83
0
    {
84
0
        m_poSharedArrowArrayStreamPrivateData->m_poLayer = nullptr;
85
0
    }
86
0
}
87
88
/************************************************************************/
89
/*                             Reference()                              */
90
/************************************************************************/
91
92
/**
93
\brief Increment layer reference count.
94
95
This method is the same as the C function OGR_L_Reference().
96
97
@return the reference count after incrementing.
98
*/
99
int OGRLayer::Reference()
100
101
0
{
102
0
    return ++m_nRefCount;
103
0
}
104
105
/************************************************************************/
106
/*                          OGR_L_Reference()                           */
107
/************************************************************************/
108
109
int OGR_L_Reference(OGRLayerH hLayer)
110
111
0
{
112
0
    VALIDATE_POINTER1(hLayer, "OGR_L_Reference", 0);
113
114
0
    return OGRLayer::FromHandle(hLayer)->Reference();
115
0
}
116
117
/************************************************************************/
118
/*                            Dereference()                             */
119
/************************************************************************/
120
121
/**
122
\brief Decrement layer reference count.
123
124
This method is the same as the C function OGR_L_Dereference().
125
126
@return the reference count after decrementing.
127
*/
128
129
int OGRLayer::Dereference()
130
131
0
{
132
0
    return --m_nRefCount;
133
0
}
134
135
/************************************************************************/
136
/*                         OGR_L_Dereference()                          */
137
/************************************************************************/
138
139
int OGR_L_Dereference(OGRLayerH hLayer)
140
141
0
{
142
0
    VALIDATE_POINTER1(hLayer, "OGR_L_Dereference", 0);
143
144
0
    return OGRLayer::FromHandle(hLayer)->Dereference();
145
0
}
146
147
/************************************************************************/
148
/*                            GetRefCount()                             */
149
/************************************************************************/
150
151
/**
152
\brief Fetch reference count.
153
154
This method is the same as the C function OGR_L_GetRefCount().
155
156
@return the current reference count for the layer object itself.
157
*/
158
159
int OGRLayer::GetRefCount() const
160
161
0
{
162
0
    return m_nRefCount;
163
0
}
164
165
/************************************************************************/
166
/*                         OGR_L_GetRefCount()                          */
167
/************************************************************************/
168
169
int OGR_L_GetRefCount(OGRLayerH hLayer)
170
171
0
{
172
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetRefCount", 0);
173
174
0
    return OGRLayer::FromHandle(hLayer)->GetRefCount();
175
0
}
176
177
/************************************************************************/
178
/*                          GetFeatureCount()                           */
179
/************************************************************************/
180
181
/**
182
 \brief Fetch the feature count in this layer.
183
184
 Returns the number of features in the layer.  For dynamic databases the
185
 count may not be exact.  If bForce is FALSE, and it would be expensive
186
 to establish the feature count a value of -1 may be returned indicating
187
 that the count isn't know.  If bForce is TRUE some implementations will
188
 actually scan the entire layer once to count objects.
189
190
 The returned count takes the spatial filter into account.
191
192
 Note that some implementations of this method may alter the read cursor
193
 of the layer.
194
195
 This method is the same as the C function OGR_L_GetFeatureCount().
196
197
198
 @param bForce Flag indicating whether the count should be computed even
199
 if it is expensive.
200
201
 @return feature count, -1 if count not known.
202
*/
203
204
GIntBig OGRLayer::GetFeatureCount(int bForce)
205
206
0
{
207
0
    if (!bForce)
208
0
        return -1;
209
210
0
    GIntBig nFeatureCount = 0;
211
0
    for (auto &&poFeature : *this)
212
0
    {
213
0
        CPL_IGNORE_RET_VAL(poFeature.get());
214
0
        nFeatureCount++;
215
0
    }
216
0
    ResetReading();
217
218
0
    return nFeatureCount;
219
0
}
220
221
/************************************************************************/
222
/*                       OGR_L_GetFeatureCount()                        */
223
/************************************************************************/
224
225
/**
226
 \brief Fetch the feature count in this layer.
227
228
 Returns the number of features in the layer.  For dynamic databases the
229
 count may not be exact.  If bForce is FALSE, and it would be expensive
230
 to establish the feature count a value of -1 may be returned indicating
231
 that the count isn't know.  If bForce is TRUE some implementations will
232
 actually scan the entire layer once to count objects.
233
234
 The returned count takes the spatial filter into account.
235
236
 Note that some implementations of this method may alter the read cursor
237
 of the layer.
238
239
 This function is the same as the CPP OGRLayer::GetFeatureCount().
240
241
242
 @param hLayer handle to the layer that owned the features.
243
 @param bForce Flag indicating whether the count should be computed even
244
 if it is expensive.
245
246
 @return feature count, -1 if count not known.
247
*/
248
249
GIntBig OGR_L_GetFeatureCount(OGRLayerH hLayer, int bForce)
250
251
0
{
252
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetFeatureCount", 0);
253
254
0
#ifdef OGRAPISPY_ENABLED
255
0
    if (bOGRAPISpyEnabled)
256
0
        OGRAPISpy_L_GetFeatureCount(hLayer, bForce);
257
0
#endif
258
259
0
    return OGRLayer::FromHandle(hLayer)->GetFeatureCount(bForce);
260
0
}
261
262
/************************************************************************/
263
/*                             GetExtent()                              */
264
/************************************************************************/
265
266
/**
267
 \brief Fetch the extent of this layer.
268
269
 Returns the extent (MBR) of the data in the layer.  If bForce is FALSE,
270
 and it would be expensive to establish the extent then OGRERR_FAILURE
271
 will be returned indicating that the extent isn't know.  If bForce is
272
 TRUE then some implementations will actually scan the entire layer once
273
 to compute the MBR of all the features in the layer.
274
275
 Depending on the drivers, the returned extent may or may not take the
276
 spatial filter into account.  So it is safer to call GetExtent() without
277
 setting a spatial filter.
278
279
 Layers without any geometry may return OGRERR_FAILURE just indicating that
280
 no meaningful extents could be collected.
281
282
 Note that some implementations of this method may alter the read cursor
283
 of the layer.
284
285
 This method is the same as the C function OGR_L_GetExtent().
286
287
 @param psExtent the structure in which the extent value will be returned.
288
 @param bForce Flag indicating whether the extent should be computed even
289
 if it is expensive.
290
291
 @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known.
292
*/
293
294
OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, bool bForce)
295
0
{
296
0
    return GetExtent(0, psExtent, bForce);
297
0
}
298
299
/**
300
 \brief Fetch the extent of this layer, on the specified geometry field.
301
302
 Returns the extent (MBR) of the data in the layer.  If bForce is FALSE,
303
 and it would be expensive to establish the extent then OGRERR_FAILURE
304
 will be returned indicating that the extent isn't know.  If bForce is
305
 TRUE then some implementations will actually scan the entire layer once
306
 to compute the MBR of all the features in the layer.
307
308
 Depending on the drivers, the returned extent may or may not take the
309
 spatial filter into account.  So it is safer to call GetExtent() without
310
 setting a spatial filter.
311
312
 Layers without any geometry may return OGRERR_FAILURE just indicating that
313
 no meaningful extents could be collected.
314
315
 Note that some implementations of this method may alter the read cursor
316
 of the layer.
317
318
 This method is the same as the C function OGR_L_GetExtentEx().
319
320
 @param iGeomField the index of the geometry field on which to compute the extent.
321
 @param psExtent the structure in which the extent value will be returned.
322
 @param bForce Flag indicating whether the extent should be computed even
323
 if it is expensive.
324
325
 @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known.
326
327
*/
328
329
OGRErr OGRLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, bool bForce)
330
0
{
331
0
    psExtent->MinX = 0.0;
332
0
    psExtent->MaxX = 0.0;
333
0
    psExtent->MinY = 0.0;
334
0
    psExtent->MaxY = 0.0;
335
336
    /* -------------------------------------------------------------------- */
337
    /*      If this layer has a none geometry type, then we can             */
338
    /*      reasonably assume there are not extents available.              */
339
    /* -------------------------------------------------------------------- */
340
0
    if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
341
0
        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone)
342
0
    {
343
0
        if (iGeomField != 0)
344
0
        {
345
0
            CPLError(CE_Failure, CPLE_AppDefined,
346
0
                     "Invalid geometry field index : %d", iGeomField);
347
0
        }
348
0
        return OGRERR_FAILURE;
349
0
    }
350
351
0
    return IGetExtent(iGeomField, psExtent, bForce);
352
0
}
353
354
/************************************************************************/
355
/*                             IGetExtent()                             */
356
/************************************************************************/
357
358
/**
359
 \brief Fetch the extent of this layer, on the specified geometry field.
360
361
 Virtual method implemented by drivers since 3.11. In previous versions,
362
 GetExtent() itself was the virtual method.
363
364
 Driver implementations, when wanting to call the base method, must take
365
 care of calling OGRLayer::IGetExtent() (and note the public method without
366
 the leading I).
367
368
 @param iGeomField 0-based index of the geometry field to consider.
369
 @param psExtent the computed extent of the layer.
370
 @param bForce if TRUE, the extent will be computed even if all the
371
        layer features have to be fetched.
372
 @return OGRERR_NONE on success or an error code in case of failure.
373
 @since GDAL 3.11
374
*/
375
376
OGRErr OGRLayer::IGetExtent(int iGeomField, OGREnvelope *psExtent, bool bForce)
377
378
0
{
379
    /* -------------------------------------------------------------------- */
380
    /*      If not forced, we should avoid having to scan all the           */
381
    /*      features and just return a failure.                             */
382
    /* -------------------------------------------------------------------- */
383
0
    if (!bForce)
384
0
        return OGRERR_FAILURE;
385
386
    /* -------------------------------------------------------------------- */
387
    /*      OK, we hate to do this, but go ahead and read through all       */
388
    /*      the features to collect geometries and build extents.           */
389
    /* -------------------------------------------------------------------- */
390
0
    OGREnvelope oEnv;
391
0
    bool bExtentSet = false;
392
393
0
    for (auto &&poFeature : *this)
394
0
    {
395
0
        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeomField);
396
0
        if (poGeom == nullptr || poGeom->IsEmpty())
397
0
        {
398
            /* Do nothing */
399
0
        }
400
0
        else if (!bExtentSet)
401
0
        {
402
0
            poGeom->getEnvelope(psExtent);
403
0
            if (!(std::isnan(psExtent->MinX) || std::isnan(psExtent->MinY) ||
404
0
                  std::isnan(psExtent->MaxX) || std::isnan(psExtent->MaxY)))
405
0
            {
406
0
                bExtentSet = true;
407
0
            }
408
0
        }
409
0
        else
410
0
        {
411
0
            poGeom->getEnvelope(&oEnv);
412
0
            if (oEnv.MinX < psExtent->MinX)
413
0
                psExtent->MinX = oEnv.MinX;
414
0
            if (oEnv.MinY < psExtent->MinY)
415
0
                psExtent->MinY = oEnv.MinY;
416
0
            if (oEnv.MaxX > psExtent->MaxX)
417
0
                psExtent->MaxX = oEnv.MaxX;
418
0
            if (oEnv.MaxY > psExtent->MaxY)
419
0
                psExtent->MaxY = oEnv.MaxY;
420
0
        }
421
0
    }
422
0
    ResetReading();
423
424
0
    return bExtentSet ? OGRERR_NONE : OGRERR_FAILURE;
425
0
}
426
427
/************************************************************************/
428
/*                          OGR_L_GetExtent()                           */
429
/************************************************************************/
430
431
/**
432
 \brief Fetch the extent of this layer.
433
434
 Returns the extent (MBR) of the data in the layer.  If bForce is FALSE,
435
 and it would be expensive to establish the extent then OGRERR_FAILURE
436
 will be returned indicating that the extent isn't know.  If bForce is
437
 TRUE then some implementations will actually scan the entire layer once
438
 to compute the MBR of all the features in the layer.
439
440
 Depending on the drivers, the returned extent may or may not take the
441
 spatial filter into account.  So it is safer to call OGR_L_GetExtent() without
442
 setting a spatial filter.
443
444
 Layers without any geometry may return OGRERR_FAILURE just indicating that
445
 no meaningful extents could be collected.
446
447
 Note that some implementations of this method may alter the read cursor
448
 of the layer.
449
450
 This function is the same as the C++ method OGRLayer::GetExtent().
451
452
 @param hLayer handle to the layer from which to get extent.
453
 @param psExtent the structure in which the extent value will be returned.
454
 @param bForce Flag indicating whether the extent should be computed even
455
 if it is expensive.
456
457
 @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known.
458
459
*/
460
461
OGRErr OGR_L_GetExtent(OGRLayerH hLayer, OGREnvelope *psExtent, int bForce)
462
463
0
{
464
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetExtent", OGRERR_INVALID_HANDLE);
465
466
0
#ifdef OGRAPISPY_ENABLED
467
0
    if (bOGRAPISpyEnabled)
468
0
        OGRAPISpy_L_GetExtent(hLayer, bForce);
469
0
#endif
470
471
0
    return OGRLayer::FromHandle(hLayer)->GetExtent(0, psExtent,
472
0
                                                   bForce != FALSE);
473
0
}
474
475
/************************************************************************/
476
/*                         OGR_L_GetExtentEx()                          */
477
/************************************************************************/
478
479
/**
480
 \brief Fetch the extent of this layer, on the specified geometry field.
481
482
 Returns the extent (MBR) of the data in the layer.  If bForce is FALSE,
483
 and it would be expensive to establish the extent then OGRERR_FAILURE
484
 will be returned indicating that the extent isn't know.  If bForce is
485
 TRUE then some implementations will actually scan the entire layer once
486
 to compute the MBR of all the features in the layer.
487
488
 Depending on the drivers, the returned extent may or may not take the
489
 spatial filter into account.  So it is safer to call OGR_L_GetExtent() without
490
 setting a spatial filter.
491
492
 Layers without any geometry may return OGRERR_FAILURE just indicating that
493
 no meaningful extents could be collected.
494
495
 Note that some implementations of this method may alter the read cursor
496
 of the layer.
497
498
 This function is the same as the C++ method OGRLayer::GetExtent().
499
500
 @param hLayer handle to the layer from which to get extent.
501
 @param iGeomField the index of the geometry field on which to compute the extent.
502
 @param psExtent the structure in which the extent value will be returned.
503
 @param bForce Flag indicating whether the extent should be computed even
504
 if it is expensive.
505
506
 @return OGRERR_NONE on success, OGRERR_FAILURE if extent not known.
507
508
*/
509
OGRErr OGR_L_GetExtentEx(OGRLayerH hLayer, int iGeomField,
510
                         OGREnvelope *psExtent, int bForce)
511
512
0
{
513
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetExtentEx", OGRERR_INVALID_HANDLE);
514
515
0
#ifdef OGRAPISPY_ENABLED
516
0
    if (bOGRAPISpyEnabled)
517
0
        OGRAPISpy_L_GetExtentEx(hLayer, iGeomField, bForce);
518
0
#endif
519
520
0
    return OGRLayer::FromHandle(hLayer)->GetExtent(iGeomField, psExtent,
521
0
                                                   bForce != FALSE);
522
0
}
523
524
/************************************************************************/
525
/*                            GetExtent3D()                             */
526
/************************************************************************/
527
528
/**
529
 \brief Fetch the 3D extent of this layer, on the specified geometry field.
530
531
 Returns the 3D extent (MBR) of the data in the layer.  If bForce is FALSE,
532
 and it would be expensive to establish the extent then OGRERR_FAILURE
533
 will be returned indicating that the extent isn't know.  If bForce is
534
 TRUE then some implementations will actually scan the entire layer once
535
 to compute the MBR of all the features in the layer.
536
537
 (Contrary to GetExtent() 2D), the returned extent will always take into
538
 account the attribute and spatial filters that may be installed.
539
540
 Layers without any geometry may return OGRERR_FAILURE just indicating that
541
 no meaningful extents could be collected.
542
543
 For layers that have no 3D geometries, the psExtent3D->MinZ and psExtent3D->MaxZ
544
 fields will be respectively set to +Infinity and -Infinity.
545
546
 Note that some implementations of this method may alter the read cursor
547
 of the layer.
548
549
 This function is the same as the C function OGR_L_GetExtent3D().
550
551
 @param iGeomField 0-based index of the geometry field to consider.
552
 @param psExtent3D the computed 3D extent of the layer.
553
 @param bForce if TRUE, the extent will be computed even if all the
554
        layer features have to be fetched.
555
 @return OGRERR_NONE on success or an error code in case of failure.
556
 @since GDAL 3.9
557
*/
558
559
OGRErr OGRLayer::GetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
560
                             bool bForce)
561
562
0
{
563
0
    psExtent3D->MinX = 0.0;
564
0
    psExtent3D->MaxX = 0.0;
565
0
    psExtent3D->MinY = 0.0;
566
0
    psExtent3D->MaxY = 0.0;
567
0
    psExtent3D->MinZ = std::numeric_limits<double>::infinity();
568
0
    psExtent3D->MaxZ = -std::numeric_limits<double>::infinity();
569
570
    /* -------------------------------------------------------------------- */
571
    /*      If this layer has a none geometry type, then we can             */
572
    /*      reasonably assume there are not extents available.              */
573
    /* -------------------------------------------------------------------- */
574
0
    if (iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
575
0
        GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone)
576
0
    {
577
0
        if (iGeomField != 0)
578
0
        {
579
0
            CPLError(CE_Failure, CPLE_AppDefined,
580
0
                     "Invalid geometry field index : %d", iGeomField);
581
0
        }
582
0
        return OGRERR_FAILURE;
583
0
    }
584
585
0
    return IGetExtent3D(iGeomField, psExtent3D, bForce);
586
0
}
587
588
/************************************************************************/
589
/*                            IGetExtent3D()                            */
590
/************************************************************************/
591
592
/**
593
 \brief Fetch the 3D extent of this layer, on the specified geometry field.
594
595
 See GetExtent3D() documentation.
596
597
 Virtual method implemented by drivers since 3.11. In previous versions,
598
 GetExtent3D() itself was the virtual method.
599
600
 Driver implementations, when wanting to call the base method, must take
601
 care of calling OGRLayer::IGetExtent3D() (and note the public method without
602
 the leading I).
603
604
 @param iGeomField 0-based index of the geometry field to consider.
605
 @param psExtent3D the computed 3D extent of the layer.
606
 @param bForce if TRUE, the extent will be computed even if all the
607
        layer features have to be fetched.
608
 @return OGRERR_NONE on success or an error code in case of failure.
609
 @since GDAL 3.11
610
*/
611
612
OGRErr OGRLayer::IGetExtent3D(int iGeomField, OGREnvelope3D *psExtent3D,
613
                              bool bForce)
614
615
0
{
616
    /* -------------------------------------------------------------------- */
617
    /*      If not forced, we should avoid having to scan all the           */
618
    /*      features and just return a failure.                             */
619
    /* -------------------------------------------------------------------- */
620
0
    if (!bForce)
621
0
        return OGRERR_FAILURE;
622
623
    /* -------------------------------------------------------------------- */
624
    /*      OK, we hate to do this, but go ahead and read through all       */
625
    /*      the features to collect geometries and build extents.           */
626
    /* -------------------------------------------------------------------- */
627
0
    OGREnvelope3D oEnv;
628
0
    bool bExtentSet = false;
629
630
0
    for (auto &&poFeature : *this)
631
0
    {
632
0
        OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeomField);
633
0
        if (poGeom == nullptr || poGeom->IsEmpty())
634
0
        {
635
            /* Do nothing */
636
0
        }
637
0
        else if (!bExtentSet)
638
0
        {
639
0
            poGeom->getEnvelope(psExtent3D);
640
            // This is required because getEnvelope initializes Z to 0 for 2D geometries
641
0
            if (!poGeom->Is3D())
642
0
            {
643
0
                psExtent3D->MinZ = std::numeric_limits<double>::infinity();
644
0
                psExtent3D->MaxZ = -std::numeric_limits<double>::infinity();
645
0
            }
646
0
            bExtentSet = true;
647
0
        }
648
0
        else
649
0
        {
650
0
            poGeom->getEnvelope(&oEnv);
651
            // This is required because getEnvelope initializes Z to 0 for 2D geometries
652
0
            if (!poGeom->Is3D())
653
0
            {
654
0
                oEnv.MinZ = std::numeric_limits<double>::infinity();
655
0
                oEnv.MaxZ = -std::numeric_limits<double>::infinity();
656
0
            }
657
            // Merge handles infinity correctly
658
0
            psExtent3D->Merge(oEnv);
659
0
        }
660
0
    }
661
0
    ResetReading();
662
663
0
    return bExtentSet ? OGRERR_NONE : OGRERR_FAILURE;
664
0
}
665
666
/************************************************************************/
667
/*                         OGR_L_GetExtent3D()                          */
668
/************************************************************************/
669
670
/**
671
 \brief Fetch the 3D extent of this layer, on the specified geometry field.
672
673
 Returns the 3D extent (MBR) of the data in the layer.  If bForce is FALSE,
674
 and it would be expensive to establish the extent then OGRERR_FAILURE
675
 will be returned indicating that the extent isn't know.  If bForce is
676
 TRUE then some implementations will actually scan the entire layer once
677
 to compute the MBR of all the features in the layer.
678
679
 (Contrary to GetExtent() 2D), the returned extent will always take into
680
 account the attribute and spatial filters that may be installed.
681
682
 Layers without any geometry may return OGRERR_FAILURE just indicating that
683
 no meaningful extents could be collected.
684
685
 For layers that have no 3D geometries, the psExtent3D->MinZ and psExtent3D->MaxZ
686
 fields will be respectively set to +Infinity and -Infinity.
687
688
 Note that some implementations of this method may alter the read cursor
689
 of the layer.
690
691
 This function is the same as the C++ method OGRLayer::GetExtent3D().
692
693
 @param hLayer the layer to consider.
694
 @param iGeomField 0-based index of the geometry field to consider.
695
 @param psExtent3D the computed 3D extent of the layer.
696
 @param bForce if TRUE, the extent will be computed even if all the
697
        layer features have to be fetched.
698
 @return OGRERR_NONE on success or an error code in case of failure.
699
 @since GDAL 3.9
700
*/
701
702
OGRErr OGR_L_GetExtent3D(OGRLayerH hLayer, int iGeomField,
703
                         OGREnvelope3D *psExtent3D, int bForce)
704
705
0
{
706
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetExtent3D", OGRERR_INVALID_HANDLE);
707
708
0
#ifdef OGRAPISPY_ENABLED
709
0
    if (bOGRAPISpyEnabled)
710
0
        OGRAPISpy_L_GetExtent3D(hLayer, iGeomField, bForce);
711
0
#endif
712
713
0
    return OGRLayer::FromHandle(hLayer)->GetExtent3D(iGeomField, psExtent3D,
714
0
                                                     bForce != FALSE);
715
0
}
716
717
/************************************************************************/
718
/*                         SetAttributeFilter()                         */
719
/************************************************************************/
720
721
/**
722
 \brief Set a new attribute query.
723
724
 This method sets the attribute query string to be used when
725
 fetching features via the GetNextFeature() method.  Only features for which
726
 the query evaluates as true will be returned.
727
728
 The query string should be in the format of an SQL WHERE clause.  For
729
 instance "population > 1000000 and population < 5000000" where population
730
 is an attribute in the layer. The query format is normally a SQL WHERE clause
731
 as described in the
732
 <a href="https://gdal.org/user/ogr_sql_dialect.html#where">"WHERE"</a> section
733
 of the OGR SQL dialect documentation.
734
 In some cases (RDBMS backed drivers, SQLite, GeoPackage) the native
735
 capabilities of the database may be used to to interpret the WHERE clause, in
736
 which case the capabilities will be broader than those of OGR SQL.
737
738
 Note that installing a query string will generally result in resetting
739
 the current reading position (ala ResetReading()).
740
741
 This method is the same as the C function OGR_L_SetAttributeFilter().
742
743
 @param pszQuery query in restricted SQL WHERE format, or NULL to clear the
744
 current query.
745
746
 @see GetAttrQueryString() to retrieve the currently installed query string.
747
748
 @return OGRERR_NONE if successfully installed, or an error code if the
749
 query expression is in error, or some other failure occurs.
750
 */
751
752
OGRErr OGRLayer::SetAttributeFilter(const char *pszQuery)
753
754
0
{
755
0
    CPLFree(m_pszAttrQueryString);
756
0
    m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : nullptr;
757
758
    /* -------------------------------------------------------------------- */
759
    /*      Are we just clearing any existing query?                        */
760
    /* -------------------------------------------------------------------- */
761
0
    if (pszQuery == nullptr || strlen(pszQuery) == 0)
762
0
    {
763
0
        if (m_poAttrQuery)
764
0
        {
765
0
            delete m_poAttrQuery;
766
0
            m_poAttrQuery = nullptr;
767
0
            ResetReading();
768
0
        }
769
0
        return OGRERR_NONE;
770
0
    }
771
772
    /* -------------------------------------------------------------------- */
773
    /*      Or are we installing a new query?                               */
774
    /* -------------------------------------------------------------------- */
775
0
    OGRErr eErr;
776
777
0
    if (!m_poAttrQuery)
778
0
        m_poAttrQuery = new OGRFeatureQuery();
779
780
0
    eErr = m_poAttrQuery->Compile(this, pszQuery);
781
0
    if (eErr != OGRERR_NONE)
782
0
    {
783
0
        delete m_poAttrQuery;
784
0
        m_poAttrQuery = nullptr;
785
0
    }
786
787
0
    ResetReading();
788
789
0
    return eErr;
790
0
}
791
792
/************************************************************************/
793
/*                      ContainGeomSpecialField()                       */
794
/************************************************************************/
795
796
static int ContainGeomSpecialField(swq_expr_node *expr, int nLayerFieldCount)
797
0
{
798
0
    if (expr->eNodeType == SNT_COLUMN)
799
0
    {
800
0
        if (expr->table_index == 0 && expr->field_index != -1)
801
0
        {
802
0
            int nSpecialFieldIdx = expr->field_index - nLayerFieldCount;
803
0
            return nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
804
0
                   nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
805
0
                   nSpecialFieldIdx == SPF_OGR_GEOM_AREA;
806
0
        }
807
0
    }
808
0
    else if (expr->eNodeType == SNT_OPERATION)
809
0
    {
810
0
        for (int i = 0; i < expr->nSubExprCount; i++)
811
0
        {
812
0
            if (ContainGeomSpecialField(expr->papoSubExpr[i], nLayerFieldCount))
813
0
                return TRUE;
814
0
        }
815
0
    }
816
0
    return FALSE;
817
0
}
818
819
/************************************************************************/
820
/*               AttributeFilterEvaluationNeedsGeometry()               */
821
/************************************************************************/
822
823
//! @cond Doxygen_Suppress
824
int OGRLayer::AttributeFilterEvaluationNeedsGeometry()
825
0
{
826
0
    if (!m_poAttrQuery)
827
0
        return FALSE;
828
829
0
    swq_expr_node *expr =
830
0
        static_cast<swq_expr_node *>(m_poAttrQuery->GetSWQExpr());
831
0
    int nLayerFieldCount = GetLayerDefn()->GetFieldCount();
832
833
0
    return ContainGeomSpecialField(expr, nLayerFieldCount);
834
0
}
835
836
//! @endcond
837
838
/************************************************************************/
839
/*                      OGR_L_SetAttributeFilter()                      */
840
/************************************************************************/
841
842
/**
843
 \brief Set a new attribute query.
844
845
 This function sets the attribute query string to be used when
846
 fetching features via the OGR_L_GetNextFeature() function.
847
 Only features for which the query evaluates as true will be returned.
848
849
 The query string should be in the format of an SQL WHERE clause.  For
850
 instance "population > 1000000 and population < 5000000" where population
851
 is an attribute in the layer. The query format is normally a SQL WHERE clause
852
 as described in the
853
 <a href="https://gdal.org/user/ogr_sql_dialect.html#where">"WHERE"</a> section
854
 of the OGR SQL dialect documentation.
855
 In some cases (RDBMS backed drivers, SQLite, GeoPackage) the native
856
 capabilities of the database may be used to to interpret the WHERE clause, in
857
 which case the capabilities will be broader than those of OGR SQL.
858
859
 Note that installing a query string will generally result in resetting
860
 the current reading position (ala OGR_L_ResetReading()).
861
862
 This function is the same as the C++ method OGRLayer::SetAttributeFilter().
863
864
 @param hLayer handle to the layer on which attribute query will be executed.
865
 @param pszQuery query in restricted SQL WHERE format, or NULL to clear the
866
 current query.
867
868
 @return OGRERR_NONE if successfully installed, or an error code if the
869
 query expression is in error, or some other failure occurs.
870
 */
871
872
OGRErr OGR_L_SetAttributeFilter(OGRLayerH hLayer, const char *pszQuery)
873
874
0
{
875
0
    VALIDATE_POINTER1(hLayer, "OGR_L_SetAttributeFilter",
876
0
                      OGRERR_INVALID_HANDLE);
877
878
0
#ifdef OGRAPISPY_ENABLED
879
0
    if (bOGRAPISpyEnabled)
880
0
        OGRAPISpy_L_SetAttributeFilter(hLayer, pszQuery);
881
0
#endif
882
883
0
    return OGRLayer::FromHandle(hLayer)->SetAttributeFilter(pszQuery);
884
0
}
885
886
/************************************************************************/
887
/*                      OGR_L_GetAttributeFilter()                      */
888
/************************************************************************/
889
890
/**
891
 * @brief Fetch the current attribute query string.
892
 *
893
 * This function is the same as the C++ method OGRLayer::GetAttrQueryString().
894
 *
895
 * @return the current attribute query string, or NULL if no attribute query is
896
 * currently installed. The returned string is short lived and owned by the layer
897
 * and should not be modified or freed by the caller.
898
 *
899
 * @see OGR_L_SetAttributeFilter() to set a new attribute query string.
900
 * @since GDAL 3.13
901
 */
902
const char *OGR_L_GetAttributeFilter(OGRLayerH hLayer)
903
0
{
904
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetAttributeFilter", nullptr);
905
906
0
    return OGRLayer::FromHandle(hLayer)->GetAttrQueryString();
907
0
}
908
909
/************************************************************************/
910
/*                             GetFeature()                             */
911
/************************************************************************/
912
913
/**
914
 \brief Fetch a feature by its identifier.
915
916
 This function will attempt to read the identified feature.  The nFID
917
 value cannot be OGRNullFID.  Success or failure of this operation is
918
 unaffected by the spatial or attribute filters (and specialized implementations
919
 in drivers should make sure that they do not take into account spatial or
920
 attribute filters).
921
922
 If this method returns a non-NULL feature, it is guaranteed that its
923
 feature id (OGRFeature::GetFID()) will be the same as nFID.
924
925
 Use OGRLayer::TestCapability(OLCRandomRead) to establish if this layer
926
 supports efficient random access reading via GetFeature(); however, the
927
 call should always work if the feature exists as a fallback implementation
928
 just scans all the features in the layer looking for the desired feature.
929
930
 Sequential reads (with GetNextFeature()) are generally considered interrupted
931
 by a GetFeature() call.
932
933
 The returned feature should be free with OGRFeature::DestroyFeature().
934
935
 This method is the same as the C function OGR_L_GetFeature().
936
937
 @param nFID the feature id of the feature to read.
938
939
 @return a feature now owned by the caller, or NULL on failure.
940
*/
941
942
OGRFeature *OGRLayer::GetFeature(GIntBig nFID)
943
944
0
{
945
    /* Save old attribute and spatial filters */
946
0
    char *pszOldFilter =
947
0
        m_pszAttrQueryString ? CPLStrdup(m_pszAttrQueryString) : nullptr;
948
0
    OGRGeometry *poOldFilterGeom =
949
0
        (m_poFilterGeom != nullptr) ? m_poFilterGeom->clone() : nullptr;
950
0
    int iOldGeomFieldFilter = m_iGeomFieldFilter;
951
    /* Unset filters */
952
0
    SetAttributeFilter(nullptr);
953
0
    SetSpatialFilter(0, nullptr);
954
955
0
    OGRFeatureUniquePtr poFeature;
956
0
    for (auto &&poFeatureIter : *this)
957
0
    {
958
0
        if (poFeatureIter->GetFID() == nFID)
959
0
        {
960
0
            poFeature.swap(poFeatureIter);
961
0
            break;
962
0
        }
963
0
    }
964
965
    /* Restore filters */
966
0
    SetAttributeFilter(pszOldFilter);
967
0
    CPLFree(pszOldFilter);
968
0
    SetSpatialFilter(iOldGeomFieldFilter, poOldFilterGeom);
969
0
    delete poOldFilterGeom;
970
971
0
    return poFeature.release();
972
0
}
973
974
/************************************************************************/
975
/*                          OGR_L_GetFeature()                          */
976
/************************************************************************/
977
978
/**
979
 \brief Fetch a feature by its identifier.
980
981
 This function will attempt to read the identified feature.  The nFID
982
 value cannot be OGRNullFID.  Success or failure of this operation is
983
 unaffected by the spatial or attribute filters (and specialized implementations
984
 in drivers should make sure that they do not take into account spatial or
985
 attribute filters).
986
987
 If this function returns a non-NULL feature, it is guaranteed that its
988
 feature id (OGR_F_GetFID()) will be the same as nFID.
989
990
 Use OGR_L_TestCapability(OLCRandomRead) to establish if this layer
991
 supports efficient random access reading via OGR_L_GetFeature(); however,
992
 the call should always work if the feature exists as a fallback
993
 implementation just scans all the features in the layer looking for the
994
 desired feature.
995
996
 Sequential reads (with OGR_L_GetNextFeature()) are generally considered interrupted by a
997
 OGR_L_GetFeature() call.
998
999
 The returned feature should be free with OGR_F_Destroy().
1000
1001
 This function is the same as the C++ method OGRLayer::GetFeature( ).
1002
1003
 @param hLayer handle to the layer that owned the feature.
1004
 @param nFeatureId the feature id of the feature to read.
1005
1006
 @return a handle to a feature now owned by the caller, or NULL on failure.
1007
*/
1008
1009
OGRFeatureH OGR_L_GetFeature(OGRLayerH hLayer, GIntBig nFeatureId)
1010
1011
0
{
1012
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetFeature", nullptr);
1013
1014
0
#ifdef OGRAPISPY_ENABLED
1015
0
    if (bOGRAPISpyEnabled)
1016
0
        OGRAPISpy_L_GetFeature(hLayer, nFeatureId);
1017
0
#endif
1018
1019
0
    return OGRFeature::ToHandle(
1020
0
        OGRLayer::FromHandle(hLayer)->GetFeature(nFeatureId));
1021
0
}
1022
1023
/************************************************************************/
1024
/*                           SetNextByIndex()                           */
1025
/************************************************************************/
1026
1027
/**
1028
 \brief Move read cursor to the nIndex'th feature in the current resultset.
1029
1030
 This method allows positioning of a layer such that the GetNextFeature()
1031
 call will read the requested feature, where nIndex is an absolute index
1032
 into the current result set.   So, setting it to 3 would mean the next
1033
 feature read with GetNextFeature() would have been the 4th feature to have
1034
 been read if sequential reading took place from the beginning of the layer,
1035
 including accounting for spatial and attribute filters.
1036
1037
 Only in rare circumstances is SetNextByIndex() efficiently implemented.
1038
 In all other cases the default implementation which calls ResetReading()
1039
 and then calls GetNextFeature() nIndex times is used.  To determine if
1040
 fast seeking is available on the current layer use the TestCapability()
1041
 method with a value of OLCFastSetNextByIndex.
1042
1043
 Starting with GDAL 3.12, when implementations can detect that nIndex is
1044
 invalid (at the minimum all should detect negative indices), they should
1045
 return OGRERR_NON_EXISTING_FEATURE, and following calls to GetNextFeature()
1046
 should return nullptr, until ResetReading() or a valid call to
1047
 SetNextByIndex() is done.
1048
1049
 This method is the same as the C function OGR_L_SetNextByIndex().
1050
1051
 @param nIndex the index indicating how many steps into the result set
1052
 to seek.
1053
1054
 @return OGRERR_NONE on success or an error code.
1055
*/
1056
1057
OGRErr OGRLayer::SetNextByIndex(GIntBig nIndex)
1058
1059
0
{
1060
0
    if (nIndex < 0)
1061
0
        nIndex = GINTBIG_MAX;
1062
1063
0
    ResetReading();
1064
1065
0
    while (nIndex-- > 0)
1066
0
    {
1067
0
        auto poFeature = std::unique_ptr<OGRFeature>(GetNextFeature());
1068
0
        if (poFeature == nullptr)
1069
0
            return OGRERR_NON_EXISTING_FEATURE;
1070
0
    }
1071
1072
0
    return OGRERR_NONE;
1073
0
}
1074
1075
/************************************************************************/
1076
/*                        OGR_L_SetNextByIndex()                        */
1077
/************************************************************************/
1078
1079
/**
1080
 \brief Move read cursor to the nIndex'th feature in the current resultset.
1081
1082
 This method allows positioning of a layer such that the GetNextFeature()
1083
 call will read the requested feature, where nIndex is an absolute index
1084
 into the current result set.   So, setting it to 3 would mean the next
1085
 feature read with GetNextFeature() would have been the 4th feature to have
1086
 been read if sequential reading took place from the beginning of the layer,
1087
 including accounting for spatial and attribute filters.
1088
1089
 Only in rare circumstances is SetNextByIndex() efficiently implemented.
1090
 In all other cases the default implementation which calls ResetReading()
1091
 and then calls GetNextFeature() nIndex times is used.  To determine if
1092
 fast seeking is available on the current layer use the TestCapability()
1093
 method with a value of OLCFastSetNextByIndex.
1094
1095
 Starting with GDAL 3.12, when implementations can detect that nIndex is
1096
 invalid (at the minimum all should detect negative indices), they should
1097
 return OGRERR_NON_EXISTING_FEATURE, and following calls to GetNextFeature()
1098
 should return nullptr, until ResetReading() or a valid call to
1099
 SetNextByIndex() is done.
1100
1101
 This method is the same as the C++ method OGRLayer::SetNextByIndex()
1102
1103
 @param hLayer handle to the layer
1104
 @param nIndex the index indicating how many steps into the result set
1105
 to seek.
1106
1107
 @return OGRERR_NONE on success or an error code.
1108
*/
1109
1110
OGRErr OGR_L_SetNextByIndex(OGRLayerH hLayer, GIntBig nIndex)
1111
1112
0
{
1113
0
    VALIDATE_POINTER1(hLayer, "OGR_L_SetNextByIndex", OGRERR_INVALID_HANDLE);
1114
1115
0
#ifdef OGRAPISPY_ENABLED
1116
0
    if (bOGRAPISpyEnabled)
1117
0
        OGRAPISpy_L_SetNextByIndex(hLayer, nIndex);
1118
0
#endif
1119
1120
0
    return OGRLayer::FromHandle(hLayer)->SetNextByIndex(nIndex);
1121
0
}
1122
1123
/************************************************************************/
1124
/*                      OGRLayer::GetNextFeature()                      */
1125
/************************************************************************/
1126
1127
/**
1128
 \fn OGRFeature *OGRLayer::GetNextFeature();
1129
1130
 \brief Fetch the next available feature from this layer.
1131
1132
 The returned feature becomes the responsibility of the caller to
1133
 delete with OGRFeature::DestroyFeature(). It is critical that all
1134
 features associated with an OGRLayer (more specifically an
1135
 OGRFeatureDefn) be deleted before that layer/datasource is deleted.
1136
1137
 Only features matching the current spatial filter (set with
1138
 SetSpatialFilter()) will be returned.
1139
1140
 This method implements sequential access to the features of a layer.  The
1141
 ResetReading() method can be used to start at the beginning again.
1142
1143
 Starting with GDAL 3.6, it is possible to retrieve them by batches, with a
1144
 column-oriented memory layout, using the GetArrowStream() method.
1145
1146
 Features returned by GetNextFeature() may or may not be affected by
1147
 concurrent modifications depending on drivers. A guaranteed way of seeing
1148
 modifications in effect is to call ResetReading() on layers where
1149
 GetNextFeature() has been called, before reading again.  Structural changes
1150
 in layers (field addition, deletion, ...) when a read is in progress may or
1151
 may not be possible depending on drivers.  If a transaction is
1152
 committed/aborted, the current sequential reading may or may not be valid
1153
 after that operation and a call to ResetReading() might be needed.
1154
1155
 This method is the same as the C function OGR_L_GetNextFeature().
1156
1157
 @return a feature, or NULL if no more features are available.
1158
1159
*/
1160
1161
/************************************************************************/
1162
/*                        OGR_L_GetNextFeature()                        */
1163
/************************************************************************/
1164
1165
/**
1166
 \brief Fetch the next available feature from this layer.
1167
1168
 The returned feature becomes the responsibility of the caller to
1169
 delete with OGR_F_Destroy().  It is critical that all features
1170
 associated with an OGRLayer (more specifically an OGRFeatureDefn) be
1171
 deleted before that layer/datasource is deleted.
1172
1173
 Only features matching the current spatial filter (set with
1174
 SetSpatialFilter()) will be returned.
1175
1176
 This function implements sequential access to the features of a layer.
1177
 The OGR_L_ResetReading() function can be used to start at the beginning
1178
 again.
1179
1180
 Starting with GDAL 3.6, it is possible to retrieve them by batches, with a
1181
 column-oriented memory layout, using the OGR_L_GetArrowStream() function.
1182
1183
 Features returned by OGR_GetNextFeature() may or may not be affected by
1184
 concurrent modifications depending on drivers. A guaranteed way of seeing
1185
 modifications in effect is to call OGR_L_ResetReading() on layers where
1186
 OGR_GetNextFeature() has been called, before reading again.  Structural
1187
 changes in layers (field addition, deletion, ...) when a read is in progress
1188
 may or may not be possible depending on drivers.  If a transaction is
1189
 committed/aborted, the current sequential reading may or may not be valid
1190
 after that operation and a call to OGR_L_ResetReading() might be needed.
1191
1192
 This function is the same as the C++ method OGRLayer::GetNextFeature().
1193
1194
 @param hLayer handle to the layer from which feature are read.
1195
 @return a handle to a feature, or NULL if no more features are available.
1196
1197
*/
1198
1199
OGRFeatureH OGR_L_GetNextFeature(OGRLayerH hLayer)
1200
1201
0
{
1202
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetNextFeature", nullptr);
1203
1204
0
#ifdef OGRAPISPY_ENABLED
1205
0
    if (bOGRAPISpyEnabled)
1206
0
        OGRAPISpy_L_GetNextFeature(hLayer);
1207
0
#endif
1208
1209
0
    return OGRFeature::ToHandle(OGRLayer::FromHandle(hLayer)->GetNextFeature());
1210
0
}
1211
1212
/************************************************************************/
1213
/*                      ConvertGeomsIfNecessary()                       */
1214
/************************************************************************/
1215
1216
void OGRLayer::ConvertGeomsIfNecessary(OGRFeature *poFeature)
1217
0
{
1218
0
    if (!m_poPrivate->m_bConvertGeomsIfNecessaryAlreadyCalled)
1219
0
    {
1220
        // One time initialization
1221
0
        m_poPrivate->m_bConvertGeomsIfNecessaryAlreadyCalled = true;
1222
0
        m_poPrivate->m_bSupportsCurve = TestCapability(OLCCurveGeometries);
1223
0
        m_poPrivate->m_bSupportsM = TestCapability(OLCMeasuredGeometries);
1224
0
        if (CPLTestBool(
1225
0
                CPLGetConfigOption("OGR_APPLY_GEOM_SET_PRECISION", "FALSE")))
1226
0
        {
1227
0
            const auto poFeatureDefn = GetLayerDefn();
1228
0
            const int nGeomFieldCount = poFeatureDefn->GetGeomFieldCount();
1229
0
            for (int i = 0; i < nGeomFieldCount; i++)
1230
0
            {
1231
0
                const double dfXYResolution = poFeatureDefn->GetGeomFieldDefn(i)
1232
0
                                                  ->GetCoordinatePrecision()
1233
0
                                                  .dfXYResolution;
1234
0
                if (dfXYResolution != OGRGeomCoordinatePrecision::UNKNOWN &&
1235
0
                    OGRGeometryFactory::haveGEOS())
1236
0
                {
1237
0
                    m_poPrivate->m_bApplyGeomSetPrecision = true;
1238
0
                    break;
1239
0
                }
1240
0
            }
1241
0
        }
1242
0
    }
1243
1244
0
    if (!m_poPrivate->m_bSupportsCurve || !m_poPrivate->m_bSupportsM ||
1245
0
        m_poPrivate->m_bApplyGeomSetPrecision)
1246
0
    {
1247
0
        const auto poFeatureDefn = GetLayerDefn();
1248
0
        const int nGeomFieldCount = poFeatureDefn->GetGeomFieldCount();
1249
0
        for (int i = 0; i < nGeomFieldCount; i++)
1250
0
        {
1251
0
            OGRGeometry *poGeom = poFeature->GetGeomFieldRef(i);
1252
0
            if (poGeom)
1253
0
            {
1254
0
                if (!m_poPrivate->m_bSupportsM &&
1255
0
                    OGR_GT_HasM(poGeom->getGeometryType()))
1256
0
                {
1257
0
                    poGeom->setMeasured(FALSE);
1258
0
                }
1259
1260
0
                if (!m_poPrivate->m_bSupportsCurve &&
1261
0
                    OGR_GT_IsNonLinear(poGeom->getGeometryType()))
1262
0
                {
1263
0
                    OGRwkbGeometryType eTargetType =
1264
0
                        OGR_GT_GetLinear(poGeom->getGeometryType());
1265
0
                    auto poGeomUniquePtr = OGRGeometryFactory::forceTo(
1266
0
                        std::unique_ptr<OGRGeometry>(
1267
0
                            poFeature->StealGeometry(i)),
1268
0
                        eTargetType);
1269
0
                    poFeature->SetGeomField(i, std::move(poGeomUniquePtr));
1270
0
                    poGeom = poFeature->GetGeomFieldRef(i);
1271
0
                }
1272
1273
0
                if (poGeom && m_poPrivate->m_bApplyGeomSetPrecision)
1274
0
                {
1275
0
                    const double dfXYResolution =
1276
0
                        poFeatureDefn->GetGeomFieldDefn(i)
1277
0
                            ->GetCoordinatePrecision()
1278
0
                            .dfXYResolution;
1279
0
                    if (dfXYResolution != OGRGeomCoordinatePrecision::UNKNOWN &&
1280
0
                        !poGeom->hasCurveGeometry())
1281
0
                    {
1282
0
                        auto poNewGeom = poGeom->SetPrecision(dfXYResolution,
1283
0
                                                              /* nFlags = */ 0);
1284
0
                        if (poNewGeom)
1285
0
                        {
1286
0
                            poFeature->SetGeomFieldDirectly(i, poNewGeom);
1287
                            // If there was potential further processing...
1288
                            // poGeom = poFeature->GetGeomFieldRef(i);
1289
0
                        }
1290
0
                    }
1291
0
                }
1292
0
            }
1293
0
        }
1294
0
    }
1295
0
}
1296
1297
/************************************************************************/
1298
/*                             SetFeature()                             */
1299
/************************************************************************/
1300
1301
/**
1302
 \brief Rewrite/replace an existing feature.
1303
1304
 This method will write a feature to the layer, based on the feature id
1305
 within the OGRFeature.
1306
1307
 Use OGRLayer::TestCapability(OLCRandomWrite) to establish if this layer
1308
 supports random access writing via SetFeature().
1309
1310
 The way unset fields in the provided poFeature are processed is driver dependent:
1311
 <ul>
1312
 <li>
1313
 SQL based drivers which implement SetFeature() through SQL UPDATE will skip
1314
 unset fields, and thus the content of the existing feature will be preserved.
1315
 </li>
1316
 <li>
1317
 The shapefile driver will write a NULL value in the DBF file.
1318
 </li>
1319
 <li>
1320
 The GeoJSON driver will take into account unset fields to remove the corresponding
1321
 JSON member.
1322
 </li>
1323
 </ul>
1324
1325
 Drivers should specialize the ISetFeature() method.
1326
1327
 This method is the same as the C function OGR_L_SetFeature().
1328
1329
 To set a feature, but create it if it doesn't exist see OGRLayer::UpsertFeature().
1330
1331
 @param poFeature the feature to write.
1332
1333
 @return OGRERR_NONE if the operation works, otherwise an appropriate error
1334
 code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
1335
1336
 @see UpdateFeature(), CreateFeature(), UpsertFeature()
1337
*/
1338
1339
OGRErr OGRLayer::SetFeature(OGRFeature *poFeature)
1340
1341
0
{
1342
0
    ConvertGeomsIfNecessary(poFeature);
1343
0
    return ISetFeature(poFeature);
1344
0
}
1345
1346
/************************************************************************/
1347
/*                            ISetFeature()                             */
1348
/************************************************************************/
1349
1350
/**
1351
 \brief Rewrite/replace an existing feature.
1352
1353
 This method is implemented by drivers and not called directly. User code should
1354
 use SetFeature() instead.
1355
1356
 This method will write a feature to the layer, based on the feature id
1357
 within the OGRFeature.
1358
1359
 @param poFeature the feature to write.
1360
1361
 @return OGRERR_NONE if the operation works, otherwise an appropriate error
1362
 code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
1363
1364
 @see SetFeature()
1365
*/
1366
1367
OGRErr OGRLayer::ISetFeature(OGRFeature *poFeature)
1368
1369
0
{
1370
0
    (void)poFeature;
1371
0
    return OGRERR_UNSUPPORTED_OPERATION;
1372
0
}
1373
1374
/************************************************************************/
1375
/*                          OGR_L_SetFeature()                          */
1376
/************************************************************************/
1377
1378
/**
1379
 \brief Rewrite/replace an existing feature.
1380
1381
 This function will write a feature to the layer, based on the feature id
1382
 within the OGRFeature.
1383
1384
 Use OGR_L_TestCapability(OLCRandomWrite) to establish if this layer
1385
 supports random access writing via OGR_L_SetFeature().
1386
1387
 The way unset fields in the provided poFeature are processed is driver dependent:
1388
 <ul>
1389
 <li>
1390
 SQL based drivers which implement SetFeature() through SQL UPDATE will skip
1391
 unset fields, and thus the content of the existing feature will be preserved.
1392
 </li>
1393
 <li>
1394
 The shapefile driver will write a NULL value in the DBF file.
1395
 </li>
1396
 <li>
1397
 The GeoJSON driver will take into account unset fields to remove the corresponding
1398
 JSON member.
1399
 </li>
1400
 </ul>
1401
1402
 This function is the same as the C++ method OGRLayer::SetFeature().
1403
1404
 To set a feature, but create it if it doesn't exist see OGR_L_UpsertFeature().
1405
1406
 @param hLayer handle to the layer to write the feature.
1407
 @param hFeat the feature to write.
1408
1409
 @return OGRERR_NONE if the operation works, otherwise an appropriate error
1410
 code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
1411
1412
 @see OGR_L_UpdateFeature(), OGR_L_CreateFeature(), OGR_L_UpsertFeature()
1413
*/
1414
1415
OGRErr OGR_L_SetFeature(OGRLayerH hLayer, OGRFeatureH hFeat)
1416
1417
0
{
1418
0
    VALIDATE_POINTER1(hLayer, "OGR_L_SetFeature", OGRERR_INVALID_HANDLE);
1419
0
    VALIDATE_POINTER1(hFeat, "OGR_L_SetFeature", OGRERR_INVALID_HANDLE);
1420
1421
0
#ifdef OGRAPISPY_ENABLED
1422
0
    if (bOGRAPISpyEnabled)
1423
0
        OGRAPISpy_L_SetFeature(hLayer, hFeat);
1424
0
#endif
1425
1426
0
    return OGRLayer::FromHandle(hLayer)->SetFeature(
1427
0
        OGRFeature::FromHandle(hFeat));
1428
0
}
1429
1430
/************************************************************************/
1431
/*                             SetFeature()                             */
1432
/************************************************************************/
1433
1434
/**
1435
 \brief Rewrite/replace an existing feature, transferring ownership
1436
        of the feature to the layer
1437
1438
 This method will write a feature to the layer, based on the feature id
1439
 within the OGRFeature.
1440
1441
 Use OGRLayer::TestCapability(OLCRandomWrite) to establish if this layer
1442
 supports random access writing via SetFeature().
1443
1444
 The way unset fields in the provided poFeature are processed is driver dependent:
1445
 <ul>
1446
 <li>
1447
 SQL based drivers which implement SetFeature() through SQL UPDATE will skip
1448
 unset fields, and thus the content of the existing feature will be preserved.
1449
 </li>
1450
 <li>
1451
 The shapefile driver will write a NULL value in the DBF file.
1452
 </li>
1453
 <li>
1454
 The GeoJSON driver will take into account unset fields to remove the corresponding
1455
 JSON member.
1456
 </li>
1457
 </ul>
1458
1459
 Drivers should specialize the ISetFeatureUniqPtr() method.
1460
1461
 To set a feature, but create it if it doesn't exist see OGRLayer::UpsertFeature().
1462
1463
 @param poFeature the feature to write.
1464
1465
 @return OGRERR_NONE if the operation works, otherwise an appropriate error
1466
 code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
1467
1468
 @see UpdateFeature(), CreateFeature(), UpsertFeature()
1469
 @since 3.13
1470
*/
1471
1472
OGRErr OGRLayer::SetFeature(std::unique_ptr<OGRFeature> poFeature)
1473
1474
0
{
1475
0
    ConvertGeomsIfNecessary(poFeature.get());
1476
0
    return ISetFeatureUniqPtr(std::move(poFeature));
1477
0
}
1478
1479
/************************************************************************/
1480
/*                         ISetFeatureUniqPtr()                         */
1481
/************************************************************************/
1482
1483
/**
1484
 \brief Rewrite/replace an existing feature, transferring ownership
1485
        of the feature to the layer
1486
1487
 WARNING: if drivers implement this method, they *MUST* also implement
1488
 ISetFeature()
1489
1490
 This method is implemented by drivers and not called directly. User code should
1491
 use SetFeature() instead.
1492
1493
 This method will write a feature to the layer, based on the feature id
1494
 within the OGRFeature.
1495
1496
 @param poFeature the feature to write.
1497
1498
 @return OGRERR_NONE if the operation works, otherwise an appropriate error
1499
 code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
1500
1501
 @see SetFeature()
1502
 @since 3.13
1503
*/
1504
1505
OGRErr OGRLayer::ISetFeatureUniqPtr(std::unique_ptr<OGRFeature> poFeature)
1506
1507
0
{
1508
0
    return ISetFeature(poFeature.get());
1509
0
}
1510
1511
/************************************************************************/
1512
/*                           CreateFeature()                            */
1513
/************************************************************************/
1514
1515
/**
1516
 \brief Create and write a new feature within a layer.
1517
1518
 The passed feature is written to the layer as a new feature, rather than
1519
 overwriting an existing one.  If the feature has a feature id other than
1520
 OGRNullFID, then the native implementation may use that as the feature id
1521
 of the new feature, but not necessarily.  Upon successful return the
1522
 passed feature will have been updated with the new feature id.
1523
1524
 Drivers should specialize the ICreateFeature() method.
1525
1526
 This method is the same as the C function OGR_L_CreateFeature().
1527
1528
 To create a feature, but set it if it exists see OGRLayer::UpsertFeature().
1529
1530
 @param poFeature the feature to write to disk.
1531
1532
 @return OGRERR_NONE on success.
1533
1534
 @see SetFeature(), UpdateFeature(), UpsertFeature()
1535
*/
1536
1537
OGRErr OGRLayer::CreateFeature(OGRFeature *poFeature)
1538
1539
0
{
1540
0
    ConvertGeomsIfNecessary(poFeature);
1541
0
    return ICreateFeature(poFeature);
1542
0
}
1543
1544
/************************************************************************/
1545
/*                           ICreateFeature()                           */
1546
/************************************************************************/
1547
1548
/**
1549
 \brief Create and write a new feature within a layer.
1550
1551
 This method is implemented by drivers and not called directly. User code should
1552
 use CreateFeature() instead.
1553
1554
 The passed feature is written to the layer as a new feature, rather than
1555
 overwriting an existing one.  If the feature has a feature id other than
1556
 OGRNullFID, then the native implementation may use that as the feature id
1557
 of the new feature, but not necessarily.  Upon successful return the
1558
 passed feature will have been updated with the new feature id.
1559
1560
 @param poFeature the feature to write to disk.
1561
1562
 @return OGRERR_NONE on success.
1563
1564
 @see CreateFeature()
1565
*/
1566
1567
OGRErr OGRLayer::ICreateFeature(OGRFeature *poFeature)
1568
1569
0
{
1570
0
    (void)poFeature;
1571
0
    return OGRERR_UNSUPPORTED_OPERATION;
1572
0
}
1573
1574
/************************************************************************/
1575
/*                        OGR_L_CreateFeature()                         */
1576
/************************************************************************/
1577
1578
/**
1579
 \brief Create and write a new feature within a layer.
1580
1581
 The passed feature is written to the layer as a new feature, rather than
1582
 overwriting an existing one.  If the feature has a feature id other than
1583
 OGRNullFID, then the native implementation may use that as the feature id
1584
 of the new feature, but not necessarily.  Upon successful return the
1585
 passed feature will have been updated with the new feature id.
1586
1587
 This function is the same as the C++ method OGRLayer::CreateFeature().
1588
1589
 To create a feature, but set it if it exists see OGR_L_UpsertFeature().
1590
1591
 @param hLayer handle to the layer to write the feature to.
1592
 @param hFeat the handle of the feature to write to disk.
1593
1594
 @return OGRERR_NONE on success.
1595
1596
 @see OGR_L_SetFeature(), OGR_L_UpdateFeature(), OGR_L_UpsertFeature()
1597
*/
1598
1599
OGRErr OGR_L_CreateFeature(OGRLayerH hLayer, OGRFeatureH hFeat)
1600
1601
0
{
1602
0
    VALIDATE_POINTER1(hLayer, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE);
1603
0
    VALIDATE_POINTER1(hFeat, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE);
1604
1605
0
#ifdef OGRAPISPY_ENABLED
1606
0
    if (bOGRAPISpyEnabled)
1607
0
        OGRAPISpy_L_CreateFeature(hLayer, hFeat);
1608
0
#endif
1609
1610
0
    return OGRLayer::FromHandle(hLayer)->CreateFeature(
1611
0
        OGRFeature::FromHandle(hFeat));
1612
0
}
1613
1614
/************************************************************************/
1615
/*                           CreateFeature()                            */
1616
/************************************************************************/
1617
1618
/**
1619
 \brief Create and write a new feature within a layer, transferring ownership
1620
        of the feature to the layer
1621
1622
 The passed feature is written to the layer as a new feature, rather than
1623
 overwriting an existing one.  If the feature has a feature id other than
1624
 OGRNullFID, then the native implementation may use that as the feature id
1625
 of the new feature, but not necessarily.  Upon successful return the
1626
 passed feature will have been updated with the new feature id.
1627
1628
 Drivers should specialize the ICreateFeatureUniqPtr() method.
1629
1630
 To create a feature, but set it if it exists see OGRLayer::UpsertFeature().
1631
1632
 @param poFeature the feature to write to disk.
1633
 @param[out] pnFID Pointer to an integer that will receive the potentially
1634
             updated FID
1635
1636
 @return OGRERR_NONE on success.
1637
1638
 @see SetFeature(), UpdateFeature(), UpsertFeature()
1639
 @since 3.13
1640
*/
1641
1642
OGRErr OGRLayer::CreateFeature(std::unique_ptr<OGRFeature> poFeature,
1643
                               GIntBig *pnFID)
1644
1645
0
{
1646
0
    ConvertGeomsIfNecessary(poFeature.get());
1647
0
    return ICreateFeatureUniqPtr(std::move(poFeature), pnFID);
1648
0
}
1649
1650
/************************************************************************/
1651
/*                       ICreateFeatureUniqPtr()                        */
1652
/************************************************************************/
1653
1654
/**
1655
 \brief Create and write a new feature within a layer, transferring ownership
1656
        of the feature to the layer
1657
1658
 WARNING: if drivers implement this method, they *MUST* also implement
1659
 ICreateFeature()
1660
1661
 The passed feature is written to the layer as a new feature, rather than
1662
 overwriting an existing one.  If the feature has a feature id other than
1663
 OGRNullFID, then the native implementation may use that as the feature id
1664
 of the new feature, but not necessarily.  Upon successful return the
1665
 passed feature will have been updated with the new feature id.
1666
1667
 @param poFeature the feature to write to disk.
1668
 @param[out] pnFID Pointer to an integer that will receive the potentially
1669
             updated FID
1670
1671
 @return OGRERR_NONE on success.
1672
1673
 @see ICreateFeature()
1674
 @see CreateFeature(std::unique_ptr<OGRFeature> , GIntBig*)
1675
 @since 3.13
1676
*/
1677
1678
OGRErr OGRLayer::ICreateFeatureUniqPtr(std::unique_ptr<OGRFeature> poFeature,
1679
                                       GIntBig *pnFID)
1680
1681
0
{
1682
0
    const OGRErr eErr = ICreateFeature(poFeature.get());
1683
0
    if (pnFID)
1684
0
        *pnFID = poFeature->GetFID();
1685
0
    return eErr;
1686
0
}
1687
1688
/************************************************************************/
1689
/*                           UpsertFeature()                            */
1690
/************************************************************************/
1691
1692
/**
1693
 \brief Rewrite/replace an existing feature or create a new feature within a layer.
1694
1695
 This function will write a feature to the layer, based on the feature id
1696
 within the OGRFeature.  If the feature id doesn't exist a new feature will be
1697
 written.  Otherwise, the existing feature will be rewritten.
1698
1699
 Use OGRLayer::TestCapability(OLCUpsertFeature) to establish if this layer
1700
 supports upsert writing.
1701
1702
 This method is the same as the C function OGR_L_UpsertFeature().
1703
1704
 @param poFeature the feature to write to disk.
1705
1706
 @return OGRERR_NONE on success.
1707
 @since GDAL 3.6.0
1708
1709
 @see SetFeature(), CreateFeature(), UpdateFeature()
1710
*/
1711
1712
OGRErr OGRLayer::UpsertFeature(OGRFeature *poFeature)
1713
1714
0
{
1715
0
    ConvertGeomsIfNecessary(poFeature);
1716
0
    return IUpsertFeature(poFeature);
1717
0
}
1718
1719
/************************************************************************/
1720
/*                           IUpsertFeature()                           */
1721
/************************************************************************/
1722
1723
/**
1724
 \brief Rewrite/replace an existing feature or create a new feature within a layer.
1725
1726
 This method is implemented by drivers and not called directly. User code should
1727
 use UpsertFeature() instead.
1728
1729
 This function will write a feature to the layer, based on the feature id
1730
 within the OGRFeature.  If the feature id doesn't exist a new feature will be
1731
 written.  Otherwise, the existing feature will be rewritten.
1732
1733
 @param poFeature the feature to write to disk.
1734
1735
 @return OGRERR_NONE on success.
1736
 @since GDAL 3.6.0
1737
1738
 @see UpsertFeature()
1739
*/
1740
1741
OGRErr OGRLayer::IUpsertFeature(OGRFeature *poFeature)
1742
0
{
1743
0
    (void)poFeature;
1744
0
    return OGRERR_UNSUPPORTED_OPERATION;
1745
0
}
1746
1747
/************************************************************************/
1748
/*                        OGR_L_UpsertFeature()                         */
1749
/************************************************************************/
1750
1751
/**
1752
 \brief Rewrite/replace an existing feature or create a new feature within a layer.
1753
1754
 This function will write a feature to the layer, based on the feature id
1755
 within the OGRFeature.  If the feature id doesn't exist a new feature will be
1756
 written.  Otherwise, the existing feature will be rewritten.
1757
1758
 Use OGR_L_TestCapability(OLCUpsertFeature) to establish if this layer
1759
 supports upsert writing.
1760
1761
 This function is the same as the C++ method OGRLayer::UpsertFeature().
1762
1763
 @param hLayer handle to the layer to write the feature to.
1764
 @param hFeat the handle of the feature to write to disk.
1765
1766
 @return OGRERR_NONE on success.
1767
 @since GDAL 3.6.0
1768
1769
 @see OGR_L_SetFeature(), OGR_L_CreateFeature(), OGR_L_UpdateFeature()
1770
*/
1771
1772
OGRErr OGR_L_UpsertFeature(OGRLayerH hLayer, OGRFeatureH hFeat)
1773
1774
0
{
1775
0
    VALIDATE_POINTER1(hLayer, "OGR_L_UpsertFeature", OGRERR_INVALID_HANDLE);
1776
0
    VALIDATE_POINTER1(hFeat, "OGR_L_UpsertFeature", OGRERR_INVALID_HANDLE);
1777
1778
0
#ifdef OGRAPISPY_ENABLED
1779
0
    if (bOGRAPISpyEnabled)
1780
0
        OGRAPISpy_L_UpsertFeature(hLayer, hFeat);
1781
0
#endif
1782
1783
0
    return OGRLayer::FromHandle(hLayer)->UpsertFeature(
1784
0
        OGRFeature::FromHandle(hFeat));
1785
0
}
1786
1787
/************************************************************************/
1788
/*                           UpdateFeature()                            */
1789
/************************************************************************/
1790
1791
/**
1792
 \brief Update (part of) an existing feature.
1793
1794
 This method will update the specified attribute and geometry fields of a
1795
 feature to the layer, based on the feature id within the OGRFeature.
1796
1797
 Use OGRLayer::TestCapability(OLCRandomWrite) to establish if this layer
1798
 supports random access writing via UpdateFeature(). And to know if the
1799
 driver supports a dedicated/efficient UpdateFeature() method, test for the
1800
 OLCUpdateFeature capability.
1801
1802
 The way unset fields in the provided poFeature are processed is driver dependent:
1803
 <ul>
1804
 <li>
1805
 SQL based drivers which implement SetFeature() through SQL UPDATE will skip
1806
 unset fields, and thus the content of the existing feature will be preserved.
1807
 </li>
1808
 <li>
1809
 The shapefile driver will write a NULL value in the DBF file.
1810
 </li>
1811
 <li>
1812
 The GeoJSON driver will take into account unset fields to remove the corresponding
1813
 JSON member.
1814
 </li>
1815
 </ul>
1816
1817
 This method is the same as the C function OGR_L_UpdateFeature().
1818
1819
 To fully replace a feature, see OGRLayer::SetFeature().
1820
1821
 Note that after this call the content of hFeat might have changed, and will
1822
 *not* reflect the content you would get with GetFeature().
1823
 In particular for performance reasons, passed geometries might have been "stolen",
1824
 in particular for the default implementation of UpdateFeature() which relies
1825
 on GetFeature() + SetFeature().
1826
1827
 @param poFeature the feature to update.
1828
1829
 @param nUpdatedFieldsCount number of attribute fields to update. May be 0
1830
1831
 @param panUpdatedFieldsIdx array of nUpdatedFieldsCount values, each between
1832
                            0 and GetLayerDefn()->GetFieldCount() - 1, indicating
1833
                            which fields of poFeature must be updated in the
1834
                            layer.
1835
1836
 @param nUpdatedGeomFieldsCount number of geometry fields to update. May be 0
1837
1838
 @param panUpdatedGeomFieldsIdx array of nUpdatedGeomFieldsCount values, each between
1839
                                0 and GetLayerDefn()->GetGeomFieldCount() - 1, indicating
1840
                                which geometry fields of poFeature must be updated in the
1841
                                layer.
1842
1843
 @param bUpdateStyleString whether the feature style string in the layer should
1844
                           be updated with the one of poFeature.
1845
1846
 @return OGRERR_NONE if the operation works, otherwise an appropriate error
1847
 code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
1848
1849
 @since GDAL 3.7
1850
1851
 @see UpdateFeature(), CreateFeature(), UpsertFeature()
1852
*/
1853
1854
OGRErr OGRLayer::UpdateFeature(OGRFeature *poFeature, int nUpdatedFieldsCount,
1855
                               const int *panUpdatedFieldsIdx,
1856
                               int nUpdatedGeomFieldsCount,
1857
                               const int *panUpdatedGeomFieldsIdx,
1858
                               bool bUpdateStyleString)
1859
1860
0
{
1861
0
    ConvertGeomsIfNecessary(poFeature);
1862
0
    const int nFieldCount = GetLayerDefn()->GetFieldCount();
1863
0
    for (int i = 0; i < nUpdatedFieldsCount; ++i)
1864
0
    {
1865
0
        if (panUpdatedFieldsIdx[i] < 0 || panUpdatedFieldsIdx[i] >= nFieldCount)
1866
0
        {
1867
0
            CPLError(CE_Failure, CPLE_AppDefined,
1868
0
                     "Invalid panUpdatedFieldsIdx[%d] = %d", i,
1869
0
                     panUpdatedFieldsIdx[i]);
1870
0
            return OGRERR_FAILURE;
1871
0
        }
1872
0
    }
1873
0
    const int nGeomFieldCount = GetLayerDefn()->GetGeomFieldCount();
1874
0
    for (int i = 0; i < nUpdatedGeomFieldsCount; ++i)
1875
0
    {
1876
0
        if (panUpdatedGeomFieldsIdx[i] < 0 ||
1877
0
            panUpdatedGeomFieldsIdx[i] >= nGeomFieldCount)
1878
0
        {
1879
0
            CPLError(CE_Failure, CPLE_AppDefined,
1880
0
                     "Invalid panUpdatedGeomFieldsIdx[%d] = %d", i,
1881
0
                     panUpdatedGeomFieldsIdx[i]);
1882
0
            return OGRERR_FAILURE;
1883
0
        }
1884
0
    }
1885
0
    return IUpdateFeature(poFeature, nUpdatedFieldsCount, panUpdatedFieldsIdx,
1886
0
                          nUpdatedGeomFieldsCount, panUpdatedGeomFieldsIdx,
1887
0
                          bUpdateStyleString);
1888
0
}
1889
1890
/************************************************************************/
1891
/*                           IUpdateFeature()                           */
1892
/************************************************************************/
1893
1894
/**
1895
 \brief Update (part of) an existing feature.
1896
1897
 This method is implemented by drivers and not called directly. User code should
1898
 use UpdateFeature() instead.
1899
1900
 @param poFeature the feature to update.
1901
1902
 @param nUpdatedFieldsCount number of attribute fields to update. May be 0
1903
1904
 @param panUpdatedFieldsIdx array of nUpdatedFieldsCount values, each between
1905
                            0 and GetLayerDefn()->GetFieldCount() - 1, indicating
1906
                            which fields of poFeature must be updated in the
1907
                            layer.
1908
1909
 @param nUpdatedGeomFieldsCount number of geometry fields to update. May be 0
1910
1911
 @param panUpdatedGeomFieldsIdx array of nUpdatedGeomFieldsCount values, each between
1912
                                0 and GetLayerDefn()->GetGeomFieldCount() - 1, indicating
1913
                                which geometry fields of poFeature must be updated in the
1914
                                layer.
1915
1916
 @param bUpdateStyleString whether the feature style string in the layer should
1917
                           be updated with the one of poFeature.
1918
1919
 @return OGRERR_NONE if the operation works, otherwise an appropriate error
1920
 code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
1921
1922
 @since GDAL 3.7
1923
1924
 @see UpdateFeature()
1925
*/
1926
1927
OGRErr OGRLayer::IUpdateFeature(OGRFeature *poFeature, int nUpdatedFieldsCount,
1928
                                const int *panUpdatedFieldsIdx,
1929
                                int nUpdatedGeomFieldsCount,
1930
                                const int *panUpdatedGeomFieldsIdx,
1931
                                bool bUpdateStyleString)
1932
0
{
1933
0
    if (!TestCapability(OLCRandomWrite))
1934
0
        return OGRERR_UNSUPPORTED_OPERATION;
1935
1936
0
    auto poFeatureExisting =
1937
0
        std::unique_ptr<OGRFeature>(GetFeature(poFeature->GetFID()));
1938
0
    if (!poFeatureExisting)
1939
0
        return OGRERR_NON_EXISTING_FEATURE;
1940
1941
0
    for (int i = 0; i < nUpdatedFieldsCount; ++i)
1942
0
    {
1943
0
        poFeatureExisting->SetField(
1944
0
            panUpdatedFieldsIdx[i],
1945
0
            poFeature->GetRawFieldRef(panUpdatedFieldsIdx[i]));
1946
0
    }
1947
0
    for (int i = 0; i < nUpdatedGeomFieldsCount; ++i)
1948
0
    {
1949
0
        poFeatureExisting->SetGeomFieldDirectly(
1950
0
            panUpdatedGeomFieldsIdx[i],
1951
0
            poFeature->StealGeometry(panUpdatedGeomFieldsIdx[i]));
1952
0
    }
1953
0
    if (bUpdateStyleString)
1954
0
    {
1955
0
        poFeatureExisting->SetStyleString(poFeature->GetStyleString());
1956
0
    }
1957
0
    return ISetFeature(poFeatureExisting.get());
1958
0
}
1959
1960
/************************************************************************/
1961
/*                        OGR_L_UpdateFeature()                         */
1962
/************************************************************************/
1963
1964
/**
1965
 \brief Update (part of) an existing feature.
1966
1967
 This function will update the specified attribute and geometry fields of a
1968
 feature to the layer, based on the feature id within the OGRFeature.
1969
1970
 Use OGR_L_TestCapability(OLCRandomWrite) to establish if this layer
1971
 supports random access writing via UpdateFeature(). And to know if the
1972
 driver supports a dedicated/efficient UpdateFeature() method, test for the
1973
 OLCUpdateFeature capability.
1974
1975
 The way unset fields in the provided poFeature are processed is driver dependent:
1976
 <ul>
1977
 <li>
1978
 SQL based drivers which implement SetFeature() through SQL UPDATE will skip
1979
 unset fields, and thus the content of the existing feature will be preserved.
1980
 </li>
1981
 <li>
1982
 The shapefile driver will write a NULL value in the DBF file.
1983
 </li>
1984
 <li>
1985
 The GeoJSON driver will take into account unset fields to remove the corresponding
1986
 JSON member.
1987
 </li>
1988
 </ul>
1989
1990
 This method is the same as the C++ method OGRLayer::UpdateFeature().
1991
1992
 To fully replace a feature, see OGR_L_SetFeature()
1993
1994
 Note that after this call the content of hFeat might have changed, and will
1995
 *not* reflect the content you would get with OGR_L_GetFeature().
1996
 In particular for performance reasons, passed geometries might have been "stolen",
1997
 in particular for the default implementation of UpdateFeature() which relies
1998
 on GetFeature() + SetFeature().
1999
2000
 @param hLayer handle to the layer to write the feature.
2001
2002
 @param hFeat the feature to update.
2003
2004
 @param nUpdatedFieldsCount number of attribute fields to update. May be 0
2005
2006
 @param panUpdatedFieldsIdx array of nUpdatedFieldsCount values, each between
2007
                            0 and GetLayerDefn()->GetFieldCount() - 1, indicating
2008
                            which fields of hFeat must be updated in the
2009
                            layer.
2010
2011
 @param nUpdatedGeomFieldsCount number of geometry fields to update. May be 0
2012
2013
 @param panUpdatedGeomFieldsIdx array of nUpdatedGeomFieldsCount values, each between
2014
                                0 and GetLayerDefn()->GetGeomFieldCount() - 1, indicating
2015
                                which geometry fields of hFeat must be updated in the
2016
                                layer.
2017
2018
 @param bUpdateStyleString whether the feature style string in the layer should
2019
                           be updated with the one of hFeat.
2020
2021
 @return OGRERR_NONE if the operation works, otherwise an appropriate error
2022
 code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
2023
2024
 @since GDAL 3.7
2025
2026
 @see OGR_L_UpdateFeature(), OGR_L_CreateFeature(), OGR_L_UpsertFeature()
2027
*/
2028
2029
OGRErr OGR_L_UpdateFeature(OGRLayerH hLayer, OGRFeatureH hFeat,
2030
                           int nUpdatedFieldsCount,
2031
                           const int *panUpdatedFieldsIdx,
2032
                           int nUpdatedGeomFieldsCount,
2033
                           const int *panUpdatedGeomFieldsIdx,
2034
                           bool bUpdateStyleString)
2035
2036
0
{
2037
0
    VALIDATE_POINTER1(hLayer, "OGR_L_UpdateFeature", OGRERR_INVALID_HANDLE);
2038
0
    VALIDATE_POINTER1(hFeat, "OGR_L_UpdateFeature", OGRERR_INVALID_HANDLE);
2039
2040
0
    return OGRLayer::FromHandle(hLayer)->UpdateFeature(
2041
0
        OGRFeature::FromHandle(hFeat), nUpdatedFieldsCount, panUpdatedFieldsIdx,
2042
0
        nUpdatedGeomFieldsCount, panUpdatedGeomFieldsIdx, bUpdateStyleString);
2043
0
}
2044
2045
/************************************************************************/
2046
/*                            CreateField()                             */
2047
/************************************************************************/
2048
2049
/**
2050
\brief Create a new field on a layer.
2051
2052
You must use this to create new fields
2053
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
2054
to reflect the new field.  Applications should never modify the OGRFeatureDefn
2055
used by a layer directly.
2056
2057
This method should not be called while there are feature objects in existence that
2058
were obtained or created with the previous layer definition.
2059
2060
Not all drivers support this method. You can query a layer to check if it supports it
2061
with the OLCCreateField capability. Some drivers may only support this method while
2062
there are still no features in the layer. When it is supported, the existing features of the
2063
backing file/database should be updated accordingly.
2064
2065
Drivers may or may not support not-null constraints. If they support creating
2066
fields with not-null constraints, this is generally before creating any feature to the layer.
2067
2068
This function is the same as the C function OGR_L_CreateField().
2069
2070
@param poField field definition to write to disk.
2071
@param bApproxOK If TRUE, the field may be created in a slightly different
2072
form depending on the limitations of the format driver.
2073
2074
@return OGRERR_NONE on success.
2075
*/
2076
2077
OGRErr OGRLayer::CreateField(const OGRFieldDefn *poField, int bApproxOK)
2078
2079
0
{
2080
0
    (void)poField;
2081
0
    (void)bApproxOK;
2082
2083
0
    CPLError(CE_Failure, CPLE_NotSupported,
2084
0
             "CreateField() not supported by this layer.");
2085
2086
0
    return OGRERR_UNSUPPORTED_OPERATION;
2087
0
}
2088
2089
/************************************************************************/
2090
/*                         OGR_L_CreateField()                          */
2091
/************************************************************************/
2092
2093
/**
2094
\brief Create a new field on a layer.
2095
2096
You must use this to create new fields
2097
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
2098
to reflect the new field.  Applications should never modify the OGRFeatureDefn
2099
used by a layer directly.
2100
2101
This function should not be called while there are feature objects in existence that
2102
were obtained or created with the previous layer definition.
2103
2104
Not all drivers support this function. You can query a layer to check if it supports it
2105
with the OLCCreateField capability. Some drivers may only support this method while
2106
there are still no features in the layer. When it is supported, the existing features of the
2107
backing file/database should be updated accordingly.
2108
2109
Drivers may or may not support not-null constraints. If they support creating
2110
fields with not-null constraints, this is generally before creating any feature to the layer.
2111
2112
 This function is the same as the C++ method OGRLayer::CreateField().
2113
2114
 @param hLayer handle to the layer to write the field definition.
2115
 @param hField handle of the field definition to write to disk.
2116
 @param bApproxOK If TRUE, the field may be created in a slightly different
2117
form depending on the limitations of the format driver.
2118
2119
 @return OGRERR_NONE on success.
2120
*/
2121
2122
OGRErr OGR_L_CreateField(OGRLayerH hLayer, OGRFieldDefnH hField, int bApproxOK)
2123
2124
0
{
2125
0
    VALIDATE_POINTER1(hLayer, "OGR_L_CreateField", OGRERR_INVALID_HANDLE);
2126
0
    VALIDATE_POINTER1(hField, "OGR_L_CreateField", OGRERR_INVALID_HANDLE);
2127
2128
0
#ifdef OGRAPISPY_ENABLED
2129
0
    if (bOGRAPISpyEnabled)
2130
0
        OGRAPISpy_L_CreateField(hLayer, hField, bApproxOK);
2131
0
#endif
2132
2133
0
    return OGRLayer::FromHandle(hLayer)->CreateField(
2134
0
        OGRFieldDefn::FromHandle(hField), bApproxOK);
2135
0
}
2136
2137
/************************************************************************/
2138
/*                            DeleteField()                             */
2139
/************************************************************************/
2140
2141
/**
2142
\brief Delete an existing field on a layer.
2143
2144
You must use this to delete existing fields
2145
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
2146
to reflect the deleted field.  Applications should never modify the OGRFeatureDefn
2147
used by a layer directly.
2148
2149
This method should not be called while there are feature objects in existence that
2150
were obtained or created with the previous layer definition.
2151
2152
If a OGRFieldDefn* object corresponding to the deleted field has been retrieved
2153
from the layer definition before the call to DeleteField(), it must no longer be
2154
used after the call to DeleteField(), which will have destroyed it.
2155
2156
Not all drivers support this method. You can query a layer to check if it supports it
2157
with the OLCDeleteField capability. Some drivers may only support this method while
2158
there are still no features in the layer. When it is supported, the existing features of the
2159
backing file/database should be updated accordingly.
2160
2161
This function is the same as the C function OGR_L_DeleteField().
2162
2163
@param iField index of the field to delete.
2164
2165
@return OGRERR_NONE on success.
2166
*/
2167
2168
OGRErr OGRLayer::DeleteField(int iField)
2169
2170
0
{
2171
0
    (void)iField;
2172
2173
0
    CPLError(CE_Failure, CPLE_NotSupported,
2174
0
             "DeleteField() not supported by this layer.");
2175
2176
0
    return OGRERR_UNSUPPORTED_OPERATION;
2177
0
}
2178
2179
/************************************************************************/
2180
/*                         OGR_L_DeleteField()                          */
2181
/************************************************************************/
2182
2183
/**
2184
\brief Delete an existing field on a layer.
2185
2186
You must use this to delete existing fields
2187
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
2188
to reflect the deleted field.  Applications should never modify the OGRFeatureDefn
2189
used by a layer directly.
2190
2191
This function should not be called while there are feature objects in existence that
2192
were obtained or created with the previous layer definition.
2193
2194
If a OGRFieldDefnH object corresponding to the deleted field has been retrieved
2195
from the layer definition before the call to DeleteField(), it must no longer be
2196
used after the call to DeleteField(), which will have destroyed it.
2197
2198
Not all drivers support this function. You can query a layer to check if it supports it
2199
with the OLCDeleteField capability. Some drivers may only support this method while
2200
there are still no features in the layer. When it is supported, the existing features of the
2201
backing file/database should be updated accordingly.
2202
2203
This function is the same as the C++ method OGRLayer::DeleteField().
2204
2205
@param hLayer handle to the layer.
2206
@param iField index of the field to delete.
2207
2208
@return OGRERR_NONE on success.
2209
*/
2210
2211
OGRErr OGR_L_DeleteField(OGRLayerH hLayer, int iField)
2212
2213
0
{
2214
0
    VALIDATE_POINTER1(hLayer, "OGR_L_DeleteField", OGRERR_INVALID_HANDLE);
2215
2216
0
#ifdef OGRAPISPY_ENABLED
2217
0
    if (bOGRAPISpyEnabled)
2218
0
        OGRAPISpy_L_DeleteField(hLayer, iField);
2219
0
#endif
2220
2221
0
    return OGRLayer::FromHandle(hLayer)->DeleteField(iField);
2222
0
}
2223
2224
/************************************************************************/
2225
/*                           ReorderFields()                            */
2226
/************************************************************************/
2227
2228
/**
2229
\brief Reorder all the fields of a layer.
2230
2231
You must use this to reorder existing fields
2232
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
2233
to reflect the reordering of the fields.  Applications should never modify the OGRFeatureDefn
2234
used by a layer directly.
2235
2236
This method should not be called while there are feature objects in existence that
2237
were obtained or created with the previous layer definition.
2238
2239
panMap is such that,for each field definition at position i after reordering,
2240
its position before reordering was panMap[i].
2241
2242
For example, let suppose the fields were "0","1","2","3","4" initially.
2243
ReorderFields([0,2,3,1,4]) will reorder them as "0","2","3","1","4".
2244
2245
Not all drivers support this method. You can query a layer to check if it supports it
2246
with the OLCReorderFields capability. Some drivers may only support this method while
2247
there are still no features in the layer. When it is supported, the existing features of the
2248
backing file/database should be updated accordingly.
2249
2250
This function is the same as the C function OGR_L_ReorderFields().
2251
2252
@param panMap an array of GetLayerDefn()->OGRFeatureDefn::GetFieldCount() elements which
2253
is a permutation of [0, GetLayerDefn()->OGRFeatureDefn::GetFieldCount()-1].
2254
2255
@return OGRERR_NONE on success.
2256
*/
2257
2258
OGRErr OGRLayer::ReorderFields(int *panMap)
2259
2260
0
{
2261
0
    (void)panMap;
2262
2263
0
    CPLError(CE_Failure, CPLE_NotSupported,
2264
0
             "ReorderFields() not supported by this layer.");
2265
2266
0
    return OGRERR_UNSUPPORTED_OPERATION;
2267
0
}
2268
2269
/************************************************************************/
2270
/*                        OGR_L_ReorderFields()                         */
2271
/************************************************************************/
2272
2273
/**
2274
\brief Reorder all the fields of a layer.
2275
2276
You must use this to reorder existing fields
2277
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
2278
to reflect the reordering of the fields.  Applications should never modify the OGRFeatureDefn
2279
used by a layer directly.
2280
2281
This function should not be called while there are feature objects in existence that
2282
were obtained or created with the previous layer definition.
2283
2284
panMap is such that,for each field definition at position i after reordering,
2285
its position before reordering was panMap[i].
2286
2287
For example, let suppose the fields were "0","1","2","3","4" initially.
2288
ReorderFields([0,2,3,1,4]) will reorder them as "0","2","3","1","4".
2289
2290
Not all drivers support this function. You can query a layer to check if it supports it
2291
with the OLCReorderFields capability. Some drivers may only support this method while
2292
there are still no features in the layer. When it is supported, the existing features of the
2293
backing file/database should be updated accordingly.
2294
2295
This function is the same as the C++ method OGRLayer::ReorderFields().
2296
2297
@param hLayer handle to the layer.
2298
@param panMap an array of GetLayerDefn()->OGRFeatureDefn::GetFieldCount() elements which
2299
is a permutation of [0, GetLayerDefn()->OGRFeatureDefn::GetFieldCount()-1].
2300
2301
@return OGRERR_NONE on success.
2302
*/
2303
2304
OGRErr OGR_L_ReorderFields(OGRLayerH hLayer, int *panMap)
2305
2306
0
{
2307
0
    VALIDATE_POINTER1(hLayer, "OGR_L_ReorderFields", OGRERR_INVALID_HANDLE);
2308
2309
0
#ifdef OGRAPISPY_ENABLED
2310
0
    if (bOGRAPISpyEnabled)
2311
0
        OGRAPISpy_L_ReorderFields(hLayer, panMap);
2312
0
#endif
2313
2314
0
    return OGRLayer::FromHandle(hLayer)->ReorderFields(panMap);
2315
0
}
2316
2317
/************************************************************************/
2318
/*                            ReorderField()                            */
2319
/************************************************************************/
2320
2321
/**
2322
\brief Reorder an existing field on a layer.
2323
2324
This method is a convenience wrapper of ReorderFields() dedicated to move a single field.
2325
It is a non-virtual method, so drivers should implement ReorderFields() instead.
2326
2327
You must use this to reorder existing fields
2328
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
2329
to reflect the reordering of the fields.  Applications should never modify the OGRFeatureDefn
2330
used by a layer directly.
2331
2332
This method should not be called while there are feature objects in existence that
2333
were obtained or created with the previous layer definition.
2334
2335
The field definition that was at initial position iOldFieldPos will be moved at
2336
position iNewFieldPos, and elements between will be shuffled accordingly.
2337
2338
For example, let suppose the fields were "0","1","2","3","4" initially.
2339
ReorderField(1, 3) will reorder them as "0","2","3","1","4".
2340
2341
Not all drivers support this method. You can query a layer to check if it supports it
2342
with the OLCReorderFields capability. Some drivers may only support this method while
2343
there are still no features in the layer. When it is supported, the existing features of the
2344
backing file/database should be updated accordingly.
2345
2346
This function is the same as the C function OGR_L_ReorderField().
2347
2348
@param iOldFieldPos previous position of the field to move. Must be in the range [0,GetFieldCount()-1].
2349
@param iNewFieldPos new position of the field to move. Must be in the range [0,GetFieldCount()-1].
2350
2351
@return OGRERR_NONE on success.
2352
*/
2353
2354
OGRErr OGRLayer::ReorderField(int iOldFieldPos, int iNewFieldPos)
2355
2356
0
{
2357
0
    OGRErr eErr;
2358
2359
0
    int nFieldCount = GetLayerDefn()->GetFieldCount();
2360
2361
0
    if (iOldFieldPos < 0 || iOldFieldPos >= nFieldCount)
2362
0
    {
2363
0
        CPLError(CE_Failure, CPLE_NotSupported, "Invalid field index");
2364
0
        return OGRERR_FAILURE;
2365
0
    }
2366
0
    if (iNewFieldPos < 0 || iNewFieldPos >= nFieldCount)
2367
0
    {
2368
0
        CPLError(CE_Failure, CPLE_NotSupported, "Invalid field index");
2369
0
        return OGRERR_FAILURE;
2370
0
    }
2371
0
    if (iNewFieldPos == iOldFieldPos)
2372
0
        return OGRERR_NONE;
2373
2374
0
    int *panMap = static_cast<int *>(CPLMalloc(sizeof(int) * nFieldCount));
2375
0
    if (iOldFieldPos < iNewFieldPos)
2376
0
    {
2377
        /* "0","1","2","3","4" (1,3) -> "0","2","3","1","4" */
2378
0
        int i = 0;  // Used after for.
2379
0
        for (; i < iOldFieldPos; i++)
2380
0
            panMap[i] = i;
2381
0
        for (; i < iNewFieldPos; i++)
2382
0
            panMap[i] = i + 1;
2383
0
        panMap[iNewFieldPos] = iOldFieldPos;
2384
0
        for (i = iNewFieldPos + 1; i < nFieldCount; i++)
2385
0
            panMap[i] = i;
2386
0
    }
2387
0
    else
2388
0
    {
2389
        /* "0","1","2","3","4" (3,1) -> "0","3","1","2","4" */
2390
0
        for (int i = 0; i < iNewFieldPos; i++)
2391
0
            panMap[i] = i;
2392
0
        panMap[iNewFieldPos] = iOldFieldPos;
2393
0
        int i = iNewFieldPos + 1;  // Used after for.
2394
0
        for (; i <= iOldFieldPos; i++)
2395
0
            panMap[i] = i - 1;
2396
0
        for (; i < nFieldCount; i++)
2397
0
            panMap[i] = i;
2398
0
    }
2399
2400
0
    eErr = ReorderFields(panMap);
2401
2402
0
    CPLFree(panMap);
2403
2404
0
    return eErr;
2405
0
}
2406
2407
/************************************************************************/
2408
/*                         OGR_L_ReorderField()                         */
2409
/************************************************************************/
2410
2411
/**
2412
\brief Reorder an existing field on a layer.
2413
2414
This function is a convenience wrapper of OGR_L_ReorderFields() dedicated to move a single field.
2415
2416
You must use this to reorder existing fields
2417
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
2418
to reflect the reordering of the fields.  Applications should never modify the OGRFeatureDefn
2419
used by a layer directly.
2420
2421
This function should not be called while there are feature objects in existence that
2422
were obtained or created with the previous layer definition.
2423
2424
The field definition that was at initial position iOldFieldPos will be moved at
2425
position iNewFieldPos, and elements between will be shuffled accordingly.
2426
2427
For example, let suppose the fields were "0","1","2","3","4" initially.
2428
ReorderField(1, 3) will reorder them as "0","2","3","1","4".
2429
2430
Not all drivers support this function. You can query a layer to check if it supports it
2431
with the OLCReorderFields capability. Some drivers may only support this method while
2432
there are still no features in the layer. When it is supported, the existing features of the
2433
backing file/database should be updated accordingly.
2434
2435
This function is the same as the C++ method OGRLayer::ReorderField().
2436
2437
@param hLayer handle to the layer.
2438
@param iOldFieldPos previous position of the field to move. Must be in the range [0,GetFieldCount()-1].
2439
@param iNewFieldPos new position of the field to move. Must be in the range [0,GetFieldCount()-1].
2440
2441
@return OGRERR_NONE on success.
2442
*/
2443
2444
OGRErr OGR_L_ReorderField(OGRLayerH hLayer, int iOldFieldPos, int iNewFieldPos)
2445
2446
0
{
2447
0
    VALIDATE_POINTER1(hLayer, "OGR_L_ReorderField", OGRERR_INVALID_HANDLE);
2448
2449
0
#ifdef OGRAPISPY_ENABLED
2450
0
    if (bOGRAPISpyEnabled)
2451
0
        OGRAPISpy_L_ReorderField(hLayer, iOldFieldPos, iNewFieldPos);
2452
0
#endif
2453
2454
0
    return OGRLayer::FromHandle(hLayer)->ReorderField(iOldFieldPos,
2455
0
                                                      iNewFieldPos);
2456
0
}
2457
2458
/************************************************************************/
2459
/*                           AlterFieldDefn()                           */
2460
/************************************************************************/
2461
2462
/**
2463
\brief Alter the definition of an existing field on a layer.
2464
2465
You must use this to alter the definition of an existing field of a real layer.
2466
Internally the OGRFeatureDefn for the layer will be updated
2467
to reflect the altered field.  Applications should never modify the OGRFeatureDefn
2468
used by a layer directly.
2469
2470
This method should not be called while there are feature objects in existence that
2471
were obtained or created with the previous layer definition.
2472
2473
Not all drivers support this method. You can query a layer to check if it supports it
2474
with the OLCAlterFieldDefn capability. Some drivers may only support this method while
2475
there are still no features in the layer. When it is supported, the existing features of the
2476
backing file/database should be updated accordingly. Some drivers might also not support
2477
all update flags.
2478
2479
This function is the same as the C function OGR_L_AlterFieldDefn().
2480
2481
@param iField index of the field whose definition must be altered.
2482
@param poNewFieldDefn new field definition
2483
@param nFlagsIn combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG, ALTER_WIDTH_PRECISION_FLAG,
2484
ALTER_NULLABLE_FLAG and ALTER_DEFAULT_FLAG
2485
to indicate which of the name and/or type and/or width and precision fields and/or nullability from the new field
2486
definition must be taken into account.
2487
2488
@return OGRERR_NONE on success.
2489
*/
2490
2491
OGRErr OGRLayer::AlterFieldDefn(int iField, OGRFieldDefn *poNewFieldDefn,
2492
                                int nFlagsIn)
2493
2494
0
{
2495
0
    (void)iField;
2496
0
    (void)poNewFieldDefn;
2497
0
    (void)nFlagsIn;
2498
0
    CPLError(CE_Failure, CPLE_NotSupported,
2499
0
             "AlterFieldDefn() not supported by this layer.");
2500
2501
0
    return OGRERR_UNSUPPORTED_OPERATION;
2502
0
}
2503
2504
/************************************************************************/
2505
/*                        OGR_L_AlterFieldDefn()                        */
2506
/************************************************************************/
2507
2508
/**
2509
\brief Alter the definition of an existing field on a layer.
2510
2511
You must use this to alter the definition of an existing field of a real layer.
2512
Internally the OGRFeatureDefn for the layer will be updated
2513
to reflect the altered field.  Applications should never modify the OGRFeatureDefn
2514
used by a layer directly.
2515
2516
This function should not be called while there are feature objects in existence that
2517
were obtained or created with the previous layer definition.
2518
2519
Not all drivers support this function. You can query a layer to check if it supports it
2520
with the OLCAlterFieldDefn capability. Some drivers may only support this method while
2521
there are still no features in the layer. When it is supported, the existing features of the
2522
backing file/database should be updated accordingly. Some drivers might also not support
2523
all update flags.
2524
2525
This function is the same as the C++ method OGRLayer::AlterFieldDefn().
2526
2527
@param hLayer handle to the layer.
2528
@param iField index of the field whose definition must be altered.
2529
@param hNewFieldDefn new field definition
2530
@param nFlags combination of ALTER_NAME_FLAG, ALTER_TYPE_FLAG, ALTER_WIDTH_PRECISION_FLAG,
2531
ALTER_NULLABLE_FLAG and ALTER_DEFAULT_FLAG
2532
to indicate which of the name and/or type and/or width and precision fields and/or nullability from the new field
2533
definition must be taken into account.
2534
2535
@return OGRERR_NONE on success.
2536
*/
2537
2538
OGRErr OGR_L_AlterFieldDefn(OGRLayerH hLayer, int iField,
2539
                            OGRFieldDefnH hNewFieldDefn, int nFlags)
2540
2541
0
{
2542
0
    VALIDATE_POINTER1(hLayer, "OGR_L_AlterFieldDefn", OGRERR_INVALID_HANDLE);
2543
0
    VALIDATE_POINTER1(hNewFieldDefn, "OGR_L_AlterFieldDefn",
2544
0
                      OGRERR_INVALID_HANDLE);
2545
2546
0
#ifdef OGRAPISPY_ENABLED
2547
0
    if (bOGRAPISpyEnabled)
2548
0
        OGRAPISpy_L_AlterFieldDefn(hLayer, iField, hNewFieldDefn, nFlags);
2549
0
#endif
2550
2551
0
    return OGRLayer::FromHandle(hLayer)->AlterFieldDefn(
2552
0
        iField, OGRFieldDefn::FromHandle(hNewFieldDefn), nFlags);
2553
0
}
2554
2555
/************************************************************************/
2556
/*                         AlterGeomFieldDefn()                         */
2557
/************************************************************************/
2558
2559
/**
2560
\brief Alter the definition of an existing geometry field on a layer.
2561
2562
You must use this to alter the definition of an existing geometry field of a real layer.
2563
Internally the OGRFeatureDefn for the layer will be updated
2564
to reflect the altered field.  Applications should never modify the OGRFeatureDefn
2565
used by a layer directly.
2566
2567
Note that altering the SRS does *not* cause coordinate reprojection to occur:
2568
this is simply a modification of the layer metadata (correcting a wrong SRS
2569
definition). No modification to existing geometries will ever be performed,
2570
so this method cannot be used to e.g. promote single part geometries to their
2571
multipart equivalents.
2572
2573
This method should not be called while there are feature objects in existence that
2574
were obtained or created with the previous layer definition.
2575
2576
Not all drivers support this method. You can query a layer to check if it supports it
2577
with the OLCAlterGeomFieldDefn capability. Some drivers might not support
2578
all update flags. The GDAL_DMD_ALTER_GEOM_FIELD_DEFN_FLAGS driver metadata item
2579
can be queried to examine which flags may be supported by a driver.
2580
2581
This function is the same as the C function OGR_L_AlterGeomFieldDefn().
2582
2583
@param iGeomField index of the field whose definition must be altered.
2584
@param poNewGeomFieldDefn new field definition
2585
@param nFlagsIn combination of ALTER_GEOM_FIELD_DEFN_NAME_FLAG, ALTER_GEOM_FIELD_DEFN_TYPE_FLAG, ALTER_GEOM_FIELD_DEFN_NULLABLE_FLAG, ALTER_GEOM_FIELD_DEFN_SRS_FLAG, ALTER_GEOM_FIELD_DEFN_SRS_COORD_EPOCH_FLAG
2586
to indicate which of the name and/or type and/or nullability and/or SRS and/or coordinate epoch from the new field
2587
definition must be taken into account. Or ALTER_GEOM_FIELD_DEFN_ALL_FLAG to update all members.
2588
2589
@return OGRERR_NONE on success.
2590
2591
@since OGR 3.6.0
2592
*/
2593
2594
OGRErr OGRLayer::AlterGeomFieldDefn(int iGeomField,
2595
                                    const OGRGeomFieldDefn *poNewGeomFieldDefn,
2596
                                    int nFlagsIn)
2597
2598
0
{
2599
0
    (void)iGeomField;
2600
0
    (void)poNewGeomFieldDefn;
2601
0
    (void)nFlagsIn;
2602
2603
0
    CPLError(CE_Failure, CPLE_NotSupported,
2604
0
             "AlterGeomFieldDefn() not supported by this layer.");
2605
2606
0
    return OGRERR_UNSUPPORTED_OPERATION;
2607
0
}
2608
2609
/************************************************************************/
2610
/*                      OGR_L_AlterGeomFieldDefn()                      */
2611
/************************************************************************/
2612
2613
/**
2614
\brief Alter the definition of an existing geometry field on a layer.
2615
2616
You must use this to alter the definition of an existing geometry field of a real layer.
2617
Internally the OGRFeatureDefn for the layer will be updated
2618
to reflect the altered field.  Applications should never modify the OGRFeatureDefn
2619
used by a layer directly.
2620
2621
Note that altering the SRS does *not* cause coordinate reprojection to occur:
2622
this is simply a modification of the layer metadata (correcting a wrong SRS
2623
definition). No modification to existing geometries will ever be performed,
2624
so this method cannot be used to e.g. promote single part geometries to their
2625
multipart equivalents.
2626
2627
This function should not be called while there are feature objects in existence that
2628
were obtained or created with the previous layer definition.
2629
2630
Not all drivers support this function. You can query a layer to check if it supports it
2631
with the OLCAlterGeomFieldDefn capability. Some drivers might not support
2632
all update flags. The GDAL_DMD_ALTER_GEOM_FIELD_DEFN_FLAGS driver metadata item
2633
can be queried to examine which flags may be supported by a driver.
2634
2635
This function is the same as the C++ method OGRLayer::AlterFieldDefn().
2636
2637
@param hLayer handle to the layer.
2638
@param iGeomField index of the field whose definition must be altered.
2639
@param hNewGeomFieldDefn new field definition
2640
@param nFlags combination of ALTER_GEOM_FIELD_DEFN_NAME_FLAG, ALTER_GEOM_FIELD_DEFN_TYPE_FLAG, ALTER_GEOM_FIELD_DEFN_NULLABLE_FLAG, ALTER_GEOM_FIELD_DEFN_SRS_FLAG, ALTER_GEOM_FIELD_DEFN_SRS_COORD_EPOCH_FLAG
2641
to indicate which of the name and/or type and/or nullability and/or SRS and/or coordinate epoch from the new field
2642
definition must be taken into account. Or ALTER_GEOM_FIELD_DEFN_ALL_FLAG to update all members.
2643
2644
@return OGRERR_NONE on success.
2645
2646
@since OGR 3.6.0
2647
*/
2648
2649
OGRErr OGR_L_AlterGeomFieldDefn(OGRLayerH hLayer, int iGeomField,
2650
                                OGRGeomFieldDefnH hNewGeomFieldDefn, int nFlags)
2651
2652
0
{
2653
0
    VALIDATE_POINTER1(hLayer, "OGR_L_AlterGeomFieldDefn",
2654
0
                      OGRERR_INVALID_HANDLE);
2655
0
    VALIDATE_POINTER1(hNewGeomFieldDefn, "OGR_L_AlterGeomFieldDefn",
2656
0
                      OGRERR_INVALID_HANDLE);
2657
2658
0
    return OGRLayer::FromHandle(hLayer)->AlterGeomFieldDefn(
2659
0
        iGeomField,
2660
0
        const_cast<const OGRGeomFieldDefn *>(
2661
0
            OGRGeomFieldDefn::FromHandle(hNewGeomFieldDefn)),
2662
0
        nFlags);
2663
0
}
2664
2665
/************************************************************************/
2666
/*                          CreateGeomField()                           */
2667
/************************************************************************/
2668
2669
/**
2670
\brief Create a new geometry field on a layer.
2671
2672
You must use this to create new geometry fields
2673
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
2674
to reflect the new field.  Applications should never modify the OGRFeatureDefn
2675
used by a layer directly.
2676
2677
This method should not be called while there are feature objects in existence that
2678
were obtained or created with the previous layer definition.
2679
2680
Not all drivers support this method. You can query a layer to check if it supports it
2681
with the OLCCreateGeomField capability. Some drivers may only support this method while
2682
there are still no features in the layer. When it is supported, the existing features of the
2683
backing file/database should be updated accordingly.
2684
2685
Drivers may or may not support not-null constraints. If they support creating
2686
fields with not-null constraints, this is generally before creating any feature to the layer.
2687
2688
This function is the same as the C function OGR_L_CreateGeomField().
2689
2690
@param poField geometry field definition to write to disk.
2691
@param bApproxOK If TRUE, the field may be created in a slightly different
2692
form depending on the limitations of the format driver.
2693
2694
@return OGRERR_NONE on success.
2695
*/
2696
2697
OGRErr OGRLayer::CreateGeomField(const OGRGeomFieldDefn *poField, int bApproxOK)
2698
2699
0
{
2700
0
    (void)poField;
2701
0
    (void)bApproxOK;
2702
2703
0
    CPLError(CE_Failure, CPLE_NotSupported,
2704
0
             "CreateGeomField() not supported by this layer.");
2705
2706
0
    return OGRERR_UNSUPPORTED_OPERATION;
2707
0
}
2708
2709
/************************************************************************/
2710
/*                       OGR_L_CreateGeomField()                        */
2711
/************************************************************************/
2712
2713
/**
2714
\brief Create a new geometry field on a layer.
2715
2716
You must use this to create new geometry fields
2717
on a real layer. Internally the OGRFeatureDefn for the layer will be updated
2718
to reflect the new field.  Applications should never modify the OGRFeatureDefn
2719
used by a layer directly.
2720
2721
This function should not be called while there are feature objects in existence that
2722
were obtained or created with the previous layer definition.
2723
2724
Not all drivers support this function. You can query a layer to check if it supports it
2725
with the OLCCreateField capability. Some drivers may only support this method while
2726
there are still no features in the layer. When it is supported, the existing features of the
2727
backing file/database should be updated accordingly.
2728
2729
Drivers may or may not support not-null constraints. If they support creating
2730
fields with not-null constraints, this is generally before creating any feature to the layer.
2731
2732
 This function is the same as the C++ method OGRLayer::CreateField().
2733
2734
 @param hLayer handle to the layer to write the field definition.
2735
 @param hField handle of the geometry field definition to write to disk.
2736
 @param bApproxOK If TRUE, the field may be created in a slightly different
2737
form depending on the limitations of the format driver.
2738
2739
 @return OGRERR_NONE on success.
2740
*/
2741
2742
OGRErr OGR_L_CreateGeomField(OGRLayerH hLayer, OGRGeomFieldDefnH hField,
2743
                             int bApproxOK)
2744
2745
0
{
2746
0
    VALIDATE_POINTER1(hLayer, "OGR_L_CreateGeomField", OGRERR_INVALID_HANDLE);
2747
0
    VALIDATE_POINTER1(hField, "OGR_L_CreateGeomField", OGRERR_INVALID_HANDLE);
2748
2749
0
#ifdef OGRAPISPY_ENABLED
2750
0
    if (bOGRAPISpyEnabled)
2751
0
        OGRAPISpy_L_CreateGeomField(hLayer, hField, bApproxOK);
2752
0
#endif
2753
2754
0
    return OGRLayer::FromHandle(hLayer)->CreateGeomField(
2755
0
        OGRGeomFieldDefn::FromHandle(hField), bApproxOK);
2756
0
}
2757
2758
/************************************************************************/
2759
/*                          StartTransaction()                          */
2760
/************************************************************************/
2761
2762
/**
2763
 \brief For datasources which support transactions, StartTransaction creates a transaction.
2764
2765
 If starting the transaction fails, will return
2766
 OGRERR_FAILURE. Datasources which do not support transactions will
2767
 always return OGRERR_NONE.
2768
2769
 Use of this API is discouraged when the dataset offers
2770
 dataset level transaction with GDALDataset::StartTransaction(). The reason is
2771
 that most drivers can only offer transactions at dataset level, and not layer level.
2772
 Very few drivers really support transactions at layer scope.
2773
2774
 This function is the same as the C function OGR_L_StartTransaction().
2775
2776
 @return OGRERR_NONE on success.
2777
*/
2778
2779
OGRErr OGRLayer::StartTransaction()
2780
2781
0
{
2782
0
    return OGRERR_NONE;
2783
0
}
2784
2785
/************************************************************************/
2786
/*                       OGR_L_StartTransaction()                       */
2787
/************************************************************************/
2788
2789
/**
2790
 \brief For datasources which support transactions, StartTransaction creates a transaction.
2791
2792
 If starting the transaction fails, will return
2793
 OGRERR_FAILURE. Datasources which do not support transactions will
2794
 always return OGRERR_NONE.
2795
2796
 Use of this API is discouraged when the dataset offers
2797
 dataset level transaction with GDALDataset::StartTransaction(). The reason is
2798
 that most drivers can only offer transactions at dataset level, and not layer level.
2799
 Very few drivers really support transactions at layer scope.
2800
2801
 This function is the same as the C++ method OGRLayer::StartTransaction().
2802
2803
 @param hLayer handle to the layer
2804
2805
 @return OGRERR_NONE on success.
2806
2807
*/
2808
2809
OGRErr OGR_L_StartTransaction(OGRLayerH hLayer)
2810
2811
0
{
2812
0
    VALIDATE_POINTER1(hLayer, "OGR_L_StartTransaction", OGRERR_INVALID_HANDLE);
2813
2814
0
#ifdef OGRAPISPY_ENABLED
2815
0
    if (bOGRAPISpyEnabled)
2816
0
        OGRAPISpy_L_StartTransaction(hLayer);
2817
0
#endif
2818
2819
0
    return OGRLayer::FromHandle(hLayer)->StartTransaction();
2820
0
}
2821
2822
/************************************************************************/
2823
/*                         CommitTransaction()                          */
2824
/************************************************************************/
2825
2826
/**
2827
 \brief For datasources which support transactions, CommitTransaction commits a transaction.
2828
2829
 If no transaction is active, or the commit fails, will return
2830
 OGRERR_FAILURE. Datasources which do not support transactions will
2831
 always return OGRERR_NONE.
2832
2833
 This function is the same as the C function OGR_L_CommitTransaction().
2834
2835
 @return OGRERR_NONE on success.
2836
*/
2837
2838
OGRErr OGRLayer::CommitTransaction()
2839
2840
0
{
2841
0
    return OGRERR_NONE;
2842
0
}
2843
2844
/************************************************************************/
2845
/*                      OGR_L_CommitTransaction()                       */
2846
/************************************************************************/
2847
2848
/**
2849
 \brief For datasources which support transactions, CommitTransaction commits a transaction.
2850
2851
 If no transaction is active, or the commit fails, will return
2852
 OGRERR_FAILURE. Datasources which do not support transactions will
2853
 always return OGRERR_NONE.
2854
2855
 This function is the same as the C function OGR_L_CommitTransaction().
2856
2857
 @return OGRERR_NONE on success.
2858
*/
2859
2860
OGRErr OGR_L_CommitTransaction(OGRLayerH hLayer)
2861
2862
0
{
2863
0
    VALIDATE_POINTER1(hLayer, "OGR_L_CommitTransaction", OGRERR_INVALID_HANDLE);
2864
2865
0
#ifdef OGRAPISPY_ENABLED
2866
0
    if (bOGRAPISpyEnabled)
2867
0
        OGRAPISpy_L_CommitTransaction(hLayer);
2868
0
#endif
2869
2870
0
    return OGRLayer::FromHandle(hLayer)->CommitTransaction();
2871
0
}
2872
2873
/************************************************************************/
2874
/*                        RollbackTransaction()                         */
2875
/************************************************************************/
2876
2877
/**
2878
 \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction.
2879
 If no transaction is active, or the rollback fails, will return
2880
 OGRERR_FAILURE. Datasources which do not support transactions will
2881
 always return OGRERR_NONE.
2882
2883
 This function is the same as the C function OGR_L_RollbackTransaction().
2884
2885
2886
 OGRFeature* instances acquired or created between the StartTransaction() and RollbackTransaction() should
2887
 be destroyed before RollbackTransaction() if the field structure has been modified during the transaction.
2888
2889
 In particular, the following is invalid:
2890
2891
 \code
2892
 lyr->StartTransaction();
2893
 lyr->DeleteField(...);
2894
 f = new OGRFeature(lyr->GetLayerDefn());
2895
 lyr->RollbackTransaction();
2896
 // f is in a inconsistent state at this point, given its array of fields doesn't match
2897
 // the updated layer definition, and thus it cannot even be safely deleted !
2898
 \endcode
2899
2900
 Instead, the feature should be destroyed before the rollback:
2901
2902
 \code
2903
 lyr->StartTransaction();
2904
 lyr->DeleteField(...);
2905
 f = new OGRFeature(lyr->GetLayerDefn());
2906
 ...
2907
 delete f;
2908
 \endcode
2909
2910
 @return OGRERR_NONE on success.
2911
*/
2912
2913
OGRErr OGRLayer::RollbackTransaction()
2914
2915
0
{
2916
0
    return OGRERR_UNSUPPORTED_OPERATION;
2917
0
}
2918
2919
/************************************************************************/
2920
/*                     OGR_L_RollbackTransaction()                      */
2921
/************************************************************************/
2922
2923
/**
2924
 \brief For datasources which support transactions, RollbackTransaction will roll back a datasource to its state before the start of the current transaction.
2925
 If no transaction is active, or the rollback fails, will return
2926
 OGRERR_FAILURE. Datasources which do not support transactions will
2927
 always return OGRERR_NONE.
2928
2929
 This function is the same as the C++ method OGRLayer::RollbackTransaction().
2930
2931
 @param hLayer handle to the layer
2932
2933
 @return OGRERR_NONE on success.
2934
*/
2935
2936
OGRErr OGR_L_RollbackTransaction(OGRLayerH hLayer)
2937
2938
0
{
2939
0
    VALIDATE_POINTER1(hLayer, "OGR_L_RollbackTransaction",
2940
0
                      OGRERR_INVALID_HANDLE);
2941
2942
0
#ifdef OGRAPISPY_ENABLED
2943
0
    if (bOGRAPISpyEnabled)
2944
0
        OGRAPISpy_L_RollbackTransaction(hLayer);
2945
0
#endif
2946
2947
0
    return OGRLayer::FromHandle(hLayer)->RollbackTransaction();
2948
0
}
2949
2950
/************************************************************************/
2951
/*                       OGRLayer::GetLayerDefn()                       */
2952
/************************************************************************/
2953
2954
/**
2955
 \fn OGRFeatureDefn *OGRLayer::GetLayerDefn();
2956
2957
 \brief Fetch the schema information for this layer.
2958
2959
 The returned OGRFeatureDefn is owned by the OGRLayer, and should not be
2960
 modified or freed by the application.  It encapsulates the attribute schema
2961
 of the features of the layer.
2962
2963
 This method is the same as the C function OGR_L_GetLayerDefn().
2964
2965
 @return feature definition.
2966
*/
2967
2968
/**
2969
 \fn const OGRFeatureDefn *OGRLayer::GetLayerDefn() const;
2970
2971
 \brief Fetch the schema information for this layer.
2972
2973
 The returned OGRFeatureDefn is owned by the OGRLayer, and should not be
2974
 modified or freed by the application.  It encapsulates the attribute schema
2975
 of the features of the layer.
2976
2977
 Note that even if this method is const, there is no guarantee it can be
2978
 safely called by concurrent threads on the same GDALDataset object.
2979
2980
 This method is the same as the C function OGR_L_GetLayerDefn().
2981
2982
 @return feature definition.
2983
2984
 @since 3.12
2985
*/
2986
2987
/************************************************************************/
2988
/*                         OGR_L_GetLayerDefn()                         */
2989
/************************************************************************/
2990
2991
/**
2992
 \brief Fetch the schema information for this layer.
2993
2994
 The returned handle to the OGRFeatureDefn is owned by the OGRLayer,
2995
 and should not be modified or freed by the application.  It encapsulates
2996
 the attribute schema of the features of the layer.
2997
2998
 This function is the same as the C++ method OGRLayer::GetLayerDefn().
2999
3000
 @param hLayer handle to the layer to get the schema information.
3001
 @return a handle to the feature definition.
3002
3003
*/
3004
OGRFeatureDefnH OGR_L_GetLayerDefn(OGRLayerH hLayer)
3005
3006
0
{
3007
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetLayerDefn", nullptr);
3008
3009
0
#ifdef OGRAPISPY_ENABLED
3010
0
    if (bOGRAPISpyEnabled)
3011
0
        OGRAPISpy_L_GetLayerDefn(hLayer);
3012
0
#endif
3013
3014
0
    return OGRFeatureDefn::ToHandle(
3015
0
        OGRLayer::FromHandle(hLayer)->GetLayerDefn());
3016
0
}
3017
3018
/************************************************************************/
3019
/*                        OGR_L_FindFieldIndex()                        */
3020
/************************************************************************/
3021
3022
/**
3023
 \brief Find the index of field in a layer.
3024
3025
 The returned number is the index of the field in the layers, or -1 if the
3026
 field doesn't exist.
3027
3028
 If bExactMatch is set to FALSE and the field doesn't exist in the given form
3029
 the driver might apply some changes to make it match, like those it might do
3030
 if the layer was created (eg. like LAUNDER in the OCI driver).
3031
3032
 This method is the same as the C++ method OGRLayer::FindFieldIndex().
3033
3034
 @return field index, or -1 if the field doesn't exist
3035
*/
3036
3037
int OGR_L_FindFieldIndex(OGRLayerH hLayer, const char *pszFieldName,
3038
                         int bExactMatch)
3039
3040
0
{
3041
0
    VALIDATE_POINTER1(hLayer, "OGR_L_FindFieldIndex", -1);
3042
3043
0
#ifdef OGRAPISPY_ENABLED
3044
0
    if (bOGRAPISpyEnabled)
3045
0
        OGRAPISpy_L_FindFieldIndex(hLayer, pszFieldName, bExactMatch);
3046
0
#endif
3047
3048
0
    return OGRLayer::FromHandle(hLayer)->FindFieldIndex(pszFieldName,
3049
0
                                                        bExactMatch);
3050
0
}
3051
3052
/************************************************************************/
3053
/*                           FindFieldIndex()                           */
3054
/************************************************************************/
3055
3056
/**
3057
 \brief Find the index of field in the layer.
3058
3059
 The returned number is the index of the field in the layers, or -1 if the
3060
 field doesn't exist.
3061
3062
 If bExactMatch is set to FALSE and the field doesn't exist in the given form
3063
 the driver might apply some changes to make it match, like those it might do
3064
 if the layer was created (eg. like LAUNDER in the OCI driver).
3065
3066
 This method is the same as the C function OGR_L_FindFieldIndex().
3067
3068
 @return field index, or -1 if the field doesn't exist
3069
*/
3070
3071
int OGRLayer::FindFieldIndex(const char *pszFieldName,
3072
                             CPL_UNUSED int bExactMatch)
3073
0
{
3074
0
    return GetLayerDefn()->GetFieldIndex(pszFieldName);
3075
0
}
3076
3077
/************************************************************************/
3078
/*                           GetSpatialRef()                            */
3079
/************************************************************************/
3080
3081
/**
3082
 \brief Fetch the spatial reference system for this layer.
3083
3084
 The returned object is owned by the OGRLayer and should not be modified
3085
 or freed by the application.
3086
3087
 Note that even if this method is const (since GDAL 3.12), there is no guarantee
3088
 it can be safely called by concurrent threads on the same GDALDataset object.
3089
3090
 Several geometry fields can be associated to a
3091
 feature definition. Each geometry field can have its own spatial reference
3092
 system, which is returned by OGRGeomFieldDefn::GetSpatialRef().
3093
 OGRLayer::GetSpatialRef() is equivalent to
3094
 GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(0)->GetSpatialRef()
3095
3096
 This method is the same as the C function OGR_L_GetSpatialRef().
3097
3098
 @return spatial reference, or NULL if there isn't one.
3099
*/
3100
3101
const OGRSpatialReference *OGRLayer::GetSpatialRef() const
3102
0
{
3103
0
    const auto poLayerDefn = GetLayerDefn();
3104
0
    if (poLayerDefn->GetGeomFieldCount() > 0)
3105
0
        return poLayerDefn->GetGeomFieldDefn(0)->GetSpatialRef();
3106
0
    else
3107
0
        return nullptr;
3108
0
}
3109
3110
/************************************************************************/
3111
/*                        OGR_L_GetSpatialRef()                         */
3112
/************************************************************************/
3113
3114
/**
3115
 \brief Fetch the spatial reference system for this layer.
3116
3117
 The returned object is owned by the OGRLayer and should not be modified
3118
 or freed by the application.
3119
3120
 This function is the same as the C++ method OGRLayer::GetSpatialRef().
3121
3122
 @param hLayer handle to the layer to get the spatial reference from.
3123
 @return spatial reference, or NULL if there isn't one.
3124
*/
3125
3126
OGRSpatialReferenceH OGR_L_GetSpatialRef(OGRLayerH hLayer)
3127
3128
0
{
3129
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetSpatialRef", nullptr);
3130
3131
0
#ifdef OGRAPISPY_ENABLED
3132
0
    if (bOGRAPISpyEnabled)
3133
0
        OGRAPISpy_L_GetSpatialRef(hLayer);
3134
0
#endif
3135
3136
0
    return OGRSpatialReference::ToHandle(const_cast<OGRSpatialReference *>(
3137
0
        OGRLayer::FromHandle(hLayer)->GetSpatialRef()));
3138
0
}
3139
3140
/************************************************************************/
3141
/*                      OGRLayer::TestCapability()                      */
3142
/************************************************************************/
3143
3144
/**
3145
 \fn bool OGRLayer::TestCapability( const char * pszCap ) const;
3146
3147
 \brief Test if this layer supported the named capability.
3148
3149
 The capability codes that can be tested are represented as strings, but
3150
 \#defined constants exists to ensure correct spelling.  Specific layer
3151
 types may implement class specific capabilities, but this can't generally
3152
 be discovered by the caller. <p>
3153
3154
<ul>
3155
3156
 <li> <b>OLCRandomRead</b> / "RandomRead": TRUE if the GetFeature() method
3157
is implemented in an optimized way for this layer, as opposed to the default
3158
implementation using ResetReading() and GetNextFeature() to find the requested
3159
feature id.<p>
3160
3161
 <li> <b>OLCSequentialWrite</b> / "SequentialWrite": TRUE if the
3162
CreateFeature() method works for this layer.  Note this means that this
3163
particular layer is writable.  The same OGRLayer class may return FALSE
3164
for other layer instances that are effectively read-only.<p>
3165
3166
 <li> <b>OLCRandomWrite</b> / "RandomWrite": TRUE if the SetFeature() method
3167
is operational on this layer.  Note this means that this
3168
particular layer is writable.  The same OGRLayer class may return FALSE
3169
for other layer instances that are effectively read-only.<p>
3170
3171
 <li> <b>OLCUpsertFeature</b> / "UpsertFeature": TRUE if the UpsertFeature()
3172
method is operational on this layer.  Note this means that this
3173
particular layer is writable.  The same OGRLayer class may return FALSE
3174
for other layer instances that are effectively read-only.<p>
3175
3176
 <li> <b>OLCFastSpatialFilter</b> / "FastSpatialFilter": TRUE if this layer
3177
implements spatial filtering efficiently.  Layers that effectively read all
3178
features, and test them with the OGRFeature intersection methods should
3179
return FALSE.  This can be used as a clue by the application whether it
3180
should build and maintain its own spatial index for features in this layer.<p>
3181
3182
 <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount":
3183
TRUE if this layer can return a feature
3184
count (via GetFeatureCount()) efficiently. i.e. without counting
3185
the features.  In some cases this will return TRUE until a spatial filter is
3186
installed after which it will return FALSE.<p>
3187
3188
 <li> <b>OLCFastGetExtent</b> / "FastGetExtent":
3189
TRUE if this layer can return its data extent (via GetExtent())
3190
efficiently, i.e. without scanning all the features.  In some cases this
3191
will return TRUE until a spatial filter is installed after which it will
3192
return FALSE.<p>
3193
3194
 <li> <b>OLCFastSetNextByIndex</b> / "FastSetNextByIndex":
3195
TRUE if this layer can perform the SetNextByIndex() call efficiently, otherwise
3196
FALSE.<p>
3197
3198
 <li> <b>OLCCreateField</b> / "CreateField": TRUE if this layer can create
3199
new fields on the current layer using CreateField(), otherwise FALSE.<p>
3200
3201
 <li> <b>OLCCreateGeomField</b> / "CreateGeomField": (GDAL >= 1.11) TRUE if this layer can create
3202
new geometry fields on the current layer using CreateGeomField(), otherwise FALSE.<p>
3203
3204
 <li> <b>OLCDeleteField</b> / "DeleteField": TRUE if this layer can delete
3205
existing fields on the current layer using DeleteField(), otherwise FALSE.<p>
3206
3207
 <li> <b>OLCReorderFields</b> / "ReorderFields": TRUE if this layer can reorder
3208
existing fields on the current layer using ReorderField() or ReorderFields(), otherwise FALSE.<p>
3209
3210
 <li> <b>OLCAlterFieldDefn</b> / "AlterFieldDefn": TRUE if this layer can alter
3211
the definition of an existing field on the current layer using AlterFieldDefn(), otherwise FALSE.<p>
3212
3213
 <li> <b>OLCAlterGeomFieldDefn</b> / "AlterGeomFieldDefn": TRUE if this layer can alter
3214
the definition of an existing geometry field on the current layer using AlterGeomFieldDefn(), otherwise FALSE.<p>
3215
3216
 <li> <b>OLCDeleteFeature</b> / "DeleteFeature": TRUE if the DeleteFeature()
3217
method is supported on this layer, otherwise FALSE.<p>
3218
3219
 <li> <b>OLCStringsAsUTF8</b> / "StringsAsUTF8": TRUE if values of OFTString
3220
fields are assured to be in UTF-8 format.  If FALSE the encoding of fields
3221
is uncertain, though it might still be UTF-8.<p>
3222
3223
<li> <b>OLCTransactions</b> / "Transactions": TRUE if the StartTransaction(),
3224
CommitTransaction() and RollbackTransaction() methods work in a meaningful way,
3225
otherwise FALSE.<p>
3226
3227
<li> <b>OLCIgnoreFields</b> / "IgnoreFields": TRUE if fields, geometry and style
3228
will be omitted when fetching features as set by SetIgnoredFields() method.
3229
3230
<li> <b>OLCCurveGeometries</b> / "CurveGeometries": TRUE if this layer supports
3231
writing curve geometries or may return such geometries.
3232
3233
<p>
3234
3235
</ul>
3236
3237
 This method is the same as the C function OGR_L_TestCapability().
3238
3239
 @param pszCap the name of the capability to test.
3240
3241
 @return TRUE if the layer has the requested capability, or FALSE otherwise.
3242
OGRLayers will return FALSE for any unrecognized capabilities.<p>
3243
3244
*/
3245
3246
/************************************************************************/
3247
/*                        OGR_L_TestCapability()                        */
3248
/************************************************************************/
3249
3250
/**
3251
 \brief Test if this layer supported the named capability.
3252
3253
 The capability codes that can be tested are represented as strings, but
3254
 \#defined constants exists to ensure correct spelling.  Specific layer
3255
 types may implement class specific capabilities, but this can't generally
3256
 be discovered by the caller. <p>
3257
3258
<ul>
3259
3260
 <li> <b>OLCRandomRead</b> / "RandomRead": TRUE if the GetFeature() method
3261
is implemented in an optimized way for this layer, as opposed to the default
3262
implementation using ResetReading() and GetNextFeature() to find the requested
3263
feature id.<p>
3264
3265
 <li> <b>OLCSequentialWrite</b> / "SequentialWrite": TRUE if the
3266
CreateFeature() method works for this layer.  Note this means that this
3267
particular layer is writable.  The same OGRLayer class may return FALSE
3268
for other layer instances that are effectively read-only.<p>
3269
3270
 <li> <b>OLCRandomWrite</b> / "RandomWrite": TRUE if the SetFeature() method
3271
is operational on this layer.  Note this means that this
3272
particular layer is writable.  The same OGRLayer class may return FALSE
3273
for other layer instances that are effectively read-only.<p>
3274
3275
 <li> <b>OLCUpsertFeature</b> / "UpsertFeature": TRUE if the UpsertFeature()
3276
method is operational on this layer.  Note this means that this
3277
particular layer is writable.  The same OGRLayer class may return FALSE
3278
for other layer instances that are effectively read-only.<p>
3279
3280
 <li> <b>OLCFastSpatialFilter</b> / "FastSpatialFilter": TRUE if this layer
3281
implements spatial filtering efficiently.  Layers that effectively read all
3282
features, and test them with the OGRFeature intersection methods should
3283
return FALSE.  This can be used as a clue by the application whether it
3284
should build and maintain its own spatial index for features in this
3285
layer.<p>
3286
3287
 <li> <b>OLCFastFeatureCount</b> / "FastFeatureCount":
3288
TRUE if this layer can return a feature
3289
count (via OGR_L_GetFeatureCount()) efficiently, i.e. without counting
3290
the features.  In some cases this will return TRUE until a spatial filter is
3291
installed after which it will return FALSE.<p>
3292
3293
 <li> <b>OLCFastGetExtent</b> / "FastGetExtent":
3294
TRUE if this layer can return its data extent (via OGR_L_GetExtent())
3295
efficiently, i.e. without scanning all the features.  In some cases this
3296
will return TRUE until a spatial filter is installed after which it will
3297
return FALSE.<p>
3298
3299
 <li> <b>OLCFastSetNextByIndex</b> / "FastSetNextByIndex":
3300
TRUE if this layer can perform the SetNextByIndex() call efficiently, otherwise
3301
FALSE.<p>
3302
3303
 <li> <b>OLCCreateField</b> / "CreateField": TRUE if this layer can create
3304
new fields on the current layer using CreateField(), otherwise FALSE.<p>
3305
3306
 <li> <b>OLCCreateGeomField</b> / "CreateGeomField": (GDAL >= 1.11) TRUE if this layer can create
3307
new geometry fields on the current layer using CreateGeomField(), otherwise FALSE.<p>
3308
3309
 <li> <b>OLCDeleteField</b> / "DeleteField": TRUE if this layer can delete
3310
existing fields on the current layer using DeleteField(), otherwise FALSE.<p>
3311
3312
 <li> <b>OLCReorderFields</b> / "ReorderFields": TRUE if this layer can reorder
3313
existing fields on the current layer using ReorderField() or ReorderFields(), otherwise FALSE.<p>
3314
3315
 <li> <b>OLCAlterFieldDefn</b> / "AlterFieldDefn": TRUE if this layer can alter
3316
the definition of an existing field on the current layer using AlterFieldDefn(), otherwise FALSE.<p>
3317
3318
 <li> <b>OLCAlterGeomFieldDefn</b> / "AlterGeomFieldDefn": TRUE if this layer can alter
3319
the definition of an existing geometry field on the current layer using AlterGeomFieldDefn(), otherwise FALSE.<p>
3320
3321
 <li> <b>OLCDeleteFeature</b> / "DeleteFeature": TRUE if the DeleteFeature()
3322
method is supported on this layer, otherwise FALSE.<p>
3323
3324
 <li> <b>OLCStringsAsUTF8</b> / "StringsAsUTF8": TRUE if values of OFTString
3325
fields are assured to be in UTF-8 format.  If FALSE the encoding of fields
3326
is uncertain, though it might still be UTF-8.<p>
3327
3328
<li> <b>OLCTransactions</b> / "Transactions": TRUE if the StartTransaction(),
3329
CommitTransaction() and RollbackTransaction() methods work in a meaningful way,
3330
otherwise FALSE.<p>
3331
3332
<li> <b>OLCCurveGeometries</b> / "CurveGeometries": TRUE if this layer supports
3333
writing curve geometries or may return such geometries.
3334
3335
<p>
3336
3337
</ul>
3338
3339
 This function is the same as the C++ method OGRLayer::TestCapability().
3340
3341
 @param hLayer handle to the layer to get the capability from.
3342
 @param pszCap the name of the capability to test.
3343
3344
 @return TRUE if the layer has the requested capability, or FALSE otherwise.
3345
OGRLayers will return FALSE for any unrecognized capabilities.<p>
3346
3347
*/
3348
3349
int OGR_L_TestCapability(OGRLayerH hLayer, const char *pszCap)
3350
3351
0
{
3352
0
    VALIDATE_POINTER1(hLayer, "OGR_L_TestCapability", 0);
3353
0
    VALIDATE_POINTER1(pszCap, "OGR_L_TestCapability", 0);
3354
3355
0
#ifdef OGRAPISPY_ENABLED
3356
0
    if (bOGRAPISpyEnabled)
3357
0
        OGRAPISpy_L_TestCapability(hLayer, pszCap);
3358
0
#endif
3359
3360
0
    return OGRLayer::FromHandle(hLayer)->TestCapability(pszCap);
3361
0
}
3362
3363
/************************************************************************/
3364
/*                          GetSpatialFilter()                          */
3365
/************************************************************************/
3366
3367
/**
3368
 \brief This method returns the current spatial filter for this layer.
3369
3370
 The returned pointer is to an internally owned object, and should not
3371
 be altered or deleted by the caller.
3372
3373
 This method is the same as the C function OGR_L_GetSpatialFilter().
3374
3375
 @return spatial filter geometry.
3376
 */
3377
3378
OGRGeometry *OGRLayer::GetSpatialFilter()
3379
3380
0
{
3381
0
    return m_poFilterGeom;
3382
0
}
3383
3384
/************************************************************************/
3385
/*                       OGR_L_GetSpatialFilter()                       */
3386
/************************************************************************/
3387
3388
/**
3389
 \brief This function returns the current spatial filter for this layer.
3390
3391
 The returned pointer is to an internally owned object, and should not
3392
 be altered or deleted by the caller.
3393
3394
 This function is the same as the C++ method OGRLayer::GetSpatialFilter().
3395
3396
 @param hLayer handle to the layer to get the spatial filter from.
3397
 @return a handle to the spatial filter geometry.
3398
 */
3399
3400
OGRGeometryH OGR_L_GetSpatialFilter(OGRLayerH hLayer)
3401
3402
0
{
3403
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetSpatialFilter", nullptr);
3404
3405
0
#ifdef OGRAPISPY_ENABLED
3406
0
    if (bOGRAPISpyEnabled)
3407
0
        OGRAPISpy_L_GetSpatialFilter(hLayer);
3408
0
#endif
3409
3410
0
    return OGRGeometry::ToHandle(
3411
0
        OGRLayer::FromHandle(hLayer)->GetSpatialFilter());
3412
0
}
3413
3414
/************************************************************************/
3415
/*           ValidateGeometryFieldIndexForSetSpatialFilter()            */
3416
/************************************************************************/
3417
3418
//! @cond Doxygen_Suppress
3419
bool OGRLayer::ValidateGeometryFieldIndexForSetSpatialFilter(
3420
    int iGeomField, const OGRGeometry *poGeomIn, bool bIsSelectLayer)
3421
0
{
3422
0
    if (iGeomField == 0 && poGeomIn == nullptr &&
3423
0
        GetLayerDefn()->GetGeomFieldCount() == 0)
3424
0
    {
3425
        // Setting a null spatial filter on geometry field idx 0
3426
        // when there are no geometry field can't harm, and is accepted silently
3427
        // for backward compatibility with existing practice.
3428
0
    }
3429
0
    else if (iGeomField < 0 ||
3430
0
             iGeomField >= GetLayerDefn()->GetGeomFieldCount())
3431
0
    {
3432
0
        if (iGeomField == 0)
3433
0
        {
3434
0
            CPLError(
3435
0
                CE_Failure, CPLE_AppDefined,
3436
0
                bIsSelectLayer
3437
0
                    ? "Cannot set spatial filter: no geometry field selected."
3438
0
                    : "Cannot set spatial filter: no geometry field present in "
3439
0
                      "layer.");
3440
0
        }
3441
0
        else
3442
0
        {
3443
0
            CPLError(CE_Failure, CPLE_AppDefined,
3444
0
                     "Cannot set spatial filter on non-existing geometry field "
3445
0
                     "of index %d.",
3446
0
                     iGeomField);
3447
0
        }
3448
0
        return false;
3449
0
    }
3450
0
    return true;
3451
0
}
3452
3453
//! @endcond
3454
3455
/************************************************************************/
3456
/*                          SetSpatialFilter()                          */
3457
/************************************************************************/
3458
3459
/**
3460
 \brief Set a new spatial filter.
3461
3462
 This method set the geometry to be used as a spatial filter when
3463
 fetching features via the GetNextFeature() method.  Only features that
3464
 geometrically intersect the filter geometry will be returned.
3465
3466
 Currently this test is may be inaccurately implemented, but it is
3467
 guaranteed that all features whose envelope (as returned by
3468
 OGRGeometry::getEnvelope()) overlaps the envelope of the spatial filter
3469
 will be returned.  This can result in more shapes being returned that
3470
 should strictly be the case.
3471
3472
 Features with null or empty geometries will never
3473
 be considered as matching a spatial filter.
3474
3475
 This method makes an internal copy of the passed geometry.  The
3476
 passed geometry remains the responsibility of the caller, and may
3477
 be safely destroyed.
3478
3479
 For the time being the passed filter geometry should be in the same
3480
 SRS as the layer (as returned by OGRLayer::GetSpatialRef()).  In the
3481
 future this may be generalized.
3482
3483
 This method is the same as the C function OGR_L_SetSpatialFilter().
3484
3485
 @param poFilter the geometry to use as a filtering region.  NULL may
3486
 be passed indicating that the current spatial filter should be cleared,
3487
 but no new one instituted.
3488
 */
3489
3490
OGRErr OGRLayer::SetSpatialFilter(const OGRGeometry *poFilter)
3491
3492
0
{
3493
0
    return SetSpatialFilter(0, poFilter);
3494
0
}
3495
3496
/**
3497
 \brief Set a new spatial filter.
3498
3499
 This method set the geometry to be used as a spatial filter when
3500
 fetching features via the GetNextFeature() method.  Only features that
3501
 geometrically intersect the filter geometry will be returned.
3502
3503
 Currently this test is may be inaccurately implemented, but it is
3504
 guaranteed that all features who's envelope (as returned by
3505
 OGRGeometry::getEnvelope()) overlaps the envelope of the spatial filter
3506
 will be returned.  This can result in more shapes being returned that
3507
 should strictly be the case.
3508
3509
 This method makes an internal copy of the passed geometry.  The
3510
 passed geometry remains the responsibility of the caller, and may
3511
 be safely destroyed.
3512
3513
 For the time being the passed filter geometry should be in the same
3514
 SRS as the geometry field definition it corresponds to (as returned by
3515
 GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(iGeomField)->GetSpatialRef()).  In the
3516
 future this may be generalized.
3517
3518
 Note that only the last spatial filter set is applied, even if several
3519
 successive calls are done with different iGeomField values.
3520
3521
 This method is the same as the C function OGR_L_SetSpatialFilterEx().
3522
3523
 @param iGeomField index of the geometry field on which the spatial filter
3524
 operates.
3525
 @param poFilter the geometry to use as a filtering region.  NULL may
3526
 be passed indicating that the current spatial filter should be cleared,
3527
 but no new one instituted.
3528
 */
3529
3530
OGRErr OGRLayer::SetSpatialFilter(int iGeomField, const OGRGeometry *poFilter)
3531
3532
0
{
3533
0
    if (iGeomField == 0)
3534
0
    {
3535
0
        if (poFilter &&
3536
0
            !ValidateGeometryFieldIndexForSetSpatialFilter(0, poFilter))
3537
0
        {
3538
0
            return OGRERR_FAILURE;
3539
0
        }
3540
0
    }
3541
0
    else
3542
0
    {
3543
0
        if (!ValidateGeometryFieldIndexForSetSpatialFilter(iGeomField,
3544
0
                                                           poFilter))
3545
0
        {
3546
0
            return OGRERR_FAILURE;
3547
0
        }
3548
0
    }
3549
3550
0
    return ISetSpatialFilter(iGeomField, poFilter);
3551
0
}
3552
3553
/************************************************************************/
3554
/*                         ISetSpatialFilter()                          */
3555
/************************************************************************/
3556
3557
/**
3558
 \brief Set a new spatial filter.
3559
3560
 Virtual method implemented by drivers since 3.11. In previous versions,
3561
 SetSpatialFilter() / SetSpatialFilterRect() itself was the virtual method.
3562
3563
 Driver implementations, when wanting to call the base method, must take
3564
 care of calling OGRLayer::ISetSpatialFilter() (and note the public method without
3565
 the leading I).
3566
3567
 @param iGeomField index of the geometry field on which the spatial filter
3568
 operates.
3569
 @param poFilter the geometry to use as a filtering region.  NULL may
3570
 be passed indicating that the current spatial filter should be cleared,
3571
 but no new one instituted.
3572
3573
 @since GDAL 3.11
3574
 */
3575
3576
OGRErr OGRLayer::ISetSpatialFilter(int iGeomField, const OGRGeometry *poFilter)
3577
3578
0
{
3579
0
    m_iGeomFieldFilter = iGeomField;
3580
0
    if (InstallFilter(poFilter))
3581
0
        ResetReading();
3582
0
    return OGRERR_NONE;
3583
0
}
3584
3585
/************************************************************************/
3586
/*                       OGR_L_SetSpatialFilter()                       */
3587
/************************************************************************/
3588
3589
/**
3590
 \brief Set a new spatial filter.
3591
3592
 This function set the geometry to be used as a spatial filter when
3593
 fetching features via the OGR_L_GetNextFeature() function.  Only
3594
 features that geometrically intersect the filter geometry will be
3595
 returned.
3596
3597
 Currently this test is may be inaccurately implemented, but it is
3598
 guaranteed that all features whose envelope (as returned by
3599
 OGR_G_GetEnvelope()) overlaps the envelope of the spatial filter
3600
 will be returned.  This can result in more shapes being returned that
3601
 should strictly be the case.
3602
3603
 Features with null or empty geometries will never
3604
 be considered as matching a spatial filter.
3605
3606
 This function makes an internal copy of the passed geometry.  The
3607
 passed geometry remains the responsibility of the caller, and may
3608
 be safely destroyed.
3609
3610
 For the time being the passed filter geometry should be in the same
3611
 SRS as the layer (as returned by OGR_L_GetSpatialRef()).  In the
3612
 future this may be generalized.
3613
3614
 This function is the same as the C++ method OGRLayer::SetSpatialFilter.
3615
3616
 @param hLayer handle to the layer on which to set the spatial filter.
3617
 @param hGeom handle to the geometry to use as a filtering region.  NULL may
3618
 be passed indicating that the current spatial filter should be cleared,
3619
 but no new one instituted.
3620
3621
 */
3622
3623
void OGR_L_SetSpatialFilter(OGRLayerH hLayer, OGRGeometryH hGeom)
3624
3625
0
{
3626
0
    VALIDATE_POINTER0(hLayer, "OGR_L_SetSpatialFilter");
3627
3628
0
#ifdef OGRAPISPY_ENABLED
3629
0
    if (bOGRAPISpyEnabled)
3630
0
        OGRAPISpy_L_SetSpatialFilter(hLayer, hGeom);
3631
0
#endif
3632
3633
0
    OGRLayer::FromHandle(hLayer)->SetSpatialFilter(
3634
0
        OGRGeometry::FromHandle(hGeom));
3635
0
}
3636
3637
/************************************************************************/
3638
/*                      OGR_L_SetSpatialFilterEx()                      */
3639
/************************************************************************/
3640
3641
/**
3642
 \brief Set a new spatial filter.
3643
3644
 This function set the geometry to be used as a spatial filter when
3645
 fetching features via the OGR_L_GetNextFeature() function.  Only
3646
 features that geometrically intersect the filter geometry will be
3647
 returned.
3648
3649
 Currently this test is may be inaccurately implemented, but it is
3650
 guaranteed that all features who's envelope (as returned by
3651
 OGR_G_GetEnvelope()) overlaps the envelope of the spatial filter
3652
 will be returned.  This can result in more shapes being returned that
3653
 should strictly be the case.
3654
3655
 This function makes an internal copy of the passed geometry.  The
3656
 passed geometry remains the responsibility of the caller, and may
3657
 be safely destroyed.
3658
3659
 For the time being the passed filter geometry should be in the same
3660
 SRS as the geometry field definition it corresponds to (as returned by
3661
 GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(iGeomField)->GetSpatialRef()).  In the
3662
 future this may be generalized.
3663
3664
 Note that only the last spatial filter set is applied, even if several
3665
 successive calls are done with different iGeomField values.
3666
3667
 This function is the same as the C++ method OGRLayer::SetSpatialFilter.
3668
3669
 @param hLayer handle to the layer on which to set the spatial filter.
3670
 @param iGeomField index of the geometry field on which the spatial filter
3671
 operates.
3672
 @param hGeom handle to the geometry to use as a filtering region.  NULL may
3673
 be passed indicating that the current spatial filter should be cleared,
3674
 but no new one instituted.
3675
3676
 */
3677
3678
void OGR_L_SetSpatialFilterEx(OGRLayerH hLayer, int iGeomField,
3679
                              OGRGeometryH hGeom)
3680
3681
0
{
3682
0
    VALIDATE_POINTER0(hLayer, "OGR_L_SetSpatialFilterEx");
3683
3684
0
#ifdef OGRAPISPY_ENABLED
3685
0
    if (bOGRAPISpyEnabled)
3686
0
        OGRAPISpy_L_SetSpatialFilterEx(hLayer, iGeomField, hGeom);
3687
0
#endif
3688
3689
0
    OGRLayer::FromHandle(hLayer)->SetSpatialFilter(
3690
0
        iGeomField, OGRGeometry::FromHandle(hGeom));
3691
0
}
3692
3693
/************************************************************************/
3694
/*                        SetSpatialFilterRect()                        */
3695
/************************************************************************/
3696
3697
/**
3698
 \brief Set a new rectangular spatial filter.
3699
3700
 This method set rectangle to be used as a spatial filter when
3701
 fetching features via the GetNextFeature() method.  Only features that
3702
 geometrically intersect the given rectangle will be returned.
3703
3704
 The x/y values should be in the same coordinate system as the layer as
3705
 a whole (as returned by OGRLayer::GetSpatialRef()).   Internally this
3706
 method is normally implemented as creating a 5 vertex closed rectangular
3707
 polygon and passing it to OGRLayer::SetSpatialFilter().  It exists as
3708
 a convenience.
3709
3710
 The only way to clear a spatial filter set with this method is to
3711
 call OGRLayer::SetSpatialFilter(NULL).
3712
3713
 This method is the same as the C function OGR_L_SetSpatialFilterRect().
3714
3715
 @param dfMinX the minimum X coordinate for the rectangular region.
3716
 @param dfMinY the minimum Y coordinate for the rectangular region.
3717
 @param dfMaxX the maximum X coordinate for the rectangular region.
3718
 @param dfMaxY the maximum Y coordinate for the rectangular region.
3719
3720
 */
3721
3722
OGRErr OGRLayer::SetSpatialFilterRect(double dfMinX, double dfMinY,
3723
                                      double dfMaxX, double dfMaxY)
3724
3725
0
{
3726
0
    return SetSpatialFilterRect(0, dfMinX, dfMinY, dfMaxX, dfMaxY);
3727
0
}
3728
3729
/**
3730
 \brief Set a new rectangular spatial filter.
3731
3732
 This method set rectangle to be used as a spatial filter when
3733
 fetching features via the GetNextFeature() method.  Only features that
3734
 geometrically intersect the given rectangle will be returned.
3735
3736
 The x/y values should be in the same coordinate system as as the geometry
3737
 field definition it corresponds to (as returned by
3738
 GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(iGeomField)->GetSpatialRef()). Internally this
3739
 method is normally implemented as creating a 5 vertex closed rectangular
3740
 polygon and passing it to OGRLayer::SetSpatialFilter().  It exists as
3741
 a convenience.
3742
3743
 The only way to clear a spatial filter set with this method is to
3744
 call OGRLayer::SetSpatialFilter(NULL).
3745
3746
 This method is the same as the C function OGR_L_SetSpatialFilterRectEx().
3747
3748
 @param iGeomField index of the geometry field on which the spatial filter
3749
 operates.
3750
 @param dfMinX the minimum X coordinate for the rectangular region.
3751
 @param dfMinY the minimum Y coordinate for the rectangular region.
3752
 @param dfMaxX the maximum X coordinate for the rectangular region.
3753
 @param dfMaxY the maximum Y coordinate for the rectangular region.
3754
 */
3755
3756
OGRErr OGRLayer::SetSpatialFilterRect(int iGeomField, double dfMinX,
3757
                                      double dfMinY, double dfMaxX,
3758
                                      double dfMaxY)
3759
3760
0
{
3761
0
    auto poRing = std::make_unique<OGRLinearRing>();
3762
0
    OGRPolygon oPoly;
3763
3764
0
    poRing->addPoint(dfMinX, dfMinY);
3765
0
    poRing->addPoint(dfMinX, dfMaxY);
3766
0
    poRing->addPoint(dfMaxX, dfMaxY);
3767
0
    poRing->addPoint(dfMaxX, dfMinY);
3768
0
    poRing->addPoint(dfMinX, dfMinY);
3769
3770
0
    oPoly.addRing(std::move(poRing));
3771
3772
0
    return SetSpatialFilter(iGeomField, &oPoly);
3773
0
}
3774
3775
/************************************************************************/
3776
/*                     OGR_L_SetSpatialFilterRect()                     */
3777
/************************************************************************/
3778
3779
/**
3780
 \brief Set a new rectangular spatial filter.
3781
3782
 This method set rectangle to be used as a spatial filter when
3783
 fetching features via the OGR_L_GetNextFeature() method.  Only features that
3784
 geometrically intersect the given rectangle will be returned.
3785
3786
 The x/y values should be in the same coordinate system as the layer as
3787
 a whole (as returned by OGRLayer::GetSpatialRef()).   Internally this
3788
 method is normally implemented as creating a 5 vertex closed rectangular
3789
 polygon and passing it to OGRLayer::SetSpatialFilter().  It exists as
3790
 a convenience.
3791
3792
 The only way to clear a spatial filter set with this method is to
3793
 call OGRLayer::SetSpatialFilter(NULL).
3794
3795
 This method is the same as the C++ method OGRLayer::SetSpatialFilterRect().
3796
3797
 @param hLayer handle to the layer on which to set the spatial filter.
3798
 @param dfMinX the minimum X coordinate for the rectangular region.
3799
 @param dfMinY the minimum Y coordinate for the rectangular region.
3800
 @param dfMaxX the maximum X coordinate for the rectangular region.
3801
 @param dfMaxY the maximum Y coordinate for the rectangular region.
3802
3803
 */
3804
3805
void OGR_L_SetSpatialFilterRect(OGRLayerH hLayer, double dfMinX, double dfMinY,
3806
                                double dfMaxX, double dfMaxY)
3807
3808
0
{
3809
0
    VALIDATE_POINTER0(hLayer, "OGR_L_SetSpatialFilterRect");
3810
3811
0
#ifdef OGRAPISPY_ENABLED
3812
0
    if (bOGRAPISpyEnabled)
3813
0
        OGRAPISpy_L_SetSpatialFilterRect(hLayer, dfMinX, dfMinY, dfMaxX,
3814
0
                                         dfMaxY);
3815
0
#endif
3816
3817
0
    OGRLayer::FromHandle(hLayer)->SetSpatialFilterRect(dfMinX, dfMinY, dfMaxX,
3818
0
                                                       dfMaxY);
3819
0
}
3820
3821
/************************************************************************/
3822
/*                    OGR_L_SetSpatialFilterRectEx()                    */
3823
/************************************************************************/
3824
3825
/**
3826
 \brief Set a new rectangular spatial filter.
3827
3828
 This method set rectangle to be used as a spatial filter when
3829
 fetching features via the OGR_L_GetNextFeature() method.  Only features that
3830
 geometrically intersect the given rectangle will be returned.
3831
3832
 The x/y values should be in the same coordinate system as as the geometry
3833
 field definition it corresponds to (as returned by
3834
 GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(iGeomField)->GetSpatialRef()). Internally this
3835
 method is normally implemented as creating a 5 vertex closed rectangular
3836
 polygon and passing it to OGRLayer::SetSpatialFilter().  It exists as
3837
 a convenience.
3838
3839
 The only way to clear a spatial filter set with this method is to
3840
 call OGRLayer::SetSpatialFilter(NULL).
3841
3842
 This method is the same as the C++ method OGRLayer::SetSpatialFilterRect().
3843
3844
 @param hLayer handle to the layer on which to set the spatial filter.
3845
 @param iGeomField index of the geometry field on which the spatial filter
3846
 operates.
3847
 @param dfMinX the minimum X coordinate for the rectangular region.
3848
 @param dfMinY the minimum Y coordinate for the rectangular region.
3849
 @param dfMaxX the maximum X coordinate for the rectangular region.
3850
 @param dfMaxY the maximum Y coordinate for the rectangular region.
3851
*/
3852
3853
void OGR_L_SetSpatialFilterRectEx(OGRLayerH hLayer, int iGeomField,
3854
                                  double dfMinX, double dfMinY, double dfMaxX,
3855
                                  double dfMaxY)
3856
3857
0
{
3858
0
    VALIDATE_POINTER0(hLayer, "OGR_L_SetSpatialFilterRectEx");
3859
3860
0
#ifdef OGRAPISPY_ENABLED
3861
0
    if (bOGRAPISpyEnabled)
3862
0
        OGRAPISpy_L_SetSpatialFilterRectEx(hLayer, iGeomField, dfMinX, dfMinY,
3863
0
                                           dfMaxX, dfMaxY);
3864
0
#endif
3865
3866
0
    OGRLayer::FromHandle(hLayer)->SetSpatialFilterRect(iGeomField, dfMinX,
3867
0
                                                       dfMinY, dfMaxX, dfMaxY);
3868
0
}
3869
3870
/************************************************************************/
3871
/*                           InstallFilter()                            */
3872
/*                                                                      */
3873
/*      This method is only intended to be used from within             */
3874
/*      drivers, normally from the SetSpatialFilter() method.           */
3875
/*      It installs a filter, and also tests it to see if it is         */
3876
/*      rectangular.  If so, it this is kept track of alongside the     */
3877
/*      filter geometry itself so we can do cheaper comparisons in      */
3878
/*      the FilterGeometry() call.                                      */
3879
/*                                                                      */
3880
/*      Returns TRUE if the newly installed filter differs in some      */
3881
/*      way from the current one.                                       */
3882
/************************************************************************/
3883
3884
//! @cond Doxygen_Suppress
3885
int OGRLayer::InstallFilter(const OGRGeometry *poFilter)
3886
3887
0
{
3888
0
    if (m_poFilterGeom == poFilter)
3889
0
        return FALSE;
3890
3891
    /* -------------------------------------------------------------------- */
3892
    /*      Replace the existing filter.                                    */
3893
    /* -------------------------------------------------------------------- */
3894
0
    if (m_poFilterGeom != nullptr)
3895
0
    {
3896
0
        delete m_poFilterGeom;
3897
0
        m_poFilterGeom = nullptr;
3898
0
    }
3899
3900
0
    if (m_pPreparedFilterGeom != nullptr)
3901
0
    {
3902
0
        OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
3903
0
        m_pPreparedFilterGeom = nullptr;
3904
0
    }
3905
3906
0
    if (poFilter != nullptr)
3907
0
        m_poFilterGeom = poFilter->clone();
3908
3909
0
    m_bFilterIsEnvelope = FALSE;
3910
3911
0
    if (m_poFilterGeom == nullptr)
3912
0
        return TRUE;
3913
3914
0
    m_poFilterGeom->getEnvelope(&m_sFilterEnvelope);
3915
3916
    /* Compile geometry filter as a prepared geometry */
3917
0
    m_pPreparedFilterGeom =
3918
0
        OGRCreatePreparedGeometry(OGRGeometry::ToHandle(m_poFilterGeom));
3919
3920
0
    m_bFilterIsEnvelope = m_poFilterGeom->IsRectangle();
3921
3922
0
    return TRUE;
3923
0
}
3924
3925
//! @endcond
3926
3927
/************************************************************************/
3928
/*                  DoesGeometryHavePointInEnvelope()                   */
3929
/************************************************************************/
3930
3931
static bool DoesGeometryHavePointInEnvelope(const OGRGeometry *poGeometry,
3932
                                            const OGREnvelope &sEnvelope)
3933
0
{
3934
0
    const OGRLineString *poLS = nullptr;
3935
3936
0
    switch (wkbFlatten(poGeometry->getGeometryType()))
3937
0
    {
3938
0
        case wkbPoint:
3939
0
        {
3940
0
            const auto poPoint = poGeometry->toPoint();
3941
0
            const double x = poPoint->getX();
3942
0
            const double y = poPoint->getY();
3943
0
            return (x >= sEnvelope.MinX && y >= sEnvelope.MinY &&
3944
0
                    x <= sEnvelope.MaxX && y <= sEnvelope.MaxY);
3945
0
        }
3946
3947
0
        case wkbLineString:
3948
0
            poLS = poGeometry->toLineString();
3949
0
            break;
3950
3951
0
        case wkbPolygon:
3952
0
        {
3953
0
            const OGRPolygon *poPoly = poGeometry->toPolygon();
3954
0
            poLS = poPoly->getExteriorRing();
3955
0
            break;
3956
0
        }
3957
3958
0
        case wkbMultiPoint:
3959
0
        case wkbMultiLineString:
3960
0
        case wkbMultiPolygon:
3961
0
        case wkbGeometryCollection:
3962
0
        {
3963
0
            for (const auto &poSubGeom : *(poGeometry->toGeometryCollection()))
3964
0
            {
3965
0
                if (DoesGeometryHavePointInEnvelope(poSubGeom, sEnvelope))
3966
0
                    return true;
3967
0
            }
3968
0
            return false;
3969
0
        }
3970
3971
0
        default:
3972
0
            return false;
3973
0
    }
3974
3975
0
    if (poLS != nullptr)
3976
0
    {
3977
0
        const int nNumPoints = poLS->getNumPoints();
3978
0
        for (int i = 0; i < nNumPoints; i++)
3979
0
        {
3980
0
            const double x = poLS->getX(i);
3981
0
            const double y = poLS->getY(i);
3982
0
            if (x >= sEnvelope.MinX && y >= sEnvelope.MinY &&
3983
0
                x <= sEnvelope.MaxX && y <= sEnvelope.MaxY)
3984
0
            {
3985
0
                return true;
3986
0
            }
3987
0
        }
3988
0
    }
3989
3990
0
    return false;
3991
0
}
3992
3993
/************************************************************************/
3994
/*                           FilterGeometry()                           */
3995
/*                                                                      */
3996
/*      Compare the passed in geometry to the currently installed       */
3997
/*      filter.  Optimize for case where filter is just an              */
3998
/*      envelope.                                                       */
3999
/************************************************************************/
4000
4001
//! @cond Doxygen_Suppress
4002
int OGRLayer::FilterGeometry(const OGRGeometry *poGeometry)
4003
4004
0
{
4005
    /* -------------------------------------------------------------------- */
4006
    /*      In trivial cases of new filter or target geometry, we accept    */
4007
    /*      an intersection.  No geometry is taken to mean "the whole       */
4008
    /*      world".                                                         */
4009
    /* -------------------------------------------------------------------- */
4010
0
    if (m_poFilterGeom == nullptr)
4011
0
        return TRUE;
4012
4013
0
    if (poGeometry == nullptr || poGeometry->IsEmpty())
4014
0
        return FALSE;
4015
4016
    /* -------------------------------------------------------------------- */
4017
    /*      Compute the target geometry envelope, and if there is no        */
4018
    /*      intersection between the envelopes we are sure not to have      */
4019
    /*      any intersection.                                               */
4020
    /* -------------------------------------------------------------------- */
4021
0
    OGREnvelope sGeomEnv;
4022
4023
0
    poGeometry->getEnvelope(&sGeomEnv);
4024
4025
0
    if (sGeomEnv.MaxX < m_sFilterEnvelope.MinX ||
4026
0
        sGeomEnv.MaxY < m_sFilterEnvelope.MinY ||
4027
0
        m_sFilterEnvelope.MaxX < sGeomEnv.MinX ||
4028
0
        m_sFilterEnvelope.MaxY < sGeomEnv.MinY)
4029
0
        return FALSE;
4030
4031
    /* -------------------------------------------------------------------- */
4032
    /*      If the filter geometry is its own envelope and if the           */
4033
    /*      envelope of the geometry is inside the filter geometry,         */
4034
    /*      the geometry itself is inside the filter geometry               */
4035
    /* -------------------------------------------------------------------- */
4036
0
    if (m_bFilterIsEnvelope && sGeomEnv.MinX >= m_sFilterEnvelope.MinX &&
4037
0
        sGeomEnv.MinY >= m_sFilterEnvelope.MinY &&
4038
0
        sGeomEnv.MaxX <= m_sFilterEnvelope.MaxX &&
4039
0
        sGeomEnv.MaxY <= m_sFilterEnvelope.MaxY)
4040
0
    {
4041
0
        return TRUE;
4042
0
    }
4043
0
    else
4044
0
    {
4045
        // If the filter geometry is its own envelope and if the geometry has
4046
        // at least one point inside the filter geometry, the geometry itself
4047
        // intersects the filter geometry.
4048
0
        if (m_bFilterIsEnvelope)
4049
0
        {
4050
0
            if (DoesGeometryHavePointInEnvelope(poGeometry, m_sFilterEnvelope))
4051
0
                return true;
4052
0
        }
4053
4054
        /* --------------------------------------------------------------------
4055
         */
4056
        /*      Fallback to full intersect test (using GEOS) if we still */
4057
        /*      don't know for sure. */
4058
        /* --------------------------------------------------------------------
4059
         */
4060
0
        if (OGRGeometryFactory::haveGEOS())
4061
0
        {
4062
            // CPLDebug("OGRLayer", "GEOS intersection");
4063
0
            if (m_pPreparedFilterGeom != nullptr)
4064
0
                return OGRPreparedGeometryIntersects(
4065
0
                    m_pPreparedFilterGeom,
4066
0
                    OGRGeometry::ToHandle(
4067
0
                        const_cast<OGRGeometry *>(poGeometry)));
4068
0
            else
4069
0
                return m_poFilterGeom->Intersects(poGeometry);
4070
0
        }
4071
0
        else
4072
0
            return TRUE;
4073
0
    }
4074
0
}
4075
4076
/************************************************************************/
4077
/*                         FilterWKBGeometry()                          */
4078
/************************************************************************/
4079
4080
bool OGRLayer::FilterWKBGeometry(const GByte *pabyWKB, size_t nWKBSize,
4081
                                 bool bEnvelopeAlreadySet,
4082
                                 OGREnvelope &sEnvelope) const
4083
0
{
4084
0
    OGRPreparedGeometry *pPreparedFilterGeom = m_pPreparedFilterGeom;
4085
0
    bool bRet =
4086
0
        FilterWKBGeometry(pabyWKB, nWKBSize, bEnvelopeAlreadySet, sEnvelope,
4087
0
                          m_poFilterGeom, CPL_TO_BOOL(m_bFilterIsEnvelope),
4088
0
                          m_sFilterEnvelope, pPreparedFilterGeom);
4089
0
    const_cast<OGRLayer *>(this)->m_pPreparedFilterGeom = pPreparedFilterGeom;
4090
0
    return bRet;
4091
0
}
4092
4093
/* static */
4094
bool OGRLayer::FilterWKBGeometry(const GByte *pabyWKB, size_t nWKBSize,
4095
                                 bool bEnvelopeAlreadySet,
4096
                                 OGREnvelope &sEnvelope,
4097
                                 const OGRGeometry *poFilterGeom,
4098
                                 bool bFilterIsEnvelope,
4099
                                 const OGREnvelope &sFilterEnvelope,
4100
                                 OGRPreparedGeometry *&pPreparedFilterGeom)
4101
0
{
4102
0
    if (!poFilterGeom)
4103
0
        return true;
4104
4105
0
    if ((bEnvelopeAlreadySet ||
4106
0
         OGRWKBGetBoundingBox(pabyWKB, nWKBSize, sEnvelope)) &&
4107
0
        sFilterEnvelope.Intersects(sEnvelope))
4108
0
    {
4109
0
        if (bFilterIsEnvelope && sFilterEnvelope.Contains(sEnvelope))
4110
0
        {
4111
0
            return true;
4112
0
        }
4113
0
        else
4114
0
        {
4115
0
            if (bFilterIsEnvelope &&
4116
0
                OGRWKBIntersectsPessimistic(pabyWKB, nWKBSize, sFilterEnvelope))
4117
0
            {
4118
0
                return true;
4119
0
            }
4120
0
            else if (OGRGeometryFactory::haveGEOS())
4121
0
            {
4122
0
                OGRGeometry *poGeom = nullptr;
4123
0
                int ret = FALSE;
4124
0
                if (OGRGeometryFactory::createFromWkb(pabyWKB, nullptr, &poGeom,
4125
0
                                                      nWKBSize) == OGRERR_NONE)
4126
0
                {
4127
0
                    if (!pPreparedFilterGeom)
4128
0
                    {
4129
0
                        pPreparedFilterGeom =
4130
0
                            OGRCreatePreparedGeometry(OGRGeometry::ToHandle(
4131
0
                                const_cast<OGRGeometry *>(poFilterGeom)));
4132
0
                    }
4133
0
                    if (pPreparedFilterGeom)
4134
0
                        ret = OGRPreparedGeometryIntersects(
4135
0
                            pPreparedFilterGeom,
4136
0
                            OGRGeometry::ToHandle(
4137
0
                                const_cast<OGRGeometry *>(poGeom)));
4138
0
                    else
4139
0
                        ret = poFilterGeom->Intersects(poGeom);
4140
0
                }
4141
0
                delete poGeom;
4142
0
                return CPL_TO_BOOL(ret);
4143
0
            }
4144
0
            else
4145
0
            {
4146
                // Assume intersection
4147
0
                return true;
4148
0
            }
4149
0
        }
4150
0
    }
4151
4152
0
    return false;
4153
0
}
4154
4155
/************************************************************************/
4156
/*                      PrepareStartTransaction()                       */
4157
/************************************************************************/
4158
4159
void OGRLayer::PrepareStartTransaction()
4160
0
{
4161
0
    m_apoFieldDefnChanges.clear();
4162
0
    m_apoGeomFieldDefnChanges.clear();
4163
0
}
4164
4165
/************************************************************************/
4166
/*                     FinishRollbackTransaction()                      */
4167
/************************************************************************/
4168
4169
void OGRLayer::FinishRollbackTransaction(const std::string &osSavepointName)
4170
0
{
4171
4172
    // Deleted fields can be safely removed from the storage after being restored.
4173
0
    std::vector<int> toBeRemoved;
4174
4175
0
    bool bSavepointFound = false;
4176
4177
    // Loop through all changed fields and reset them to their previous state.
4178
0
    for (int i = static_cast<int>(m_apoFieldDefnChanges.size()) - 1; i >= 0;
4179
0
         i--)
4180
0
    {
4181
0
        auto &oFieldChange = m_apoFieldDefnChanges[i];
4182
4183
0
        if (!osSavepointName.empty())
4184
0
        {
4185
0
            if (oFieldChange.osSavepointName == osSavepointName)
4186
0
            {
4187
0
                bSavepointFound = true;
4188
0
            }
4189
0
            else if (bSavepointFound)
4190
0
            {
4191
0
                continue;
4192
0
            }
4193
0
        }
4194
4195
0
        CPLAssert(oFieldChange.poFieldDefn);
4196
0
        const char *pszName = oFieldChange.poFieldDefn->GetNameRef();
4197
0
        const int iField = oFieldChange.iField;
4198
0
        if (iField >= 0)
4199
0
        {
4200
0
            switch (oFieldChange.eChangeType)
4201
0
            {
4202
0
                case FieldChangeType::DELETE_FIELD:
4203
0
                {
4204
                    // Transfer ownership of the field to the layer
4205
0
                    whileUnsealing(GetLayerDefn())
4206
0
                        ->AddFieldDefn(std::move(oFieldChange.poFieldDefn));
4207
4208
                    // Now move the field to the right place
4209
                    // from the last position to its original position
4210
0
                    const int iFieldCount = GetLayerDefn()->GetFieldCount();
4211
0
                    CPLAssert(iFieldCount > 0);
4212
0
                    CPLAssert(iFieldCount > iField);
4213
0
                    std::vector<int> anOrder(iFieldCount);
4214
0
                    for (int j = 0; j < iField; j++)
4215
0
                    {
4216
0
                        anOrder[j] = j;
4217
0
                    }
4218
0
                    for (int j = iField + 1; j < iFieldCount; j++)
4219
0
                    {
4220
0
                        anOrder[j] = j - 1;
4221
0
                    }
4222
0
                    anOrder[iField] = iFieldCount - 1;
4223
0
                    if (OGRERR_NONE == whileUnsealing(GetLayerDefn())
4224
0
                                           ->ReorderFieldDefns(anOrder.data()))
4225
0
                    {
4226
0
                        toBeRemoved.push_back(i);
4227
0
                    }
4228
0
                    else
4229
0
                    {
4230
0
                        CPLError(CE_Failure, CPLE_AppDefined,
4231
0
                                 "Failed to restore deleted field %s", pszName);
4232
0
                    }
4233
0
                    break;
4234
0
                }
4235
0
                case FieldChangeType::ALTER_FIELD:
4236
0
                {
4237
0
                    OGRFieldDefn *poFieldDefn =
4238
0
                        GetLayerDefn()->GetFieldDefn(iField);
4239
0
                    if (poFieldDefn)
4240
0
                    {
4241
0
                        *poFieldDefn = *oFieldChange.poFieldDefn;
4242
0
                        toBeRemoved.push_back(i);
4243
0
                    }
4244
0
                    else
4245
0
                    {
4246
0
                        CPLError(CE_Failure, CPLE_AppDefined,
4247
0
                                 "Failed to restore altered field %s", pszName);
4248
0
                    }
4249
0
                    break;
4250
0
                }
4251
0
                case FieldChangeType::ADD_FIELD:
4252
0
                {
4253
0
                    std::unique_ptr<OGRFieldDefn> poFieldDef =
4254
0
                        GetLayerDefn()->StealFieldDefn(iField);
4255
0
                    if (poFieldDef)
4256
0
                    {
4257
0
                        oFieldChange.poFieldDefn = std::move(poFieldDef);
4258
0
                    }
4259
0
                    else
4260
0
                    {
4261
0
                        CPLError(CE_Failure, CPLE_AppDefined,
4262
0
                                 "Failed to delete added field %s", pszName);
4263
0
                    }
4264
0
                    break;
4265
0
                }
4266
0
            }
4267
0
        }
4268
0
        else
4269
0
        {
4270
0
            CPLError(CE_Failure, CPLE_AppDefined,
4271
0
                     "Failed to restore field %s (field not found at index %d)",
4272
0
                     pszName, iField);
4273
0
        }
4274
0
    }
4275
4276
    // Remove from the storage the deleted fields that have been restored
4277
0
    for (const auto &i : toBeRemoved)
4278
0
    {
4279
0
        m_apoFieldDefnChanges.erase(m_apoFieldDefnChanges.begin() + i);
4280
0
    }
4281
4282
    /**********************************************************************/
4283
    /* Reset geometry fields to their previous state.                    */
4284
    /**********************************************************************/
4285
4286
0
    bSavepointFound = false;
4287
4288
    // Loop through all changed geometry fields and reset them to their previous state.
4289
0
    for (int i = static_cast<int>(m_apoGeomFieldDefnChanges.size()) - 1; i >= 0;
4290
0
         i--)
4291
0
    {
4292
0
        auto &oGeomFieldChange = m_apoGeomFieldDefnChanges[i];
4293
4294
0
        if (!osSavepointName.empty())
4295
0
        {
4296
0
            if (oGeomFieldChange.osSavepointName == osSavepointName)
4297
0
            {
4298
0
                bSavepointFound = true;
4299
0
            }
4300
0
            else if (bSavepointFound)
4301
0
            {
4302
0
                continue;
4303
0
            }
4304
0
        }
4305
0
        const char *pszName = oGeomFieldChange.poFieldDefn->GetNameRef();
4306
0
        const int iGeomField = oGeomFieldChange.iField;
4307
0
        if (iGeomField >= 0)
4308
0
        {
4309
0
            switch (oGeomFieldChange.eChangeType)
4310
0
            {
4311
0
                case FieldChangeType::DELETE_FIELD:
4312
0
                case FieldChangeType::ALTER_FIELD:
4313
0
                {
4314
                    // Currently not handled by OGR for geometry fields
4315
0
                    break;
4316
0
                }
4317
0
                case FieldChangeType::ADD_FIELD:
4318
0
                {
4319
0
                    std::unique_ptr<OGRGeomFieldDefn> poGeomFieldDef =
4320
0
                        GetLayerDefn()->StealGeomFieldDefn(
4321
0
                            oGeomFieldChange.iField);
4322
0
                    if (poGeomFieldDef)
4323
0
                    {
4324
0
                        oGeomFieldChange.poFieldDefn =
4325
0
                            std::move(poGeomFieldDef);
4326
0
                    }
4327
0
                    else
4328
0
                    {
4329
0
                        CPLError(CE_Failure, CPLE_AppDefined,
4330
0
                                 "Failed to delete added geometry field %s",
4331
0
                                 pszName);
4332
0
                    }
4333
0
                    break;
4334
0
                }
4335
0
            }
4336
0
        }
4337
0
        else
4338
0
        {
4339
0
            CPLError(CE_Failure, CPLE_AppDefined,
4340
0
                     "Failed to restore geometry field %s (field not found at "
4341
0
                     "index %d)",
4342
0
                     pszName, oGeomFieldChange.iField);
4343
0
        }
4344
0
    }
4345
0
}
4346
4347
//! @endcond
4348
4349
/************************************************************************/
4350
/*                       OGRLayer::ResetReading()                       */
4351
/************************************************************************/
4352
4353
/**
4354
 \fn void OGRLayer::ResetReading();
4355
4356
 \brief Reset feature reading to start on the first feature.
4357
4358
 This affects GetNextFeature() and GetArrowStream().
4359
4360
 This method is the same as the C function OGR_L_ResetReading().
4361
*/
4362
4363
/************************************************************************/
4364
/*                         OGR_L_ResetReading()                         */
4365
/************************************************************************/
4366
4367
/**
4368
 \brief Reset feature reading to start on the first feature.
4369
4370
 This affects GetNextFeature() and GetArrowStream().
4371
4372
 This function is the same as the C++ method OGRLayer::ResetReading().
4373
4374
 @param hLayer handle to the layer on which features are read.
4375
*/
4376
4377
void OGR_L_ResetReading(OGRLayerH hLayer)
4378
4379
0
{
4380
0
    VALIDATE_POINTER0(hLayer, "OGR_L_ResetReading");
4381
4382
0
#ifdef OGRAPISPY_ENABLED
4383
0
    if (bOGRAPISpyEnabled)
4384
0
        OGRAPISpy_L_ResetReading(hLayer);
4385
0
#endif
4386
4387
0
    OGRLayer::FromHandle(hLayer)->ResetReading();
4388
0
}
4389
4390
/************************************************************************/
4391
/*                       InitializeIndexSupport()                       */
4392
/*                                                                      */
4393
/*      This is only intended to be called by driver layer              */
4394
/*      implementations but we don't make it protected so that the      */
4395
/*      datasources can do it too if that is more appropriate.          */
4396
/************************************************************************/
4397
4398
//! @cond Doxygen_Suppress
4399
OGRErr
4400
OGRLayer::InitializeIndexSupport([[maybe_unused]] const char *pszFilename)
4401
4402
0
{
4403
#ifdef HAVE_MITAB
4404
    OGRErr eErr;
4405
4406
    if (m_poAttrIndex != nullptr)
4407
        return OGRERR_NONE;
4408
4409
    m_poAttrIndex = OGRCreateDefaultLayerIndex();
4410
4411
    eErr = m_poAttrIndex->Initialize(pszFilename, this);
4412
    if (eErr != OGRERR_NONE)
4413
    {
4414
        delete m_poAttrIndex;
4415
        m_poAttrIndex = nullptr;
4416
    }
4417
4418
    return eErr;
4419
#else
4420
0
    return OGRERR_FAILURE;
4421
0
#endif
4422
0
}
4423
4424
//! @endcond
4425
4426
/************************************************************************/
4427
/*                             SyncToDisk()                             */
4428
/************************************************************************/
4429
4430
/**
4431
\brief Flush pending changes to disk.
4432
4433
This call is intended to force the layer to flush any pending writes to
4434
disk, and leave the disk file in a consistent state.  It would not normally
4435
have any effect on read-only datasources.
4436
4437
Some layers do not implement this method, and will still return
4438
OGRERR_NONE.  The default implementation just returns OGRERR_NONE.  An error
4439
is only returned if an error occurs while attempting to flush to disk.
4440
4441
In any event, you should always close any opened datasource with
4442
OGRDataSource::DestroyDataSource() that will ensure all data is correctly flushed.
4443
4444
This method is the same as the C function OGR_L_SyncToDisk().
4445
4446
@return OGRERR_NONE if no error occurs (even if nothing is done) or an
4447
error code.
4448
*/
4449
4450
OGRErr OGRLayer::SyncToDisk()
4451
4452
0
{
4453
0
    return OGRERR_NONE;
4454
0
}
4455
4456
/************************************************************************/
4457
/*                          OGR_L_SyncToDisk()                          */
4458
/************************************************************************/
4459
4460
/**
4461
\brief Flush pending changes to disk.
4462
4463
This call is intended to force the layer to flush any pending writes to
4464
disk, and leave the disk file in a consistent state.  It would not normally
4465
have any effect on read-only datasources.
4466
4467
Some layers do not implement this method, and will still return
4468
OGRERR_NONE.  The default implementation just returns OGRERR_NONE.  An error
4469
is only returned if an error occurs while attempting to flush to disk.
4470
4471
In any event, you should always close any opened datasource with
4472
OGR_DS_Destroy() that will ensure all data is correctly flushed.
4473
4474
This method is the same as the C++ method OGRLayer::SyncToDisk()
4475
4476
@param hLayer handle to the layer
4477
4478
@return OGRERR_NONE if no error occurs (even if nothing is done) or an
4479
error code.
4480
*/
4481
4482
OGRErr OGR_L_SyncToDisk(OGRLayerH hLayer)
4483
4484
0
{
4485
0
    VALIDATE_POINTER1(hLayer, "OGR_L_SyncToDisk", OGRERR_INVALID_HANDLE);
4486
4487
0
#ifdef OGRAPISPY_ENABLED
4488
0
    if (bOGRAPISpyEnabled)
4489
0
        OGRAPISpy_L_SyncToDisk(hLayer);
4490
0
#endif
4491
4492
0
    return OGRLayer::FromHandle(hLayer)->SyncToDisk();
4493
0
}
4494
4495
/************************************************************************/
4496
/*                           DeleteFeature()                            */
4497
/************************************************************************/
4498
4499
/**
4500
 \brief Delete feature from layer.
4501
4502
 The feature with the indicated feature id is deleted from the layer if
4503
 supported by the driver.  Most drivers do not support feature deletion,
4504
 and will return OGRERR_UNSUPPORTED_OPERATION.  The TestCapability()
4505
 layer method may be called with OLCDeleteFeature to check if the driver
4506
 supports feature deletion.
4507
4508
 This method is the same as the C function OGR_L_DeleteFeature().
4509
4510
 @param nFID the feature id to be deleted from the layer
4511
4512
 @return OGRERR_NONE if the operation works, otherwise an appropriate error
4513
 code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
4514
4515
*/
4516
4517
OGRErr OGRLayer::DeleteFeature(CPL_UNUSED GIntBig nFID)
4518
0
{
4519
0
    return OGRERR_UNSUPPORTED_OPERATION;
4520
0
}
4521
4522
/************************************************************************/
4523
/*                        OGR_L_DeleteFeature()                         */
4524
/************************************************************************/
4525
4526
/**
4527
 \brief Delete feature from layer.
4528
4529
 The feature with the indicated feature id is deleted from the layer if
4530
 supported by the driver.  Most drivers do not support feature deletion,
4531
 and will return OGRERR_UNSUPPORTED_OPERATION.  The OGR_L_TestCapability()
4532
 function may be called with OLCDeleteFeature to check if the driver
4533
 supports feature deletion.
4534
4535
 This method is the same as the C++ method OGRLayer::DeleteFeature().
4536
4537
 @param hLayer handle to the layer
4538
 @param nFID the feature id to be deleted from the layer
4539
4540
 @return OGRERR_NONE if the operation works, otherwise an appropriate error
4541
 code (e.g OGRERR_NON_EXISTING_FEATURE if the feature does not exist).
4542
*/
4543
4544
OGRErr OGR_L_DeleteFeature(OGRLayerH hLayer, GIntBig nFID)
4545
4546
0
{
4547
0
    VALIDATE_POINTER1(hLayer, "OGR_L_DeleteFeature", OGRERR_INVALID_HANDLE);
4548
4549
0
#ifdef OGRAPISPY_ENABLED
4550
0
    if (bOGRAPISpyEnabled)
4551
0
        OGRAPISpy_L_DeleteFeature(hLayer, nFID);
4552
0
#endif
4553
4554
0
    return OGRLayer::FromHandle(hLayer)->DeleteFeature(nFID);
4555
0
}
4556
4557
/************************************************************************/
4558
/*                          GetFeaturesRead()                           */
4559
/************************************************************************/
4560
4561
//! @cond Doxygen_Suppress
4562
GIntBig OGRLayer::GetFeaturesRead()
4563
4564
0
{
4565
0
    return m_nFeaturesRead;
4566
0
}
4567
4568
//! @endcond
4569
4570
/************************************************************************/
4571
/*                       OGR_L_GetFeaturesRead()                        */
4572
/************************************************************************/
4573
4574
GIntBig OGR_L_GetFeaturesRead(OGRLayerH hLayer)
4575
4576
0
{
4577
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetFeaturesRead", 0);
4578
4579
0
    return OGRLayer::FromHandle(hLayer)->GetFeaturesRead();
4580
0
}
4581
4582
/************************************************************************/
4583
/*                             GetFIDColumn                             */
4584
/************************************************************************/
4585
4586
/**
4587
 \brief This method returns the name of the underlying database column being used as the FID column, or "" if not supported.
4588
4589
 This method is the same as the C function OGR_L_GetFIDColumn().
4590
4591
 @return fid column name.
4592
*/
4593
4594
const char *OGRLayer::GetFIDColumn() const
4595
4596
0
{
4597
0
    return "";
4598
0
}
4599
4600
/************************************************************************/
4601
/*                         OGR_L_GetFIDColumn()                         */
4602
/************************************************************************/
4603
4604
/**
4605
 \brief This method returns the name of the underlying database column being used as the FID column, or "" if not supported.
4606
4607
 This method is the same as the C++ method OGRLayer::GetFIDColumn()
4608
4609
 @param hLayer handle to the layer
4610
 @return fid column name.
4611
*/
4612
4613
const char *OGR_L_GetFIDColumn(OGRLayerH hLayer)
4614
4615
0
{
4616
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetFIDColumn", nullptr);
4617
4618
0
#ifdef OGRAPISPY_ENABLED
4619
0
    if (bOGRAPISpyEnabled)
4620
0
        OGRAPISpy_L_GetFIDColumn(hLayer);
4621
0
#endif
4622
4623
0
    return OGRLayer::FromHandle(hLayer)->GetFIDColumn();
4624
0
}
4625
4626
/************************************************************************/
4627
/*                         GetGeometryColumn()                          */
4628
/************************************************************************/
4629
4630
/**
4631
 \brief This method returns the name of the underlying database column being used as the geometry column, or "" if not supported.
4632
4633
 For layers with multiple geometry fields, this method only returns the name
4634
 of the first geometry column. For other columns, use
4635
 GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(i)->GetNameRef().
4636
4637
 This method is the same as the C function OGR_L_GetGeometryColumn().
4638
4639
 @return geometry column name.
4640
*/
4641
4642
const char *OGRLayer::GetGeometryColumn() const
4643
4644
0
{
4645
0
    const auto poLayerDefn = GetLayerDefn();
4646
0
    if (poLayerDefn->GetGeomFieldCount() > 0)
4647
0
        return poLayerDefn->GetGeomFieldDefn(0)->GetNameRef();
4648
0
    else
4649
0
        return "";
4650
0
}
4651
4652
/************************************************************************/
4653
/*                      OGR_L_GetGeometryColumn()                       */
4654
/************************************************************************/
4655
4656
/**
4657
 \brief This method returns the name of the underlying database column being used as the geometry column, or "" if not supported.
4658
4659
 For layers with multiple geometry fields, this method only returns the geometry
4660
 type of the first geometry column. For other columns, use
4661
 OGR_GFld_GetNameRef(OGR_FD_GetGeomFieldDefn(OGR_L_GetLayerDefn(hLayer), i)).
4662
4663
 This method is the same as the C++ method OGRLayer::GetGeometryColumn()
4664
4665
 @param hLayer handle to the layer
4666
 @return geometry column name.
4667
*/
4668
4669
const char *OGR_L_GetGeometryColumn(OGRLayerH hLayer)
4670
4671
0
{
4672
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetGeometryColumn", nullptr);
4673
4674
0
#ifdef OGRAPISPY_ENABLED
4675
0
    if (bOGRAPISpyEnabled)
4676
0
        OGRAPISpy_L_GetGeometryColumn(hLayer);
4677
0
#endif
4678
4679
0
    return OGRLayer::FromHandle(hLayer)->GetGeometryColumn();
4680
0
}
4681
4682
/************************************************************************/
4683
/*                           GetStyleTable()                            */
4684
/************************************************************************/
4685
4686
/**
4687
 \brief Returns layer style table.
4688
4689
 This method is the same as the C function OGR_L_GetStyleTable().
4690
4691
 @return pointer to a style table which should not be modified or freed by the
4692
 caller.
4693
*/
4694
4695
OGRStyleTable *OGRLayer::GetStyleTable()
4696
0
{
4697
0
    return m_poStyleTable;
4698
0
}
4699
4700
/************************************************************************/
4701
/*                       SetStyleTableDirectly()                        */
4702
/************************************************************************/
4703
4704
/**
4705
 \brief Set layer style table.
4706
4707
 This method operate exactly as OGRLayer::SetStyleTable() except that it
4708
 assumes ownership of the passed table.
4709
4710
 This method is the same as the C function OGR_L_SetStyleTableDirectly().
4711
4712
 @param poStyleTable pointer to style table to set
4713
*/
4714
4715
void OGRLayer::SetStyleTableDirectly(OGRStyleTable *poStyleTable)
4716
0
{
4717
0
    if (m_poStyleTable)
4718
0
        delete m_poStyleTable;
4719
0
    m_poStyleTable = poStyleTable;
4720
0
}
4721
4722
/************************************************************************/
4723
/*                           SetStyleTable()                            */
4724
/************************************************************************/
4725
4726
/**
4727
 \brief Set layer style table.
4728
4729
 This method operate exactly as OGRLayer::SetStyleTableDirectly() except
4730
 that it does not assume ownership of the passed table.
4731
4732
 This method is the same as the C function OGR_L_SetStyleTable().
4733
4734
 @param poStyleTable pointer to style table to set
4735
*/
4736
4737
void OGRLayer::SetStyleTable(OGRStyleTable *poStyleTable)
4738
0
{
4739
0
    if (m_poStyleTable)
4740
0
        delete m_poStyleTable;
4741
0
    if (poStyleTable)
4742
0
        m_poStyleTable = poStyleTable->Clone();
4743
0
}
4744
4745
/************************************************************************/
4746
/*                        OGR_L_GetStyleTable()                         */
4747
/************************************************************************/
4748
4749
OGRStyleTableH OGR_L_GetStyleTable(OGRLayerH hLayer)
4750
4751
0
{
4752
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetStyleTable", nullptr);
4753
4754
0
    return reinterpret_cast<OGRStyleTableH>(
4755
0
        OGRLayer::FromHandle(hLayer)->GetStyleTable());
4756
0
}
4757
4758
/************************************************************************/
4759
/*                    OGR_L_SetStyleTableDirectly()                     */
4760
/************************************************************************/
4761
4762
void OGR_L_SetStyleTableDirectly(OGRLayerH hLayer, OGRStyleTableH hStyleTable)
4763
4764
0
{
4765
0
    VALIDATE_POINTER0(hLayer, "OGR_L_SetStyleTableDirectly");
4766
4767
0
    OGRLayer::FromHandle(hLayer)->SetStyleTableDirectly(
4768
0
        reinterpret_cast<OGRStyleTable *>(hStyleTable));
4769
0
}
4770
4771
/************************************************************************/
4772
/*                        OGR_L_SetStyleTable()                         */
4773
/************************************************************************/
4774
4775
void OGR_L_SetStyleTable(OGRLayerH hLayer, OGRStyleTableH hStyleTable)
4776
4777
0
{
4778
0
    VALIDATE_POINTER0(hLayer, "OGR_L_SetStyleTable");
4779
0
    VALIDATE_POINTER0(hStyleTable, "OGR_L_SetStyleTable");
4780
4781
0
    OGRLayer::FromHandle(hLayer)->SetStyleTable(
4782
0
        reinterpret_cast<OGRStyleTable *>(hStyleTable));
4783
0
}
4784
4785
/************************************************************************/
4786
/*                              GetName()                               */
4787
/************************************************************************/
4788
4789
/**
4790
 \brief Return the layer name.
4791
4792
 This returns the same content as GetLayerDefn()->OGRFeatureDefn::GetName(), but for a
4793
 few drivers, calling GetName() directly can avoid lengthy layer
4794
 definition initialization.
4795
4796
 This method is the same as the C function OGR_L_GetName().
4797
4798
 If this method is derived in a driver, it must be done such that it
4799
 returns the same content as GetLayerDefn()->OGRFeatureDefn::GetName().
4800
4801
 @return the layer name (must not been freed)
4802
*/
4803
4804
const char *OGRLayer::GetName() const
4805
4806
0
{
4807
0
    return GetLayerDefn()->GetName();
4808
0
}
4809
4810
/************************************************************************/
4811
/*                           OGR_L_GetName()                            */
4812
/************************************************************************/
4813
4814
/**
4815
 \brief Return the layer name.
4816
4817
 This returns the same content as OGR_FD_GetName(OGR_L_GetLayerDefn(hLayer)),
4818
 but for a few drivers, calling OGR_L_GetName() directly can avoid lengthy
4819
 layer definition initialization.
4820
4821
 This function is the same as the C++ method OGRLayer::GetName().
4822
4823
 @param hLayer handle to the layer.
4824
 @return the layer name (must not been freed)
4825
*/
4826
4827
const char *OGR_L_GetName(OGRLayerH hLayer)
4828
4829
0
{
4830
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetName", "");
4831
4832
0
#ifdef OGRAPISPY_ENABLED
4833
0
    if (bOGRAPISpyEnabled)
4834
0
        OGRAPISpy_L_GetName(hLayer);
4835
0
#endif
4836
4837
0
    return OGRLayer::FromHandle(hLayer)->GetName();
4838
0
}
4839
4840
/************************************************************************/
4841
/*                            GetGeomType()                             */
4842
/************************************************************************/
4843
4844
/**
4845
 \brief Return the layer geometry type.
4846
4847
 This returns the same result as GetLayerDefn()->OGRFeatureDefn::GetGeomType(), but for a
4848
 few drivers, calling GetGeomType() directly can avoid lengthy layer
4849
 definition initialization.
4850
4851
 Note that even if this method is const (since GDAL 3.12), there is no guarantee
4852
 it can be safely called by concurrent threads on the same GDALDataset object.
4853
4854
 For layers with multiple geometry fields, this method only returns the geometry
4855
 type of the first geometry column. For other columns, use
4856
 GetLayerDefn()->OGRFeatureDefn::GetGeomFieldDefn(i)->GetType().
4857
 For layers without any geometry field, this method returns wkbNone.
4858
4859
 This method is the same as the C function OGR_L_GetGeomType().
4860
4861
 If this method is derived in a driver, it must be done such that it
4862
 returns the same content as GetLayerDefn()->OGRFeatureDefn::GetGeomType().
4863
4864
 @return the geometry type
4865
*/
4866
4867
OGRwkbGeometryType OGRLayer::GetGeomType() const
4868
0
{
4869
0
    const OGRFeatureDefn *poLayerDefn = GetLayerDefn();
4870
0
    if (poLayerDefn == nullptr)
4871
0
    {
4872
0
        CPLDebug("OGR", "GetLayerType() returns NULL !");
4873
0
        return wkbUnknown;
4874
0
    }
4875
0
    return poLayerDefn->GetGeomType();
4876
0
}
4877
4878
/************************************************************************/
4879
/*                         OGR_L_GetGeomType()                          */
4880
/************************************************************************/
4881
4882
/**
4883
 \brief Return the layer geometry type.
4884
4885
 This returns the same result as OGR_FD_GetGeomType(OGR_L_GetLayerDefn(hLayer)),
4886
 but for a few drivers, calling OGR_L_GetGeomType() directly can avoid lengthy
4887
 layer definition initialization.
4888
4889
 For layers with multiple geometry fields, this method only returns the geometry
4890
 type of the first geometry column. For other columns, use
4891
 OGR_GFld_GetType(OGR_FD_GetGeomFieldDefn(OGR_L_GetLayerDefn(hLayer), i)).
4892
 For layers without any geometry field, this method returns wkbNone.
4893
4894
 This function is the same as the C++ method OGRLayer::GetGeomType().
4895
4896
 @param hLayer handle to the layer.
4897
 @return the geometry type
4898
*/
4899
4900
OGRwkbGeometryType OGR_L_GetGeomType(OGRLayerH hLayer)
4901
4902
0
{
4903
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetGeomType", wkbUnknown);
4904
4905
0
#ifdef OGRAPISPY_ENABLED
4906
0
    if (bOGRAPISpyEnabled)
4907
0
        OGRAPISpy_L_GetGeomType(hLayer);
4908
0
#endif
4909
4910
0
    OGRwkbGeometryType eType = OGRLayer::FromHandle(hLayer)->GetGeomType();
4911
0
    if (OGR_GT_IsNonLinear(eType) && !OGRGetNonLinearGeometriesEnabledFlag())
4912
0
    {
4913
0
        eType = OGR_GT_GetLinear(eType);
4914
0
    }
4915
0
    return eType;
4916
0
}
4917
4918
/************************************************************************/
4919
/*                          SetIgnoredFields()                          */
4920
/************************************************************************/
4921
4922
/**
4923
 \brief Set which fields can be omitted when retrieving features from the layer.
4924
4925
 If the driver supports this functionality (testable using OLCIgnoreFields capability), it will not fetch the specified fields
4926
 in subsequent calls to GetFeature() / GetNextFeature() and thus save some processing time and/or bandwidth.
4927
4928
 Besides field names of the layers, the following special fields can be passed: "OGR_GEOMETRY" to ignore geometry and
4929
 "OGR_STYLE" to ignore layer style.
4930
4931
 By default, no fields are ignored.
4932
4933
 Note that fields that are used in an attribute filter should generally not be set as
4934
 ignored fields, as most drivers (such as those relying on the OGR SQL engine)
4935
 will be unable to correctly evaluate the attribute filter.
4936
4937
 This method is the same as the C function OGR_L_SetIgnoredFields()
4938
4939
 @param papszFields an array of field names terminated by NULL item. If NULL is passed, the ignored list is cleared.
4940
 @return OGRERR_NONE if all field names have been resolved (even if the driver does not support this method)
4941
*/
4942
4943
OGRErr OGRLayer::SetIgnoredFields(CSLConstList papszFields)
4944
0
{
4945
0
    OGRFeatureDefn *poDefn = GetLayerDefn();
4946
4947
    // first set everything as *not* ignored
4948
0
    for (int iField = 0; iField < poDefn->GetFieldCount(); iField++)
4949
0
    {
4950
0
        poDefn->GetFieldDefn(iField)->SetIgnored(FALSE);
4951
0
    }
4952
0
    for (int iField = 0; iField < poDefn->GetGeomFieldCount(); iField++)
4953
0
    {
4954
0
        poDefn->GetGeomFieldDefn(iField)->SetIgnored(FALSE);
4955
0
    }
4956
0
    poDefn->SetStyleIgnored(FALSE);
4957
4958
    // ignore some fields
4959
0
    for (const char *pszFieldName : cpl::Iterate(papszFields))
4960
0
    {
4961
        // check special fields
4962
0
        if (EQUAL(pszFieldName, "OGR_GEOMETRY"))
4963
0
            poDefn->SetGeometryIgnored(TRUE);
4964
0
        else if (EQUAL(pszFieldName, "OGR_STYLE"))
4965
0
            poDefn->SetStyleIgnored(TRUE);
4966
0
        else
4967
0
        {
4968
            // check ordinary fields
4969
0
            int iField = poDefn->GetFieldIndex(pszFieldName);
4970
0
            if (iField == -1)
4971
0
            {
4972
                // check geometry field
4973
0
                iField = poDefn->GetGeomFieldIndex(pszFieldName);
4974
0
                if (iField == -1)
4975
0
                {
4976
0
                    return OGRERR_FAILURE;
4977
0
                }
4978
0
                else
4979
0
                    poDefn->GetGeomFieldDefn(iField)->SetIgnored(TRUE);
4980
0
            }
4981
0
            else
4982
0
                poDefn->GetFieldDefn(iField)->SetIgnored(TRUE);
4983
0
        }
4984
0
    }
4985
4986
0
    return OGRERR_NONE;
4987
0
}
4988
4989
/************************************************************************/
4990
/*                       OGR_L_SetIgnoredFields()                       */
4991
/************************************************************************/
4992
4993
/**
4994
 \brief Set which fields can be omitted when retrieving features from the layer.
4995
4996
 If the driver supports this functionality (testable using OLCIgnoreFields capability), it will not fetch the specified fields
4997
 in subsequent calls to GetFeature() / GetNextFeature() and thus save some processing time and/or bandwidth.
4998
4999
 Besides field names of the layers, the following special fields can be passed: "OGR_GEOMETRY" to ignore geometry and
5000
 "OGR_STYLE" to ignore layer style.
5001
5002
 By default, no fields are ignored.
5003
5004
 Note that fields that are used in an attribute filter should generally not be set as
5005
 ignored fields, as most drivers (such as those relying on the OGR SQL engine)
5006
 will be unable to correctly evaluate the attribute filter.
5007
5008
 This method is the same as the C++ method OGRLayer::SetIgnoredFields()
5009
5010
 @param hLayer handle to the layer
5011
 @param papszFields an array of field names terminated by NULL item. If NULL is passed, the ignored list is cleared.
5012
 @return OGRERR_NONE if all field names have been resolved (even if the driver does not support this method)
5013
*/
5014
5015
OGRErr OGR_L_SetIgnoredFields(OGRLayerH hLayer, const char **papszFields)
5016
5017
0
{
5018
0
    VALIDATE_POINTER1(hLayer, "OGR_L_SetIgnoredFields", OGRERR_INVALID_HANDLE);
5019
5020
0
#ifdef OGRAPISPY_ENABLED
5021
0
    if (bOGRAPISpyEnabled)
5022
0
        OGRAPISpy_L_SetIgnoredFields(hLayer, papszFields);
5023
0
#endif
5024
5025
0
    return OGRLayer::FromHandle(hLayer)->SetIgnoredFields(papszFields);
5026
0
}
5027
5028
/************************************************************************/
5029
/*                               Rename()                               */
5030
/************************************************************************/
5031
5032
/** Rename layer.
5033
 *
5034
 * This operation is implemented only by layers that expose the OLCRename
5035
 * capability, and drivers that expose the GDAL_DCAP_RENAME_LAYERS capability
5036
 *
5037
 * This operation will fail if a layer with the new name already exists.
5038
 *
5039
 * On success, GetDescription() and GetLayerDefn()->GetName() will return
5040
 * pszNewName.
5041
 *
5042
 * Renaming the layer may interrupt current feature iteration.
5043
 *
5044
 * @param pszNewName New layer name. Must not be NULL.
5045
 * @return OGRERR_NONE in case of success
5046
 *
5047
 * @since GDAL 3.5
5048
 */
5049
OGRErr OGRLayer::Rename(CPL_UNUSED const char *pszNewName)
5050
0
{
5051
0
    CPLError(CE_Failure, CPLE_NotSupported,
5052
0
             "Rename() not supported by this layer.");
5053
5054
0
    return OGRERR_UNSUPPORTED_OPERATION;
5055
0
}
5056
5057
/************************************************************************/
5058
/*                            OGR_L_Rename()                            */
5059
/************************************************************************/
5060
5061
/** Rename layer.
5062
 *
5063
 * This operation is implemented only by layers that expose the OLCRename
5064
 * capability, and drivers that expose the GDAL_DCAP_RENAME_LAYERS capability
5065
 *
5066
 * This operation will fail if a layer with the new name already exists.
5067
 *
5068
 * On success, GetDescription() and GetLayerDefn()->GetName() will return
5069
 * pszNewName.
5070
 *
5071
 * Renaming the layer may interrupt current feature iteration.
5072
 *
5073
 * @param hLayer     Layer to rename.
5074
 * @param pszNewName New layer name. Must not be NULL.
5075
 * @return OGRERR_NONE in case of success
5076
 *
5077
 * @since GDAL 3.5
5078
 */
5079
OGRErr OGR_L_Rename(OGRLayerH hLayer, const char *pszNewName)
5080
5081
0
{
5082
0
    VALIDATE_POINTER1(hLayer, "OGR_L_Rename", OGRERR_INVALID_HANDLE);
5083
0
    VALIDATE_POINTER1(pszNewName, "OGR_L_Rename", OGRERR_FAILURE);
5084
5085
0
    return OGRLayer::FromHandle(hLayer)->Rename(pszNewName);
5086
0
}
5087
5088
/************************************************************************/
5089
/*              helper functions for layer overlay methods              */
5090
/************************************************************************/
5091
5092
static OGRErr clone_spatial_filter(OGRLayer *pLayer, OGRGeometry **ppGeometry)
5093
0
{
5094
0
    OGRErr ret = OGRERR_NONE;
5095
0
    OGRGeometry *g = pLayer->GetSpatialFilter();
5096
0
    *ppGeometry = g ? g->clone() : nullptr;
5097
0
    return ret;
5098
0
}
5099
5100
static OGRErr create_field_map(OGRFeatureDefn *poDefn, int **map)
5101
0
{
5102
0
    OGRErr ret = OGRERR_NONE;
5103
0
    int n = poDefn->GetFieldCount();
5104
0
    if (n > 0)
5105
0
    {
5106
0
        *map = static_cast<int *>(VSI_MALLOC_VERBOSE(sizeof(int) * n));
5107
0
        if (!(*map))
5108
0
            return OGRERR_NOT_ENOUGH_MEMORY;
5109
0
        for (int i = 0; i < n; i++)
5110
0
            (*map)[i] = -1;
5111
0
    }
5112
0
    return ret;
5113
0
}
5114
5115
static OGRErr set_result_schema(OGRLayer *pLayerResult,
5116
                                OGRFeatureDefn *poDefnInput,
5117
                                OGRFeatureDefn *poDefnMethod, int *mapInput,
5118
                                int *mapMethod, bool combined,
5119
                                const char *const *papszOptions)
5120
0
{
5121
0
    if (!CPLTestBool(CSLFetchNameValueDef(papszOptions, "ADD_FIELDS", "YES")))
5122
0
        return OGRERR_NONE;
5123
5124
0
    OGRErr ret = OGRERR_NONE;
5125
0
    OGRFeatureDefn *poDefnResult = pLayerResult->GetLayerDefn();
5126
0
    const char *pszInputPrefix =
5127
0
        CSLFetchNameValue(papszOptions, "INPUT_PREFIX");
5128
0
    const char *pszMethodPrefix =
5129
0
        CSLFetchNameValue(papszOptions, "METHOD_PREFIX");
5130
0
    const bool bSkipFailures =
5131
0
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
5132
0
    if (poDefnResult->GetFieldCount() > 0)
5133
0
    {
5134
        // the user has defined the schema of the output layer
5135
0
        if (mapInput)
5136
0
        {
5137
0
            for (int iField = 0; iField < poDefnInput->GetFieldCount();
5138
0
                 iField++)
5139
0
            {
5140
0
                CPLString osName(
5141
0
                    poDefnInput->GetFieldDefn(iField)->GetNameRef());
5142
0
                if (pszInputPrefix != nullptr)
5143
0
                    osName = pszInputPrefix + osName;
5144
0
                mapInput[iField] = poDefnResult->GetFieldIndex(osName);
5145
0
            }
5146
0
        }
5147
0
        if (!mapMethod)
5148
0
            return ret;
5149
        // cppcheck-suppress nullPointer
5150
0
        for (int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++)
5151
0
        {
5152
            // cppcheck-suppress nullPointer
5153
0
            CPLString osName(poDefnMethod->GetFieldDefn(iField)->GetNameRef());
5154
0
            if (pszMethodPrefix != nullptr)
5155
0
                osName = pszMethodPrefix + osName;
5156
0
            mapMethod[iField] = poDefnResult->GetFieldIndex(osName);
5157
0
        }
5158
0
    }
5159
0
    else
5160
0
    {
5161
        // use schema from the input layer or from input and method layers
5162
0
        const int nFieldsInput = poDefnInput->GetFieldCount();
5163
5164
        // If no prefix is specified and we have input+method layers, make
5165
        // sure we will generate unique field names
5166
0
        std::set<std::string> oSetInputFieldNames;
5167
0
        std::set<std::string> oSetMethodFieldNames;
5168
0
        if (poDefnMethod != nullptr && pszInputPrefix == nullptr &&
5169
0
            pszMethodPrefix == nullptr)
5170
0
        {
5171
0
            for (int iField = 0; iField < nFieldsInput; iField++)
5172
0
            {
5173
0
                oSetInputFieldNames.insert(
5174
0
                    poDefnInput->GetFieldDefn(iField)->GetNameRef());
5175
0
            }
5176
0
            const int nFieldsMethod = poDefnMethod->GetFieldCount();
5177
0
            for (int iField = 0; iField < nFieldsMethod; iField++)
5178
0
            {
5179
0
                oSetMethodFieldNames.insert(
5180
0
                    poDefnMethod->GetFieldDefn(iField)->GetNameRef());
5181
0
            }
5182
0
        }
5183
5184
0
        const bool bAddInputFields = CPLTestBool(
5185
0
            CSLFetchNameValueDef(papszOptions, "ADD_INPUT_FIELDS", "YES"));
5186
0
        if (bAddInputFields)
5187
0
        {
5188
0
            for (int iField = 0; iField < nFieldsInput; iField++)
5189
0
            {
5190
0
                OGRFieldDefn oFieldDefn(poDefnInput->GetFieldDefn(iField));
5191
0
                if (pszInputPrefix != nullptr)
5192
0
                    oFieldDefn.SetName(CPLSPrintf("%s%s", pszInputPrefix,
5193
0
                                                  oFieldDefn.GetNameRef()));
5194
0
                else if (!oSetMethodFieldNames.empty() &&
5195
0
                         oSetMethodFieldNames.find(oFieldDefn.GetNameRef()) !=
5196
0
                             oSetMethodFieldNames.end())
5197
0
                {
5198
                    // Field of same name present in method layer
5199
0
                    oFieldDefn.SetName(
5200
0
                        CPLSPrintf("input_%s", oFieldDefn.GetNameRef()));
5201
0
                }
5202
0
                ret = pLayerResult->CreateField(&oFieldDefn);
5203
0
                if (ret != OGRERR_NONE)
5204
0
                {
5205
0
                    if (!bSkipFailures)
5206
0
                        return ret;
5207
0
                    else
5208
0
                    {
5209
0
                        CPLErrorReset();
5210
0
                        ret = OGRERR_NONE;
5211
0
                    }
5212
0
                }
5213
0
                if (mapInput)
5214
0
                    mapInput[iField] =
5215
0
                        pLayerResult->GetLayerDefn()->GetFieldCount() - 1;
5216
0
            }
5217
0
        }
5218
5219
0
        if (!combined)
5220
0
            return ret;
5221
0
        if (!mapMethod)
5222
0
            return ret;
5223
0
        if (!poDefnMethod)
5224
0
            return ret;
5225
5226
0
        const bool bAddMethodFields = CPLTestBool(
5227
0
            CSLFetchNameValueDef(papszOptions, "ADD_METHOD_FIELDS", "YES"));
5228
0
        if (bAddMethodFields)
5229
0
        {
5230
0
            const int nFieldsMethod = poDefnMethod->GetFieldCount();
5231
0
            for (int iField = 0; iField < nFieldsMethod; iField++)
5232
0
            {
5233
0
                OGRFieldDefn oFieldDefn(poDefnMethod->GetFieldDefn(iField));
5234
0
                if (pszMethodPrefix != nullptr)
5235
0
                    oFieldDefn.SetName(CPLSPrintf("%s%s", pszMethodPrefix,
5236
0
                                                  oFieldDefn.GetNameRef()));
5237
0
                else if (!oSetInputFieldNames.empty() &&
5238
0
                         oSetInputFieldNames.find(oFieldDefn.GetNameRef()) !=
5239
0
                             oSetInputFieldNames.end())
5240
0
                {
5241
                    // Field of same name present in method layer
5242
0
                    oFieldDefn.SetName(
5243
0
                        CPLSPrintf("method_%s", oFieldDefn.GetNameRef()));
5244
0
                }
5245
0
                ret = pLayerResult->CreateField(&oFieldDefn);
5246
0
                if (ret != OGRERR_NONE)
5247
0
                {
5248
0
                    if (!bSkipFailures)
5249
0
                        return ret;
5250
0
                    else
5251
0
                    {
5252
0
                        CPLErrorReset();
5253
0
                        ret = OGRERR_NONE;
5254
0
                    }
5255
0
                }
5256
0
                mapMethod[iField] =
5257
0
                    pLayerResult->GetLayerDefn()->GetFieldCount() - 1;
5258
0
            }
5259
0
        }
5260
0
    }
5261
0
    return ret;
5262
0
}
5263
5264
static OGRGeometry *set_filter_from(OGRLayer *pLayer,
5265
                                    OGRGeometry *pGeometryExistingFilter,
5266
                                    OGRFeature *pFeature)
5267
0
{
5268
0
    OGRGeometry *geom = pFeature->GetGeometryRef();
5269
0
    if (!geom)
5270
0
        return nullptr;
5271
0
    if (pGeometryExistingFilter)
5272
0
    {
5273
0
        if (!geom->Intersects(pGeometryExistingFilter))
5274
0
            return nullptr;
5275
0
        OGRGeometry *intersection = geom->Intersection(pGeometryExistingFilter);
5276
0
        if (intersection)
5277
0
        {
5278
0
            pLayer->SetSpatialFilter(intersection);
5279
0
            delete intersection;
5280
0
        }
5281
0
        else
5282
0
            return nullptr;
5283
0
    }
5284
0
    else
5285
0
    {
5286
0
        pLayer->SetSpatialFilter(geom);
5287
0
    }
5288
0
    return geom;
5289
0
}
5290
5291
static std::unique_ptr<OGRGeometry>
5292
promote_to_multi(std::unique_ptr<OGRGeometry> poGeom)
5293
0
{
5294
0
    OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
5295
0
    if (eType == wkbPoint)
5296
0
        return std::unique_ptr<OGRGeometry>(
5297
0
            OGRGeometryFactory::forceToMultiPoint(poGeom.release()));
5298
0
    else if (eType == wkbPolygon)
5299
0
        return std::unique_ptr<OGRGeometry>(
5300
0
            OGRGeometryFactory::forceToMultiPolygon(poGeom.release()));
5301
0
    else if (eType == wkbLineString)
5302
0
        return std::unique_ptr<OGRGeometry>(
5303
0
            OGRGeometryFactory::forceToMultiLineString(poGeom.release()));
5304
0
    else
5305
0
        return poGeom;
5306
0
}
5307
5308
static std::unique_ptr<OGRGeometry>
5309
convert_geometry(std::unique_ptr<OGRGeometry> poGeom, bool bPromoteToMulti,
5310
                 OGRwkbGeometryType eOutputGeometryType)
5311
0
{
5312
0
    if (eOutputGeometryType != wkbUnknown)
5313
0
    {
5314
0
        poGeom =
5315
0
            OGRGeometryFactory::forceTo(std::move(poGeom), eOutputGeometryType);
5316
0
        if (poGeom && poGeom->getGeometryType() != eOutputGeometryType)
5317
0
            return nullptr;
5318
0
        return poGeom;
5319
0
    }
5320
0
    else if (bPromoteToMulti)
5321
0
        return promote_to_multi(std::move(poGeom));
5322
0
    else
5323
0
        return poGeom;
5324
0
}
5325
5326
/************************************************************************/
5327
/*                            Intersection()                            */
5328
/************************************************************************/
5329
/**
5330
 * \brief Intersection of two layers.
5331
 *
5332
 * The result layer contains features whose geometries represent areas
5333
 * that are common between features in the input layer and in the
5334
 * method layer. The features in the result layer have attributes from
5335
 * both input and method layers. The schema of the result layer can be
5336
 * set by the user or, if it is empty, is initialized to contain all
5337
 * fields in the input and method layers.
5338
 *
5339
 * \note If the schema of the result is set by user and contains
5340
 * fields that have the same name as a field in input and in method
5341
 * layer, then the attribute in the result feature will get the value
5342
 * from the feature of the method layer.
5343
 *
5344
 * \note For best performance use the minimum amount of features in
5345
 * the method layer and copy it into a memory layer.
5346
 *
5347
 * \note This method relies on GEOS support. Do not use unless the
5348
 * GEOS support is compiled in.
5349
 *
5350
 * The recognized list of options is:
5351
 * <ul>
5352
 * <li>SKIP_FAILURES=YES/NO. Set to YES to go on, even when a
5353
 *     feature could not be inserted or a GEOS call failed.
5354
 * </li>
5355
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
5356
 *     into MultiPolygons, LineStrings to MultiLineStrings or
5357
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
5358
 * </li>
5359
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
5360
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
5361
 *     be converted to it, the corresponding output feature is silently skipped.
5362
 *     Takes precedence over PROMOTE_TO_MULTI.
5363
 * </li>
5364
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
5365
 *     will be created from the fields of the input layer.
5366
 * </li>
5367
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
5368
 *     will be created from the fields of the method layer.
5369
 * </li>
5370
 * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
5371
 *     geometries to pretest intersection of features of method layer
5372
 *     with features of this layer.
5373
 * </li>
5374
 * <li>PRETEST_CONTAINMENT=YES/NO. Set to YES to pretest the
5375
 *     containment of features of method layer within the features of
5376
 *     this layer. This will speed up the method significantly in some
5377
 *     cases. Requires that the prepared geometries are in effect.
5378
 * </li>
5379
 * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
5380
 *     result features with lower dimension geometry that would
5381
 *     otherwise be added to the result layer. The default is YES, to add
5382
 *     features with lower dimension geometry, but only if the result layer
5383
 *     has an unknown geometry type.
5384
 * </li>
5385
 * </ul>
5386
 *
5387
 * This method is the same as the C function OGR_L_Intersection().
5388
 *
5389
 * @param pLayerMethod the method layer. Should not be NULL.
5390
 *
5391
 * @param pLayerResult the layer where the features resulting from the
5392
 * operation are inserted. Should not be NULL. See above the note
5393
 * about the schema.
5394
 *
5395
 * @param papszOptions NULL terminated list of options (may be NULL).
5396
 *
5397
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
5398
 * reporting progress or NULL.
5399
 *
5400
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
5401
 *
5402
 * @return an error code if there was an error or the execution was
5403
 * interrupted, OGRERR_NONE otherwise.
5404
 *
5405
 * @note The first geometry field is always used.
5406
 *
5407
 * @since OGR 1.10
5408
 */
5409
5410
OGRErr OGRLayer::Intersection(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
5411
                              CSLConstList papszOptions,
5412
                              GDALProgressFunc pfnProgress, void *pProgressArg)
5413
0
{
5414
0
    OGRErr ret = OGRERR_NONE;
5415
0
    OGRFeatureDefn *poDefnInput = GetLayerDefn();
5416
0
    OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
5417
0
    OGRFeatureDefn *poDefnResult = nullptr;
5418
0
    OGRGeometry *pGeometryMethodFilter = nullptr;
5419
0
    int *mapInput = nullptr;
5420
0
    int *mapMethod = nullptr;
5421
0
    OGREnvelope sEnvelopeMethod;
5422
0
    GBool bEnvelopeSet;
5423
0
    double progress_max = static_cast<double>(GetFeatureCount(FALSE));
5424
0
    double progress_counter = 0;
5425
0
    double progress_ticker = 0;
5426
0
    const bool bSkipFailures =
5427
0
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
5428
0
    const bool bPromoteToMulti = CPLTestBool(
5429
0
        CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
5430
0
    const bool bUsePreparedGeometries = CPLTestBool(
5431
0
        CSLFetchNameValueDef(papszOptions, "USE_PREPARED_GEOMETRIES", "YES"));
5432
0
    const bool bPretestContainment = CPLTestBool(
5433
0
        CSLFetchNameValueDef(papszOptions, "PRETEST_CONTAINMENT", "NO"));
5434
0
    bool bKeepLowerDimGeom = CPLTestBool(CSLFetchNameValueDef(
5435
0
        papszOptions, "KEEP_LOWER_DIMENSION_GEOMETRIES", "YES"));
5436
0
    const char *pszOutputGeometryType =
5437
0
        CSLFetchNameValueDef(papszOptions, "OUTPUT_GEOMETRY_TYPE", "GEOMETRY");
5438
0
    const auto eOutputGeometryType = OGRFromOGCGeomType(pszOutputGeometryType);
5439
5440
    // check for GEOS
5441
0
    if (!OGRGeometryFactory::haveGEOS())
5442
0
    {
5443
0
        CPLError(CE_Failure, CPLE_AppDefined,
5444
0
                 "OGRLayer::Intersection() requires GEOS support");
5445
0
        return OGRERR_UNSUPPORTED_OPERATION;
5446
0
    }
5447
5448
    // get resources
5449
0
    ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
5450
0
    if (ret != OGRERR_NONE)
5451
0
        goto done;
5452
0
    ret = create_field_map(poDefnInput, &mapInput);
5453
0
    if (ret != OGRERR_NONE)
5454
0
        goto done;
5455
0
    ret = create_field_map(poDefnMethod, &mapMethod);
5456
0
    if (ret != OGRERR_NONE)
5457
0
        goto done;
5458
0
    ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput,
5459
0
                            mapMethod, true, papszOptions);
5460
0
    if (ret != OGRERR_NONE)
5461
0
        goto done;
5462
0
    poDefnResult = pLayerResult->GetLayerDefn();
5463
0
    bEnvelopeSet = pLayerMethod->GetExtent(&sEnvelopeMethod, 1) == OGRERR_NONE;
5464
0
    if (bKeepLowerDimGeom)
5465
0
    {
5466
        // require that the result layer is of geom type unknown
5467
0
        if (pLayerResult->GetGeomType() != wkbUnknown)
5468
0
        {
5469
0
            CPLDebug("OGR", "Resetting KEEP_LOWER_DIMENSION_GEOMETRIES to NO "
5470
0
                            "since the result layer does not allow it.");
5471
0
            bKeepLowerDimGeom = false;
5472
0
        }
5473
0
    }
5474
5475
0
    for (auto &&x : this)
5476
0
    {
5477
5478
0
        if (pfnProgress)
5479
0
        {
5480
0
            double p = progress_counter / progress_max;
5481
0
            if (p > progress_ticker)
5482
0
            {
5483
0
                if (!pfnProgress(p, "", pProgressArg))
5484
0
                {
5485
0
                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
5486
0
                    ret = OGRERR_FAILURE;
5487
0
                    goto done;
5488
0
                }
5489
0
            }
5490
0
            progress_counter += 1.0;
5491
0
        }
5492
5493
        // is it worth to proceed?
5494
0
        if (bEnvelopeSet)
5495
0
        {
5496
0
            OGRGeometry *x_geom = x->GetGeometryRef();
5497
0
            if (x_geom)
5498
0
            {
5499
0
                OGREnvelope x_env;
5500
0
                x_geom->getEnvelope(&x_env);
5501
0
                if (x_env.MaxX < sEnvelopeMethod.MinX ||
5502
0
                    x_env.MaxY < sEnvelopeMethod.MinY ||
5503
0
                    sEnvelopeMethod.MaxX < x_env.MinX ||
5504
0
                    sEnvelopeMethod.MaxY < x_env.MinY)
5505
0
                {
5506
0
                    continue;
5507
0
                }
5508
0
            }
5509
0
            else
5510
0
            {
5511
0
                continue;
5512
0
            }
5513
0
        }
5514
5515
        // set up the filter for method layer
5516
0
        CPLErrorReset();
5517
0
        OGRGeometry *x_geom =
5518
0
            set_filter_from(pLayerMethod, pGeometryMethodFilter, x.get());
5519
0
        if (CPLGetLastErrorType() != CE_None)
5520
0
        {
5521
0
            if (!bSkipFailures)
5522
0
            {
5523
0
                ret = OGRERR_FAILURE;
5524
0
                goto done;
5525
0
            }
5526
0
            else
5527
0
            {
5528
0
                CPLErrorReset();
5529
0
                ret = OGRERR_NONE;
5530
0
            }
5531
0
        }
5532
0
        if (!x_geom)
5533
0
        {
5534
0
            continue;
5535
0
        }
5536
5537
0
        OGRPreparedGeometryUniquePtr x_prepared_geom;
5538
0
        if (bUsePreparedGeometries)
5539
0
        {
5540
0
            x_prepared_geom.reset(
5541
0
                OGRCreatePreparedGeometry(OGRGeometry::ToHandle(x_geom)));
5542
0
            if (!x_prepared_geom)
5543
0
            {
5544
0
                goto done;
5545
0
            }
5546
0
        }
5547
5548
0
        for (auto &&y : pLayerMethod)
5549
0
        {
5550
0
            OGRGeometry *y_geom = y->GetGeometryRef();
5551
0
            if (!y_geom)
5552
0
                continue;
5553
0
            std::unique_ptr<OGRGeometry> z_geom;
5554
5555
0
            if (x_prepared_geom)
5556
0
            {
5557
0
                CPLErrorReset();
5558
0
                ret = OGRERR_NONE;
5559
0
                if (bPretestContainment &&
5560
0
                    OGRPreparedGeometryContains(x_prepared_geom.get(),
5561
0
                                                OGRGeometry::ToHandle(y_geom)))
5562
0
                {
5563
0
                    if (CPLGetLastErrorType() == CE_None)
5564
0
                        z_geom.reset(y_geom->clone());
5565
0
                }
5566
0
                else if (!(OGRPreparedGeometryIntersects(
5567
0
                             x_prepared_geom.get(),
5568
0
                             OGRGeometry::ToHandle(y_geom))))
5569
0
                {
5570
0
                    if (CPLGetLastErrorType() == CE_None)
5571
0
                    {
5572
0
                        continue;
5573
0
                    }
5574
0
                }
5575
0
                if (CPLGetLastErrorType() != CE_None)
5576
0
                {
5577
0
                    if (!bSkipFailures)
5578
0
                    {
5579
0
                        ret = OGRERR_FAILURE;
5580
0
                        goto done;
5581
0
                    }
5582
0
                    else
5583
0
                    {
5584
0
                        CPLErrorReset();
5585
0
                        ret = OGRERR_NONE;
5586
0
                        continue;
5587
0
                    }
5588
0
                }
5589
0
            }
5590
0
            if (!z_geom)
5591
0
            {
5592
0
                CPLErrorReset();
5593
0
                z_geom.reset(x_geom->Intersection(y_geom));
5594
0
                if (CPLGetLastErrorType() != CE_None || z_geom == nullptr)
5595
0
                {
5596
0
                    if (!bSkipFailures)
5597
0
                    {
5598
0
                        ret = OGRERR_FAILURE;
5599
0
                        goto done;
5600
0
                    }
5601
0
                    else
5602
0
                    {
5603
0
                        CPLErrorReset();
5604
0
                        ret = OGRERR_NONE;
5605
0
                        continue;
5606
0
                    }
5607
0
                }
5608
0
                if (z_geom->IsEmpty() ||
5609
0
                    (!bKeepLowerDimGeom &&
5610
0
                     (x_geom->getDimension() == y_geom->getDimension() &&
5611
0
                      z_geom->getDimension() < x_geom->getDimension())))
5612
0
                {
5613
0
                    continue;
5614
0
                }
5615
0
            }
5616
0
            OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
5617
0
            z->SetFieldsFrom(x.get(), mapInput);
5618
0
            z->SetFieldsFrom(y.get(), mapMethod);
5619
0
            z_geom = convert_geometry(std::move(z_geom), bPromoteToMulti,
5620
0
                                      eOutputGeometryType);
5621
0
            if (!z_geom)
5622
0
                continue;
5623
0
            z->SetGeometryDirectly(z_geom.release());
5624
0
            ret = pLayerResult->CreateFeature(z.get());
5625
5626
0
            if (ret != OGRERR_NONE)
5627
0
            {
5628
0
                if (!bSkipFailures)
5629
0
                {
5630
0
                    goto done;
5631
0
                }
5632
0
                else
5633
0
                {
5634
0
                    CPLErrorReset();
5635
0
                    ret = OGRERR_NONE;
5636
0
                }
5637
0
            }
5638
0
        }
5639
0
    }
5640
0
    if (pfnProgress && !pfnProgress(1.0, "", pProgressArg))
5641
0
    {
5642
0
        CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
5643
0
        ret = OGRERR_FAILURE;
5644
0
        goto done;
5645
0
    }
5646
0
done:
5647
    // release resources
5648
0
    pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
5649
0
    if (pGeometryMethodFilter)
5650
0
        delete pGeometryMethodFilter;
5651
0
    if (mapInput)
5652
0
        VSIFree(mapInput);
5653
0
    if (mapMethod)
5654
0
        VSIFree(mapMethod);
5655
0
    return ret;
5656
0
}
5657
5658
/************************************************************************/
5659
/*                         OGR_L_Intersection()                         */
5660
/************************************************************************/
5661
/**
5662
 * \brief Intersection of two layers.
5663
 *
5664
 * The result layer contains features whose geometries represent areas
5665
 * that are common between features in the input layer and in the
5666
 * method layer. The features in the result layer have attributes from
5667
 * both input and method layers. The schema of the result layer can be
5668
 * set by the user or, if it is empty, is initialized to contain all
5669
 * fields in the input and method layers.
5670
 *
5671
 * \note If the schema of the result is set by user and contains
5672
 * fields that have the same name as a field in input and in method
5673
 * layer, then the attribute in the result feature will get the value
5674
 * from the feature of the method layer.
5675
 *
5676
 * \note For best performance use the minimum amount of features in
5677
 * the method layer and copy it into a memory layer.
5678
 *
5679
 * \note This method relies on GEOS support. Do not use unless the
5680
 * GEOS support is compiled in.
5681
 *
5682
 * The recognized list of options is :
5683
 * <ul>
5684
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
5685
 *     feature could not be inserted or a GEOS call failed.
5686
 * </li>
5687
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
5688
 *     into MultiPolygons, LineStrings to MultiLineStrings or
5689
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
5690
 * </li>
5691
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
5692
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
5693
 *     be converted to it, the corresponding output feature is silently skipped.
5694
 *     Takes precedence over PROMOTE_TO_MULTI.
5695
 * </li>
5696
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
5697
 *     will be created from the fields of the input layer.
5698
 * </li>
5699
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
5700
 *     will be created from the fields of the method layer.
5701
 * </li>
5702
 * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
5703
 *     geometries to pretest intersection of features of method layer
5704
 *     with features of this layer.
5705
 * </li>
5706
 * <li>PRETEST_CONTAINMENT=YES/NO. Set to YES to pretest the
5707
 *     containment of features of method layer within the features of
5708
 *     this layer. This will speed up the method significantly in some
5709
 *     cases. Requires that the prepared geometries are in effect.
5710
 * </li>
5711
 * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
5712
 *     result features with lower dimension geometry that would
5713
 *     otherwise be added to the result layer. The default is YES, to add
5714
 *     features with lower dimension geometry, but only if the result layer
5715
 *     has an unknown geometry type.
5716
 * </li>
5717
 * </ul>
5718
 *
5719
 * This function is the same as the C++ method OGRLayer::Intersection().
5720
 *
5721
 * @param pLayerInput the input layer. Should not be NULL.
5722
 *
5723
 * @param pLayerMethod the method layer. Should not be NULL.
5724
 *
5725
 * @param pLayerResult the layer where the features resulting from the
5726
 * operation are inserted. Should not be NULL. See above the note
5727
 * about the schema.
5728
 *
5729
 * @param papszOptions NULL terminated list of options (may be NULL).
5730
 *
5731
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
5732
 * reporting progress or NULL.
5733
 *
5734
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
5735
 *
5736
 * @return an error code if there was an error or the execution was
5737
 * interrupted, OGRERR_NONE otherwise.
5738
 *
5739
 * @note The first geometry field is always used.
5740
 *
5741
 * @since OGR 1.10
5742
 */
5743
5744
OGRErr OGR_L_Intersection(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
5745
                          OGRLayerH pLayerResult, CSLConstList papszOptions,
5746
                          GDALProgressFunc pfnProgress, void *pProgressArg)
5747
5748
0
{
5749
0
    VALIDATE_POINTER1(pLayerInput, "OGR_L_Intersection", OGRERR_INVALID_HANDLE);
5750
0
    VALIDATE_POINTER1(pLayerMethod, "OGR_L_Intersection",
5751
0
                      OGRERR_INVALID_HANDLE);
5752
0
    VALIDATE_POINTER1(pLayerResult, "OGR_L_Intersection",
5753
0
                      OGRERR_INVALID_HANDLE);
5754
5755
0
    return OGRLayer::FromHandle(pLayerInput)
5756
0
        ->Intersection(OGRLayer::FromHandle(pLayerMethod),
5757
0
                       OGRLayer::FromHandle(pLayerResult), papszOptions,
5758
0
                       pfnProgress, pProgressArg);
5759
0
}
5760
5761
/************************************************************************/
5762
/*                               Union()                                */
5763
/************************************************************************/
5764
5765
/**
5766
 * \brief Union of two layers.
5767
 *
5768
 * The result layer contains features whose geometries represent areas
5769
 * that are either in the input layer, in the method layer, or in
5770
 * both. The features in the result layer have attributes from both
5771
 * input and method layers. For features which represent areas that
5772
 * are only in the input or in the method layer the respective
5773
 * attributes have undefined values. The schema of the result layer
5774
 * can be set by the user or, if it is empty, is initialized to
5775
 * contain all fields in the input and method layers.
5776
 *
5777
 * \note If the schema of the result is set by user and contains
5778
 * fields that have the same name as a field in input and in method
5779
 * layer, then the attribute in the result feature will get the value
5780
 * from the feature of the method layer (even if it is undefined).
5781
 *
5782
 * \note For best performance use the minimum amount of features in
5783
 * the method layer and copy it into a memory layer.
5784
 *
5785
 * \note This method relies on GEOS support. Do not use unless the
5786
 * GEOS support is compiled in.
5787
 *
5788
 * The recognized list of options is :
5789
 * <ul>
5790
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
5791
 *     feature could not be inserted or a GEOS call failed.
5792
 * </li>
5793
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
5794
 *     into MultiPolygons, LineStrings to MultiLineStrings or
5795
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
5796
 * </li>
5797
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
5798
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
5799
 *     be converted to it, the corresponding output feature is silently skipped.
5800
 *     Takes precedence over PROMOTE_TO_MULTI.
5801
 * </li>
5802
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
5803
 *     will be created from the fields of the input layer.
5804
 * </li>
5805
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
5806
 *     will be created from the fields of the method layer.
5807
 * </li>
5808
 * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
5809
 *     geometries to pretest intersection of features of method layer
5810
 *     with features of this layer.
5811
 * </li>
5812
 * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
5813
 *     result features with lower dimension geometry that would
5814
 *     otherwise be added to the result layer. The default is YES, to add
5815
 *     features with lower dimension geometry, but only if the result layer
5816
 *     has an unknown geometry type.
5817
 * </li>
5818
 * </ul>
5819
 *
5820
 * This method is the same as the C function OGR_L_Union().
5821
 *
5822
 * @param pLayerMethod the method layer. Should not be NULL.
5823
 *
5824
 * @param pLayerResult the layer where the features resulting from the
5825
 * operation are inserted. Should not be NULL. See above the note
5826
 * about the schema.
5827
 *
5828
 * @param papszOptions NULL terminated list of options (may be NULL).
5829
 *
5830
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
5831
 * reporting progress or NULL.
5832
 *
5833
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
5834
 *
5835
 * @return an error code if there was an error or the execution was
5836
 * interrupted, OGRERR_NONE otherwise.
5837
 *
5838
 * @note The first geometry field is always used.
5839
 *
5840
 * @since OGR 1.10
5841
 */
5842
5843
OGRErr OGRLayer::Union(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
5844
                       CSLConstList papszOptions, GDALProgressFunc pfnProgress,
5845
                       void *pProgressArg)
5846
0
{
5847
0
    OGRErr ret = OGRERR_NONE;
5848
0
    OGRFeatureDefn *poDefnInput = GetLayerDefn();
5849
0
    OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
5850
0
    OGRFeatureDefn *poDefnResult = nullptr;
5851
0
    OGRGeometry *pGeometryMethodFilter = nullptr;
5852
0
    OGRGeometry *pGeometryInputFilter = nullptr;
5853
0
    int *mapInput = nullptr;
5854
0
    int *mapMethod = nullptr;
5855
0
    double progress_max =
5856
0
        static_cast<double>(GetFeatureCount(FALSE)) +
5857
0
        static_cast<double>(pLayerMethod->GetFeatureCount(FALSE));
5858
0
    double progress_counter = 0;
5859
0
    double progress_ticker = 0;
5860
0
    const bool bSkipFailures =
5861
0
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
5862
0
    const bool bPromoteToMulti = CPLTestBool(
5863
0
        CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
5864
0
    const bool bUsePreparedGeometries = CPLTestBool(
5865
0
        CSLFetchNameValueDef(papszOptions, "USE_PREPARED_GEOMETRIES", "YES"));
5866
0
    bool bKeepLowerDimGeom = CPLTestBool(CSLFetchNameValueDef(
5867
0
        papszOptions, "KEEP_LOWER_DIMENSION_GEOMETRIES", "YES"));
5868
0
    const char *pszOutputGeometryType =
5869
0
        CSLFetchNameValueDef(papszOptions, "OUTPUT_GEOMETRY_TYPE", "GEOMETRY");
5870
0
    const auto eOutputGeometryType = OGRFromOGCGeomType(pszOutputGeometryType);
5871
5872
    // check for GEOS
5873
0
    if (!OGRGeometryFactory::haveGEOS())
5874
0
    {
5875
0
        CPLError(CE_Failure, CPLE_AppDefined,
5876
0
                 "OGRLayer::Union() requires GEOS support");
5877
0
        return OGRERR_UNSUPPORTED_OPERATION;
5878
0
    }
5879
5880
    // get resources
5881
0
    ret = clone_spatial_filter(this, &pGeometryInputFilter);
5882
0
    if (ret != OGRERR_NONE)
5883
0
        goto done;
5884
0
    ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
5885
0
    if (ret != OGRERR_NONE)
5886
0
        goto done;
5887
0
    ret = create_field_map(poDefnInput, &mapInput);
5888
0
    if (ret != OGRERR_NONE)
5889
0
        goto done;
5890
0
    ret = create_field_map(poDefnMethod, &mapMethod);
5891
0
    if (ret != OGRERR_NONE)
5892
0
        goto done;
5893
0
    ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput,
5894
0
                            mapMethod, true, papszOptions);
5895
0
    if (ret != OGRERR_NONE)
5896
0
        goto done;
5897
0
    poDefnResult = pLayerResult->GetLayerDefn();
5898
0
    if (bKeepLowerDimGeom)
5899
0
    {
5900
        // require that the result layer is of geom type unknown
5901
0
        if (pLayerResult->GetGeomType() != wkbUnknown)
5902
0
        {
5903
0
            CPLDebug("OGR", "Resetting KEEP_LOWER_DIMENSION_GEOMETRIES to NO "
5904
0
                            "since the result layer does not allow it.");
5905
0
            bKeepLowerDimGeom = FALSE;
5906
0
        }
5907
0
    }
5908
5909
    // add features based on input layer
5910
0
    for (auto &&x : this)
5911
0
    {
5912
5913
0
        if (pfnProgress)
5914
0
        {
5915
0
            double p = progress_counter / progress_max;
5916
0
            if (p > progress_ticker)
5917
0
            {
5918
0
                if (!pfnProgress(p, "", pProgressArg))
5919
0
                {
5920
0
                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
5921
0
                    ret = OGRERR_FAILURE;
5922
0
                    goto done;
5923
0
                }
5924
0
            }
5925
0
            progress_counter += 1.0;
5926
0
        }
5927
5928
        // set up the filter on method layer
5929
0
        CPLErrorReset();
5930
0
        OGRGeometry *x_geom =
5931
0
            set_filter_from(pLayerMethod, pGeometryMethodFilter, x.get());
5932
0
        if (CPLGetLastErrorType() != CE_None)
5933
0
        {
5934
0
            if (!bSkipFailures)
5935
0
            {
5936
0
                ret = OGRERR_FAILURE;
5937
0
                goto done;
5938
0
            }
5939
0
            else
5940
0
            {
5941
0
                CPLErrorReset();
5942
0
                ret = OGRERR_NONE;
5943
0
            }
5944
0
        }
5945
0
        if (!x_geom)
5946
0
        {
5947
0
            continue;
5948
0
        }
5949
5950
0
        OGRPreparedGeometryUniquePtr x_prepared_geom;
5951
0
        if (bUsePreparedGeometries)
5952
0
        {
5953
0
            x_prepared_geom.reset(
5954
0
                OGRCreatePreparedGeometry(OGRGeometry::ToHandle(x_geom)));
5955
0
            if (!x_prepared_geom)
5956
0
            {
5957
0
                goto done;
5958
0
            }
5959
0
        }
5960
5961
0
        std::unique_ptr<OGRGeometry> x_geom_diff(
5962
0
            x_geom
5963
0
                ->clone());  // this will be the geometry of the result feature
5964
0
        for (auto &&y : pLayerMethod)
5965
0
        {
5966
0
            OGRGeometry *y_geom = y->GetGeometryRef();
5967
0
            if (!y_geom)
5968
0
            {
5969
0
                continue;
5970
0
            }
5971
5972
0
            CPLErrorReset();
5973
0
            if (x_prepared_geom &&
5974
0
                !(OGRPreparedGeometryIntersects(x_prepared_geom.get(),
5975
0
                                                OGRGeometry::ToHandle(y_geom))))
5976
0
            {
5977
0
                if (CPLGetLastErrorType() == CE_None)
5978
0
                {
5979
0
                    continue;
5980
0
                }
5981
0
            }
5982
0
            if (CPLGetLastErrorType() != CE_None)
5983
0
            {
5984
0
                if (!bSkipFailures)
5985
0
                {
5986
0
                    ret = OGRERR_FAILURE;
5987
0
                    goto done;
5988
0
                }
5989
0
                else
5990
0
                {
5991
0
                    CPLErrorReset();
5992
0
                    ret = OGRERR_NONE;
5993
0
                }
5994
0
            }
5995
5996
0
            CPLErrorReset();
5997
0
            std::unique_ptr<OGRGeometry> poIntersection(
5998
0
                x_geom->Intersection(y_geom));
5999
0
            if (CPLGetLastErrorType() != CE_None || poIntersection == nullptr)
6000
0
            {
6001
0
                if (!bSkipFailures)
6002
0
                {
6003
0
                    ret = OGRERR_FAILURE;
6004
0
                    goto done;
6005
0
                }
6006
0
                else
6007
0
                {
6008
0
                    CPLErrorReset();
6009
0
                    ret = OGRERR_NONE;
6010
0
                    continue;
6011
0
                }
6012
0
            }
6013
0
            if (poIntersection->IsEmpty() ||
6014
0
                (!bKeepLowerDimGeom &&
6015
0
                 (x_geom->getDimension() == y_geom->getDimension() &&
6016
0
                  poIntersection->getDimension() < x_geom->getDimension())))
6017
0
            {
6018
                // ok
6019
0
            }
6020
0
            else
6021
0
            {
6022
0
                OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
6023
0
                z->SetFieldsFrom(x.get(), mapInput);
6024
0
                z->SetFieldsFrom(y.get(), mapMethod);
6025
0
                poIntersection =
6026
0
                    convert_geometry(std::move(poIntersection), bPromoteToMulti,
6027
0
                                     eOutputGeometryType);
6028
0
                z->SetGeometryDirectly(poIntersection.release());
6029
6030
0
                if (x_geom_diff)
6031
0
                {
6032
0
                    CPLErrorReset();
6033
0
                    std::unique_ptr<OGRGeometry> x_geom_diff_new(
6034
0
                        x_geom_diff->Difference(y_geom));
6035
0
                    if (CPLGetLastErrorType() != CE_None ||
6036
0
                        x_geom_diff_new == nullptr)
6037
0
                    {
6038
0
                        if (!bSkipFailures)
6039
0
                        {
6040
0
                            ret = OGRERR_FAILURE;
6041
0
                            goto done;
6042
0
                        }
6043
0
                        else
6044
0
                        {
6045
0
                            CPLErrorReset();
6046
0
                        }
6047
0
                    }
6048
0
                    else
6049
0
                    {
6050
0
                        x_geom_diff.swap(x_geom_diff_new);
6051
0
                    }
6052
0
                }
6053
6054
0
                ret = pLayerResult->CreateFeature(z.get());
6055
0
                if (ret != OGRERR_NONE)
6056
0
                {
6057
0
                    if (!bSkipFailures)
6058
0
                    {
6059
0
                        goto done;
6060
0
                    }
6061
0
                    else
6062
0
                    {
6063
0
                        CPLErrorReset();
6064
0
                        ret = OGRERR_NONE;
6065
0
                    }
6066
0
                }
6067
0
            }
6068
0
        }
6069
0
        x_prepared_geom.reset();
6070
6071
0
        if (x_geom_diff == nullptr || x_geom_diff->IsEmpty())
6072
0
        {
6073
            // ok
6074
0
        }
6075
0
        else
6076
0
        {
6077
0
            OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
6078
0
            z->SetFieldsFrom(x.get(), mapInput);
6079
0
            x_geom_diff = convert_geometry(
6080
0
                std::move(x_geom_diff), bPromoteToMulti, eOutputGeometryType);
6081
0
            if (!x_geom_diff)
6082
0
                continue;
6083
0
            z->SetGeometryDirectly(x_geom_diff.release());
6084
0
            ret = pLayerResult->CreateFeature(z.get());
6085
0
            if (ret != OGRERR_NONE)
6086
0
            {
6087
0
                if (!bSkipFailures)
6088
0
                {
6089
0
                    goto done;
6090
0
                }
6091
0
                else
6092
0
                {
6093
0
                    CPLErrorReset();
6094
0
                    ret = OGRERR_NONE;
6095
0
                }
6096
0
            }
6097
0
        }
6098
0
    }
6099
6100
    // restore filter on method layer and add features based on it
6101
0
    pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
6102
0
    for (auto &&x : pLayerMethod)
6103
0
    {
6104
6105
0
        if (pfnProgress)
6106
0
        {
6107
0
            double p = progress_counter / progress_max;
6108
0
            if (p > progress_ticker)
6109
0
            {
6110
0
                if (!pfnProgress(p, "", pProgressArg))
6111
0
                {
6112
0
                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
6113
0
                    ret = OGRERR_FAILURE;
6114
0
                    goto done;
6115
0
                }
6116
0
            }
6117
0
            progress_counter += 1.0;
6118
0
        }
6119
6120
        // set up the filter on input layer
6121
0
        CPLErrorReset();
6122
0
        OGRGeometry *x_geom =
6123
0
            set_filter_from(this, pGeometryInputFilter, x.get());
6124
0
        if (CPLGetLastErrorType() != CE_None)
6125
0
        {
6126
0
            if (!bSkipFailures)
6127
0
            {
6128
0
                ret = OGRERR_FAILURE;
6129
0
                goto done;
6130
0
            }
6131
0
            else
6132
0
            {
6133
0
                CPLErrorReset();
6134
0
                ret = OGRERR_NONE;
6135
0
            }
6136
0
        }
6137
0
        if (!x_geom)
6138
0
        {
6139
0
            continue;
6140
0
        }
6141
6142
0
        std::unique_ptr<OGRGeometry> x_geom_diff(
6143
0
            x_geom
6144
0
                ->clone());  // this will be the geometry of the result feature
6145
0
        for (auto &&y : this)
6146
0
        {
6147
0
            OGRGeometry *y_geom = y->GetGeometryRef();
6148
0
            if (!y_geom)
6149
0
            {
6150
0
                continue;
6151
0
            }
6152
6153
0
            if (x_geom_diff)
6154
0
            {
6155
0
                CPLErrorReset();
6156
0
                std::unique_ptr<OGRGeometry> x_geom_diff_new(
6157
0
                    x_geom_diff->Difference(y_geom));
6158
0
                if (CPLGetLastErrorType() != CE_None ||
6159
0
                    x_geom_diff_new == nullptr)
6160
0
                {
6161
0
                    if (!bSkipFailures)
6162
0
                    {
6163
0
                        ret = OGRERR_FAILURE;
6164
0
                        goto done;
6165
0
                    }
6166
0
                    else
6167
0
                    {
6168
0
                        CPLErrorReset();
6169
0
                        ret = OGRERR_NONE;
6170
0
                    }
6171
0
                }
6172
0
                else
6173
0
                {
6174
0
                    x_geom_diff.swap(x_geom_diff_new);
6175
0
                }
6176
0
            }
6177
0
        }
6178
6179
0
        if (x_geom_diff == nullptr || x_geom_diff->IsEmpty())
6180
0
        {
6181
            // ok
6182
0
        }
6183
0
        else
6184
0
        {
6185
0
            OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
6186
0
            z->SetFieldsFrom(x.get(), mapMethod);
6187
0
            x_geom_diff = convert_geometry(
6188
0
                std::move(x_geom_diff), bPromoteToMulti, eOutputGeometryType);
6189
0
            if (!x_geom_diff)
6190
0
                continue;
6191
0
            z->SetGeometryDirectly(x_geom_diff.release());
6192
0
            ret = pLayerResult->CreateFeature(z.get());
6193
0
            if (ret != OGRERR_NONE)
6194
0
            {
6195
0
                if (!bSkipFailures)
6196
0
                {
6197
0
                    goto done;
6198
0
                }
6199
0
                else
6200
0
                {
6201
0
                    CPLErrorReset();
6202
0
                    ret = OGRERR_NONE;
6203
0
                }
6204
0
            }
6205
0
        }
6206
0
    }
6207
0
    if (pfnProgress && !pfnProgress(1.0, "", pProgressArg))
6208
0
    {
6209
0
        CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
6210
0
        ret = OGRERR_FAILURE;
6211
0
        goto done;
6212
0
    }
6213
0
done:
6214
    // release resources
6215
0
    SetSpatialFilter(pGeometryInputFilter);
6216
0
    pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
6217
0
    if (pGeometryMethodFilter)
6218
0
        delete pGeometryMethodFilter;
6219
0
    if (pGeometryInputFilter)
6220
0
        delete pGeometryInputFilter;
6221
0
    if (mapInput)
6222
0
        VSIFree(mapInput);
6223
0
    if (mapMethod)
6224
0
        VSIFree(mapMethod);
6225
0
    return ret;
6226
0
}
6227
6228
/************************************************************************/
6229
/*                            OGR_L_Union()                             */
6230
/************************************************************************/
6231
6232
/**
6233
 * \brief Union of two layers.
6234
 *
6235
 * The result layer contains features whose geometries represent areas
6236
 * that are in either in the input layer, in the method layer, or in
6237
 * both. The features in the result layer have attributes from both
6238
 * input and method layers. For features which represent areas that
6239
 * are only in the input or in the method layer the respective
6240
 * attributes have undefined values. The schema of the result layer
6241
 * can be set by the user or, if it is empty, is initialized to
6242
 * contain all fields in the input and method layers.
6243
 *
6244
 * \note If the schema of the result is set by user and contains
6245
 * fields that have the same name as a field in input and in method
6246
 * layer, then the attribute in the result feature will get the value
6247
 * from the feature of the method layer (even if it is undefined).
6248
 *
6249
 * \note For best performance use the minimum amount of features in
6250
 * the method layer and copy it into a memory layer.
6251
 *
6252
 * \note This method relies on GEOS support. Do not use unless the
6253
 * GEOS support is compiled in.
6254
 *
6255
 * The recognized list of options is :
6256
 * <ul>
6257
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
6258
 *     feature could not be inserted or a GEOS call failed.
6259
 * </li>
6260
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
6261
 *     into MultiPolygons, LineStrings to MultiLineStrings or
6262
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
6263
 * </li>
6264
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
6265
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
6266
 *     be converted to it, the corresponding output feature is silently skipped.
6267
 *     Takes precedence over PROMOTE_TO_MULTI.
6268
 * </li>
6269
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
6270
 *     will be created from the fields of the input layer.
6271
 * </li>
6272
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
6273
 *     will be created from the fields of the method layer.
6274
 * </li>
6275
 * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
6276
 *     geometries to pretest intersection of features of method layer
6277
 *     with features of this layer.
6278
 * </li>
6279
 * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
6280
 *     result features with lower dimension geometry that would
6281
 *     otherwise be added to the result layer. The default is YES, to add
6282
 *     features with lower dimension geometry, but only if the result layer
6283
 *     has an unknown geometry type.
6284
 * </li>
6285
 * </ul>
6286
 *
6287
 * This function is the same as the C++ method OGRLayer::Union().
6288
 *
6289
 * @param pLayerInput the input layer. Should not be NULL.
6290
 *
6291
 * @param pLayerMethod the method layer. Should not be NULL.
6292
 *
6293
 * @param pLayerResult the layer where the features resulting from the
6294
 * operation are inserted. Should not be NULL. See above the note
6295
 * about the schema.
6296
 *
6297
 * @param papszOptions NULL terminated list of options (may be NULL).
6298
 *
6299
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
6300
 * reporting progress or NULL.
6301
 *
6302
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
6303
 *
6304
 * @return an error code if there was an error or the execution was
6305
 * interrupted, OGRERR_NONE otherwise.
6306
 *
6307
 * @note The first geometry field is always used.
6308
 *
6309
 * @since OGR 1.10
6310
 */
6311
6312
OGRErr OGR_L_Union(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
6313
                   OGRLayerH pLayerResult, CSLConstList papszOptions,
6314
                   GDALProgressFunc pfnProgress, void *pProgressArg)
6315
6316
0
{
6317
0
    VALIDATE_POINTER1(pLayerInput, "OGR_L_Union", OGRERR_INVALID_HANDLE);
6318
0
    VALIDATE_POINTER1(pLayerMethod, "OGR_L_Union", OGRERR_INVALID_HANDLE);
6319
0
    VALIDATE_POINTER1(pLayerResult, "OGR_L_Union", OGRERR_INVALID_HANDLE);
6320
6321
0
    return OGRLayer::FromHandle(pLayerInput)
6322
0
        ->Union(OGRLayer::FromHandle(pLayerMethod),
6323
0
                OGRLayer::FromHandle(pLayerResult), papszOptions, pfnProgress,
6324
0
                pProgressArg);
6325
0
}
6326
6327
/************************************************************************/
6328
/*                           SymDifference()                            */
6329
/************************************************************************/
6330
6331
/**
6332
 * \brief Symmetrical difference of two layers.
6333
 *
6334
 * The result layer contains features whose geometries represent areas
6335
 * that are in either in the input layer or in the method layer but
6336
 * not in both. The features in the result layer have attributes from
6337
 * both input and method layers. For features which represent areas
6338
 * that are only in the input or in the method layer the respective
6339
 * attributes have undefined values. The schema of the result layer
6340
 * can be set by the user or, if it is empty, is initialized to
6341
 * contain all fields in the input and method layers.
6342
 *
6343
 * \note If the schema of the result is set by user and contains
6344
 * fields that have the same name as a field in input and in method
6345
 * layer, then the attribute in the result feature will get the value
6346
 * from the feature of the method layer (even if it is undefined).
6347
 *
6348
 * \note For best performance use the minimum amount of features in
6349
 * the method layer and copy it into a memory layer.
6350
 *
6351
 * \note This method relies on GEOS support. Do not use unless the
6352
 * GEOS support is compiled in.
6353
 *
6354
 * The recognized list of options is :
6355
 * <ul>
6356
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
6357
 *     feature could not be inserted or a GEOS call failed.
6358
 * </li>
6359
 * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
6360
 *     into MultiPolygons, or LineStrings to MultiLineStrings.
6361
 * </li>
6362
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
6363
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
6364
 *     be converted to it, the corresponding output feature is silently skipped.
6365
 *     Takes precedence over PROMOTE_TO_MULTI.
6366
 * </li>
6367
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
6368
 *     will be created from the fields of the input layer.
6369
 * </li>
6370
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
6371
 *     will be created from the fields of the method layer.
6372
 * </li>
6373
 * </ul>
6374
 *
6375
 * This method is the same as the C function OGR_L_SymDifference().
6376
 *
6377
 * @param pLayerMethod the method layer. Should not be NULL.
6378
 *
6379
 * @param pLayerResult the layer where the features resulting from the
6380
 * operation are inserted. Should not be NULL. See above the note
6381
 * about the schema.
6382
 *
6383
 * @param papszOptions NULL terminated list of options (may be NULL).
6384
 *
6385
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
6386
 * reporting progress or NULL.
6387
 *
6388
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
6389
 *
6390
 * @return an error code if there was an error or the execution was
6391
 * interrupted, OGRERR_NONE otherwise.
6392
 *
6393
 * @note The first geometry field is always used.
6394
 *
6395
 * @since OGR 1.10
6396
 */
6397
6398
OGRErr OGRLayer::SymDifference(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
6399
                               CSLConstList papszOptions,
6400
                               GDALProgressFunc pfnProgress, void *pProgressArg)
6401
0
{
6402
0
    OGRErr ret = OGRERR_NONE;
6403
0
    OGRFeatureDefn *poDefnInput = GetLayerDefn();
6404
0
    OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
6405
0
    OGRFeatureDefn *poDefnResult = nullptr;
6406
0
    OGRGeometry *pGeometryMethodFilter = nullptr;
6407
0
    OGRGeometry *pGeometryInputFilter = nullptr;
6408
0
    int *mapInput = nullptr;
6409
0
    int *mapMethod = nullptr;
6410
0
    double progress_max =
6411
0
        static_cast<double>(GetFeatureCount(FALSE)) +
6412
0
        static_cast<double>(pLayerMethod->GetFeatureCount(FALSE));
6413
0
    double progress_counter = 0;
6414
0
    double progress_ticker = 0;
6415
0
    const bool bSkipFailures =
6416
0
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
6417
0
    const bool bPromoteToMulti = CPLTestBool(
6418
0
        CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
6419
0
    const char *pszOutputGeometryType =
6420
0
        CSLFetchNameValueDef(papszOptions, "OUTPUT_GEOMETRY_TYPE", "GEOMETRY");
6421
0
    const auto eOutputGeometryType = OGRFromOGCGeomType(pszOutputGeometryType);
6422
6423
    // check for GEOS
6424
0
    if (!OGRGeometryFactory::haveGEOS())
6425
0
    {
6426
0
        CPLError(CE_Failure, CPLE_AppDefined,
6427
0
                 "OGRLayer::SymDifference() requires GEOS support");
6428
0
        return OGRERR_UNSUPPORTED_OPERATION;
6429
0
    }
6430
6431
    // get resources
6432
0
    ret = clone_spatial_filter(this, &pGeometryInputFilter);
6433
0
    if (ret != OGRERR_NONE)
6434
0
        goto done;
6435
0
    ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
6436
0
    if (ret != OGRERR_NONE)
6437
0
        goto done;
6438
0
    ret = create_field_map(poDefnInput, &mapInput);
6439
0
    if (ret != OGRERR_NONE)
6440
0
        goto done;
6441
0
    ret = create_field_map(poDefnMethod, &mapMethod);
6442
0
    if (ret != OGRERR_NONE)
6443
0
        goto done;
6444
0
    ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput,
6445
0
                            mapMethod, true, papszOptions);
6446
0
    if (ret != OGRERR_NONE)
6447
0
        goto done;
6448
0
    poDefnResult = pLayerResult->GetLayerDefn();
6449
6450
    // add features based on input layer
6451
0
    for (auto &&x : this)
6452
0
    {
6453
6454
0
        if (pfnProgress)
6455
0
        {
6456
0
            double p = progress_counter / progress_max;
6457
0
            if (p > progress_ticker)
6458
0
            {
6459
0
                if (!pfnProgress(p, "", pProgressArg))
6460
0
                {
6461
0
                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
6462
0
                    ret = OGRERR_FAILURE;
6463
0
                    goto done;
6464
0
                }
6465
0
            }
6466
0
            progress_counter += 1.0;
6467
0
        }
6468
6469
        // set up the filter on method layer
6470
0
        CPLErrorReset();
6471
0
        OGRGeometry *x_geom =
6472
0
            set_filter_from(pLayerMethod, pGeometryMethodFilter, x.get());
6473
0
        if (CPLGetLastErrorType() != CE_None)
6474
0
        {
6475
0
            if (!bSkipFailures)
6476
0
            {
6477
0
                ret = OGRERR_FAILURE;
6478
0
                goto done;
6479
0
            }
6480
0
            else
6481
0
            {
6482
0
                CPLErrorReset();
6483
0
                ret = OGRERR_NONE;
6484
0
            }
6485
0
        }
6486
0
        if (!x_geom)
6487
0
        {
6488
0
            continue;
6489
0
        }
6490
6491
0
        std::unique_ptr<OGRGeometry> geom(
6492
0
            x_geom
6493
0
                ->clone());  // this will be the geometry of the result feature
6494
0
        for (auto &&y : pLayerMethod)
6495
0
        {
6496
0
            OGRGeometry *y_geom = y->GetGeometryRef();
6497
0
            if (!y_geom)
6498
0
            {
6499
0
                continue;
6500
0
            }
6501
0
            if (geom)
6502
0
            {
6503
0
                CPLErrorReset();
6504
0
                std::unique_ptr<OGRGeometry> geom_new(geom->Difference(y_geom));
6505
0
                if (CPLGetLastErrorType() != CE_None || geom_new == nullptr)
6506
0
                {
6507
0
                    if (!bSkipFailures)
6508
0
                    {
6509
0
                        ret = OGRERR_FAILURE;
6510
0
                        goto done;
6511
0
                    }
6512
0
                    else
6513
0
                    {
6514
0
                        CPLErrorReset();
6515
0
                        ret = OGRERR_NONE;
6516
0
                    }
6517
0
                }
6518
0
                else
6519
0
                {
6520
0
                    geom.swap(geom_new);
6521
0
                }
6522
0
            }
6523
0
            if (geom && geom->IsEmpty())
6524
0
                break;
6525
0
        }
6526
6527
0
        if (geom && !geom->IsEmpty())
6528
0
        {
6529
0
            OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
6530
0
            z->SetFieldsFrom(x.get(), mapInput);
6531
0
            geom = convert_geometry(std::move(geom), bPromoteToMulti,
6532
0
                                    eOutputGeometryType);
6533
0
            if (!geom)
6534
0
                continue;
6535
0
            z->SetGeometryDirectly(geom.release());
6536
0
            ret = pLayerResult->CreateFeature(z.get());
6537
0
            if (ret != OGRERR_NONE)
6538
0
            {
6539
0
                if (!bSkipFailures)
6540
0
                {
6541
0
                    goto done;
6542
0
                }
6543
0
                else
6544
0
                {
6545
0
                    CPLErrorReset();
6546
0
                    ret = OGRERR_NONE;
6547
0
                }
6548
0
            }
6549
0
        }
6550
0
    }
6551
6552
    // restore filter on method layer and add features based on it
6553
0
    pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
6554
0
    for (auto &&x : pLayerMethod)
6555
0
    {
6556
6557
0
        if (pfnProgress)
6558
0
        {
6559
0
            double p = progress_counter / progress_max;
6560
0
            if (p > progress_ticker)
6561
0
            {
6562
0
                if (!pfnProgress(p, "", pProgressArg))
6563
0
                {
6564
0
                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
6565
0
                    ret = OGRERR_FAILURE;
6566
0
                    goto done;
6567
0
                }
6568
0
            }
6569
0
            progress_counter += 1.0;
6570
0
        }
6571
6572
        // set up the filter on input layer
6573
0
        CPLErrorReset();
6574
0
        OGRGeometry *x_geom =
6575
0
            set_filter_from(this, pGeometryInputFilter, x.get());
6576
0
        if (CPLGetLastErrorType() != CE_None)
6577
0
        {
6578
0
            if (!bSkipFailures)
6579
0
            {
6580
0
                ret = OGRERR_FAILURE;
6581
0
                goto done;
6582
0
            }
6583
0
            else
6584
0
            {
6585
0
                CPLErrorReset();
6586
0
                ret = OGRERR_NONE;
6587
0
            }
6588
0
        }
6589
0
        if (!x_geom)
6590
0
        {
6591
0
            continue;
6592
0
        }
6593
6594
0
        std::unique_ptr<OGRGeometry> geom(
6595
0
            x_geom
6596
0
                ->clone());  // this will be the geometry of the result feature
6597
0
        for (auto &&y : this)
6598
0
        {
6599
0
            OGRGeometry *y_geom = y->GetGeometryRef();
6600
0
            if (!y_geom)
6601
0
                continue;
6602
0
            if (geom)
6603
0
            {
6604
0
                CPLErrorReset();
6605
0
                std::unique_ptr<OGRGeometry> geom_new(geom->Difference(y_geom));
6606
0
                if (CPLGetLastErrorType() != CE_None || geom_new == nullptr)
6607
0
                {
6608
0
                    if (!bSkipFailures)
6609
0
                    {
6610
0
                        ret = OGRERR_FAILURE;
6611
0
                        goto done;
6612
0
                    }
6613
0
                    else
6614
0
                    {
6615
0
                        CPLErrorReset();
6616
0
                        ret = OGRERR_NONE;
6617
0
                    }
6618
0
                }
6619
0
                else
6620
0
                {
6621
0
                    geom.swap(geom_new);
6622
0
                }
6623
0
            }
6624
0
            if (geom == nullptr || geom->IsEmpty())
6625
0
                break;
6626
0
        }
6627
6628
0
        if (geom && !geom->IsEmpty())
6629
0
        {
6630
0
            OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
6631
0
            z->SetFieldsFrom(x.get(), mapMethod);
6632
0
            geom = convert_geometry(std::move(geom), bPromoteToMulti,
6633
0
                                    eOutputGeometryType);
6634
0
            if (!geom)
6635
0
                continue;
6636
0
            z->SetGeometryDirectly(geom.release());
6637
0
            ret = pLayerResult->CreateFeature(z.get());
6638
0
            if (ret != OGRERR_NONE)
6639
0
            {
6640
0
                if (!bSkipFailures)
6641
0
                {
6642
0
                    goto done;
6643
0
                }
6644
0
                else
6645
0
                {
6646
0
                    CPLErrorReset();
6647
0
                    ret = OGRERR_NONE;
6648
0
                }
6649
0
            }
6650
0
        }
6651
0
    }
6652
0
    if (pfnProgress && !pfnProgress(1.0, "", pProgressArg))
6653
0
    {
6654
0
        CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
6655
0
        ret = OGRERR_FAILURE;
6656
0
        goto done;
6657
0
    }
6658
0
done:
6659
    // release resources
6660
0
    SetSpatialFilter(pGeometryInputFilter);
6661
0
    pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
6662
0
    if (pGeometryMethodFilter)
6663
0
        delete pGeometryMethodFilter;
6664
0
    if (pGeometryInputFilter)
6665
0
        delete pGeometryInputFilter;
6666
0
    if (mapInput)
6667
0
        VSIFree(mapInput);
6668
0
    if (mapMethod)
6669
0
        VSIFree(mapMethod);
6670
0
    return ret;
6671
0
}
6672
6673
/************************************************************************/
6674
/*                        OGR_L_SymDifference()                         */
6675
/************************************************************************/
6676
6677
/**
6678
 * \brief Symmetrical difference of two layers.
6679
 *
6680
 * The result layer contains features whose geometries represent areas
6681
 * that are in either in the input layer or in the method layer but
6682
 * not in both. The features in the result layer have attributes from
6683
 * both input and method layers. For features which represent areas
6684
 * that are only in the input or in the method layer the respective
6685
 * attributes have undefined values. The schema of the result layer
6686
 * can be set by the user or, if it is empty, is initialized to
6687
 * contain all fields in the input and method layers.
6688
 *
6689
 * \note If the schema of the result is set by user and contains
6690
 * fields that have the same name as a field in input and in method
6691
 * layer, then the attribute in the result feature will get the value
6692
 * from the feature of the method layer (even if it is undefined).
6693
 *
6694
 * \note For best performance use the minimum amount of features in
6695
 * the method layer and copy it into a memory layer.
6696
 *
6697
 * \note This method relies on GEOS support. Do not use unless the
6698
 * GEOS support is compiled in.
6699
 *
6700
 * The recognized list of options is :
6701
 * <ul>
6702
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
6703
 *     feature could not be inserted or a GEOS call failed.
6704
 * </li>
6705
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
6706
 *     into MultiPolygons, LineStrings to MultiLineStrings or
6707
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
6708
 * </li>
6709
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
6710
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
6711
 *     be converted to it, the corresponding output feature is silently skipped.
6712
 *     Takes precedence over PROMOTE_TO_MULTI.
6713
 * </li>
6714
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
6715
 *     will be created from the fields of the input layer.
6716
 * </li>
6717
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
6718
 *     will be created from the fields of the method layer.
6719
 * </li>
6720
 * </ul>
6721
 *
6722
 * This function is the same as the C++ method OGRLayer::SymDifference().
6723
 *
6724
 * @param pLayerInput the input layer. Should not be NULL.
6725
 *
6726
 * @param pLayerMethod the method layer. Should not be NULL.
6727
 *
6728
 * @param pLayerResult the layer where the features resulting from the
6729
 * operation are inserted. Should not be NULL. See above the note
6730
 * about the schema.
6731
 *
6732
 * @param papszOptions NULL terminated list of options (may be NULL).
6733
 *
6734
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
6735
 * reporting progress or NULL.
6736
 *
6737
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
6738
 *
6739
 * @return an error code if there was an error or the execution was
6740
 * interrupted, OGRERR_NONE otherwise.
6741
 *
6742
 * @note The first geometry field is always used.
6743
 *
6744
 * @since OGR 1.10
6745
 */
6746
6747
OGRErr OGR_L_SymDifference(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
6748
                           OGRLayerH pLayerResult, CSLConstList papszOptions,
6749
                           GDALProgressFunc pfnProgress, void *pProgressArg)
6750
6751
0
{
6752
0
    VALIDATE_POINTER1(pLayerInput, "OGR_L_SymDifference",
6753
0
                      OGRERR_INVALID_HANDLE);
6754
0
    VALIDATE_POINTER1(pLayerMethod, "OGR_L_SymDifference",
6755
0
                      OGRERR_INVALID_HANDLE);
6756
0
    VALIDATE_POINTER1(pLayerResult, "OGR_L_SymDifference",
6757
0
                      OGRERR_INVALID_HANDLE);
6758
6759
0
    return OGRLayer::FromHandle(pLayerInput)
6760
0
        ->SymDifference(OGRLayer::FromHandle(pLayerMethod),
6761
0
                        OGRLayer::FromHandle(pLayerResult), papszOptions,
6762
0
                        pfnProgress, pProgressArg);
6763
0
}
6764
6765
/************************************************************************/
6766
/*                              Identity()                              */
6767
/************************************************************************/
6768
6769
/**
6770
 * \brief Identify the features of this layer with the ones from the
6771
 * identity layer.
6772
 *
6773
 * The result layer contains features whose geometries represent areas
6774
 * that are in the input layer. The features in the result layer have
6775
 * attributes from both input and method layers. The schema of the
6776
 * result layer can be set by the user or, if it is empty, is
6777
 * initialized to contain all fields in input and method layers.
6778
 *
6779
 * \note If the schema of the result is set by user and contains
6780
 * fields that have the same name as a field in input and in method
6781
 * layer, then the attribute in the result feature will get the value
6782
 * from the feature of the method layer (even if it is undefined).
6783
 *
6784
 * \note For best performance use the minimum amount of features in
6785
 * the method layer and copy it into a memory layer.
6786
 *
6787
 * \note This method relies on GEOS support. Do not use unless the
6788
 * GEOS support is compiled in.
6789
 *
6790
 * The recognized list of options is :
6791
 * <ul>
6792
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
6793
 *     feature could not be inserted or a GEOS call failed.
6794
 * </li>
6795
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
6796
 *     into MultiPolygons, LineStrings to MultiLineStrings or
6797
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
6798
 * </li>
6799
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
6800
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
6801
 *     be converted to it, the corresponding output feature is silently skipped.
6802
 *     Takes precedence over PROMOTE_TO_MULTI.
6803
 * </li>
6804
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
6805
 *     will be created from the fields of the input layer.
6806
 * </li>
6807
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
6808
 *     will be created from the fields of the method layer.
6809
 * </li>
6810
 * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
6811
 *     geometries to pretest intersection of features of method layer
6812
 *     with features of this layer.
6813
 * </li>
6814
 * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
6815
 *     result features with lower dimension geometry that would
6816
 *     otherwise be added to the result layer. The default is YES, to add
6817
 *     features with lower dimension geometry, but only if the result layer
6818
 *     has an unknown geometry type.
6819
 * </li>
6820
 * </ul>
6821
 *
6822
 * This method is the same as the C function OGR_L_Identity().
6823
 *
6824
 * @param pLayerMethod the method layer. Should not be NULL.
6825
 *
6826
 * @param pLayerResult the layer where the features resulting from the
6827
 * operation are inserted. Should not be NULL. See above the note
6828
 * about the schema.
6829
 *
6830
 * @param papszOptions NULL terminated list of options (may be NULL).
6831
 *
6832
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
6833
 * reporting progress or NULL.
6834
 *
6835
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
6836
 *
6837
 * @return an error code if there was an error or the execution was
6838
 * interrupted, OGRERR_NONE otherwise.
6839
 *
6840
 * @note The first geometry field is always used.
6841
 *
6842
 * @since OGR 1.10
6843
 */
6844
6845
OGRErr OGRLayer::Identity(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
6846
                          CSLConstList papszOptions,
6847
                          GDALProgressFunc pfnProgress, void *pProgressArg)
6848
0
{
6849
0
    OGRErr ret = OGRERR_NONE;
6850
0
    OGRFeatureDefn *poDefnInput = GetLayerDefn();
6851
0
    OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
6852
0
    OGRFeatureDefn *poDefnResult = nullptr;
6853
0
    OGRGeometry *pGeometryMethodFilter = nullptr;
6854
0
    int *mapInput = nullptr;
6855
0
    int *mapMethod = nullptr;
6856
0
    double progress_max = static_cast<double>(GetFeatureCount(FALSE));
6857
0
    double progress_counter = 0;
6858
0
    double progress_ticker = 0;
6859
0
    const bool bSkipFailures =
6860
0
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
6861
0
    const bool bPromoteToMulti = CPLTestBool(
6862
0
        CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
6863
0
    const bool bUsePreparedGeometries = CPLTestBool(
6864
0
        CSLFetchNameValueDef(papszOptions, "USE_PREPARED_GEOMETRIES", "YES"));
6865
0
    bool bKeepLowerDimGeom = CPLTestBool(CSLFetchNameValueDef(
6866
0
        papszOptions, "KEEP_LOWER_DIMENSION_GEOMETRIES", "YES"));
6867
0
    const char *pszOutputGeometryType =
6868
0
        CSLFetchNameValueDef(papszOptions, "OUTPUT_GEOMETRY_TYPE", "GEOMETRY");
6869
0
    const auto eOutputGeometryType = OGRFromOGCGeomType(pszOutputGeometryType);
6870
6871
    // check for GEOS
6872
0
    if (!OGRGeometryFactory::haveGEOS())
6873
0
    {
6874
0
        CPLError(CE_Failure, CPLE_AppDefined,
6875
0
                 "OGRLayer::Identity() requires GEOS support");
6876
0
        return OGRERR_UNSUPPORTED_OPERATION;
6877
0
    }
6878
0
    if (bKeepLowerDimGeom)
6879
0
    {
6880
        // require that the result layer is of geom type unknown
6881
0
        if (pLayerResult->GetGeomType() != wkbUnknown)
6882
0
        {
6883
0
            CPLDebug("OGR", "Resetting KEEP_LOWER_DIMENSION_GEOMETRIES to NO "
6884
0
                            "since the result layer does not allow it.");
6885
0
            bKeepLowerDimGeom = FALSE;
6886
0
        }
6887
0
    }
6888
6889
    // get resources
6890
0
    ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
6891
0
    if (ret != OGRERR_NONE)
6892
0
        goto done;
6893
0
    ret = create_field_map(poDefnInput, &mapInput);
6894
0
    if (ret != OGRERR_NONE)
6895
0
        goto done;
6896
0
    ret = create_field_map(poDefnMethod, &mapMethod);
6897
0
    if (ret != OGRERR_NONE)
6898
0
        goto done;
6899
0
    ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput,
6900
0
                            mapMethod, true, papszOptions);
6901
0
    if (ret != OGRERR_NONE)
6902
0
        goto done;
6903
0
    poDefnResult = pLayerResult->GetLayerDefn();
6904
6905
    // split the features in input layer to the result layer
6906
0
    for (auto &&x : this)
6907
0
    {
6908
6909
0
        if (pfnProgress)
6910
0
        {
6911
0
            double p = progress_counter / progress_max;
6912
0
            if (p > progress_ticker)
6913
0
            {
6914
0
                if (!pfnProgress(p, "", pProgressArg))
6915
0
                {
6916
0
                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
6917
0
                    ret = OGRERR_FAILURE;
6918
0
                    goto done;
6919
0
                }
6920
0
            }
6921
0
            progress_counter += 1.0;
6922
0
        }
6923
6924
        // set up the filter on method layer
6925
0
        CPLErrorReset();
6926
0
        OGRGeometry *x_geom =
6927
0
            set_filter_from(pLayerMethod, pGeometryMethodFilter, x.get());
6928
0
        if (CPLGetLastErrorType() != CE_None)
6929
0
        {
6930
0
            if (!bSkipFailures)
6931
0
            {
6932
0
                ret = OGRERR_FAILURE;
6933
0
                goto done;
6934
0
            }
6935
0
            else
6936
0
            {
6937
0
                CPLErrorReset();
6938
0
                ret = OGRERR_NONE;
6939
0
            }
6940
0
        }
6941
0
        if (!x_geom)
6942
0
        {
6943
0
            continue;
6944
0
        }
6945
6946
0
        OGRPreparedGeometryUniquePtr x_prepared_geom;
6947
0
        if (bUsePreparedGeometries)
6948
0
        {
6949
0
            x_prepared_geom.reset(
6950
0
                OGRCreatePreparedGeometry(OGRGeometry::ToHandle(x_geom)));
6951
0
            if (!x_prepared_geom)
6952
0
            {
6953
0
                goto done;
6954
0
            }
6955
0
        }
6956
6957
0
        std::unique_ptr<OGRGeometry> x_geom_diff(
6958
0
            x_geom
6959
0
                ->clone());  // this will be the geometry of the result feature
6960
0
        for (auto &&y : pLayerMethod)
6961
0
        {
6962
0
            OGRGeometry *y_geom = y->GetGeometryRef();
6963
0
            if (!y_geom)
6964
0
                continue;
6965
6966
0
            CPLErrorReset();
6967
0
            if (x_prepared_geom &&
6968
0
                !(OGRPreparedGeometryIntersects(x_prepared_geom.get(),
6969
0
                                                OGRGeometry::ToHandle(y_geom))))
6970
0
            {
6971
0
                if (CPLGetLastErrorType() == CE_None)
6972
0
                {
6973
0
                    continue;
6974
0
                }
6975
0
            }
6976
0
            if (CPLGetLastErrorType() != CE_None)
6977
0
            {
6978
0
                if (!bSkipFailures)
6979
0
                {
6980
0
                    ret = OGRERR_FAILURE;
6981
0
                    goto done;
6982
0
                }
6983
0
                else
6984
0
                {
6985
0
                    CPLErrorReset();
6986
0
                    ret = OGRERR_NONE;
6987
0
                }
6988
0
            }
6989
6990
0
            CPLErrorReset();
6991
0
            std::unique_ptr<OGRGeometry> poIntersection(
6992
0
                x_geom->Intersection(y_geom));
6993
0
            if (CPLGetLastErrorType() != CE_None || poIntersection == nullptr)
6994
0
            {
6995
0
                if (!bSkipFailures)
6996
0
                {
6997
0
                    ret = OGRERR_FAILURE;
6998
0
                    goto done;
6999
0
                }
7000
0
                else
7001
0
                {
7002
0
                    CPLErrorReset();
7003
0
                    ret = OGRERR_NONE;
7004
0
                }
7005
0
            }
7006
0
            else if (poIntersection->IsEmpty() ||
7007
0
                     (!bKeepLowerDimGeom &&
7008
0
                      (x_geom->getDimension() == y_geom->getDimension() &&
7009
0
                       poIntersection->getDimension() <
7010
0
                           x_geom->getDimension())))
7011
0
            {
7012
                /* ok*/
7013
0
            }
7014
0
            else
7015
0
            {
7016
0
                OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
7017
0
                z->SetFieldsFrom(x.get(), mapInput);
7018
0
                z->SetFieldsFrom(y.get(), mapMethod);
7019
0
                poIntersection =
7020
0
                    convert_geometry(std::move(poIntersection), bPromoteToMulti,
7021
0
                                     eOutputGeometryType);
7022
0
                if (!poIntersection)
7023
0
                    continue;
7024
0
                z->SetGeometryDirectly(poIntersection.release());
7025
0
                if (x_geom_diff)
7026
0
                {
7027
0
                    CPLErrorReset();
7028
0
                    std::unique_ptr<OGRGeometry> x_geom_diff_new(
7029
0
                        x_geom_diff->Difference(y_geom));
7030
0
                    if (CPLGetLastErrorType() != CE_None ||
7031
0
                        x_geom_diff_new == nullptr)
7032
0
                    {
7033
0
                        if (!bSkipFailures)
7034
0
                        {
7035
0
                            ret = OGRERR_FAILURE;
7036
0
                            goto done;
7037
0
                        }
7038
0
                        else
7039
0
                        {
7040
0
                            CPLErrorReset();
7041
0
                        }
7042
0
                    }
7043
0
                    else
7044
0
                    {
7045
0
                        x_geom_diff.swap(x_geom_diff_new);
7046
0
                    }
7047
0
                }
7048
0
                ret = pLayerResult->CreateFeature(z.get());
7049
0
                if (ret != OGRERR_NONE)
7050
0
                {
7051
0
                    if (!bSkipFailures)
7052
0
                    {
7053
0
                        goto done;
7054
0
                    }
7055
0
                    else
7056
0
                    {
7057
0
                        CPLErrorReset();
7058
0
                        ret = OGRERR_NONE;
7059
0
                    }
7060
0
                }
7061
0
            }
7062
0
        }
7063
7064
0
        x_prepared_geom.reset();
7065
7066
0
        if (x_geom_diff == nullptr || x_geom_diff->IsEmpty())
7067
0
        {
7068
            /* ok */
7069
0
        }
7070
0
        else
7071
0
        {
7072
0
            OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
7073
0
            z->SetFieldsFrom(x.get(), mapInput);
7074
0
            x_geom_diff = convert_geometry(
7075
0
                std::move(x_geom_diff), bPromoteToMulti, eOutputGeometryType);
7076
0
            if (!x_geom_diff)
7077
0
                continue;
7078
0
            z->SetGeometryDirectly(x_geom_diff.release());
7079
0
            ret = pLayerResult->CreateFeature(z.get());
7080
0
            if (ret != OGRERR_NONE)
7081
0
            {
7082
0
                if (!bSkipFailures)
7083
0
                {
7084
0
                    goto done;
7085
0
                }
7086
0
                else
7087
0
                {
7088
0
                    CPLErrorReset();
7089
0
                    ret = OGRERR_NONE;
7090
0
                }
7091
0
            }
7092
0
        }
7093
0
    }
7094
0
    if (pfnProgress && !pfnProgress(1.0, "", pProgressArg))
7095
0
    {
7096
0
        CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
7097
0
        ret = OGRERR_FAILURE;
7098
0
        goto done;
7099
0
    }
7100
0
done:
7101
    // release resources
7102
0
    pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
7103
0
    if (pGeometryMethodFilter)
7104
0
        delete pGeometryMethodFilter;
7105
0
    if (mapInput)
7106
0
        VSIFree(mapInput);
7107
0
    if (mapMethod)
7108
0
        VSIFree(mapMethod);
7109
0
    return ret;
7110
0
}
7111
7112
/************************************************************************/
7113
/*                           OGR_L_Identity()                           */
7114
/************************************************************************/
7115
7116
/**
7117
 * \brief Identify the features of this layer with the ones from the
7118
 * identity layer.
7119
 *
7120
 * The result layer contains features whose geometries represent areas
7121
 * that are in the input layer. The features in the result layer have
7122
 * attributes from both input and method layers. The schema of the
7123
 * result layer can be set by the user or, if it is empty, is
7124
 * initialized to contain all fields in input and method layers.
7125
 *
7126
 * \note If the schema of the result is set by user and contains
7127
 * fields that have the same name as a field in input and in method
7128
 * layer, then the attribute in the result feature will get the value
7129
 * from the feature of the method layer (even if it is undefined).
7130
 *
7131
 * \note For best performance use the minimum amount of features in
7132
 * the method layer and copy it into a memory layer.
7133
 *
7134
 * \note This method relies on GEOS support. Do not use unless the
7135
 * GEOS support is compiled in.
7136
 *
7137
 * The recognized list of options is :
7138
 * <ul>
7139
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
7140
 *     feature could not be inserted or a GEOS call failed.
7141
 * </li>
7142
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
7143
 *     into MultiPolygons, LineStrings to MultiLineStrings or
7144
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
7145
 * </li>
7146
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
7147
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
7148
 *     be converted to it, the corresponding output feature is silently skipped.
7149
 *     Takes precedence over PROMOTE_TO_MULTI.
7150
 * </li>
7151
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
7152
 *     will be created from the fields of the input layer.
7153
 * </li>
7154
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
7155
 *     will be created from the fields of the method layer.
7156
 * </li>
7157
 * <li>USE_PREPARED_GEOMETRIES=YES/NO. Set to NO to not use prepared
7158
 *     geometries to pretest intersection of features of method layer
7159
 *     with features of this layer.
7160
 * </li>
7161
 * <li>KEEP_LOWER_DIMENSION_GEOMETRIES=YES/NO. Set to NO to skip
7162
 *     result features with lower dimension geometry that would
7163
 *     otherwise be added to the result layer. The default is YES, to add
7164
 *     features with lower dimension geometry, but only if the result layer
7165
 *     has an unknown geometry type.
7166
 * </li>
7167
 * </ul>
7168
 *
7169
 * This function is the same as the C++ method OGRLayer::Identity().
7170
 *
7171
 * @param pLayerInput the input layer. Should not be NULL.
7172
 *
7173
 * @param pLayerMethod the method layer. Should not be NULL.
7174
 *
7175
 * @param pLayerResult the layer where the features resulting from the
7176
 * operation are inserted. Should not be NULL. See above the note
7177
 * about the schema.
7178
 *
7179
 * @param papszOptions NULL terminated list of options (may be NULL).
7180
 *
7181
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
7182
 * reporting progress or NULL.
7183
 *
7184
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
7185
 *
7186
 * @return an error code if there was an error or the execution was
7187
 * interrupted, OGRERR_NONE otherwise.
7188
 *
7189
 * @note The first geometry field is always used.
7190
 *
7191
 * @since OGR 1.10
7192
 */
7193
7194
OGRErr OGR_L_Identity(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
7195
                      OGRLayerH pLayerResult, CSLConstList papszOptions,
7196
                      GDALProgressFunc pfnProgress, void *pProgressArg)
7197
7198
0
{
7199
0
    VALIDATE_POINTER1(pLayerInput, "OGR_L_Identity", OGRERR_INVALID_HANDLE);
7200
0
    VALIDATE_POINTER1(pLayerMethod, "OGR_L_Identity", OGRERR_INVALID_HANDLE);
7201
0
    VALIDATE_POINTER1(pLayerResult, "OGR_L_Identity", OGRERR_INVALID_HANDLE);
7202
7203
0
    return OGRLayer::FromHandle(pLayerInput)
7204
0
        ->Identity(OGRLayer::FromHandle(pLayerMethod),
7205
0
                   OGRLayer::FromHandle(pLayerResult), papszOptions,
7206
0
                   pfnProgress, pProgressArg);
7207
0
}
7208
7209
/************************************************************************/
7210
/*                               Update()                               */
7211
/************************************************************************/
7212
7213
/**
7214
 * \brief Update this layer with features from the update layer.
7215
 *
7216
 * The result layer contains features whose geometries represent areas
7217
 * that are either in the input layer or in the method layer. The
7218
 * features in the result layer have areas of the features of the
7219
 * method layer or those ares of the features of the input layer that
7220
 * are not covered by the method layer. The features of the result
7221
 * layer get their attributes from the input layer. The schema of the
7222
 * result layer can be set by the user or, if it is empty, is
7223
 * initialized to contain all fields in the input layer.
7224
 *
7225
 * \note If the schema of the result is set by user and contains
7226
 * fields that have the same name as a field in the method layer, then
7227
 * the attribute in the result feature the originates from the method
7228
 * layer will get the value from the feature of the method layer.
7229
 *
7230
 * \note For best performance use the minimum amount of features in
7231
 * the method layer and copy it into a memory layer.
7232
 *
7233
 * \note This method relies on GEOS support. Do not use unless the
7234
 * GEOS support is compiled in.
7235
 *
7236
 * The recognized list of options is :
7237
 * <ul>
7238
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
7239
 *     feature could not be inserted or a GEOS call failed.
7240
 * </li>
7241
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
7242
 *     into MultiPolygons, LineStrings to MultiLineStrings or
7243
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
7244
 * </li>
7245
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
7246
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
7247
 *     be converted to it, the corresponding output feature is silently skipped.
7248
 *     Takes precedence over PROMOTE_TO_MULTI.
7249
 * </li>
7250
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
7251
 *     will be created from the fields of the input layer.
7252
 * </li>
7253
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
7254
 *     will be created from the fields of the method layer.
7255
 * </li>
7256
 * </ul>
7257
 *
7258
 * This method is the same as the C function OGR_L_Update().
7259
 *
7260
 * @param pLayerMethod the method layer. Should not be NULL.
7261
 *
7262
 * @param pLayerResult the layer where the features resulting from the
7263
 * operation are inserted. Should not be NULL. See above the note
7264
 * about the schema.
7265
 *
7266
 * @param papszOptions NULL terminated list of options (may be NULL).
7267
 *
7268
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
7269
 * reporting progress or NULL.
7270
 *
7271
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
7272
 *
7273
 * @return an error code if there was an error or the execution was
7274
 * interrupted, OGRERR_NONE otherwise.
7275
 *
7276
 * @note The first geometry field is always used.
7277
 *
7278
 * @since OGR 1.10
7279
 */
7280
7281
OGRErr OGRLayer::Update(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
7282
                        CSLConstList papszOptions, GDALProgressFunc pfnProgress,
7283
                        void *pProgressArg)
7284
0
{
7285
0
    OGRErr ret = OGRERR_NONE;
7286
0
    OGRFeatureDefn *poDefnInput = GetLayerDefn();
7287
0
    OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
7288
0
    OGRFeatureDefn *poDefnResult = nullptr;
7289
0
    OGRGeometry *pGeometryMethodFilter = nullptr;
7290
0
    int *mapInput = nullptr;
7291
0
    int *mapMethod = nullptr;
7292
0
    double progress_max =
7293
0
        static_cast<double>(GetFeatureCount(FALSE)) +
7294
0
        static_cast<double>(pLayerMethod->GetFeatureCount(FALSE));
7295
0
    double progress_counter = 0;
7296
0
    double progress_ticker = 0;
7297
0
    const bool bSkipFailures =
7298
0
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
7299
0
    const bool bPromoteToMulti = CPLTestBool(
7300
0
        CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
7301
0
    const char *pszOutputGeometryType =
7302
0
        CSLFetchNameValueDef(papszOptions, "OUTPUT_GEOMETRY_TYPE", "GEOMETRY");
7303
0
    const auto eOutputGeometryType = OGRFromOGCGeomType(pszOutputGeometryType);
7304
7305
    // check for GEOS
7306
0
    if (!OGRGeometryFactory::haveGEOS())
7307
0
    {
7308
0
        CPLError(CE_Failure, CPLE_AppDefined,
7309
0
                 "OGRLayer::Update() requires GEOS support");
7310
0
        return OGRERR_UNSUPPORTED_OPERATION;
7311
0
    }
7312
7313
    // get resources
7314
0
    ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
7315
0
    if (ret != OGRERR_NONE)
7316
0
        goto done;
7317
0
    ret = create_field_map(poDefnInput, &mapInput);
7318
0
    if (ret != OGRERR_NONE)
7319
0
        goto done;
7320
0
    ret = create_field_map(poDefnMethod, &mapMethod);
7321
0
    if (ret != OGRERR_NONE)
7322
0
        goto done;
7323
0
    ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput,
7324
0
                            mapMethod, false, papszOptions);
7325
0
    if (ret != OGRERR_NONE)
7326
0
        goto done;
7327
0
    poDefnResult = pLayerResult->GetLayerDefn();
7328
7329
    // add clipped features from the input layer
7330
0
    for (auto &&x : this)
7331
0
    {
7332
7333
0
        if (pfnProgress)
7334
0
        {
7335
0
            double p = progress_counter / progress_max;
7336
0
            if (p > progress_ticker)
7337
0
            {
7338
0
                if (!pfnProgress(p, "", pProgressArg))
7339
0
                {
7340
0
                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
7341
0
                    ret = OGRERR_FAILURE;
7342
0
                    goto done;
7343
0
                }
7344
0
            }
7345
0
            progress_counter += 1.0;
7346
0
        }
7347
7348
        // set up the filter on method layer
7349
0
        CPLErrorReset();
7350
0
        OGRGeometry *x_geom =
7351
0
            set_filter_from(pLayerMethod, pGeometryMethodFilter, x.get());
7352
0
        if (CPLGetLastErrorType() != CE_None)
7353
0
        {
7354
0
            if (!bSkipFailures)
7355
0
            {
7356
0
                ret = OGRERR_FAILURE;
7357
0
                goto done;
7358
0
            }
7359
0
            else
7360
0
            {
7361
0
                CPLErrorReset();
7362
0
                ret = OGRERR_NONE;
7363
0
            }
7364
0
        }
7365
0
        if (!x_geom)
7366
0
        {
7367
0
            continue;
7368
0
        }
7369
7370
0
        std::unique_ptr<OGRGeometry> x_geom_diff(
7371
0
            x_geom->clone());  // this will be the geometry of a result feature
7372
0
        for (auto &&y : pLayerMethod)
7373
0
        {
7374
0
            OGRGeometry *y_geom = y->GetGeometryRef();
7375
0
            if (!y_geom)
7376
0
                continue;
7377
0
            if (x_geom_diff)
7378
0
            {
7379
0
                CPLErrorReset();
7380
0
                std::unique_ptr<OGRGeometry> x_geom_diff_new(
7381
0
                    x_geom_diff->Difference(y_geom));
7382
0
                if (CPLGetLastErrorType() != CE_None ||
7383
0
                    x_geom_diff_new == nullptr)
7384
0
                {
7385
0
                    if (!bSkipFailures)
7386
0
                    {
7387
0
                        ret = OGRERR_FAILURE;
7388
0
                        goto done;
7389
0
                    }
7390
0
                    else
7391
0
                    {
7392
0
                        CPLErrorReset();
7393
0
                        ret = OGRERR_NONE;
7394
0
                    }
7395
0
                }
7396
0
                else
7397
0
                {
7398
0
                    x_geom_diff.swap(x_geom_diff_new);
7399
0
                }
7400
0
            }
7401
0
        }
7402
7403
0
        if (x_geom_diff == nullptr || x_geom_diff->IsEmpty())
7404
0
        {
7405
            /* ok */
7406
0
        }
7407
0
        else
7408
0
        {
7409
0
            OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
7410
0
            z->SetFieldsFrom(x.get(), mapInput);
7411
0
            x_geom_diff = convert_geometry(
7412
0
                std::move(x_geom_diff), bPromoteToMulti, eOutputGeometryType);
7413
0
            if (!x_geom_diff)
7414
0
                continue;
7415
0
            z->SetGeometryDirectly(x_geom_diff.release());
7416
0
            ret = pLayerResult->CreateFeature(z.get());
7417
0
            if (ret != OGRERR_NONE)
7418
0
            {
7419
0
                if (!bSkipFailures)
7420
0
                {
7421
0
                    goto done;
7422
0
                }
7423
0
                else
7424
0
                {
7425
0
                    CPLErrorReset();
7426
0
                    ret = OGRERR_NONE;
7427
0
                }
7428
0
            }
7429
0
        }
7430
0
    }
7431
7432
    // restore the original filter and add features from the update layer
7433
0
    pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
7434
0
    for (auto &&y : pLayerMethod)
7435
0
    {
7436
7437
0
        if (pfnProgress)
7438
0
        {
7439
0
            double p = progress_counter / progress_max;
7440
0
            if (p > progress_ticker)
7441
0
            {
7442
0
                if (!pfnProgress(p, "", pProgressArg))
7443
0
                {
7444
0
                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
7445
0
                    ret = OGRERR_FAILURE;
7446
0
                    goto done;
7447
0
                }
7448
0
            }
7449
0
            progress_counter += 1.0;
7450
0
        }
7451
7452
0
        std::unique_ptr<OGRGeometry> y_geom(y->StealGeometry());
7453
0
        if (!y_geom)
7454
0
            continue;
7455
0
        y_geom = convert_geometry(std::move(y_geom), bPromoteToMulti,
7456
0
                                  eOutputGeometryType);
7457
0
        if (!y_geom)
7458
0
            continue;
7459
0
        OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
7460
0
        if (mapMethod)
7461
0
            z->SetFieldsFrom(y.get(), mapMethod);
7462
0
        z->SetGeometryDirectly(y_geom.release());
7463
0
        ret = pLayerResult->CreateFeature(z.get());
7464
0
        if (ret != OGRERR_NONE)
7465
0
        {
7466
0
            if (!bSkipFailures)
7467
0
            {
7468
0
                goto done;
7469
0
            }
7470
0
            else
7471
0
            {
7472
0
                CPLErrorReset();
7473
0
                ret = OGRERR_NONE;
7474
0
            }
7475
0
        }
7476
0
    }
7477
0
    if (pfnProgress && !pfnProgress(1.0, "", pProgressArg))
7478
0
    {
7479
0
        CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
7480
0
        ret = OGRERR_FAILURE;
7481
0
        goto done;
7482
0
    }
7483
0
done:
7484
    // release resources
7485
0
    pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
7486
0
    if (pGeometryMethodFilter)
7487
0
        delete pGeometryMethodFilter;
7488
0
    if (mapInput)
7489
0
        VSIFree(mapInput);
7490
0
    if (mapMethod)
7491
0
        VSIFree(mapMethod);
7492
0
    return ret;
7493
0
}
7494
7495
/************************************************************************/
7496
/*                            OGR_L_Update()                            */
7497
/************************************************************************/
7498
7499
/**
7500
 * \brief Update this layer with features from the update layer.
7501
 *
7502
 * The result layer contains features whose geometries represent areas
7503
 * that are either in the input layer or in the method layer. The
7504
 * features in the result layer have areas of the features of the
7505
 * method layer or those ares of the features of the input layer that
7506
 * are not covered by the method layer. The features of the result
7507
 * layer get their attributes from the input layer. The schema of the
7508
 * result layer can be set by the user or, if it is empty, is
7509
 * initialized to contain all fields in the input layer.
7510
 *
7511
 * \note If the schema of the result is set by user and contains
7512
 * fields that have the same name as a field in the method layer, then
7513
 * the attribute in the result feature the originates from the method
7514
 * layer will get the value from the feature of the method layer.
7515
 *
7516
 * \note For best performance use the minimum amount of features in
7517
 * the method layer and copy it into a memory layer.
7518
 *
7519
 * \note This method relies on GEOS support. Do not use unless the
7520
 * GEOS support is compiled in.
7521
 *
7522
 * The recognized list of options is :
7523
 * <ul>
7524
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
7525
 *     feature could not be inserted or a GEOS call failed.
7526
 * </li>
7527
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
7528
 *     into MultiPolygons, LineStrings to MultiLineStrings or
7529
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
7530
 * </li>
7531
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
7532
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
7533
 *     be converted to it, the corresponding output feature is silently skipped.
7534
 *     Takes precedence over PROMOTE_TO_MULTI.
7535
 * </li>
7536
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
7537
 *     will be created from the fields of the input layer.
7538
 * </li>
7539
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
7540
 *     will be created from the fields of the method layer.
7541
 * </li>
7542
 * </ul>
7543
 *
7544
 * This function is the same as the C++ method OGRLayer::Update().
7545
 *
7546
 * @param pLayerInput the input layer. Should not be NULL.
7547
 *
7548
 * @param pLayerMethod the method layer. Should not be NULL.
7549
 *
7550
 * @param pLayerResult the layer where the features resulting from the
7551
 * operation are inserted. Should not be NULL. See above the note
7552
 * about the schema.
7553
 *
7554
 * @param papszOptions NULL terminated list of options (may be NULL).
7555
 *
7556
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
7557
 * reporting progress or NULL.
7558
 *
7559
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
7560
 *
7561
 * @return an error code if there was an error or the execution was
7562
 * interrupted, OGRERR_NONE otherwise.
7563
 *
7564
 * @note The first geometry field is always used.
7565
 *
7566
 * @since OGR 1.10
7567
 */
7568
7569
OGRErr OGR_L_Update(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
7570
                    OGRLayerH pLayerResult, CSLConstList papszOptions,
7571
                    GDALProgressFunc pfnProgress, void *pProgressArg)
7572
7573
0
{
7574
0
    VALIDATE_POINTER1(pLayerInput, "OGR_L_Update", OGRERR_INVALID_HANDLE);
7575
0
    VALIDATE_POINTER1(pLayerMethod, "OGR_L_Update", OGRERR_INVALID_HANDLE);
7576
0
    VALIDATE_POINTER1(pLayerResult, "OGR_L_Update", OGRERR_INVALID_HANDLE);
7577
7578
0
    return OGRLayer::FromHandle(pLayerInput)
7579
0
        ->Update(OGRLayer::FromHandle(pLayerMethod),
7580
0
                 OGRLayer::FromHandle(pLayerResult), papszOptions, pfnProgress,
7581
0
                 pProgressArg);
7582
0
}
7583
7584
/************************************************************************/
7585
/*                                Clip()                                */
7586
/************************************************************************/
7587
7588
/**
7589
 * \brief Clip off areas that are not covered by the method layer.
7590
 *
7591
 * The result layer contains features whose geometries represent areas
7592
 * that are in the input layer and in the method layer. The features
7593
 * in the result layer have the (possibly clipped) areas of features
7594
 * in the input layer and the attributes from the same features. The
7595
 * schema of the result layer can be set by the user or, if it is
7596
 * empty, is initialized to contain all fields in the input layer.
7597
 *
7598
 * \note For best performance use the minimum amount of features in
7599
 * the method layer and copy it into a memory layer.
7600
 *
7601
 * \note This method relies on GEOS support. Do not use unless the
7602
 * GEOS support is compiled in.
7603
 *
7604
 * The recognized list of options is :
7605
 * <ul>
7606
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
7607
 *     feature could not be inserted or a GEOS call failed.
7608
 * </li>
7609
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
7610
 *     into MultiPolygons, LineStrings to MultiLineStrings or
7611
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
7612
 * </li>
7613
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
7614
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
7615
 *     be converted to it, the corresponding output feature is silently skipped.
7616
 *     Takes precedence over PROMOTE_TO_MULTI.
7617
 * </li>
7618
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
7619
 *     will be created from the fields of the input layer.
7620
 * </li>
7621
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
7622
 *     will be created from the fields of the method layer.
7623
 * </li>
7624
 * </ul>
7625
 *
7626
 * This method is the same as the C function OGR_L_Clip().
7627
 *
7628
 * @param pLayerMethod the method layer. Should not be NULL.
7629
 *
7630
 * @param pLayerResult the layer where the features resulting from the
7631
 * operation are inserted. Should not be NULL. See above the note
7632
 * about the schema.
7633
 *
7634
 * @param papszOptions NULL terminated list of options (may be NULL).
7635
 *
7636
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
7637
 * reporting progress or NULL.
7638
 *
7639
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
7640
 *
7641
 * @return an error code if there was an error or the execution was
7642
 * interrupted, OGRERR_NONE otherwise.
7643
 *
7644
 * @note The first geometry field is always used.
7645
 *
7646
 * @since OGR 1.10
7647
 */
7648
7649
OGRErr OGRLayer::Clip(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
7650
                      CSLConstList papszOptions, GDALProgressFunc pfnProgress,
7651
                      void *pProgressArg)
7652
0
{
7653
0
    OGRErr ret = OGRERR_NONE;
7654
0
    OGRFeatureDefn *poDefnInput = GetLayerDefn();
7655
0
    OGRFeatureDefn *poDefnResult = nullptr;
7656
0
    OGRGeometry *pGeometryMethodFilter = nullptr;
7657
0
    int *mapInput = nullptr;
7658
0
    double progress_max = static_cast<double>(GetFeatureCount(FALSE));
7659
0
    double progress_counter = 0;
7660
0
    double progress_ticker = 0;
7661
0
    const bool bSkipFailures =
7662
0
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
7663
0
    const bool bPromoteToMulti = CPLTestBool(
7664
0
        CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
7665
0
    const char *pszOutputGeometryType =
7666
0
        CSLFetchNameValueDef(papszOptions, "OUTPUT_GEOMETRY_TYPE", "GEOMETRY");
7667
0
    const auto eOutputGeometryType = OGRFromOGCGeomType(pszOutputGeometryType);
7668
7669
    // check for GEOS
7670
0
    if (!OGRGeometryFactory::haveGEOS())
7671
0
    {
7672
0
        CPLError(CE_Failure, CPLE_AppDefined,
7673
0
                 "OGRLayer::Clip() requires GEOS support");
7674
0
        return OGRERR_UNSUPPORTED_OPERATION;
7675
0
    }
7676
7677
0
    ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
7678
0
    if (ret != OGRERR_NONE)
7679
0
        goto done;
7680
0
    ret = create_field_map(poDefnInput, &mapInput);
7681
0
    if (ret != OGRERR_NONE)
7682
0
        goto done;
7683
0
    ret = set_result_schema(pLayerResult, poDefnInput, nullptr, mapInput,
7684
0
                            nullptr, false, papszOptions);
7685
0
    if (ret != OGRERR_NONE)
7686
0
        goto done;
7687
7688
0
    poDefnResult = pLayerResult->GetLayerDefn();
7689
0
    for (auto &&x : this)
7690
0
    {
7691
7692
0
        if (pfnProgress)
7693
0
        {
7694
0
            double p = progress_counter / progress_max;
7695
0
            if (p > progress_ticker)
7696
0
            {
7697
0
                if (!pfnProgress(p, "", pProgressArg))
7698
0
                {
7699
0
                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
7700
0
                    ret = OGRERR_FAILURE;
7701
0
                    goto done;
7702
0
                }
7703
0
            }
7704
0
            progress_counter += 1.0;
7705
0
        }
7706
7707
        // set up the filter on method layer
7708
0
        CPLErrorReset();
7709
0
        OGRGeometry *x_geom =
7710
0
            set_filter_from(pLayerMethod, pGeometryMethodFilter, x.get());
7711
0
        if (CPLGetLastErrorType() != CE_None)
7712
0
        {
7713
0
            if (!bSkipFailures)
7714
0
            {
7715
0
                ret = OGRERR_FAILURE;
7716
0
                goto done;
7717
0
            }
7718
0
            else
7719
0
            {
7720
0
                CPLErrorReset();
7721
0
                ret = OGRERR_NONE;
7722
0
            }
7723
0
        }
7724
0
        if (!x_geom)
7725
0
        {
7726
0
            continue;
7727
0
        }
7728
7729
0
        std::unique_ptr<OGRGeometry>
7730
0
            geom;  // this will be the geometry of the result feature
7731
        // incrementally add area from y to geom
7732
0
        for (auto &&y : pLayerMethod)
7733
0
        {
7734
0
            OGRGeometry *y_geom = y->GetGeometryRef();
7735
0
            if (!y_geom)
7736
0
                continue;
7737
0
            if (!geom)
7738
0
            {
7739
0
                geom.reset(y_geom->clone());
7740
0
            }
7741
0
            else
7742
0
            {
7743
0
                CPLErrorReset();
7744
0
                std::unique_ptr<OGRGeometry> geom_new(geom->Union(y_geom));
7745
0
                if (CPLGetLastErrorType() != CE_None || geom_new == nullptr)
7746
0
                {
7747
0
                    if (!bSkipFailures)
7748
0
                    {
7749
0
                        ret = OGRERR_FAILURE;
7750
0
                        goto done;
7751
0
                    }
7752
0
                    else
7753
0
                    {
7754
0
                        CPLErrorReset();
7755
0
                        ret = OGRERR_NONE;
7756
0
                    }
7757
0
                }
7758
0
                else
7759
0
                {
7760
0
                    geom.swap(geom_new);
7761
0
                }
7762
0
            }
7763
0
        }
7764
7765
        // possibly add a new feature with area x intersection sum of y
7766
0
        if (geom)
7767
0
        {
7768
0
            CPLErrorReset();
7769
0
            std::unique_ptr<OGRGeometry> poIntersection(
7770
0
                x_geom->Intersection(geom.get()));
7771
0
            if (CPLGetLastErrorType() != CE_None || poIntersection == nullptr)
7772
0
            {
7773
0
                if (!bSkipFailures)
7774
0
                {
7775
0
                    ret = OGRERR_FAILURE;
7776
0
                    goto done;
7777
0
                }
7778
0
                else
7779
0
                {
7780
0
                    CPLErrorReset();
7781
0
                    ret = OGRERR_NONE;
7782
0
                }
7783
0
            }
7784
0
            else if (!poIntersection->IsEmpty())
7785
0
            {
7786
0
                OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
7787
0
                z->SetFieldsFrom(x.get(), mapInput);
7788
0
                poIntersection =
7789
0
                    convert_geometry(std::move(poIntersection), bPromoteToMulti,
7790
0
                                     eOutputGeometryType);
7791
0
                if (!poIntersection)
7792
0
                    continue;
7793
0
                z->SetGeometryDirectly(poIntersection.release());
7794
0
                ret = pLayerResult->CreateFeature(z.get());
7795
0
                if (ret != OGRERR_NONE)
7796
0
                {
7797
0
                    if (!bSkipFailures)
7798
0
                    {
7799
0
                        goto done;
7800
0
                    }
7801
0
                    else
7802
0
                    {
7803
0
                        CPLErrorReset();
7804
0
                        ret = OGRERR_NONE;
7805
0
                    }
7806
0
                }
7807
0
            }
7808
0
        }
7809
0
    }
7810
0
    if (pfnProgress && !pfnProgress(1.0, "", pProgressArg))
7811
0
    {
7812
0
        CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
7813
0
        ret = OGRERR_FAILURE;
7814
0
        goto done;
7815
0
    }
7816
0
done:
7817
    // release resources
7818
0
    pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
7819
0
    if (pGeometryMethodFilter)
7820
0
        delete pGeometryMethodFilter;
7821
0
    if (mapInput)
7822
0
        VSIFree(mapInput);
7823
0
    return ret;
7824
0
}
7825
7826
/************************************************************************/
7827
/*                             OGR_L_Clip()                             */
7828
/************************************************************************/
7829
7830
/**
7831
 * \brief Clip off areas that are not covered by the method layer.
7832
 *
7833
 * The result layer contains features whose geometries represent areas
7834
 * that are in the input layer and in the method layer. The features
7835
 * in the result layer have the (possibly clipped) areas of features
7836
 * in the input layer and the attributes from the same features. The
7837
 * schema of the result layer can be set by the user or, if it is
7838
 * empty, is initialized to contain all fields in the input layer.
7839
 *
7840
 * \note For best performance use the minimum amount of features in
7841
 * the method layer and copy it into a memory layer.
7842
 *
7843
 * \note This method relies on GEOS support. Do not use unless the
7844
 * GEOS support is compiled in.
7845
 *
7846
 * The recognized list of options is :
7847
 * <ul>
7848
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
7849
 *     feature could not be inserted or a GEOS call failed.
7850
 * </li>
7851
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
7852
 *     into MultiPolygons, LineStrings to MultiLineStrings or
7853
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
7854
 * </li>
7855
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
7856
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
7857
 *     be converted to it, the corresponding output feature is silently skipped.
7858
 *     Takes precedence over PROMOTE_TO_MULTI.
7859
 * </li>
7860
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
7861
 *     will be created from the fields of the input layer.
7862
 * </li>
7863
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
7864
 *     will be created from the fields of the method layer.
7865
 * </li>
7866
 * </ul>
7867
 *
7868
 * This function is the same as the C++ method OGRLayer::Clip().
7869
 *
7870
 * @param pLayerInput the input layer. Should not be NULL.
7871
 *
7872
 * @param pLayerMethod the method layer. Should not be NULL.
7873
 *
7874
 * @param pLayerResult the layer where the features resulting from the
7875
 * operation are inserted. Should not be NULL. See above the note
7876
 * about the schema.
7877
 *
7878
 * @param papszOptions NULL terminated list of options (may be NULL).
7879
 *
7880
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
7881
 * reporting progress or NULL.
7882
 *
7883
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
7884
 *
7885
 * @return an error code if there was an error or the execution was
7886
 * interrupted, OGRERR_NONE otherwise.
7887
 *
7888
 * @note The first geometry field is always used.
7889
 *
7890
 * @since OGR 1.10
7891
 */
7892
7893
OGRErr OGR_L_Clip(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
7894
                  OGRLayerH pLayerResult, CSLConstList papszOptions,
7895
                  GDALProgressFunc pfnProgress, void *pProgressArg)
7896
7897
0
{
7898
0
    VALIDATE_POINTER1(pLayerInput, "OGR_L_Clip", OGRERR_INVALID_HANDLE);
7899
0
    VALIDATE_POINTER1(pLayerMethod, "OGR_L_Clip", OGRERR_INVALID_HANDLE);
7900
0
    VALIDATE_POINTER1(pLayerResult, "OGR_L_Clip", OGRERR_INVALID_HANDLE);
7901
7902
0
    return OGRLayer::FromHandle(pLayerInput)
7903
0
        ->Clip(OGRLayer::FromHandle(pLayerMethod),
7904
0
               OGRLayer::FromHandle(pLayerResult), papszOptions, pfnProgress,
7905
0
               pProgressArg);
7906
0
}
7907
7908
/************************************************************************/
7909
/*                               Erase()                                */
7910
/************************************************************************/
7911
7912
/**
7913
 * \brief Remove areas that are covered by the method layer.
7914
 *
7915
 * The result layer contains features whose geometries represent areas
7916
 * that are in the input layer but not in the method layer. The
7917
 * features in the result layer have attributes from the input
7918
 * layer. The schema of the result layer can be set by the user or, if
7919
 * it is empty, is initialized to contain all fields in the input
7920
 * layer.
7921
 *
7922
 * \note For best performance use the minimum amount of features in
7923
 * the method layer and copy it into a memory layer.
7924
 *
7925
 * \note This method relies on GEOS support. Do not use unless the
7926
 * GEOS support is compiled in.
7927
 *
7928
 * The recognized list of options is :
7929
 * <ul>
7930
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
7931
 *     feature could not be inserted or a GEOS call failed.
7932
 * </li>
7933
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
7934
 *     into MultiPolygons, LineStrings to MultiLineStrings or
7935
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
7936
 * </li>
7937
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
7938
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
7939
 *     be converted to it, the corresponding output feature is silently skipped.
7940
 *     Takes precedence over PROMOTE_TO_MULTI.
7941
 * </li>
7942
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
7943
 *     will be created from the fields of the input layer.
7944
 * </li>
7945
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
7946
 *     will be created from the fields of the method layer.
7947
 * </li>
7948
 * </ul>
7949
 *
7950
 * This method is the same as the C function OGR_L_Erase().
7951
 *
7952
 * @param pLayerMethod the method layer. Should not be NULL.
7953
 *
7954
 * @param pLayerResult the layer where the features resulting from the
7955
 * operation are inserted. Should not be NULL. See above the note
7956
 * about the schema.
7957
 *
7958
 * @param papszOptions NULL terminated list of options (may be NULL).
7959
 *
7960
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
7961
 * reporting progress or NULL.
7962
 *
7963
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
7964
 *
7965
 * @return an error code if there was an error or the execution was
7966
 * interrupted, OGRERR_NONE otherwise.
7967
 *
7968
 * @note The first geometry field is always used.
7969
 *
7970
 * @since OGR 1.10
7971
 */
7972
7973
OGRErr OGRLayer::Erase(OGRLayer *pLayerMethod, OGRLayer *pLayerResult,
7974
                       CSLConstList papszOptions, GDALProgressFunc pfnProgress,
7975
                       void *pProgressArg)
7976
0
{
7977
0
    OGRErr ret = OGRERR_NONE;
7978
0
    OGRFeatureDefn *poDefnInput = GetLayerDefn();
7979
0
    OGRFeatureDefn *poDefnResult = nullptr;
7980
0
    OGRGeometry *pGeometryMethodFilter = nullptr;
7981
0
    int *mapInput = nullptr;
7982
0
    double progress_max = static_cast<double>(GetFeatureCount(FALSE));
7983
0
    double progress_counter = 0;
7984
0
    double progress_ticker = 0;
7985
0
    const bool bSkipFailures =
7986
0
        CPLTestBool(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
7987
0
    const bool bPromoteToMulti = CPLTestBool(
7988
0
        CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
7989
0
    const char *pszOutputGeometryType =
7990
0
        CSLFetchNameValueDef(papszOptions, "OUTPUT_GEOMETRY_TYPE", "GEOMETRY");
7991
0
    const auto eOutputGeometryType = OGRFromOGCGeomType(pszOutputGeometryType);
7992
7993
    // check for GEOS
7994
0
    if (!OGRGeometryFactory::haveGEOS())
7995
0
    {
7996
0
        CPLError(CE_Failure, CPLE_AppDefined,
7997
0
                 "OGRLayer::Erase() requires GEOS support");
7998
0
        return OGRERR_UNSUPPORTED_OPERATION;
7999
0
    }
8000
8001
    // get resources
8002
0
    ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
8003
0
    if (ret != OGRERR_NONE)
8004
0
        goto done;
8005
0
    ret = create_field_map(poDefnInput, &mapInput);
8006
0
    if (ret != OGRERR_NONE)
8007
0
        goto done;
8008
0
    ret = set_result_schema(pLayerResult, poDefnInput, nullptr, mapInput,
8009
0
                            nullptr, false, papszOptions);
8010
0
    if (ret != OGRERR_NONE)
8011
0
        goto done;
8012
0
    poDefnResult = pLayerResult->GetLayerDefn();
8013
8014
0
    for (auto &&x : this)
8015
0
    {
8016
8017
0
        if (pfnProgress)
8018
0
        {
8019
0
            double p = progress_counter / progress_max;
8020
0
            if (p > progress_ticker)
8021
0
            {
8022
0
                if (!pfnProgress(p, "", pProgressArg))
8023
0
                {
8024
0
                    CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
8025
0
                    ret = OGRERR_FAILURE;
8026
0
                    goto done;
8027
0
                }
8028
0
            }
8029
0
            progress_counter += 1.0;
8030
0
        }
8031
8032
        // set up the filter on the method layer
8033
0
        CPLErrorReset();
8034
0
        OGRGeometry *x_geom =
8035
0
            set_filter_from(pLayerMethod, pGeometryMethodFilter, x.get());
8036
0
        if (CPLGetLastErrorType() != CE_None)
8037
0
        {
8038
0
            if (!bSkipFailures)
8039
0
            {
8040
0
                ret = OGRERR_FAILURE;
8041
0
                goto done;
8042
0
            }
8043
0
            else
8044
0
            {
8045
0
                CPLErrorReset();
8046
0
                ret = OGRERR_NONE;
8047
0
            }
8048
0
        }
8049
0
        if (!x_geom)
8050
0
        {
8051
0
            continue;
8052
0
        }
8053
8054
0
        std::unique_ptr<OGRGeometry> geom(
8055
0
            x_geom
8056
0
                ->clone());  // this will be the geometry of the result feature
8057
        // incrementally erase y from geom
8058
0
        for (auto &&y : pLayerMethod)
8059
0
        {
8060
0
            OGRGeometry *y_geom = y->GetGeometryRef();
8061
0
            if (!y_geom)
8062
0
                continue;
8063
0
            CPLErrorReset();
8064
0
            std::unique_ptr<OGRGeometry> geom_new(geom->Difference(y_geom));
8065
0
            if (CPLGetLastErrorType() != CE_None || geom_new == nullptr)
8066
0
            {
8067
0
                if (!bSkipFailures)
8068
0
                {
8069
0
                    ret = OGRERR_FAILURE;
8070
0
                    goto done;
8071
0
                }
8072
0
                else
8073
0
                {
8074
0
                    CPLErrorReset();
8075
0
                    ret = OGRERR_NONE;
8076
0
                }
8077
0
            }
8078
0
            else
8079
0
            {
8080
0
                geom.swap(geom_new);
8081
0
                if (geom->IsEmpty())
8082
0
                {
8083
0
                    break;
8084
0
                }
8085
0
            }
8086
0
        }
8087
8088
        // add a new feature if there is remaining area
8089
0
        if (!geom->IsEmpty())
8090
0
        {
8091
0
            OGRFeatureUniquePtr z(new OGRFeature(poDefnResult));
8092
0
            z->SetFieldsFrom(x.get(), mapInput);
8093
0
            geom = convert_geometry(std::move(geom), bPromoteToMulti,
8094
0
                                    eOutputGeometryType);
8095
0
            if (!geom)
8096
0
                continue;
8097
0
            z->SetGeometryDirectly(geom.release());
8098
0
            ret = pLayerResult->CreateFeature(z.get());
8099
0
            if (ret != OGRERR_NONE)
8100
0
            {
8101
0
                if (!bSkipFailures)
8102
0
                {
8103
0
                    goto done;
8104
0
                }
8105
0
                else
8106
0
                {
8107
0
                    CPLErrorReset();
8108
0
                    ret = OGRERR_NONE;
8109
0
                }
8110
0
            }
8111
0
        }
8112
0
    }
8113
0
    if (pfnProgress && !pfnProgress(1.0, "", pProgressArg))
8114
0
    {
8115
0
        CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
8116
0
        ret = OGRERR_FAILURE;
8117
0
        goto done;
8118
0
    }
8119
0
done:
8120
    // release resources
8121
0
    pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
8122
0
    if (pGeometryMethodFilter)
8123
0
        delete pGeometryMethodFilter;
8124
0
    if (mapInput)
8125
0
        VSIFree(mapInput);
8126
0
    return ret;
8127
0
}
8128
8129
/************************************************************************/
8130
/*                            OGR_L_Erase()                             */
8131
/************************************************************************/
8132
8133
/**
8134
 * \brief Remove areas that are covered by the method layer.
8135
 *
8136
 * The result layer contains features whose geometries represent areas
8137
 * that are in the input layer but not in the method layer. The
8138
 * features in the result layer have attributes from the input
8139
 * layer. The schema of the result layer can be set by the user or, if
8140
 * it is empty, is initialized to contain all fields in the input
8141
 * layer.
8142
 *
8143
 * \note For best performance use the minimum amount of features in
8144
 * the method layer and copy it into a memory layer.
8145
 *
8146
 * \note This method relies on GEOS support. Do not use unless the
8147
 * GEOS support is compiled in.
8148
 *
8149
 * The recognized list of options is :
8150
 * <ul>
8151
 * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
8152
 *     feature could not be inserted or a GEOS call failed.
8153
 * </li>
8154
 * <li>PROMOTE_TO_MULTI=YES/NO. Set to YES to convert Polygons
8155
 *     into MultiPolygons, LineStrings to MultiLineStrings or
8156
 *     Points to MultiPoints (only since GDAL 3.9.2 for the later)
8157
 * </li>
8158
 * <li>OUTPUT_GEOMETRY_TYPE=[MULTI]POINT/[MULTI]LINESTRING/[MULTI]POLYGON/GEOMETRYCOLLECTION/GEOMETRY
8159
 *     Output geometry type (since GDAL 3.14.0). If the output geometry cannot
8160
 *     be converted to it, the corresponding output feature is silently skipped.
8161
 *     Takes precedence over PROMOTE_TO_MULTI.
8162
 * </li>
8163
 * <li>INPUT_PREFIX=string. Set a prefix for the field names that
8164
 *     will be created from the fields of the input layer.
8165
 * </li>
8166
 * <li>METHOD_PREFIX=string. Set a prefix for the field names that
8167
 *     will be created from the fields of the method layer.
8168
 * </li>
8169
 * </ul>
8170
 *
8171
 * This function is the same as the C++ method OGRLayer::Erase().
8172
 *
8173
 * @param pLayerInput the input layer. Should not be NULL.
8174
 *
8175
 * @param pLayerMethod the method layer. Should not be NULL.
8176
 *
8177
 * @param pLayerResult the layer where the features resulting from the
8178
 * operation are inserted. Should not be NULL. See above the note
8179
 * about the schema.
8180
 *
8181
 * @param papszOptions NULL terminated list of options (may be NULL).
8182
 *
8183
 * @param pfnProgress a GDALProgressFunc() compatible callback function for
8184
 * reporting progress or NULL.
8185
 *
8186
 * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
8187
 *
8188
 * @return an error code if there was an error or the execution was
8189
 * interrupted, OGRERR_NONE otherwise.
8190
 *
8191
 * @note The first geometry field is always used.
8192
 *
8193
 * @since OGR 1.10
8194
 */
8195
8196
OGRErr OGR_L_Erase(OGRLayerH pLayerInput, OGRLayerH pLayerMethod,
8197
                   OGRLayerH pLayerResult, CSLConstList papszOptions,
8198
                   GDALProgressFunc pfnProgress, void *pProgressArg)
8199
8200
0
{
8201
0
    VALIDATE_POINTER1(pLayerInput, "OGR_L_Erase", OGRERR_INVALID_HANDLE);
8202
0
    VALIDATE_POINTER1(pLayerMethod, "OGR_L_Erase", OGRERR_INVALID_HANDLE);
8203
0
    VALIDATE_POINTER1(pLayerResult, "OGR_L_Erase", OGRERR_INVALID_HANDLE);
8204
8205
0
    return OGRLayer::FromHandle(pLayerInput)
8206
0
        ->Erase(OGRLayer::FromHandle(pLayerMethod),
8207
0
                OGRLayer::FromHandle(pLayerResult), papszOptions, pfnProgress,
8208
0
                pProgressArg);
8209
0
}
8210
8211
/************************************************************************/
8212
/*                  OGRLayer::FeatureIterator::Private                  */
8213
/************************************************************************/
8214
8215
struct OGRLayer::FeatureIterator::Private
8216
{
8217
    CPL_DISALLOW_COPY_ASSIGN(Private)
8218
0
    Private() = default;
8219
8220
    OGRFeatureUniquePtr m_poFeature{};
8221
    OGRLayer *m_poLayer = nullptr;
8222
    bool m_bError = false;
8223
    bool m_bEOF = true;
8224
};
8225
8226
/************************************************************************/
8227
/*             OGRLayer::FeatureIterator::FeatureIterator()             */
8228
/************************************************************************/
8229
8230
OGRLayer::FeatureIterator::FeatureIterator(OGRLayer *poLayer, bool bStart)
8231
0
    : m_poPrivate(new OGRLayer::FeatureIterator::Private())
8232
0
{
8233
0
    m_poPrivate->m_poLayer = poLayer;
8234
0
    if (bStart)
8235
0
    {
8236
0
        if (m_poPrivate->m_poLayer->m_poPrivate->m_bInFeatureIterator)
8237
0
        {
8238
0
            CPLError(CE_Failure, CPLE_NotSupported,
8239
0
                     "Only one feature iterator can be "
8240
0
                     "active at a time");
8241
0
            m_poPrivate->m_bError = true;
8242
0
        }
8243
0
        else
8244
0
        {
8245
0
            m_poPrivate->m_poLayer->ResetReading();
8246
0
            m_poPrivate->m_poFeature.reset(
8247
0
                m_poPrivate->m_poLayer->GetNextFeature());
8248
0
            m_poPrivate->m_bEOF = m_poPrivate->m_poFeature == nullptr;
8249
0
            m_poPrivate->m_poLayer->m_poPrivate->m_bInFeatureIterator = true;
8250
0
        }
8251
0
    }
8252
0
}
8253
8254
/************************************************************************/
8255
/*            ~OGRLayer::FeatureIterator::FeatureIterator()             */
8256
/************************************************************************/
8257
8258
OGRLayer::FeatureIterator::~FeatureIterator()
8259
0
{
8260
0
    if (!m_poPrivate->m_bError && m_poPrivate->m_poLayer)
8261
0
        m_poPrivate->m_poLayer->m_poPrivate->m_bInFeatureIterator = false;
8262
0
}
8263
8264
/************************************************************************/
8265
/*                             operator*()                              */
8266
/************************************************************************/
8267
8268
OGRFeatureUniquePtr &OGRLayer::FeatureIterator::operator*()
8269
0
{
8270
0
    return m_poPrivate->m_poFeature;
8271
0
}
8272
8273
/************************************************************************/
8274
/*                             operator++()                             */
8275
/************************************************************************/
8276
8277
OGRLayer::FeatureIterator &OGRLayer::FeatureIterator::operator++()
8278
0
{
8279
0
    m_poPrivate->m_poFeature.reset(m_poPrivate->m_poLayer->GetNextFeature());
8280
0
    m_poPrivate->m_bEOF = m_poPrivate->m_poFeature == nullptr;
8281
0
    return *this;
8282
0
}
8283
8284
/************************************************************************/
8285
/*                             operator!=()                             */
8286
/************************************************************************/
8287
8288
bool OGRLayer::FeatureIterator::operator!=(
8289
    const OGRLayer::FeatureIterator &it) const
8290
0
{
8291
0
    return m_poPrivate->m_bEOF != it.m_poPrivate->m_bEOF;
8292
0
}
8293
8294
/************************************************************************/
8295
/*                               begin()                                */
8296
/************************************************************************/
8297
8298
OGRLayer::FeatureIterator OGRLayer::begin()
8299
0
{
8300
0
    return {this, true};
8301
0
}
8302
8303
/************************************************************************/
8304
/*                                end()                                 */
8305
/************************************************************************/
8306
8307
OGRLayer::FeatureIterator OGRLayer::end()
8308
0
{
8309
0
    return {this, false};
8310
0
}
8311
8312
/************************************************************************/
8313
/*                     OGRLayer::GetGeometryTypes()                     */
8314
/************************************************************************/
8315
8316
/** \brief Get actual geometry types found in features.
8317
 *
8318
 * This method iterates over features to retrieve their geometry types. This
8319
 * is mostly useful for layers that report a wkbUnknown geometry type with
8320
 * GetGeomType() or GetGeomFieldDefn(iGeomField)->GetType().
8321
 *
8322
 * By default this method returns an array of nEntryCount entries with each
8323
 * geometry type (in OGRGeometryTypeCounter::eGeomType) and the corresponding
8324
 * number of features (in OGRGeometryTypeCounter::nCount).
8325
 * Features without geometries are reported as eGeomType == wkbNone.
8326
 *
8327
 * The nFlagsGGT parameter can be a combination (with binary or operator) of the
8328
 * following hints:
8329
 * <ul>
8330
 * <li>OGR_GGT_COUNT_NOT_NEEDED: to indicate that only the set of geometry types
8331
 * matter, not the number of features per geometry type. Consequently the value
8332
 * of OGRGeometryTypeCounter::nCount should be ignored.</li>
8333
 * <li>OGR_GGT_STOP_IF_MIXED: to indicate that the implementation may stop
8334
 * iterating over features as soon as 2 different geometry types (not counting
8335
 * null geometries) are found. The value of OGRGeometryTypeCounter::nCount
8336
 * should be ignored (zero might be systematically reported by some
8337
 * implementations).</li> <li>OGR_GGT_GEOMCOLLECTIONZ_TINZ: to indicate that if
8338
 * a geometry is of type wkbGeometryCollection25D and its first sub-geometry is
8339
 * of type wkbTINZ, wkbTINZ should be reported as geometry type. This is mostly
8340
 * useful for the ESRI Shapefile and (Open)FileGDB drivers regarding MultiPatch
8341
 * geometries.</li>
8342
 * </ul>
8343
 *
8344
 * If the layer has no features, a non-NULL returned array with nEntryCount == 0
8345
 * will be returned.
8346
 *
8347
 * Spatial and/or attribute filters will be taken into account.
8348
 *
8349
 * This method will error out on a layer without geometry fields
8350
 * (GetGeomType() == wkbNone).
8351
 *
8352
 * A cancellation callback may be provided. The progress percentage it is called
8353
 * with is not relevant. The callback should return TRUE if processing should go
8354
 * on, or FALSE if it should be interrupted.
8355
 *
8356
 * @param iGeomField Geometry field index.
8357
 * @param nFlagsGGT Hint flags. 0, or combination of OGR_GGT_COUNT_NOT_NEEDED,
8358
 *                  OGR_GGT_STOP_IF_MIXED, OGR_GGT_GEOMCOLLECTIONZ_TINZ
8359
 * @param[out] nEntryCountOut Number of entries in the returned array.
8360
 * @param pfnProgress Cancellation callback. May be NULL.
8361
 * @param pProgressData User data for the cancellation callback. May be NULL.
8362
 * @return an array of nEntryCount that must be freed with CPLFree(),
8363
 *         or NULL in case of error
8364
 * @since GDAL 3.6
8365
 */
8366
OGRGeometryTypeCounter *
8367
OGRLayer::GetGeometryTypes(int iGeomField, int nFlagsGGT, int &nEntryCountOut,
8368
                           GDALProgressFunc pfnProgress, void *pProgressData)
8369
0
{
8370
0
    OGRFeatureDefn *poDefn = GetLayerDefn();
8371
0
    const int nGeomFieldCount = poDefn->GetGeomFieldCount();
8372
0
    if (iGeomField < 0 || iGeomField >= nGeomFieldCount)
8373
0
    {
8374
0
        CPLError(CE_Failure, CPLE_AppDefined, "Invalid value for iGeomField");
8375
0
        nEntryCountOut = 0;
8376
0
        return nullptr;
8377
0
    }
8378
8379
    // Ignore all fields but the geometry one of interest
8380
0
    CPLStringList aosIgnoredFieldsRestore;
8381
0
    CPLStringList aosIgnoredFields;
8382
0
    const int nFieldCount = poDefn->GetFieldCount();
8383
0
    for (int iField = 0; iField < nFieldCount; iField++)
8384
0
    {
8385
0
        const auto poFieldDefn = poDefn->GetFieldDefn(iField);
8386
0
        const char *pszName = poFieldDefn->GetNameRef();
8387
0
        if (poFieldDefn->IsIgnored())
8388
0
            aosIgnoredFieldsRestore.AddString(pszName);
8389
0
        if (iField != iGeomField)
8390
0
            aosIgnoredFields.AddString(pszName);
8391
0
    }
8392
0
    for (int iField = 0; iField < nGeomFieldCount; iField++)
8393
0
    {
8394
0
        const auto poFieldDefn = poDefn->GetGeomFieldDefn(iField);
8395
0
        const char *pszName = poFieldDefn->GetNameRef();
8396
0
        if (poFieldDefn->IsIgnored())
8397
0
            aosIgnoredFieldsRestore.AddString(pszName);
8398
0
        if (iField != iGeomField)
8399
0
            aosIgnoredFields.AddString(pszName);
8400
0
    }
8401
0
    if (poDefn->IsStyleIgnored())
8402
0
        aosIgnoredFieldsRestore.AddString("OGR_STYLE");
8403
0
    aosIgnoredFields.AddString("OGR_STYLE");
8404
0
    SetIgnoredFields(aosIgnoredFields.List());
8405
8406
    // Iterate over features
8407
0
    std::map<OGRwkbGeometryType, int64_t> oMapCount;
8408
0
    std::set<OGRwkbGeometryType> oSetNotNull;
8409
0
    const bool bGeomCollectionZTInZ =
8410
0
        (nFlagsGGT & OGR_GGT_GEOMCOLLECTIONZ_TINZ) != 0;
8411
0
    const bool bStopIfMixed = (nFlagsGGT & OGR_GGT_STOP_IF_MIXED) != 0;
8412
0
    if (pfnProgress == GDALDummyProgress)
8413
0
        pfnProgress = nullptr;
8414
0
    bool bInterrupted = false;
8415
0
    for (auto &&poFeature : *this)
8416
0
    {
8417
0
        const auto poGeom = poFeature->GetGeomFieldRef(iGeomField);
8418
0
        if (poGeom == nullptr)
8419
0
        {
8420
0
            ++oMapCount[wkbNone];
8421
0
        }
8422
0
        else
8423
0
        {
8424
0
            auto eGeomType = poGeom->getGeometryType();
8425
0
            if (bGeomCollectionZTInZ && eGeomType == wkbGeometryCollection25D)
8426
0
            {
8427
0
                const auto poGC = poGeom->toGeometryCollection();
8428
0
                if (poGC->getNumGeometries() > 0)
8429
0
                {
8430
0
                    auto eSubGeomType =
8431
0
                        poGC->getGeometryRef(0)->getGeometryType();
8432
0
                    if (eSubGeomType == wkbTINZ)
8433
0
                        eGeomType = wkbTINZ;
8434
0
                }
8435
0
            }
8436
0
            ++oMapCount[eGeomType];
8437
0
            if (bStopIfMixed)
8438
0
            {
8439
0
                oSetNotNull.insert(eGeomType);
8440
0
                if (oSetNotNull.size() == 2)
8441
0
                    break;
8442
0
            }
8443
0
        }
8444
0
        if (pfnProgress && !pfnProgress(0.0, "", pProgressData))
8445
0
        {
8446
0
            bInterrupted = true;
8447
0
            break;
8448
0
        }
8449
0
    }
8450
8451
    // Restore ignore fields state
8452
0
    SetIgnoredFields(aosIgnoredFieldsRestore.List());
8453
8454
0
    if (bInterrupted)
8455
0
    {
8456
0
        nEntryCountOut = 0;
8457
0
        return nullptr;
8458
0
    }
8459
8460
    // Format result
8461
0
    nEntryCountOut = static_cast<int>(oMapCount.size());
8462
0
    OGRGeometryTypeCounter *pasRet = static_cast<OGRGeometryTypeCounter *>(
8463
0
        CPLCalloc(1 + nEntryCountOut, sizeof(OGRGeometryTypeCounter)));
8464
0
    int i = 0;
8465
0
    for (const auto &oIter : oMapCount)
8466
0
    {
8467
0
        pasRet[i].eGeomType = oIter.first;
8468
0
        pasRet[i].nCount = oIter.second;
8469
0
        ++i;
8470
0
    }
8471
0
    return pasRet;
8472
0
}
8473
8474
/************************************************************************/
8475
/*                       OGR_L_GetGeometryTypes()                       */
8476
/************************************************************************/
8477
8478
/** \brief Get actual geometry types found in features.
8479
 *
8480
 * See OGRLayer::GetGeometryTypes() for details.
8481
 *
8482
 * @param hLayer Layer.
8483
 * @param iGeomField Geometry field index.
8484
 * @param nFlags Hint flags. 0, or combination of OGR_GGT_COUNT_NOT_NEEDED,
8485
 *               OGR_GGT_STOP_IF_MIXED, OGR_GGT_GEOMCOLLECTIONZ_TINZ
8486
 * @param[out] pnEntryCount Pointer to the number of entries in the returned
8487
 *                          array. Must not be NULL.
8488
 * @param pfnProgress Cancellation callback. May be NULL.
8489
 * @param pProgressData User data for the cancellation callback. May be NULL.
8490
 * @return an array of *pnEntryCount that must be freed with CPLFree(),
8491
 *         or NULL in case of error
8492
 * @since GDAL 3.6
8493
 */
8494
OGRGeometryTypeCounter *OGR_L_GetGeometryTypes(OGRLayerH hLayer, int iGeomField,
8495
                                               int nFlags, int *pnEntryCount,
8496
                                               GDALProgressFunc pfnProgress,
8497
                                               void *pProgressData)
8498
0
{
8499
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetGeometryTypes", nullptr);
8500
0
    VALIDATE_POINTER1(pnEntryCount, "OGR_L_GetGeometryTypes", nullptr);
8501
8502
0
    return OGRLayer::FromHandle(hLayer)->GetGeometryTypes(
8503
0
        iGeomField, nFlags, *pnEntryCount, pfnProgress, pProgressData);
8504
0
}
8505
8506
/************************************************************************/
8507
/*                   OGRLayer::GetSupportedSRSList()                    */
8508
/************************************************************************/
8509
8510
/** \brief Get the list of SRS supported.
8511
 *
8512
 * The base implementation of this method will return an empty list. Some
8513
 * drivers (OAPIF, WFS) may return a non-empty list.
8514
 *
8515
 * One of the SRS returned may be passed to SetActiveSRS() to change the
8516
 * active SRS.
8517
 *
8518
 * @param iGeomField Geometry field index.
8519
 * @return list of supported SRS.
8520
 * @since GDAL 3.7
8521
 */
8522
const OGRLayer::GetSupportedSRSListRetType &
8523
OGRLayer::GetSupportedSRSList(CPL_UNUSED int iGeomField)
8524
0
{
8525
0
    static OGRLayer::GetSupportedSRSListRetType empty;
8526
0
    return empty;
8527
0
}
8528
8529
/************************************************************************/
8530
/*                     OGR_L_GetSupportedSRSList()                      */
8531
/************************************************************************/
8532
8533
/** \brief Get the list of SRS supported.
8534
 *
8535
 * The base implementation of this method will return an empty list. Some
8536
 * drivers (OAPIF, WFS) may return a non-empty list.
8537
 *
8538
 * One of the SRS returned may be passed to SetActiveSRS() to change the
8539
 * active SRS.
8540
 *
8541
 * @param hLayer Layer.
8542
 * @param iGeomField Geometry field index.
8543
 * @param[out] pnCount Number of values in returned array. Must not be null.
8544
 * @return list of supported SRS, to be freed with OSRFreeSRSArray(), or
8545
 * nullptr
8546
 * @since GDAL 3.7
8547
 */
8548
OGRSpatialReferenceH *OGR_L_GetSupportedSRSList(OGRLayerH hLayer,
8549
                                                int iGeomField, int *pnCount)
8550
0
{
8551
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetSupportedSRSList", nullptr);
8552
0
    VALIDATE_POINTER1(pnCount, "OGR_L_GetSupportedSRSList", nullptr);
8553
8554
0
    const auto &srsList =
8555
0
        OGRLayer::FromHandle(hLayer)->GetSupportedSRSList(iGeomField);
8556
0
    *pnCount = static_cast<int>(srsList.size());
8557
0
    if (srsList.empty())
8558
0
    {
8559
0
        return nullptr;
8560
0
    }
8561
0
    OGRSpatialReferenceH *pahRet = static_cast<OGRSpatialReferenceH *>(
8562
0
        CPLMalloc((1 + srsList.size()) * sizeof(OGRSpatialReferenceH)));
8563
0
    size_t i = 0;
8564
0
    for (const auto &poSRS : srsList)
8565
0
    {
8566
0
        poSRS->Reference();
8567
0
        pahRet[i] = OGRSpatialReference::ToHandle(poSRS.get());
8568
0
        ++i;
8569
0
    }
8570
0
    pahRet[i] = nullptr;
8571
0
    return pahRet;
8572
0
}
8573
8574
/************************************************************************/
8575
/*                       OGRLayer::SetActiveSRS()                       */
8576
/************************************************************************/
8577
8578
/** \brief Change the active SRS.
8579
 *
8580
 * The passed SRS must be in the list returned by GetSupportedSRSList()
8581
 * (the actual pointer may be different, but should be tested as identical
8582
 * with OGRSpatialReference::IsSame()).
8583
 *
8584
 * Changing the active SRS affects:
8585
 * <ul>
8586
 * <li>the SRS in which geometries of returned features are expressed,</li>
8587
 * <li>the SRS in which geometries of passed features (CreateFeature(),
8588
 * SetFeature()) are expressed,</li>
8589
 * <li>the SRS returned by GetSpatialRef() and
8590
 * GetGeomFieldDefn()->GetSpatialRef(),</li>
8591
 * <li>the SRS used to interpret SetSpatialFilter() values.</li>
8592
 * </ul>
8593
 * This also resets feature reading and the spatial filter.
8594
 * Note however that this does not modify the storage SRS of the features of
8595
 * geometries. Said otherwise, this setting is volatile and has no persistent
8596
 * effects after dataset reopening.
8597
 *
8598
 * @param iGeomField Geometry field index.
8599
 * @param poSRS SRS to use
8600
 * @return OGRERR_NONE in case of success, or OGRERR_FAILURE if
8601
 *         the passed SRS is not in GetSupportedSRSList()
8602
 * @since GDAL 3.7
8603
 */
8604
OGRErr OGRLayer::SetActiveSRS(CPL_UNUSED int iGeomField,
8605
                              CPL_UNUSED const OGRSpatialReference *poSRS)
8606
0
{
8607
0
    return OGRERR_FAILURE;
8608
0
}
8609
8610
/************************************************************************/
8611
/*                         OGR_L_SetActiveSRS()                         */
8612
/************************************************************************/
8613
8614
/** \brief Change the active SRS.
8615
 *
8616
 * The passed SRS must be in the list returned by GetSupportedSRSList()
8617
 * (the actual pointer may be different, but should be tested as identical
8618
 * with OGRSpatialReference::IsSame()).
8619
 *
8620
 * Changing the active SRS affects:
8621
 * <ul>
8622
 * <li>the SRS in which geometries of returned features are expressed,</li>
8623
 * <li>the SRS in which geometries of passed features (CreateFeature(),
8624
 * SetFeature()) are expressed,</li>
8625
 * <li>the SRS returned by GetSpatialRef() and
8626
 * GetGeomFieldDefn()->GetSpatialRef(),</li>
8627
 * <li>the SRS used to interpret SetSpatialFilter() values.</li>
8628
 * </ul>
8629
 * This also resets feature reading and the spatial filter.
8630
 * Note however that this does not modify the storage SRS of the features of
8631
 * geometries. Said otherwise, this setting is volatile and has no persistent
8632
 * effects after dataset reopening.
8633
 *
8634
 * @param hLayer Layer.
8635
 * @param iGeomField Geometry field index.
8636
 * @param hSRS SRS to use
8637
 * @return OGRERR_NONE in case of success, OGRERR_FAILURE if
8638
 *         the passed SRS is not in GetSupportedSRSList().
8639
 * @since GDAL 3.7
8640
 */
8641
OGRErr OGR_L_SetActiveSRS(OGRLayerH hLayer, int iGeomField,
8642
                          OGRSpatialReferenceH hSRS)
8643
0
{
8644
0
    VALIDATE_POINTER1(hLayer, "OGR_L_SetActiveSRS", OGRERR_FAILURE);
8645
0
    return OGRLayer::FromHandle(hLayer)->SetActiveSRS(
8646
0
        iGeomField, OGRSpatialReference::FromHandle(hSRS));
8647
0
}
8648
8649
/************************************************************************/
8650
/*                             GetDataset()                             */
8651
/************************************************************************/
8652
8653
/** Return the dataset associated with this layer.
8654
 *
8655
 * As of GDAL 3.9, GetDataset() is implemented on all in-tree drivers that
8656
 * have CreateLayer() capability. It may not be implemented in read-only
8657
 * drivers or out-of-tree drivers.
8658
 *
8659
 * It is currently only used by the GetRecordBatchSchema()
8660
 * method to retrieve the field domain associated with a field, to fill the
8661
 * dictionary field of a struct ArrowSchema.
8662
 * It is also used by CreateFieldFromArrowSchema() to determine which field
8663
 * types and subtypes are supported by the layer, by inspecting the driver
8664
 * metadata, and potentially use fallback types when needed.
8665
 *
8666
 * This method is the same as the C function OGR_L_GetDataset().
8667
 *
8668
 * @return dataset, or nullptr when unknown.
8669
 * @since GDAL 3.6
8670
 */
8671
GDALDataset *OGRLayer::GetDataset()
8672
0
{
8673
0
    return nullptr;
8674
0
}
8675
8676
/************************************************************************/
8677
/*                          OGR_L_GetDataset()                          */
8678
/************************************************************************/
8679
8680
/** Return the dataset associated with this layer.
8681
 *
8682
 * As of GDAL 3.9, GetDataset() is implemented on all in-tree drivers that
8683
 * have CreateLayer() capability. It may not be implemented in read-only
8684
 * drivers or out-of-tree drivers.
8685
 *
8686
 * It is currently only used by the GetRecordBatchSchema()
8687
 * method to retrieve the field domain associated with a field, to fill the
8688
 * dictionary field of a struct ArrowSchema.
8689
 * It is also used by CreateFieldFromArrowSchema() to determine which field
8690
 * types and subtypes are supported by the layer, by inspecting the driver
8691
 * metadata, and potentially use fallback types when needed.
8692
 *
8693
 * This function is the same as the C++ method OGRLayer::GetDataset().
8694
 *
8695
 * @return dataset, or nullptr when unknown.
8696
 * @since GDAL 3.9
8697
 */
8698
GDALDatasetH OGR_L_GetDataset(OGRLayerH hLayer)
8699
0
{
8700
0
    VALIDATE_POINTER1(hLayer, "OGR_L_GetDataset", nullptr);
8701
0
    return GDALDataset::ToHandle(OGRLayer::FromHandle(hLayer)->GetDataset());
8702
0
}