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