Coverage Report

Created: 2026-04-01 06:20

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