1 /******************************************************************************
2  * $Id: ogrlayer.cpp 28928 2015-04-17 10:24:19Z rouault $
3  *
4  * Project:  OpenGIS Simple Features Reference Implementation
5  * Purpose:  The generic portions of the OGRSFLayer class.
6  * Author:   Frank Warmerdam, warmerdam@pobox.com
7  *
8  ******************************************************************************
9  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
10  * Copyright (c) 2008-2014, Even Rouault <even dot rouault at mines-paris dot org>
11  *
12  * Permission is hereby granted, free of charge, to any person obtaining a
13  * copy of this software and associated documentation files (the "Software"),
14  * to deal in the Software without restriction, including without limitation
15  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
16  * and/or sell copies of the Software, and to permit persons to whom the
17  * Software is furnished to do so, subject to the following conditions:
18  *
19  * The above copyright notice and this permission notice shall be included
20  * in all copies or substantial portions of the Software.
21  *
22  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
27  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28  * DEALINGS IN THE SOFTWARE.
29  ****************************************************************************/
30 
31 #include "ogrsf_frmts.h"
32 #include "ogr_api.h"
33 #include "ogr_p.h"
34 #include "ogr_attrind.h"
35 #include "swq.h"
36 #include "ograpispy.h"
37 
38 CPL_CVSID("$Id: ogrlayer.cpp 28928 2015-04-17 10:24:19Z rouault $");
39 
40 /************************************************************************/
41 /*                              OGRLayer()                              */
42 /************************************************************************/
43 
OGRLayer()44 OGRLayer::OGRLayer()
45 
46 {
47     m_poStyleTable = NULL;
48     m_poAttrQuery = NULL;
49     m_pszAttrQueryString = NULL;
50     m_poAttrIndex = NULL;
51     m_nRefCount = 0;
52 
53     m_nFeaturesRead = 0;
54 
55     m_poFilterGeom = NULL;
56     m_bFilterIsEnvelope = FALSE;
57     m_pPreparedFilterGeom = NULL;
58     m_iGeomFieldFilter = 0;
59 }
60 
61 /************************************************************************/
62 /*                             ~OGRLayer()                              */
63 /************************************************************************/
64 
~OGRLayer()65 OGRLayer::~OGRLayer()
66 
67 {
68     if ( m_poStyleTable )
69     {
70         delete m_poStyleTable;
71         m_poStyleTable = NULL;
72     }
73 
74     if( m_poAttrIndex != NULL )
75     {
76         delete m_poAttrIndex;
77         m_poAttrIndex = NULL;
78     }
79 
80     if( m_poAttrQuery != NULL )
81     {
82         delete m_poAttrQuery;
83         m_poAttrQuery = NULL;
84     }
85 
86     CPLFree( m_pszAttrQueryString );
87 
88     if( m_poFilterGeom )
89     {
90         delete m_poFilterGeom;
91         m_poFilterGeom = NULL;
92     }
93 
94     if( m_pPreparedFilterGeom != NULL )
95     {
96         OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
97         m_pPreparedFilterGeom = NULL;
98     }
99 }
100 
101 /************************************************************************/
102 /*                             Reference()                              */
103 /************************************************************************/
104 
Reference()105 int OGRLayer::Reference()
106 
107 {
108     return ++m_nRefCount;
109 }
110 
111 /************************************************************************/
112 /*                          OGR_L_Reference()                           */
113 /************************************************************************/
114 
OGR_L_Reference(OGRLayerH hLayer)115 int OGR_L_Reference( OGRLayerH hLayer )
116 
117 {
118     VALIDATE_POINTER1( hLayer, "OGR_L_Reference", 0 );
119 
120     return ((OGRLayer *) hLayer)->Reference();
121 }
122 
123 /************************************************************************/
124 /*                            Dereference()                             */
125 /************************************************************************/
126 
Dereference()127 int OGRLayer::Dereference()
128 
129 {
130     return --m_nRefCount;
131 }
132 
133 /************************************************************************/
134 /*                         OGR_L_Dereference()                          */
135 /************************************************************************/
136 
OGR_L_Dereference(OGRLayerH hLayer)137 int OGR_L_Dereference( OGRLayerH hLayer )
138 
139 {
140     VALIDATE_POINTER1( hLayer, "OGR_L_Dereference", 0 );
141 
142     return ((OGRLayer *) hLayer)->Dereference();
143 }
144 
145 /************************************************************************/
146 /*                            GetRefCount()                             */
147 /************************************************************************/
148 
GetRefCount() const149 int OGRLayer::GetRefCount() const
150 
151 {
152     return m_nRefCount;
153 }
154 
155 /************************************************************************/
156 /*                         OGR_L_GetRefCount()                          */
157 /************************************************************************/
158 
OGR_L_GetRefCount(OGRLayerH hLayer)159 int OGR_L_GetRefCount( OGRLayerH hLayer )
160 
161 {
162     VALIDATE_POINTER1( hLayer, "OGR_L_GetRefCount", 0 );
163 
164     return ((OGRLayer *) hLayer)->GetRefCount();
165 }
166 
167 /************************************************************************/
168 /*                         GetFeatureCount()                            */
169 /************************************************************************/
170 
GetFeatureCount(int bForce)171 GIntBig OGRLayer::GetFeatureCount( int bForce )
172 
173 {
174     OGRFeature     *poFeature;
175     GIntBig         nFeatureCount = 0;
176 
177     if( !bForce )
178         return -1;
179 
180     ResetReading();
181     while( (poFeature = GetNextFeature()) != NULL )
182     {
183         nFeatureCount++;
184         delete poFeature;
185     }
186     ResetReading();
187 
188     return nFeatureCount;
189 }
190 
191 /************************************************************************/
192 /*                      OGR_L_GetFeatureCount()                         */
193 /************************************************************************/
194 
OGR_L_GetFeatureCount(OGRLayerH hLayer,int bForce)195 GIntBig OGR_L_GetFeatureCount( OGRLayerH hLayer, int bForce )
196 
197 {
198     VALIDATE_POINTER1( hLayer, "OGR_L_GetFeatureCount", 0 );
199 
200 #ifdef OGRAPISPY_ENABLED
201     if( bOGRAPISpyEnabled )
202         OGRAPISpy_L_GetFeatureCount(hLayer, bForce);
203 #endif
204 
205     return ((OGRLayer *) hLayer)->GetFeatureCount(bForce);
206 }
207 
208 /************************************************************************/
209 /*                             GetExtent()                              */
210 /************************************************************************/
211 
GetExtent(OGREnvelope * psExtent,int bForce)212 OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce )
213 
214 {
215     return GetExtentInternal(0, psExtent, bForce);
216 }
217 
GetExtent(int iGeomField,OGREnvelope * psExtent,int bForce)218 OGRErr OGRLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce )
219 
220 {
221     if( iGeomField == 0 )
222         return GetExtent(psExtent, bForce);
223     else
224         return GetExtentInternal(iGeomField, psExtent, bForce);
225 }
226 
GetExtentInternal(int iGeomField,OGREnvelope * psExtent,int bForce)227 OGRErr OGRLayer::GetExtentInternal(int iGeomField, OGREnvelope *psExtent, int bForce )
228 
229 {
230     OGRFeature  *poFeature;
231     OGREnvelope oEnv;
232     GBool       bExtentSet = FALSE;
233 
234     psExtent->MinX = 0.0;
235     psExtent->MaxX = 0.0;
236     psExtent->MinY = 0.0;
237     psExtent->MaxY = 0.0;
238 
239 /* -------------------------------------------------------------------- */
240 /*      If this layer has a none geometry type, then we can             */
241 /*      reasonably assume there are not extents available.              */
242 /* -------------------------------------------------------------------- */
243     if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() ||
244         GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetType() == wkbNone )
245     {
246         if( iGeomField != 0 )
247         {
248             CPLError(CE_Failure, CPLE_AppDefined,
249                      "Invalid geometry field index : %d", iGeomField);
250         }
251         return OGRERR_FAILURE;
252     }
253 
254 /* -------------------------------------------------------------------- */
255 /*      If not forced, we should avoid having to scan all the           */
256 /*      features and just return a failure.                             */
257 /* -------------------------------------------------------------------- */
258     if( !bForce )
259         return OGRERR_FAILURE;
260 
261 /* -------------------------------------------------------------------- */
262 /*      OK, we hate to do this, but go ahead and read through all       */
263 /*      the features to collect geometries and build extents.           */
264 /* -------------------------------------------------------------------- */
265     ResetReading();
266     while( (poFeature = GetNextFeature()) != NULL )
267     {
268         OGRGeometry *poGeom = poFeature->GetGeomFieldRef(iGeomField);
269         if (poGeom == NULL || poGeom->IsEmpty())
270         {
271             /* Do nothing */
272         }
273         else if (!bExtentSet)
274         {
275             poGeom->getEnvelope(psExtent);
276             if( !(CPLIsNan(psExtent->MinX) || CPLIsNan(psExtent->MinY) ||
277                   CPLIsNan(psExtent->MaxX) || CPLIsNan(psExtent->MaxY)) )
278             {
279                 bExtentSet = TRUE;
280             }
281         }
282         else
283         {
284             poGeom->getEnvelope(&oEnv);
285             if (oEnv.MinX < psExtent->MinX)
286                 psExtent->MinX = oEnv.MinX;
287             if (oEnv.MinY < psExtent->MinY)
288                 psExtent->MinY = oEnv.MinY;
289             if (oEnv.MaxX > psExtent->MaxX)
290                 psExtent->MaxX = oEnv.MaxX;
291             if (oEnv.MaxY > psExtent->MaxY)
292                 psExtent->MaxY = oEnv.MaxY;
293         }
294         delete poFeature;
295     }
296     ResetReading();
297 
298     return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
299 }
300 
301 /************************************************************************/
302 /*                          OGR_L_GetExtent()                           */
303 /************************************************************************/
304 
OGR_L_GetExtent(OGRLayerH hLayer,OGREnvelope * psExtent,int bForce)305 OGRErr OGR_L_GetExtent( OGRLayerH hLayer, OGREnvelope *psExtent, int bForce )
306 
307 {
308     VALIDATE_POINTER1( hLayer, "OGR_L_GetExtent", OGRERR_INVALID_HANDLE );
309 
310 #ifdef OGRAPISPY_ENABLED
311     if( bOGRAPISpyEnabled )
312         OGRAPISpy_L_GetExtent(hLayer, bForce);
313 #endif
314 
315     return ((OGRLayer *) hLayer)->GetExtent( psExtent, bForce );
316 }
317 
318 /************************************************************************/
319 /*                         OGR_L_GetExtentEx()                          */
320 /************************************************************************/
321 
OGR_L_GetExtentEx(OGRLayerH hLayer,int iGeomField,OGREnvelope * psExtent,int bForce)322 OGRErr OGR_L_GetExtentEx( OGRLayerH hLayer, int iGeomField,
323                           OGREnvelope *psExtent, int bForce )
324 
325 {
326     VALIDATE_POINTER1( hLayer, "OGR_L_GetExtentEx", OGRERR_INVALID_HANDLE );
327 
328 #ifdef OGRAPISPY_ENABLED
329     if( bOGRAPISpyEnabled )
330         OGRAPISpy_L_GetExtentEx(hLayer, iGeomField, bForce);
331 #endif
332 
333     return ((OGRLayer *) hLayer)->GetExtent( iGeomField, psExtent, bForce );
334 }
335 
336 /************************************************************************/
337 /*                         SetAttributeFilter()                         */
338 /************************************************************************/
339 
SetAttributeFilter(const char * pszQuery)340 OGRErr OGRLayer::SetAttributeFilter( const char *pszQuery )
341 
342 {
343     CPLFree(m_pszAttrQueryString);
344     m_pszAttrQueryString = (pszQuery) ? CPLStrdup(pszQuery) : NULL;
345 
346 /* -------------------------------------------------------------------- */
347 /*      Are we just clearing any existing query?                        */
348 /* -------------------------------------------------------------------- */
349     if( pszQuery == NULL || strlen(pszQuery) == 0 )
350     {
351         if( m_poAttrQuery )
352         {
353             delete m_poAttrQuery;
354             m_poAttrQuery = NULL;
355             ResetReading();
356         }
357         return OGRERR_NONE;
358     }
359 
360 /* -------------------------------------------------------------------- */
361 /*      Or are we installing a new query?                               */
362 /* -------------------------------------------------------------------- */
363     OGRErr      eErr;
364 
365     if( !m_poAttrQuery )
366         m_poAttrQuery = new OGRFeatureQuery();
367 
368     eErr = m_poAttrQuery->Compile( GetLayerDefn(), pszQuery );
369     if( eErr != OGRERR_NONE )
370     {
371         delete m_poAttrQuery;
372         m_poAttrQuery = NULL;
373     }
374 
375     ResetReading();
376 
377     return eErr;
378 }
379 
380 /************************************************************************/
381 /*                        ContainGeomSpecialField()                     */
382 /************************************************************************/
383 
ContainGeomSpecialField(swq_expr_node * expr,int nLayerFieldCount)384 static int ContainGeomSpecialField(swq_expr_node* expr,
385                                    int nLayerFieldCount)
386 {
387     if (expr->eNodeType == SNT_COLUMN)
388     {
389         if( expr->table_index == 0 && expr->field_index != -1 )
390         {
391             int nSpecialFieldIdx = expr->field_index -
392                                     nLayerFieldCount;
393             return nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
394                    nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
395                    nSpecialFieldIdx == SPF_OGR_GEOM_AREA;
396         }
397     }
398     else if (expr->eNodeType == SNT_OPERATION)
399     {
400         for( int i = 0; i < expr->nSubExprCount; i++ )
401         {
402             if (ContainGeomSpecialField(expr->papoSubExpr[i],
403                                         nLayerFieldCount))
404                 return TRUE;
405         }
406     }
407     return FALSE;
408 }
409 
410 /************************************************************************/
411 /*                AttributeFilterEvaluationNeedsGeometry()              */
412 /************************************************************************/
413 
AttributeFilterEvaluationNeedsGeometry()414 int OGRLayer::AttributeFilterEvaluationNeedsGeometry()
415 {
416     if( !m_poAttrQuery )
417         return FALSE;
418 
419     swq_expr_node* expr = (swq_expr_node *) m_poAttrQuery->GetSWQExpr();
420     int nLayerFieldCount = GetLayerDefn()->GetFieldCount();
421 
422     return ContainGeomSpecialField(expr, nLayerFieldCount);
423 }
424 
425 /************************************************************************/
426 /*                      OGR_L_SetAttributeFilter()                      */
427 /************************************************************************/
428 
OGR_L_SetAttributeFilter(OGRLayerH hLayer,const char * pszQuery)429 OGRErr OGR_L_SetAttributeFilter( OGRLayerH hLayer, const char *pszQuery )
430 
431 {
432     VALIDATE_POINTER1( hLayer, "OGR_L_SetAttributeFilter", OGRERR_INVALID_HANDLE );
433 
434 #ifdef OGRAPISPY_ENABLED
435     if( bOGRAPISpyEnabled )
436         OGRAPISpy_L_SetAttributeFilter(hLayer, pszQuery);
437 #endif
438 
439     return ((OGRLayer *) hLayer)->SetAttributeFilter( pszQuery );
440 }
441 
442 /************************************************************************/
443 /*                             GetFeature()                             */
444 /************************************************************************/
445 
GetFeature(GIntBig nFID)446 OGRFeature *OGRLayer::GetFeature( GIntBig nFID )
447 
448 {
449     OGRFeature *poFeature;
450 
451     /* Save old attribute and spatial filters */
452     char* pszOldFilter = m_pszAttrQueryString ? CPLStrdup(m_pszAttrQueryString) : NULL;
453     OGRGeometry* poOldFilterGeom = ( m_poFilterGeom != NULL ) ? m_poFilterGeom->clone() : NULL;
454     int iOldGeomFieldFilter = m_iGeomFieldFilter;
455     /* Unset filters */
456     SetAttributeFilter(NULL);
457     SetSpatialFilter(0, NULL);
458 
459     ResetReading();
460     while( (poFeature = GetNextFeature()) != NULL )
461     {
462         if( poFeature->GetFID() == nFID )
463             break;
464         else
465             delete poFeature;
466     }
467 
468     /* Restore filters */
469     SetAttributeFilter(pszOldFilter);
470     CPLFree(pszOldFilter);
471     SetSpatialFilter(iOldGeomFieldFilter, poOldFilterGeom);
472     delete poOldFilterGeom;
473 
474     return poFeature;
475 }
476 
477 /************************************************************************/
478 /*                          OGR_L_GetFeature()                          */
479 /************************************************************************/
480 
OGR_L_GetFeature(OGRLayerH hLayer,GIntBig nFeatureId)481 OGRFeatureH OGR_L_GetFeature( OGRLayerH hLayer, GIntBig nFeatureId )
482 
483 {
484     VALIDATE_POINTER1( hLayer, "OGR_L_GetFeature", NULL );
485 
486 #ifdef OGRAPISPY_ENABLED
487     if( bOGRAPISpyEnabled )
488         OGRAPISpy_L_GetFeature(hLayer, nFeatureId);
489 #endif
490 
491     return (OGRFeatureH) ((OGRLayer *)hLayer)->GetFeature( nFeatureId );
492 }
493 
494 /************************************************************************/
495 /*                           SetNextByIndex()                           */
496 /************************************************************************/
497 
SetNextByIndex(GIntBig nIndex)498 OGRErr OGRLayer::SetNextByIndex( GIntBig nIndex )
499 
500 {
501     OGRFeature *poFeature;
502 
503     if( nIndex < 0 )
504         return OGRERR_FAILURE;
505 
506     ResetReading();
507     while( nIndex-- > 0 )
508     {
509         poFeature = GetNextFeature();
510         if( poFeature == NULL )
511             return OGRERR_FAILURE;
512 
513         delete poFeature;
514     }
515 
516     return OGRERR_NONE;
517 }
518 
519 /************************************************************************/
520 /*                        OGR_L_SetNextByIndex()                        */
521 /************************************************************************/
522 
OGR_L_SetNextByIndex(OGRLayerH hLayer,GIntBig nIndex)523 OGRErr OGR_L_SetNextByIndex( OGRLayerH hLayer, GIntBig nIndex )
524 
525 {
526     VALIDATE_POINTER1( hLayer, "OGR_L_SetNextByIndex", OGRERR_INVALID_HANDLE );
527 
528 #ifdef OGRAPISPY_ENABLED
529     if( bOGRAPISpyEnabled )
530         OGRAPISpy_L_SetNextByIndex(hLayer, nIndex);
531 #endif
532 
533     return ((OGRLayer *)hLayer)->SetNextByIndex( nIndex );
534 }
535 
536 /************************************************************************/
537 /*                        OGR_L_GetNextFeature()                        */
538 /************************************************************************/
539 
OGR_L_GetNextFeature(OGRLayerH hLayer)540 OGRFeatureH OGR_L_GetNextFeature( OGRLayerH hLayer )
541 
542 {
543     VALIDATE_POINTER1( hLayer, "OGR_L_GetNextFeature", NULL );
544 
545 #ifdef OGRAPISPY_ENABLED
546     if( bOGRAPISpyEnabled )
547         OGRAPISpy_L_GetNextFeature(hLayer);
548 #endif
549 
550     return (OGRFeatureH) ((OGRLayer *)hLayer)->GetNextFeature();
551 }
552 
553 /************************************************************************/
554 /*                    ConvertNonLinearGeomsIfNecessary()                */
555 /************************************************************************/
556 
ConvertNonLinearGeomsIfNecessary(OGRFeature * poFeature)557 void OGRLayer::ConvertNonLinearGeomsIfNecessary( OGRFeature *poFeature )
558 {
559     if( !TestCapability(OLCCurveGeometries) )
560     {
561         int nGeomFieldCount = GetLayerDefn()->GetGeomFieldCount();
562         for(int i=0;i<nGeomFieldCount;i++)
563         {
564             OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
565             if( poGeom != NULL && OGR_GT_IsNonLinear(poGeom->getGeometryType()) )
566             {
567                 OGRwkbGeometryType eTargetType = OGR_GT_GetLinear(poGeom->getGeometryType());
568                 poFeature->SetGeomFieldDirectly(i,
569                     OGRGeometryFactory::forceTo(poFeature->StealGeometry(i), eTargetType));
570             }
571         }
572     }
573 }
574 
575 /************************************************************************/
576 /*                             SetFeature()                             */
577 /************************************************************************/
578 
SetFeature(OGRFeature * poFeature)579 OGRErr OGRLayer::SetFeature( OGRFeature *poFeature )
580 
581 {
582     ConvertNonLinearGeomsIfNecessary(poFeature);
583     return ISetFeature(poFeature);
584 }
585 
586 /************************************************************************/
587 /*                             ISetFeature()                            */
588 /************************************************************************/
589 
ISetFeature(OGRFeature *)590 OGRErr OGRLayer::ISetFeature( OGRFeature * )
591 
592 {
593     return OGRERR_UNSUPPORTED_OPERATION;
594 }
595 
596 /************************************************************************/
597 /*                          OGR_L_SetFeature()                          */
598 /************************************************************************/
599 
OGR_L_SetFeature(OGRLayerH hLayer,OGRFeatureH hFeat)600 OGRErr OGR_L_SetFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
601 
602 {
603     VALIDATE_POINTER1( hLayer, "OGR_L_SetFeature", OGRERR_INVALID_HANDLE );
604     VALIDATE_POINTER1( hFeat, "OGR_L_SetFeature", OGRERR_INVALID_HANDLE );
605 
606 #ifdef OGRAPISPY_ENABLED
607     if( bOGRAPISpyEnabled )
608         OGRAPISpy_L_SetFeature(hLayer, hFeat);
609 #endif
610 
611     return ((OGRLayer *)hLayer)->SetFeature( (OGRFeature *) hFeat );
612 }
613 
614 /************************************************************************/
615 /*                           CreateFeature()                            */
616 /************************************************************************/
617 
CreateFeature(OGRFeature * poFeature)618 OGRErr OGRLayer::CreateFeature( OGRFeature *poFeature )
619 
620 {
621     ConvertNonLinearGeomsIfNecessary(poFeature);
622     return ICreateFeature(poFeature);
623 }
624 
625 /************************************************************************/
626 /*                           ICreateFeature()                            */
627 /************************************************************************/
628 
ICreateFeature(OGRFeature *)629 OGRErr OGRLayer::ICreateFeature( OGRFeature * )
630 
631 {
632     return OGRERR_UNSUPPORTED_OPERATION;
633 }
634 
635 /************************************************************************/
636 /*                        OGR_L_CreateFeature()                         */
637 /************************************************************************/
638 
OGR_L_CreateFeature(OGRLayerH hLayer,OGRFeatureH hFeat)639 OGRErr OGR_L_CreateFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
640 
641 {
642     VALIDATE_POINTER1( hLayer, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE );
643     VALIDATE_POINTER1( hFeat, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE );
644 
645 #ifdef OGRAPISPY_ENABLED
646     if( bOGRAPISpyEnabled )
647         OGRAPISpy_L_CreateFeature(hLayer, hFeat);
648 #endif
649 
650     return ((OGRLayer *) hLayer)->CreateFeature( (OGRFeature *) hFeat );
651 }
652 
653 /************************************************************************/
654 /*                            CreateField()                             */
655 /************************************************************************/
656 
CreateField(OGRFieldDefn * poField,int bApproxOK)657 OGRErr OGRLayer::CreateField( OGRFieldDefn * poField, int bApproxOK )
658 
659 {
660     (void) poField;
661     (void) bApproxOK;
662 
663     CPLError( CE_Failure, CPLE_NotSupported,
664               "CreateField() not supported by this layer.\n" );
665 
666     return OGRERR_UNSUPPORTED_OPERATION;
667 }
668 
669 /************************************************************************/
670 /*                         OGR_L_CreateField()                          */
671 /************************************************************************/
672 
OGR_L_CreateField(OGRLayerH hLayer,OGRFieldDefnH hField,int bApproxOK)673 OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
674                           int bApproxOK )
675 
676 {
677     VALIDATE_POINTER1( hLayer, "OGR_L_CreateField", OGRERR_INVALID_HANDLE );
678     VALIDATE_POINTER1( hField, "OGR_L_CreateField", OGRERR_INVALID_HANDLE );
679 
680 #ifdef OGRAPISPY_ENABLED
681     if( bOGRAPISpyEnabled )
682         OGRAPISpy_L_CreateField(hLayer, hField, bApproxOK);
683 #endif
684 
685     return ((OGRLayer *) hLayer)->CreateField( (OGRFieldDefn *) hField,
686                                                bApproxOK );
687 }
688 
689 /************************************************************************/
690 /*                            DeleteField()                             */
691 /************************************************************************/
692 
DeleteField(int iField)693 OGRErr OGRLayer::DeleteField( int iField )
694 
695 {
696     (void) iField;
697 
698     CPLError( CE_Failure, CPLE_NotSupported,
699               "DeleteField() not supported by this layer.\n" );
700 
701     return OGRERR_UNSUPPORTED_OPERATION;
702 }
703 
704 /************************************************************************/
705 /*                         OGR_L_DeleteField()                          */
706 /************************************************************************/
707 
OGR_L_DeleteField(OGRLayerH hLayer,int iField)708 OGRErr OGR_L_DeleteField( OGRLayerH hLayer, int iField )
709 
710 {
711     VALIDATE_POINTER1( hLayer, "OGR_L_DeleteField", OGRERR_INVALID_HANDLE );
712 
713 #ifdef OGRAPISPY_ENABLED
714     if( bOGRAPISpyEnabled )
715         OGRAPISpy_L_DeleteField(hLayer, iField);
716 #endif
717 
718     return ((OGRLayer *) hLayer)->DeleteField( iField );
719 }
720 
721 /************************************************************************/
722 /*                           ReorderFields()                            */
723 /************************************************************************/
724 
ReorderFields(int * panMap)725 OGRErr OGRLayer::ReorderFields( int* panMap )
726 
727 {
728     (void) panMap;
729 
730     CPLError( CE_Failure, CPLE_NotSupported,
731               "ReorderFields() not supported by this layer.\n" );
732 
733     return OGRERR_UNSUPPORTED_OPERATION;
734 }
735 
736 /************************************************************************/
737 /*                       OGR_L_ReorderFields()                          */
738 /************************************************************************/
739 
OGR_L_ReorderFields(OGRLayerH hLayer,int * panMap)740 OGRErr OGR_L_ReorderFields( OGRLayerH hLayer, int* panMap )
741 
742 {
743     VALIDATE_POINTER1( hLayer, "OGR_L_ReorderFields", OGRERR_INVALID_HANDLE );
744 
745 #ifdef OGRAPISPY_ENABLED
746     if( bOGRAPISpyEnabled )
747         OGRAPISpy_L_ReorderFields(hLayer, panMap);
748 #endif
749 
750     return ((OGRLayer *) hLayer)->ReorderFields( panMap );
751 }
752 
753 /************************************************************************/
754 /*                            ReorderField()                            */
755 /************************************************************************/
756 
ReorderField(int iOldFieldPos,int iNewFieldPos)757 OGRErr OGRLayer::ReorderField( int iOldFieldPos, int iNewFieldPos )
758 
759 {
760     OGRErr eErr;
761 
762     int nFieldCount = GetLayerDefn()->GetFieldCount();
763 
764     if (iOldFieldPos < 0 || iOldFieldPos >= nFieldCount)
765     {
766         CPLError( CE_Failure, CPLE_NotSupported,
767                   "Invalid field index");
768         return OGRERR_FAILURE;
769     }
770     if (iNewFieldPos < 0 || iNewFieldPos >= nFieldCount)
771     {
772         CPLError( CE_Failure, CPLE_NotSupported,
773                   "Invalid field index");
774         return OGRERR_FAILURE;
775     }
776     if (iNewFieldPos == iOldFieldPos)
777         return OGRERR_NONE;
778 
779     int* panMap = (int*) CPLMalloc(sizeof(int) * nFieldCount);
780     int i;
781     if (iOldFieldPos < iNewFieldPos)
782     {
783         /* "0","1","2","3","4" (1,3) -> "0","2","3","1","4" */
784         for(i=0;i<iOldFieldPos;i++)
785             panMap[i] = i;
786         for(;i<iNewFieldPos;i++)
787             panMap[i] = i + 1;
788         panMap[iNewFieldPos] = iOldFieldPos;
789         for(i=iNewFieldPos+1;i<nFieldCount;i++)
790             panMap[i] = i;
791     }
792     else
793     {
794         /* "0","1","2","3","4" (3,1) -> "0","3","1","2","4" */
795         for(i=0;i<iNewFieldPos;i++)
796             panMap[i] = i;
797         panMap[iNewFieldPos] = iOldFieldPos;
798         for(i=iNewFieldPos+1;i<=iOldFieldPos;i++)
799             panMap[i] = i - 1;
800         for(;i<nFieldCount;i++)
801             panMap[i] = i;
802     }
803 
804     eErr = ReorderFields(panMap);
805 
806     CPLFree(panMap);
807 
808     return eErr;
809 }
810 
811 /************************************************************************/
812 /*                        OGR_L_ReorderField()                          */
813 /************************************************************************/
814 
OGR_L_ReorderField(OGRLayerH hLayer,int iOldFieldPos,int iNewFieldPos)815 OGRErr OGR_L_ReorderField( OGRLayerH hLayer, int iOldFieldPos, int iNewFieldPos )
816 
817 {
818     VALIDATE_POINTER1( hLayer, "OGR_L_ReorderField", OGRERR_INVALID_HANDLE );
819 
820 #ifdef OGRAPISPY_ENABLED
821     if( bOGRAPISpyEnabled )
822         OGRAPISpy_L_ReorderField(hLayer, iOldFieldPos, iNewFieldPos);
823 #endif
824 
825     return ((OGRLayer *) hLayer)->ReorderField( iOldFieldPos, iNewFieldPos );
826 }
827 
828 /************************************************************************/
829 /*                           AlterFieldDefn()                           */
830 /************************************************************************/
831 
AlterFieldDefn(int iField,OGRFieldDefn * poNewFieldDefn,int nFlags)832 OGRErr OGRLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
833                                  int nFlags )
834 
835 {
836     (void) iField;
837     (void) poNewFieldDefn;
838     (void) nFlags;
839 
840     CPLError( CE_Failure, CPLE_NotSupported,
841               "AlterFieldDefn() not supported by this layer.\n" );
842 
843     return OGRERR_UNSUPPORTED_OPERATION;
844 }
845 
846 /************************************************************************/
847 /*                        OGR_L_AlterFieldDefn()                        */
848 /************************************************************************/
849 
OGR_L_AlterFieldDefn(OGRLayerH hLayer,int iField,OGRFieldDefnH hNewFieldDefn,int nFlags)850 OGRErr OGR_L_AlterFieldDefn( OGRLayerH hLayer, int iField, OGRFieldDefnH hNewFieldDefn,
851                              int nFlags )
852 
853 {
854     VALIDATE_POINTER1( hLayer, "OGR_L_AlterFieldDefn", OGRERR_INVALID_HANDLE );
855     VALIDATE_POINTER1( hNewFieldDefn, "OGR_L_AlterFieldDefn", OGRERR_INVALID_HANDLE );
856 
857 #ifdef OGRAPISPY_ENABLED
858     if( bOGRAPISpyEnabled )
859         OGRAPISpy_L_AlterFieldDefn(hLayer, iField, hNewFieldDefn, nFlags);
860 #endif
861 
862     return ((OGRLayer *) hLayer)->AlterFieldDefn( iField, (OGRFieldDefn*) hNewFieldDefn, nFlags );
863 }
864 
865 /************************************************************************/
866 /*                         CreateGeomField()                            */
867 /************************************************************************/
868 
CreateGeomField(OGRGeomFieldDefn * poField,int bApproxOK)869 OGRErr OGRLayer::CreateGeomField( OGRGeomFieldDefn * poField, int bApproxOK )
870 
871 {
872     (void) poField;
873     (void) bApproxOK;
874 
875     CPLError( CE_Failure, CPLE_NotSupported,
876               "CreateGeomField() not supported by this layer.\n" );
877 
878     return OGRERR_UNSUPPORTED_OPERATION;
879 }
880 
881 /************************************************************************/
882 /*                        OGR_L_CreateGeomField()                       */
883 /************************************************************************/
884 
OGR_L_CreateGeomField(OGRLayerH hLayer,OGRGeomFieldDefnH hField,int bApproxOK)885 OGRErr OGR_L_CreateGeomField( OGRLayerH hLayer, OGRGeomFieldDefnH hField,
886                               int bApproxOK )
887 
888 {
889     VALIDATE_POINTER1( hLayer, "OGR_L_CreateGeomField", OGRERR_INVALID_HANDLE );
890     VALIDATE_POINTER1( hField, "OGR_L_CreateGeomField", OGRERR_INVALID_HANDLE );
891 
892 #ifdef OGRAPISPY_ENABLED
893     if( bOGRAPISpyEnabled )
894         OGRAPISpy_L_CreateGeomField(hLayer, hField, bApproxOK);
895 #endif
896 
897     return ((OGRLayer *) hLayer)->CreateGeomField( (OGRGeomFieldDefn *) hField,
898                                                    bApproxOK );
899 }
900 
901 /************************************************************************/
902 /*                          StartTransaction()                          */
903 /************************************************************************/
904 
StartTransaction()905 OGRErr OGRLayer::StartTransaction()
906 
907 {
908     return OGRERR_NONE;
909 }
910 
911 /************************************************************************/
912 /*                       OGR_L_StartTransaction()                       */
913 /************************************************************************/
914 
OGR_L_StartTransaction(OGRLayerH hLayer)915 OGRErr OGR_L_StartTransaction( OGRLayerH hLayer )
916 
917 {
918     VALIDATE_POINTER1( hLayer, "OGR_L_StartTransaction", OGRERR_INVALID_HANDLE );
919 
920 #ifdef OGRAPISPY_ENABLED
921     if( bOGRAPISpyEnabled )
922         OGRAPISpy_L_StartTransaction(hLayer);
923 #endif
924 
925     return ((OGRLayer *)hLayer)->StartTransaction();
926 }
927 
928 /************************************************************************/
929 /*                         CommitTransaction()                          */
930 /************************************************************************/
931 
CommitTransaction()932 OGRErr OGRLayer::CommitTransaction()
933 
934 {
935     return OGRERR_NONE;
936 }
937 
938 /************************************************************************/
939 /*                       OGR_L_CommitTransaction()                      */
940 /************************************************************************/
941 
OGR_L_CommitTransaction(OGRLayerH hLayer)942 OGRErr OGR_L_CommitTransaction( OGRLayerH hLayer )
943 
944 {
945     VALIDATE_POINTER1( hLayer, "OGR_L_CommitTransaction", OGRERR_INVALID_HANDLE );
946 
947 #ifdef OGRAPISPY_ENABLED
948     if( bOGRAPISpyEnabled )
949         OGRAPISpy_L_CommitTransaction(hLayer);
950 #endif
951 
952     return ((OGRLayer *)hLayer)->CommitTransaction();
953 }
954 
955 /************************************************************************/
956 /*                        RollbackTransaction()                         */
957 /************************************************************************/
958 
RollbackTransaction()959 OGRErr OGRLayer::RollbackTransaction()
960 
961 {
962     return OGRERR_UNSUPPORTED_OPERATION;
963 }
964 
965 /************************************************************************/
966 /*                     OGR_L_RollbackTransaction()                      */
967 /************************************************************************/
968 
OGR_L_RollbackTransaction(OGRLayerH hLayer)969 OGRErr OGR_L_RollbackTransaction( OGRLayerH hLayer )
970 
971 {
972     VALIDATE_POINTER1( hLayer, "OGR_L_RollbackTransaction", OGRERR_INVALID_HANDLE );
973 
974 #ifdef OGRAPISPY_ENABLED
975     if( bOGRAPISpyEnabled )
976         OGRAPISpy_L_RollbackTransaction(hLayer);
977 #endif
978 
979     return ((OGRLayer *)hLayer)->RollbackTransaction();
980 }
981 
982 /************************************************************************/
983 /*                         OGR_L_GetLayerDefn()                         */
984 /************************************************************************/
985 
OGR_L_GetLayerDefn(OGRLayerH hLayer)986 OGRFeatureDefnH OGR_L_GetLayerDefn( OGRLayerH hLayer )
987 
988 {
989     VALIDATE_POINTER1( hLayer, "OGR_L_GetLayerDefn", NULL );
990 
991 #ifdef OGRAPISPY_ENABLED
992     if( bOGRAPISpyEnabled )
993         OGRAPISpy_L_GetLayerDefn(hLayer);
994 #endif
995 
996     return (OGRFeatureDefnH) ((OGRLayer *)hLayer)->GetLayerDefn();
997 }
998 
999 /************************************************************************/
1000 /*                         OGR_L_FindFieldIndex()                       */
1001 /************************************************************************/
1002 
OGR_L_FindFieldIndex(OGRLayerH hLayer,const char * pszFieldName,int bExactMatch)1003 int OGR_L_FindFieldIndex( OGRLayerH hLayer, const char *pszFieldName, int bExactMatch )
1004 
1005 {
1006     VALIDATE_POINTER1( hLayer, "OGR_L_FindFieldIndex", -1 );
1007 
1008 #ifdef OGRAPISPY_ENABLED
1009     if( bOGRAPISpyEnabled )
1010         OGRAPISpy_L_FindFieldIndex(hLayer, pszFieldName, bExactMatch);
1011 #endif
1012 
1013     return ((OGRLayer *)hLayer)->FindFieldIndex( pszFieldName, bExactMatch );
1014 }
1015 
1016 /************************************************************************/
1017 /*                           FindFieldIndex()                           */
1018 /************************************************************************/
1019 
FindFieldIndex(const char * pszFieldName,CPL_UNUSED int bExactMatch)1020 int OGRLayer::FindFieldIndex( const char *pszFieldName, CPL_UNUSED int bExactMatch )
1021 {
1022     return GetLayerDefn()->GetFieldIndex( pszFieldName );
1023 }
1024 
1025 /************************************************************************/
1026 /*                           GetSpatialRef()                            */
1027 /************************************************************************/
1028 
GetSpatialRef()1029 OGRSpatialReference *OGRLayer::GetSpatialRef()
1030 {
1031     if( GetLayerDefn()->GetGeomFieldCount() > 0 )
1032         return GetLayerDefn()->GetGeomFieldDefn(0)->GetSpatialRef();
1033     else
1034         return NULL;
1035 }
1036 
1037 /************************************************************************/
1038 /*                        OGR_L_GetSpatialRef()                         */
1039 /************************************************************************/
1040 
OGR_L_GetSpatialRef(OGRLayerH hLayer)1041 OGRSpatialReferenceH OGR_L_GetSpatialRef( OGRLayerH hLayer )
1042 
1043 {
1044     VALIDATE_POINTER1( hLayer, "OGR_L_GetSpatialRef", NULL );
1045 
1046 #ifdef OGRAPISPY_ENABLED
1047     if( bOGRAPISpyEnabled )
1048         OGRAPISpy_L_GetSpatialRef(hLayer);
1049 #endif
1050 
1051     return (OGRSpatialReferenceH) ((OGRLayer *) hLayer)->GetSpatialRef();
1052 }
1053 
1054 /************************************************************************/
1055 /*                        OGR_L_TestCapability()                        */
1056 /************************************************************************/
1057 
OGR_L_TestCapability(OGRLayerH hLayer,const char * pszCap)1058 int OGR_L_TestCapability( OGRLayerH hLayer, const char *pszCap )
1059 
1060 {
1061     VALIDATE_POINTER1( hLayer, "OGR_L_TestCapability", 0 );
1062     VALIDATE_POINTER1( pszCap, "OGR_L_TestCapability", 0 );
1063 
1064 #ifdef OGRAPISPY_ENABLED
1065     if( bOGRAPISpyEnabled )
1066         OGRAPISpy_L_TestCapability(hLayer, pszCap);
1067 #endif
1068 
1069     return ((OGRLayer *) hLayer)->TestCapability( pszCap );
1070 }
1071 
1072 /************************************************************************/
1073 /*                          GetSpatialFilter()                          */
1074 /************************************************************************/
1075 
GetSpatialFilter()1076 OGRGeometry *OGRLayer::GetSpatialFilter()
1077 
1078 {
1079     return m_poFilterGeom;
1080 }
1081 
1082 /************************************************************************/
1083 /*                       OGR_L_GetSpatialFilter()                       */
1084 /************************************************************************/
1085 
OGR_L_GetSpatialFilter(OGRLayerH hLayer)1086 OGRGeometryH OGR_L_GetSpatialFilter( OGRLayerH hLayer )
1087 
1088 {
1089     VALIDATE_POINTER1( hLayer, "OGR_L_GetSpatialFilter", NULL );
1090 
1091 #ifdef OGRAPISPY_ENABLED
1092     if( bOGRAPISpyEnabled )
1093         OGRAPISpy_L_GetSpatialFilter(hLayer);
1094 #endif
1095 
1096     return (OGRGeometryH) ((OGRLayer *) hLayer)->GetSpatialFilter();
1097 }
1098 
1099 /************************************************************************/
1100 /*                          SetSpatialFilter()                          */
1101 /************************************************************************/
1102 
SetSpatialFilter(OGRGeometry * poGeomIn)1103 void OGRLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
1104 
1105 {
1106     m_iGeomFieldFilter = 0;
1107     if( InstallFilter( poGeomIn ) )
1108         ResetReading();
1109 }
1110 
1111 
SetSpatialFilter(int iGeomField,OGRGeometry * poGeomIn)1112 void OGRLayer::SetSpatialFilter( int iGeomField, OGRGeometry * poGeomIn )
1113 
1114 {
1115     if( iGeomField == 0 )
1116     {
1117         m_iGeomFieldFilter = iGeomField;
1118         SetSpatialFilter( poGeomIn );
1119     }
1120     else
1121     {
1122         if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
1123         {
1124             CPLError(CE_Failure, CPLE_AppDefined,
1125                      "Invalid geometry field index : %d", iGeomField);
1126             return;
1127         }
1128 
1129         m_iGeomFieldFilter = iGeomField;
1130         if( InstallFilter( poGeomIn ) )
1131             ResetReading();
1132     }
1133 }
1134 
1135 /************************************************************************/
1136 /*                       OGR_L_SetSpatialFilter()                       */
1137 /************************************************************************/
1138 
OGR_L_SetSpatialFilter(OGRLayerH hLayer,OGRGeometryH hGeom)1139 void OGR_L_SetSpatialFilter( OGRLayerH hLayer, OGRGeometryH hGeom )
1140 
1141 {
1142     VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilter" );
1143 
1144 #ifdef OGRAPISPY_ENABLED
1145     if( bOGRAPISpyEnabled )
1146         OGRAPISpy_L_SetSpatialFilter(hLayer, hGeom);
1147 #endif
1148 
1149     ((OGRLayer *) hLayer)->SetSpatialFilter( (OGRGeometry *) hGeom );
1150 }
1151 
1152 /************************************************************************/
1153 /*                      OGR_L_SetSpatialFilterEx()                      */
1154 /************************************************************************/
1155 
OGR_L_SetSpatialFilterEx(OGRLayerH hLayer,int iGeomField,OGRGeometryH hGeom)1156 void OGR_L_SetSpatialFilterEx( OGRLayerH hLayer, int iGeomField,
1157                                OGRGeometryH hGeom )
1158 
1159 {
1160     VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilterEx" );
1161 
1162 #ifdef OGRAPISPY_ENABLED
1163     if( bOGRAPISpyEnabled )
1164         OGRAPISpy_L_SetSpatialFilterEx(hLayer, iGeomField, hGeom);
1165 #endif
1166 
1167     ((OGRLayer *) hLayer)->SetSpatialFilter( iGeomField, (OGRGeometry *) hGeom );
1168 }
1169 /************************************************************************/
1170 /*                        SetSpatialFilterRect()                        */
1171 /************************************************************************/
1172 
SetSpatialFilterRect(double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)1173 void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
1174                                      double dfMaxX, double dfMaxY )
1175 
1176 {
1177     SetSpatialFilterRect( 0, dfMinX, dfMinY, dfMaxX, dfMaxY );
1178 }
1179 
1180 
SetSpatialFilterRect(int iGeomField,double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)1181 void OGRLayer::SetSpatialFilterRect( int iGeomField,
1182                                      double dfMinX, double dfMinY,
1183                                      double dfMaxX, double dfMaxY )
1184 
1185 {
1186     OGRLinearRing  oRing;
1187     OGRPolygon oPoly;
1188 
1189     oRing.addPoint( dfMinX, dfMinY );
1190     oRing.addPoint( dfMinX, dfMaxY );
1191     oRing.addPoint( dfMaxX, dfMaxY );
1192     oRing.addPoint( dfMaxX, dfMinY );
1193     oRing.addPoint( dfMinX, dfMinY );
1194 
1195     oPoly.addRing( &oRing );
1196 
1197     if( iGeomField == 0 )
1198         /* for drivers that only overload SetSpatialFilter(OGRGeometry*) */
1199         SetSpatialFilter( &oPoly );
1200     else
1201         SetSpatialFilter( iGeomField, &oPoly );
1202 }
1203 
1204 /************************************************************************/
1205 /*                     OGR_L_SetSpatialFilterRect()                     */
1206 /************************************************************************/
1207 
OGR_L_SetSpatialFilterRect(OGRLayerH hLayer,double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)1208 void OGR_L_SetSpatialFilterRect( OGRLayerH hLayer,
1209                                  double dfMinX, double dfMinY,
1210                                  double dfMaxX, double dfMaxY )
1211 
1212 {
1213     VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilterRect" );
1214 
1215 #ifdef OGRAPISPY_ENABLED
1216     if( bOGRAPISpyEnabled )
1217         OGRAPISpy_L_SetSpatialFilterRect(hLayer, dfMinX, dfMinY, dfMaxX, dfMaxY);
1218 #endif
1219 
1220     ((OGRLayer *) hLayer)->SetSpatialFilterRect( dfMinX, dfMinY,
1221                                                  dfMaxX, dfMaxY );
1222 }
1223 
1224 /************************************************************************/
1225 /*                    OGR_L_SetSpatialFilterRectEx()                    */
1226 /************************************************************************/
1227 
OGR_L_SetSpatialFilterRectEx(OGRLayerH hLayer,int iGeomField,double dfMinX,double dfMinY,double dfMaxX,double dfMaxY)1228 void OGR_L_SetSpatialFilterRectEx( OGRLayerH hLayer,
1229                                    int iGeomField,
1230                                    double dfMinX, double dfMinY,
1231                                    double dfMaxX, double dfMaxY )
1232 
1233 {
1234     VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilterRectEx" );
1235 
1236 #ifdef OGRAPISPY_ENABLED
1237     if( bOGRAPISpyEnabled )
1238         OGRAPISpy_L_SetSpatialFilterRectEx(hLayer, iGeomField, dfMinX, dfMinY, dfMaxX, dfMaxY);
1239 #endif
1240 
1241     ((OGRLayer *) hLayer)->SetSpatialFilterRect( iGeomField,
1242                                                  dfMinX, dfMinY,
1243                                                  dfMaxX, dfMaxY );
1244 }
1245 
1246 /************************************************************************/
1247 /*                           InstallFilter()                            */
1248 /*                                                                      */
1249 /*      This method is only intended to be used from within             */
1250 /*      drivers, normally from the SetSpatialFilter() method.           */
1251 /*      It installs a filter, and also tests it to see if it is         */
1252 /*      rectangular.  If so, it this is kept track of alongside the     */
1253 /*      filter geometry itself so we can do cheaper comparisons in      */
1254 /*      the FilterGeometry() call.                                      */
1255 /*                                                                      */
1256 /*      Returns TRUE if the newly installed filter differs in some      */
1257 /*      way from the current one.                                       */
1258 /************************************************************************/
1259 
InstallFilter(OGRGeometry * poFilter)1260 int OGRLayer::InstallFilter( OGRGeometry * poFilter )
1261 
1262 {
1263     if( m_poFilterGeom == NULL && poFilter == NULL )
1264         return FALSE;
1265 
1266 /* -------------------------------------------------------------------- */
1267 /*      Replace the existing filter.                                    */
1268 /* -------------------------------------------------------------------- */
1269     if( m_poFilterGeom != NULL )
1270     {
1271         delete m_poFilterGeom;
1272         m_poFilterGeom = NULL;
1273     }
1274 
1275     if( m_pPreparedFilterGeom != NULL )
1276     {
1277         OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
1278         m_pPreparedFilterGeom = NULL;
1279     }
1280 
1281     if( poFilter != NULL )
1282         m_poFilterGeom = poFilter->clone();
1283 
1284     m_bFilterIsEnvelope = FALSE;
1285 
1286     if( m_poFilterGeom == NULL )
1287         return TRUE;
1288 
1289     if( m_poFilterGeom != NULL )
1290         m_poFilterGeom->getEnvelope( &m_sFilterEnvelope );
1291 
1292     /* Compile geometry filter as a prepared geometry */
1293     m_pPreparedFilterGeom = OGRCreatePreparedGeometry(m_poFilterGeom);
1294 
1295 /* -------------------------------------------------------------------- */
1296 /*      Now try to determine if the filter is really a rectangle.       */
1297 /* -------------------------------------------------------------------- */
1298     if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
1299         return TRUE;
1300 
1301     OGRPolygon *poPoly = (OGRPolygon *) m_poFilterGeom;
1302 
1303     if( poPoly->getNumInteriorRings() != 0 )
1304         return TRUE;
1305 
1306     OGRLinearRing *poRing = poPoly->getExteriorRing();
1307     if (poRing == NULL)
1308         return TRUE;
1309 
1310     if( poRing->getNumPoints() > 5 || poRing->getNumPoints() < 4 )
1311         return TRUE;
1312 
1313     // If the ring has 5 points, the last should be the first.
1314     if( poRing->getNumPoints() == 5
1315         && ( poRing->getX(0) != poRing->getX(4)
1316              || poRing->getY(0) != poRing->getY(4) ) )
1317         return TRUE;
1318 
1319     // Polygon with first segment in "y" direction.
1320     if( poRing->getX(0) == poRing->getX(1)
1321         && poRing->getY(1) == poRing->getY(2)
1322         && poRing->getX(2) == poRing->getX(3)
1323         && poRing->getY(3) == poRing->getY(0) )
1324         m_bFilterIsEnvelope = TRUE;
1325 
1326     // Polygon with first segment in "x" direction.
1327     if( poRing->getY(0) == poRing->getY(1)
1328         && poRing->getX(1) == poRing->getX(2)
1329         && poRing->getY(2) == poRing->getY(3)
1330         && poRing->getX(3) == poRing->getX(0) )
1331         m_bFilterIsEnvelope = TRUE;
1332 
1333     return TRUE;
1334 }
1335 
1336 /************************************************************************/
1337 /*                           FilterGeometry()                           */
1338 /*                                                                      */
1339 /*      Compare the passed in geometry to the currently installed       */
1340 /*      filter.  Optimize for case where filter is just an              */
1341 /*      envelope.                                                       */
1342 /************************************************************************/
1343 
FilterGeometry(OGRGeometry * poGeometry)1344 int OGRLayer::FilterGeometry( OGRGeometry *poGeometry )
1345 
1346 {
1347 /* -------------------------------------------------------------------- */
1348 /*      In trivial cases of new filter or target geometry, we accept    */
1349 /*      an intersection.  No geometry is taken to mean "the whole       */
1350 /*      world".                                                         */
1351 /* -------------------------------------------------------------------- */
1352     if( m_poFilterGeom == NULL )
1353         return TRUE;
1354 
1355     if( poGeometry == NULL )
1356         return TRUE;
1357 
1358 /* -------------------------------------------------------------------- */
1359 /*      Compute the target geometry envelope, and if there is no        */
1360 /*      intersection between the envelopes we are sure not to have      */
1361 /*      any intersection.                                               */
1362 /* -------------------------------------------------------------------- */
1363     OGREnvelope sGeomEnv;
1364 
1365     poGeometry->getEnvelope( &sGeomEnv );
1366 
1367     if( sGeomEnv.MaxX < m_sFilterEnvelope.MinX
1368         || sGeomEnv.MaxY < m_sFilterEnvelope.MinY
1369         || m_sFilterEnvelope.MaxX < sGeomEnv.MinX
1370         || m_sFilterEnvelope.MaxY < sGeomEnv.MinY )
1371         return FALSE;
1372 
1373 
1374 /* -------------------------------------------------------------------- */
1375 /*      If the filter geometry is its own envelope and if the           */
1376 /*      envelope of the geometry is inside the filter geometry,         */
1377 /*      the geometry itself is inside the filter geometry               */
1378 /* -------------------------------------------------------------------- */
1379     if( m_bFilterIsEnvelope &&
1380         sGeomEnv.MinX >= m_sFilterEnvelope.MinX &&
1381         sGeomEnv.MinY >= m_sFilterEnvelope.MinY &&
1382         sGeomEnv.MaxX <= m_sFilterEnvelope.MaxX &&
1383         sGeomEnv.MaxY <= m_sFilterEnvelope.MaxY)
1384     {
1385         return TRUE;
1386     }
1387     else
1388     {
1389 /* -------------------------------------------------------------------- */
1390 /*      If the filter geometry is its own envelope and if the           */
1391 /*      the geometry (line, or polygon without hole) h has at least one */
1392 /*      point inside the filter geometry, the geometry itself is inside */
1393 /*      the filter geometry.                                            */
1394 /* -------------------------------------------------------------------- */
1395         if( m_bFilterIsEnvelope )
1396         {
1397             OGRLineString* poLS = NULL;
1398 
1399             switch( wkbFlatten(poGeometry->getGeometryType()) )
1400             {
1401                 case wkbPolygon:
1402                 {
1403                     OGRPolygon* poPoly = (OGRPolygon* )poGeometry;
1404                     OGRLinearRing* poRing = poPoly->getExteriorRing();
1405                     if (poRing != NULL && poPoly->getNumInteriorRings() == 0)
1406                     {
1407                         poLS = poRing;
1408                     }
1409                     break;
1410                 }
1411 
1412                 case wkbLineString:
1413                     poLS = (OGRLineString* )poGeometry;
1414                     break;
1415 
1416                 default:
1417                     break;
1418             }
1419 
1420             if( poLS != NULL )
1421             {
1422                 int nNumPoints = poLS->getNumPoints();
1423                 for(int i = 0; i < nNumPoints; i++)
1424                 {
1425                     double x = poLS->getX(i);
1426                     double y = poLS->getY(i);
1427                     if (x >= m_sFilterEnvelope.MinX &&
1428                         y >= m_sFilterEnvelope.MinY &&
1429                         x <= m_sFilterEnvelope.MaxX &&
1430                         y <= m_sFilterEnvelope.MaxY)
1431                     {
1432                         return TRUE;
1433                     }
1434                 }
1435             }
1436         }
1437 
1438 /* -------------------------------------------------------------------- */
1439 /*      Fallback to full intersect test (using GEOS) if we still        */
1440 /*      don't know for sure.                                            */
1441 /* -------------------------------------------------------------------- */
1442         if( OGRGeometryFactory::haveGEOS() )
1443         {
1444             //CPLDebug("OGRLayer", "GEOS intersection");
1445             if( m_pPreparedFilterGeom != NULL )
1446                 return OGRPreparedGeometryIntersects(m_pPreparedFilterGeom,
1447                                                      poGeometry);
1448             else
1449                 return m_poFilterGeom->Intersects( poGeometry );
1450         }
1451         else
1452             return TRUE;
1453     }
1454 }
1455 
1456 /************************************************************************/
1457 /*                         OGR_L_ResetReading()                         */
1458 /************************************************************************/
1459 
OGR_L_ResetReading(OGRLayerH hLayer)1460 void OGR_L_ResetReading( OGRLayerH hLayer )
1461 
1462 {
1463     VALIDATE_POINTER0( hLayer, "OGR_L_ResetReading" );
1464 
1465 #ifdef OGRAPISPY_ENABLED
1466     if( bOGRAPISpyEnabled )
1467         OGRAPISpy_L_ResetReading(hLayer);
1468 #endif
1469 
1470     ((OGRLayer *) hLayer)->ResetReading();
1471 }
1472 
1473 /************************************************************************/
1474 /*                       InitializeIndexSupport()                       */
1475 /*                                                                      */
1476 /*      This is only intended to be called by driver layer              */
1477 /*      implementations but we don't make it protected so that the      */
1478 /*      datasources can do it too if that is more appropriate.          */
1479 /************************************************************************/
1480 
InitializeIndexSupport(const char * pszFilename)1481 OGRErr OGRLayer::InitializeIndexSupport( const char *pszFilename )
1482 
1483 {
1484     OGRErr eErr;
1485 
1486     if (m_poAttrIndex != NULL)
1487         return OGRERR_NONE;
1488 
1489     m_poAttrIndex = OGRCreateDefaultLayerIndex();
1490 
1491     eErr = m_poAttrIndex->Initialize( pszFilename, this );
1492     if( eErr != OGRERR_NONE )
1493     {
1494         delete m_poAttrIndex;
1495         m_poAttrIndex = NULL;
1496     }
1497 
1498     return eErr;
1499 }
1500 
1501 /************************************************************************/
1502 /*                             SyncToDisk()                             */
1503 /************************************************************************/
1504 
SyncToDisk()1505 OGRErr OGRLayer::SyncToDisk()
1506 
1507 {
1508     return OGRERR_NONE;
1509 }
1510 
1511 /************************************************************************/
1512 /*                          OGR_L_SyncToDisk()                          */
1513 /************************************************************************/
1514 
OGR_L_SyncToDisk(OGRLayerH hLayer)1515 OGRErr OGR_L_SyncToDisk( OGRLayerH hLayer )
1516 
1517 {
1518     VALIDATE_POINTER1( hLayer, "OGR_L_SyncToDisk", OGRERR_INVALID_HANDLE );
1519 
1520 #ifdef OGRAPISPY_ENABLED
1521     if( bOGRAPISpyEnabled )
1522         OGRAPISpy_L_SyncToDisk(hLayer);
1523 #endif
1524 
1525     return ((OGRLayer *) hLayer)->SyncToDisk();
1526 }
1527 
1528 /************************************************************************/
1529 /*                           DeleteFeature()                            */
1530 /************************************************************************/
1531 
DeleteFeature(CPL_UNUSED GIntBig nFID)1532 OGRErr OGRLayer::DeleteFeature( CPL_UNUSED GIntBig nFID )
1533 {
1534     return OGRERR_UNSUPPORTED_OPERATION;
1535 }
1536 
1537 /************************************************************************/
1538 /*                        OGR_L_DeleteFeature()                         */
1539 /************************************************************************/
1540 
OGR_L_DeleteFeature(OGRLayerH hLayer,GIntBig nFID)1541 OGRErr OGR_L_DeleteFeature( OGRLayerH hLayer, GIntBig nFID )
1542 
1543 {
1544     VALIDATE_POINTER1( hLayer, "OGR_L_DeleteFeature", OGRERR_INVALID_HANDLE );
1545 
1546 #ifdef OGRAPISPY_ENABLED
1547     if( bOGRAPISpyEnabled )
1548         OGRAPISpy_L_DeleteFeature(hLayer, nFID);
1549 #endif
1550 
1551     return ((OGRLayer *) hLayer)->DeleteFeature( nFID );
1552 }
1553 
1554 /************************************************************************/
1555 /*                          GetFeaturesRead()                           */
1556 /************************************************************************/
1557 
GetFeaturesRead()1558 GIntBig OGRLayer::GetFeaturesRead()
1559 
1560 {
1561     return m_nFeaturesRead;
1562 }
1563 
1564 /************************************************************************/
1565 /*                       OGR_L_GetFeaturesRead()                        */
1566 /************************************************************************/
1567 
OGR_L_GetFeaturesRead(OGRLayerH hLayer)1568 GIntBig OGR_L_GetFeaturesRead( OGRLayerH hLayer )
1569 
1570 {
1571     VALIDATE_POINTER1( hLayer, "OGR_L_GetFeaturesRead", 0 );
1572 
1573     return ((OGRLayer *) hLayer)->GetFeaturesRead();
1574 }
1575 
1576 /************************************************************************/
1577 /*                             GetFIDColumn                             */
1578 /************************************************************************/
1579 
GetFIDColumn()1580 const char *OGRLayer::GetFIDColumn()
1581 
1582 {
1583     return "";
1584 }
1585 
1586 /************************************************************************/
1587 /*                         OGR_L_GetFIDColumn()                         */
1588 /************************************************************************/
1589 
OGR_L_GetFIDColumn(OGRLayerH hLayer)1590 const char *OGR_L_GetFIDColumn( OGRLayerH hLayer )
1591 
1592 {
1593     VALIDATE_POINTER1( hLayer, "OGR_L_GetFIDColumn", NULL );
1594 
1595 #ifdef OGRAPISPY_ENABLED
1596     if( bOGRAPISpyEnabled )
1597         OGRAPISpy_L_GetFIDColumn(hLayer);
1598 #endif
1599 
1600     return ((OGRLayer *) hLayer)->GetFIDColumn();
1601 }
1602 
1603 /************************************************************************/
1604 /*                         GetGeometryColumn()                          */
1605 /************************************************************************/
1606 
GetGeometryColumn()1607 const char *OGRLayer::GetGeometryColumn()
1608 
1609 {
1610     if( GetLayerDefn()->GetGeomFieldCount() > 0 )
1611         return GetLayerDefn()->GetGeomFieldDefn(0)->GetNameRef();
1612     else
1613         return "";
1614 }
1615 
1616 /************************************************************************/
1617 /*                      OGR_L_GetGeometryColumn()                       */
1618 /************************************************************************/
1619 
OGR_L_GetGeometryColumn(OGRLayerH hLayer)1620 const char *OGR_L_GetGeometryColumn( OGRLayerH hLayer )
1621 
1622 {
1623     VALIDATE_POINTER1( hLayer, "OGR_L_GetGeometryColumn", NULL );
1624 
1625 #ifdef OGRAPISPY_ENABLED
1626     if( bOGRAPISpyEnabled )
1627         OGRAPISpy_L_GetGeometryColumn(hLayer);
1628 #endif
1629 
1630     return ((OGRLayer *) hLayer)->GetGeometryColumn();
1631 }
1632 
1633 /************************************************************************/
1634 /*                            GetStyleTable()                           */
1635 /************************************************************************/
1636 
GetStyleTable()1637 OGRStyleTable *OGRLayer::GetStyleTable()
1638 {
1639     return m_poStyleTable;
1640 }
1641 
1642 /************************************************************************/
1643 /*                         SetStyleTableDirectly()                      */
1644 /************************************************************************/
1645 
SetStyleTableDirectly(OGRStyleTable * poStyleTable)1646 void OGRLayer::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
1647 {
1648     if ( m_poStyleTable )
1649         delete m_poStyleTable;
1650     m_poStyleTable = poStyleTable;
1651 }
1652 
1653 /************************************************************************/
1654 /*                            SetStyleTable()                           */
1655 /************************************************************************/
1656 
SetStyleTable(OGRStyleTable * poStyleTable)1657 void OGRLayer::SetStyleTable(OGRStyleTable *poStyleTable)
1658 {
1659     if ( m_poStyleTable )
1660         delete m_poStyleTable;
1661     if ( poStyleTable )
1662         m_poStyleTable = poStyleTable->Clone();
1663 }
1664 
1665 /************************************************************************/
1666 /*                         OGR_L_GetStyleTable()                        */
1667 /************************************************************************/
1668 
OGR_L_GetStyleTable(OGRLayerH hLayer)1669 OGRStyleTableH OGR_L_GetStyleTable( OGRLayerH hLayer )
1670 
1671 {
1672     VALIDATE_POINTER1( hLayer, "OGR_L_GetStyleTable", NULL );
1673 
1674     return (OGRStyleTableH) ((OGRLayer *) hLayer)->GetStyleTable( );
1675 }
1676 
1677 /************************************************************************/
1678 /*                         OGR_L_SetStyleTableDirectly()                */
1679 /************************************************************************/
1680 
OGR_L_SetStyleTableDirectly(OGRLayerH hLayer,OGRStyleTableH hStyleTable)1681 void OGR_L_SetStyleTableDirectly( OGRLayerH hLayer,
1682                                   OGRStyleTableH hStyleTable )
1683 
1684 {
1685     VALIDATE_POINTER0( hLayer, "OGR_L_SetStyleTableDirectly" );
1686 
1687     ((OGRLayer *) hLayer)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
1688 }
1689 
1690 /************************************************************************/
1691 /*                         OGR_L_SetStyleTable()                        */
1692 /************************************************************************/
1693 
OGR_L_SetStyleTable(OGRLayerH hLayer,OGRStyleTableH hStyleTable)1694 void OGR_L_SetStyleTable( OGRLayerH hLayer,
1695                           OGRStyleTableH hStyleTable )
1696 
1697 {
1698     VALIDATE_POINTER0( hLayer, "OGR_L_SetStyleTable" );
1699     VALIDATE_POINTER0( hStyleTable, "OGR_L_SetStyleTable" );
1700 
1701     ((OGRLayer *) hLayer)->SetStyleTable( (OGRStyleTable *) hStyleTable);
1702 }
1703 
1704 /************************************************************************/
1705 /*                               GetName()                              */
1706 /************************************************************************/
1707 
GetName()1708 const char *OGRLayer::GetName()
1709 
1710 {
1711     return GetLayerDefn()->GetName();
1712 }
1713 
1714 /************************************************************************/
1715 /*                           OGR_L_GetName()                            */
1716 /************************************************************************/
1717 
OGR_L_GetName(OGRLayerH hLayer)1718 const char* OGR_L_GetName( OGRLayerH hLayer )
1719 
1720 {
1721     VALIDATE_POINTER1( hLayer, "OGR_L_GetName", "" );
1722 
1723 #ifdef OGRAPISPY_ENABLED
1724     if( bOGRAPISpyEnabled )
1725         OGRAPISpy_L_GetName(hLayer);
1726 #endif
1727 
1728     return ((OGRLayer *) hLayer)->GetName();
1729 }
1730 
1731 /************************************************************************/
1732 /*                            GetGeomType()                             */
1733 /************************************************************************/
1734 
GetGeomType()1735 OGRwkbGeometryType OGRLayer::GetGeomType()
1736 {
1737     OGRFeatureDefn* poLayerDefn = GetLayerDefn();
1738     if( poLayerDefn == NULL )
1739     {
1740         CPLDebug("OGR", "GetLayerType() returns NULL !");
1741         return wkbUnknown;
1742     }
1743     return poLayerDefn->GetGeomType();
1744 }
1745 
1746 /************************************************************************/
1747 /*                         OGR_L_GetGeomType()                          */
1748 /************************************************************************/
1749 
OGR_L_GetGeomType(OGRLayerH hLayer)1750 OGRwkbGeometryType OGR_L_GetGeomType( OGRLayerH hLayer )
1751 
1752 {
1753     VALIDATE_POINTER1( hLayer, "OGR_L_GetGeomType", wkbUnknown );
1754 
1755 #ifdef OGRAPISPY_ENABLED
1756     if( bOGRAPISpyEnabled )
1757         OGRAPISpy_L_GetGeomType(hLayer);
1758 #endif
1759 
1760     OGRwkbGeometryType eType = ((OGRLayer *) hLayer)->GetGeomType();
1761     if( OGR_GT_IsNonLinear(eType) && !OGRGetNonLinearGeometriesEnabledFlag() )
1762     {
1763         eType = OGR_GT_GetLinear(eType);
1764     }
1765     return eType;
1766 }
1767 
1768 /************************************************************************/
1769 /*                          SetIgnoredFields()                          */
1770 /************************************************************************/
1771 
SetIgnoredFields(const char ** papszFields)1772 OGRErr OGRLayer::SetIgnoredFields( const char **papszFields )
1773 {
1774     OGRFeatureDefn *poDefn = GetLayerDefn();
1775 
1776     // first set everything as *not* ignored
1777     for( int iField = 0; iField < poDefn->GetFieldCount(); iField++ )
1778     {
1779         poDefn->GetFieldDefn(iField)->SetIgnored( FALSE );
1780     }
1781     poDefn->SetGeometryIgnored( FALSE );
1782     poDefn->SetStyleIgnored( FALSE );
1783 
1784     if ( papszFields == NULL )
1785         return OGRERR_NONE;
1786 
1787     // ignore some fields
1788     while ( *papszFields )
1789     {
1790         const char* pszFieldName = *papszFields;
1791         // check special fields
1792         if ( EQUAL(pszFieldName, "OGR_GEOMETRY") )
1793             poDefn->SetGeometryIgnored( TRUE );
1794         else if ( EQUAL(pszFieldName, "OGR_STYLE") )
1795             poDefn->SetStyleIgnored( TRUE );
1796         else
1797         {
1798             // check ordinary fields
1799             int iField = poDefn->GetFieldIndex(pszFieldName);
1800             if ( iField == -1 )
1801             {
1802                 // check geometry field
1803                 iField = poDefn->GetGeomFieldIndex(pszFieldName);
1804                 if ( iField == -1 )
1805                 {
1806                     return OGRERR_FAILURE;
1807                 }
1808                 else
1809                     poDefn->GetGeomFieldDefn(iField)->SetIgnored( TRUE );
1810             }
1811             else
1812                 poDefn->GetFieldDefn(iField)->SetIgnored( TRUE );
1813         }
1814         papszFields++;
1815     }
1816 
1817     return OGRERR_NONE;
1818 }
1819 
1820 /************************************************************************/
1821 /*                       OGR_L_SetIgnoredFields()                       */
1822 /************************************************************************/
1823 
OGR_L_SetIgnoredFields(OGRLayerH hLayer,const char ** papszFields)1824 OGRErr OGR_L_SetIgnoredFields( OGRLayerH hLayer, const char **papszFields )
1825 
1826 {
1827     VALIDATE_POINTER1( hLayer, "OGR_L_SetIgnoredFields", OGRERR_INVALID_HANDLE );
1828 
1829 #ifdef OGRAPISPY_ENABLED
1830     if( bOGRAPISpyEnabled )
1831         OGRAPISpy_L_SetIgnoredFields(hLayer, papszFields);
1832 #endif
1833 
1834     return ((OGRLayer *) hLayer)->SetIgnoredFields( papszFields );
1835 }
1836 
1837 /************************************************************************/
1838 /*         helper functions for layer overlay methods                   */
1839 /************************************************************************/
1840 
1841 static
clone_spatial_filter(OGRLayer * pLayer,OGRGeometry ** ppGeometry)1842 OGRErr clone_spatial_filter(OGRLayer *pLayer, OGRGeometry **ppGeometry)
1843 {
1844     OGRErr ret = OGRERR_NONE;
1845     OGRGeometry *g = pLayer->GetSpatialFilter();
1846     *ppGeometry = g ? g->clone() : NULL;
1847     return ret;
1848 }
1849 
1850 static
create_field_map(OGRFeatureDefn * poDefn,int ** map)1851 OGRErr create_field_map(OGRFeatureDefn *poDefn, int **map)
1852 {
1853     OGRErr ret = OGRERR_NONE;
1854     int n = poDefn->GetFieldCount();
1855     if (n > 0) {
1856         *map = (int*)VSIMalloc(sizeof(int) * n);
1857         if (!(*map)) return OGRERR_NOT_ENOUGH_MEMORY;
1858         for(int i=0;i<n;i++)
1859             (*map)[i] = -1;
1860     }
1861     return ret;
1862 }
1863 
1864 static
set_result_schema(OGRLayer * pLayerResult,OGRFeatureDefn * poDefnInput,OGRFeatureDefn * poDefnMethod,int * mapInput,int * mapMethod,int combined,char ** papszOptions)1865 OGRErr set_result_schema(OGRLayer *pLayerResult,
1866                          OGRFeatureDefn *poDefnInput,
1867                          OGRFeatureDefn *poDefnMethod,
1868                          int *mapInput,
1869                          int *mapMethod,
1870                          int combined,
1871                          char** papszOptions)
1872 {
1873     OGRErr ret = OGRERR_NONE;
1874     OGRFeatureDefn *poDefnResult = pLayerResult->GetLayerDefn();
1875     const char* pszInputPrefix = CSLFetchNameValue(papszOptions, "INPUT_PREFIX");
1876     const char* pszMethodPrefix = CSLFetchNameValue(papszOptions, "METHOD_PREFIX");
1877     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
1878     if (poDefnResult->GetFieldCount() > 0) {
1879         // the user has defined the schema of the output layer
1880         for( int iField = 0; iField < poDefnInput->GetFieldCount(); iField++ ) {
1881             CPLString osName(poDefnInput->GetFieldDefn(iField)->GetNameRef());
1882             if( pszInputPrefix != NULL )
1883                 osName = pszInputPrefix + osName;
1884             mapInput[iField] = poDefnResult->GetFieldIndex(osName);
1885         }
1886         if (!mapMethod) return ret;
1887         for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
1888             CPLString osName(poDefnMethod->GetFieldDefn(iField)->GetNameRef());
1889             if( pszMethodPrefix != NULL )
1890                 osName = pszMethodPrefix + osName;
1891             mapMethod[iField] = poDefnResult->GetFieldIndex(osName);
1892         }
1893     } else {
1894         // use schema from the input layer or from input and method layers
1895         int nFieldsInput = poDefnInput->GetFieldCount();
1896         for( int iField = 0; iField < nFieldsInput; iField++ ) {
1897             OGRFieldDefn oFieldDefn(poDefnInput->GetFieldDefn(iField));
1898             if( pszInputPrefix != NULL )
1899                 oFieldDefn.SetName(CPLSPrintf("%s%s", pszInputPrefix, oFieldDefn.GetNameRef()));
1900             ret = pLayerResult->CreateField(&oFieldDefn);
1901             if (ret != OGRERR_NONE) {
1902                 if (!bSkipFailures)
1903                     return ret;
1904                 else {
1905                     CPLErrorReset();
1906                     ret = OGRERR_NONE;
1907                 }
1908             }
1909             mapInput[iField] = iField;
1910         }
1911         if (!combined) return ret;
1912         if (!mapMethod) return ret;
1913         for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
1914             OGRFieldDefn oFieldDefn(poDefnMethod->GetFieldDefn(iField));
1915             if( pszMethodPrefix != NULL )
1916                 oFieldDefn.SetName(CPLSPrintf("%s%s", pszMethodPrefix, oFieldDefn.GetNameRef()));
1917             ret = pLayerResult->CreateField(&oFieldDefn);
1918             if (ret != OGRERR_NONE) {
1919                 if (!bSkipFailures)
1920                     return ret;
1921                 else {
1922                     CPLErrorReset();
1923                     ret = OGRERR_NONE;
1924                 }
1925             }
1926             mapMethod[iField] = nFieldsInput+iField;
1927         }
1928     }
1929     return ret;
1930 }
1931 
1932 static
set_filter_from(OGRLayer * pLayer,OGRGeometry * pGeometryExistingFilter,OGRFeature * pFeature)1933 OGRGeometry *set_filter_from(OGRLayer *pLayer, OGRGeometry *pGeometryExistingFilter, OGRFeature *pFeature)
1934 {
1935     OGRGeometry *geom = pFeature->GetGeometryRef();
1936     if (!geom) return NULL;
1937     if (pGeometryExistingFilter) {
1938         if (!geom->Intersects(pGeometryExistingFilter)) return NULL;
1939         OGRGeometry *intersection = geom->Intersection(pGeometryExistingFilter);
1940         pLayer->SetSpatialFilter(intersection);
1941         if (intersection) delete intersection;
1942     } else {
1943         pLayer->SetSpatialFilter(geom);
1944     }
1945     return geom;
1946 }
1947 
promote_to_multi(OGRGeometry * poGeom)1948 static OGRGeometry* promote_to_multi(OGRGeometry* poGeom)
1949 {
1950     OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
1951     if( eType == wkbPolygon )
1952         return OGRGeometryFactory::forceToMultiPolygon(poGeom);
1953     else if( eType == wkbLineString )
1954         return OGRGeometryFactory::forceToMultiLineString(poGeom);
1955     else
1956         return poGeom;
1957 }
1958 
1959 /************************************************************************/
1960 /*                          Intersection()                              */
1961 /************************************************************************/
1962 /**
1963  * \brief Intersection of two layers.
1964  *
1965  * The result layer contains features whose geometries represent areas
1966  * that are common between features in the input layer and in the
1967  * method layer. The features in the result layer have attributes from
1968  * both input and method layers. The schema of the result layer can be
1969  * set by the user or, if it is empty, is initialized to contain all
1970  * fields in the input and method layers.
1971  *
1972  * \note If the schema of the result is set by user and contains
1973  * fields that have the same name as a field in input and in method
1974  * layer, then the attribute in the result feature will get the value
1975  * from the feature of the method layer.
1976  *
1977  * \note For best performance use the minimum amount of features in
1978  * the method layer and copy it into a memory layer.
1979  *
1980  * \note This method relies on GEOS support. Do not use unless the
1981  * GEOS support is compiled in.
1982  *
1983  * The recognized list of options is :
1984  * <ul>
1985  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
1986  *     feature could not be inserted.
1987  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
1988  *     into MultiPolygons, or LineStrings to MultiLineStrings.
1989  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
1990  *     will be created from the fields of the input layer.
1991  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
1992  *     will be created from the fields of the method layer.
1993  * </ul>
1994  *
1995  * This method is the same as the C function OGR_L_Intersection().
1996  *
1997  * @param pLayerMethod the method layer. Should not be NULL.
1998  *
1999  * @param pLayerResult the layer where the features resulting from the
2000  * operation are inserted. Should not be NULL. See above the note
2001  * about the schema.
2002  *
2003  * @param papszOptions NULL terminated list of options (may be NULL).
2004  *
2005  * @param pfnProgress a GDALProgressFunc() compatible callback function for
2006  * reporting progress or NULL.
2007  *
2008  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2009  *
2010  * @return an error code if there was an error or the execution was
2011  * interrupted, OGRERR_NONE otherwise.
2012  *
2013  * @since OGR 1.10
2014  */
2015 
Intersection(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2016 OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod,
2017                                OGRLayer *pLayerResult,
2018                                char** papszOptions,
2019                                GDALProgressFunc pfnProgress,
2020                                void * pProgressArg )
2021 {
2022     OGRErr ret = OGRERR_NONE;
2023     OGRFeatureDefn *poDefnInput = GetLayerDefn();
2024     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2025     OGRFeatureDefn *poDefnResult = NULL;
2026     OGRGeometry *pGeometryMethodFilter = NULL;
2027     int *mapInput = NULL;
2028     int *mapMethod = NULL;
2029     OGREnvelope sEnvelopeMethod;
2030     GBool bEnvelopeSet;
2031     double progress_max = (double) GetFeatureCount(0);
2032     double progress_counter = 0;
2033     double progress_ticker = 0;
2034     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
2035     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
2036 
2037     // check for GEOS
2038     if (!OGRGeometryFactory::haveGEOS()) {
2039         return OGRERR_UNSUPPORTED_OPERATION;
2040     }
2041 
2042     // get resources
2043     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2044     if (ret != OGRERR_NONE) goto done;
2045     ret = create_field_map(poDefnInput, &mapInput);
2046     if (ret != OGRERR_NONE) goto done;
2047     ret = create_field_map(poDefnMethod, &mapMethod);
2048     if (ret != OGRERR_NONE) goto done;
2049     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
2050     if (ret != OGRERR_NONE) goto done;
2051     poDefnResult = pLayerResult->GetLayerDefn();
2052     bEnvelopeSet = pLayerMethod->GetExtent(&sEnvelopeMethod, 1) == OGRERR_NONE;
2053 
2054     ResetReading();
2055     while (OGRFeature *x = GetNextFeature()) {
2056 
2057         if (pfnProgress) {
2058             double p = progress_counter/progress_max;
2059             if (p > progress_ticker) {
2060                 if (!pfnProgress(p, "", pProgressArg)) {
2061                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2062                     ret = OGRERR_FAILURE;
2063                     delete x;
2064                     goto done;
2065                 }
2066             }
2067             progress_counter += 1.0;
2068         }
2069 
2070         // is it worth to proceed?
2071         if (bEnvelopeSet) {
2072             OGRGeometry *x_geom = x->GetGeometryRef();
2073             if (x_geom) {
2074                 OGREnvelope x_env;
2075                 x_geom->getEnvelope(&x_env);
2076                 if (x_env.MaxX < sEnvelopeMethod.MinX
2077                     || x_env.MaxY < sEnvelopeMethod.MinY
2078                     || sEnvelopeMethod.MaxX < x_env.MinX
2079                     || sEnvelopeMethod.MaxY < x_env.MinY) {
2080                     delete x;
2081                     continue;
2082                 }
2083             } else {
2084                 delete x;
2085                 continue;
2086             }
2087         }
2088 
2089         // set up the filter for method layer
2090         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2091         if (!x_geom) {
2092             delete x;
2093             continue;
2094         }
2095 
2096         pLayerMethod->ResetReading();
2097         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2098             OGRGeometry *y_geom = y->GetGeometryRef();
2099             if (!y_geom) {delete y; continue;}
2100             OGRGeometry* poIntersection = x_geom->Intersection(y_geom);
2101             if( poIntersection == NULL || poIntersection->IsEmpty() ||
2102                 (x_geom->getDimension() == 2 &&
2103                 y_geom->getDimension() == 2 &&
2104                 poIntersection->getDimension() < 2) )
2105             {
2106                 delete poIntersection;
2107                 delete y;
2108             }
2109             else
2110             {
2111                 OGRFeature *z = new OGRFeature(poDefnResult);
2112                 z->SetFieldsFrom(x, mapInput);
2113                 z->SetFieldsFrom(y, mapMethod);
2114                 if( bPromoteToMulti )
2115                     poIntersection = promote_to_multi(poIntersection);
2116                 z->SetGeometryDirectly(poIntersection);
2117                 delete y;
2118                 ret = pLayerResult->CreateFeature(z);
2119                 delete z;
2120                 if (ret != OGRERR_NONE) {
2121                     if (!bSkipFailures) {
2122                         delete x;
2123                         goto done;
2124                     } else {
2125                         CPLErrorReset();
2126                         ret = OGRERR_NONE;
2127                     }
2128                 }
2129             }
2130         }
2131 
2132         delete x;
2133     }
2134     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
2135       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2136       ret = OGRERR_FAILURE;
2137       goto done;
2138     }
2139 done:
2140     // release resources
2141     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2142     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
2143     if (mapInput) VSIFree(mapInput);
2144     if (mapMethod) VSIFree(mapMethod);
2145     return ret;
2146 }
2147 
2148 /************************************************************************/
2149 /*                       OGR_L_Intersection()                           */
2150 /************************************************************************/
2151 /**
2152  * \brief Intersection of two layers.
2153  *
2154  * The result layer contains features whose geometries represent areas
2155  * that are common between features in the input layer and in the
2156  * method layer. The features in the result layer have attributes from
2157  * both input and method layers. The schema of the result layer can be
2158  * set by the user or, if it is empty, is initialized to contain all
2159  * fields in the input and method layers.
2160  *
2161  * \note If the schema of the result is set by user and contains
2162  * fields that have the same name as a field in input and in method
2163  * layer, then the attribute in the result feature will get the value
2164  * from the feature of the method layer.
2165  *
2166  * \note For best performance use the minimum amount of features in
2167  * the method layer and copy it into a memory layer.
2168  *
2169  * \note This method relies on GEOS support. Do not use unless the
2170  * GEOS support is compiled in.
2171  *
2172  * The recognized list of options is :
2173  * <ul>
2174  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2175  *     feature could not be inserted.
2176  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2177  *     into MultiPolygons, or LineStrings to MultiLineStrings.
2178  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2179  *     will be created from the fields of the input layer.
2180  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2181  *     will be created from the fields of the method layer.
2182  * </ul>
2183  *
2184  * This function is the same as the C++ method OGRLayer::Intersection().
2185  *
2186  * @param pLayerInput the input layer. Should not be NULL.
2187  *
2188  * @param pLayerMethod the method layer. Should not be NULL.
2189  *
2190  * @param pLayerResult the layer where the features resulting from the
2191  * operation are inserted. Should not be NULL. See above the note
2192  * about the schema.
2193  *
2194  * @param papszOptions NULL terminated list of options (may be NULL).
2195  *
2196  * @param pfnProgress a GDALProgressFunc() compatible callback function for
2197  * reporting progress or NULL.
2198  *
2199  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2200  *
2201  * @return an error code if there was an error or the execution was
2202  * interrupted, OGRERR_NONE otherwise.
2203  *
2204  * @since OGR 1.10
2205  */
2206 
OGR_L_Intersection(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2207 OGRErr OGR_L_Intersection( OGRLayerH pLayerInput,
2208                            OGRLayerH pLayerMethod,
2209                            OGRLayerH pLayerResult,
2210                            char** papszOptions,
2211                            GDALProgressFunc pfnProgress,
2212                            void * pProgressArg )
2213 
2214 {
2215     VALIDATE_POINTER1( pLayerInput, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
2216     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
2217     VALIDATE_POINTER1( pLayerResult, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
2218 
2219     return ((OGRLayer *)pLayerInput)->Intersection( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
2220 }
2221 
2222 /************************************************************************/
2223 /*                              Union()                                 */
2224 /************************************************************************/
2225 
2226 /**
2227  * \brief Union of two layers.
2228  *
2229  * The result layer contains features whose geometries represent areas
2230  * that are in either in the input layer or in the method layer. The
2231  * features in the result layer have attributes from both input and
2232  * method layers. For features which represent areas that are only in
2233  * the input or in the method layer the respective attributes have
2234  * undefined values. The schema of the result layer can be set by the
2235  * user or, if it is empty, is initialized to contain all fields in
2236  * the input and method layers.
2237  *
2238  * \note If the schema of the result is set by user and contains
2239  * fields that have the same name as a field in input and in method
2240  * layer, then the attribute in the result feature will get the value
2241  * from the feature of the method layer (even if it is undefined).
2242  *
2243  * \note For best performance use the minimum amount of features in
2244  * the method layer and copy it into a memory layer.
2245  *
2246  * \note This method relies on GEOS support. Do not use unless the
2247  * GEOS support is compiled in.
2248  *
2249  * The recognized list of options is :
2250  * <ul>
2251  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2252  *     feature could not be inserted.
2253  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2254  *     into MultiPolygons, or LineStrings to MultiLineStrings.
2255  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2256  *     will be created from the fields of the input layer.
2257  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2258  *     will be created from the fields of the method layer.
2259  * </ul>
2260  *
2261  * This method is the same as the C function OGR_L_Union().
2262  *
2263  * @param pLayerMethod the method layer. Should not be NULL.
2264  *
2265  * @param pLayerResult the layer where the features resulting from the
2266  * operation are inserted. Should not be NULL. See above the note
2267  * about the schema.
2268  *
2269  * @param papszOptions NULL terminated list of options (may be NULL).
2270  *
2271  * @param pfnProgress a GDALProgressFunc() compatible callback function for
2272  * reporting progress or NULL.
2273  *
2274  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2275  *
2276  * @return an error code if there was an error or the execution was
2277  * interrupted, OGRERR_NONE otherwise.
2278  *
2279  * @since OGR 1.10
2280  */
2281 
Union(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2282 OGRErr OGRLayer::Union( OGRLayer *pLayerMethod,
2283                         OGRLayer *pLayerResult,
2284                         char** papszOptions,
2285                         GDALProgressFunc pfnProgress,
2286                         void * pProgressArg )
2287 {
2288     OGRErr ret = OGRERR_NONE;
2289     OGRFeatureDefn *poDefnInput = GetLayerDefn();
2290     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2291     OGRFeatureDefn *poDefnResult = NULL;
2292     OGRGeometry *pGeometryMethodFilter = NULL;
2293     OGRGeometry *pGeometryInputFilter = NULL;
2294     int *mapInput = NULL;
2295     int *mapMethod = NULL;
2296     double progress_max = (double) GetFeatureCount(0) + (double) pLayerMethod->GetFeatureCount(0);
2297     double progress_counter = 0;
2298     double progress_ticker = 0;
2299     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
2300     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
2301 
2302     // check for GEOS
2303     if (!OGRGeometryFactory::haveGEOS()) {
2304         return OGRERR_UNSUPPORTED_OPERATION;
2305     }
2306 
2307     // get resources
2308     ret = clone_spatial_filter(this, &pGeometryInputFilter);
2309     if (ret != OGRERR_NONE) goto done;
2310     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2311     if (ret != OGRERR_NONE) goto done;
2312     ret = create_field_map(poDefnInput, &mapInput);
2313     if (ret != OGRERR_NONE) goto done;
2314     ret = create_field_map(poDefnMethod, &mapMethod);
2315     if (ret != OGRERR_NONE) goto done;
2316     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
2317     if (ret != OGRERR_NONE) goto done;
2318     poDefnResult = pLayerResult->GetLayerDefn();
2319 
2320     // add features based on input layer
2321     ResetReading();
2322     while (OGRFeature *x = GetNextFeature()) {
2323 
2324         if (pfnProgress) {
2325             double p = progress_counter/progress_max;
2326             if (p > progress_ticker) {
2327                 if (!pfnProgress(p, "", pProgressArg)) {
2328                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2329                     ret = OGRERR_FAILURE;
2330                     delete x;
2331                     goto done;
2332                 }
2333             }
2334             progress_counter += 1.0;
2335         }
2336 
2337         // set up the filter on method layer
2338         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2339         if (!x_geom) {
2340             delete x;
2341             continue;
2342         }
2343 
2344         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
2345         pLayerMethod->ResetReading();
2346         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2347             OGRGeometry *y_geom = y->GetGeometryRef();
2348             if (!y_geom) {delete y; continue;}
2349             OGRGeometry *poIntersection = x_geom->Intersection(y_geom);
2350             if( poIntersection == NULL || poIntersection->IsEmpty() ||
2351                 (x_geom->getDimension() == 2 &&
2352                 y_geom->getDimension() == 2 &&
2353                 poIntersection->getDimension() < 2) )
2354             {
2355                 delete poIntersection;
2356                 delete y;
2357             }
2358             else
2359             {
2360                 OGRFeature *z = new OGRFeature(poDefnResult);
2361                 z->SetFieldsFrom(x, mapInput);
2362                 z->SetFieldsFrom(y, mapMethod);
2363                 if( bPromoteToMulti )
2364                     poIntersection = promote_to_multi(poIntersection);
2365                 z->SetGeometryDirectly(poIntersection);
2366                 OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
2367                 if (x_geom_diff) delete x_geom_diff;
2368                 x_geom_diff = x_geom_diff_new;
2369                 delete y;
2370                 ret = pLayerResult->CreateFeature(z);
2371                 delete z;
2372                 if (ret != OGRERR_NONE) {
2373                     if (!bSkipFailures) {
2374                         delete x;
2375                         if (x_geom_diff)
2376                             delete x_geom_diff;
2377                         goto done;
2378                     } else {
2379                         CPLErrorReset();
2380                         ret = OGRERR_NONE;
2381                     }
2382                 }
2383             }
2384         }
2385 
2386         if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
2387         {
2388             delete x_geom_diff;
2389             delete x;
2390         }
2391         else
2392         {
2393             OGRFeature *z = new OGRFeature(poDefnResult);
2394             z->SetFieldsFrom(x, mapInput);
2395             if( bPromoteToMulti )
2396                 x_geom_diff = promote_to_multi(x_geom_diff);
2397             z->SetGeometryDirectly(x_geom_diff);
2398             delete x;
2399             ret = pLayerResult->CreateFeature(z);
2400             delete z;
2401             if (ret != OGRERR_NONE) {
2402                 if (!bSkipFailures) {
2403                     goto done;
2404                 } else {
2405                     CPLErrorReset();
2406                     ret = OGRERR_NONE;
2407                 }
2408             }
2409         }
2410     }
2411 
2412     // restore filter on method layer and add features based on it
2413     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2414     pLayerMethod->ResetReading();
2415     while (OGRFeature *x = pLayerMethod->GetNextFeature()) {
2416 
2417         if (pfnProgress) {
2418             double p = progress_counter/progress_max;
2419             if (p > progress_ticker) {
2420                 if (!pfnProgress(p, "", pProgressArg)) {
2421                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2422                     ret = OGRERR_FAILURE;
2423                     delete x;
2424                     goto done;
2425                 }
2426             }
2427             progress_counter += 1.0;
2428         }
2429 
2430         // set up the filter on input layer
2431         OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
2432         if (!x_geom) {
2433             delete x;
2434             continue;
2435         }
2436 
2437         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
2438         ResetReading();
2439         while (OGRFeature *y = GetNextFeature()) {
2440             OGRGeometry *y_geom = y->GetGeometryRef();
2441             if (!y_geom) {delete y; continue;}
2442             OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
2443             if (x_geom_diff) delete x_geom_diff;
2444             x_geom_diff = x_geom_diff_new;
2445             delete y;
2446         }
2447 
2448         if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
2449         {
2450             delete x_geom_diff;
2451             delete x;
2452         }
2453         else
2454         {
2455             OGRFeature *z = new OGRFeature(poDefnResult);
2456             z->SetFieldsFrom(x, mapMethod);
2457             if( bPromoteToMulti )
2458                 x_geom_diff = promote_to_multi(x_geom_diff);
2459             z->SetGeometryDirectly(x_geom_diff);
2460             delete x;
2461             ret = pLayerResult->CreateFeature(z);
2462             delete z;
2463             if (ret != OGRERR_NONE) {
2464                 if (!bSkipFailures) {
2465                     goto done;
2466                 } else {
2467                     CPLErrorReset();
2468                     ret = OGRERR_NONE;
2469                 }
2470             }
2471         }
2472     }
2473     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
2474       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2475       ret = OGRERR_FAILURE;
2476       goto done;
2477     }
2478 done:
2479     // release resources
2480     SetSpatialFilter(pGeometryInputFilter);
2481     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2482     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
2483     if (pGeometryInputFilter) delete pGeometryInputFilter;
2484     if (mapInput) VSIFree(mapInput);
2485     if (mapMethod) VSIFree(mapMethod);
2486     return ret;
2487 }
2488 
2489 /************************************************************************/
2490 /*                           OGR_L_Union()                              */
2491 /************************************************************************/
2492 
2493 /**
2494  * \brief Union of two layers.
2495  *
2496  * The result layer contains features whose geometries represent areas
2497  * that are in either in the input layer or in the method layer. The
2498  * features in the result layer have attributes from both input and
2499  * method layers. For features which represent areas that are only in
2500  * the input or in the method layer the respective attributes have
2501  * undefined values. The schema of the result layer can be set by the
2502  * user or, if it is empty, is initialized to contain all fields in
2503  * the input and method layers.
2504  *
2505  * \note If the schema of the result is set by user and contains
2506  * fields that have the same name as a field in input and in method
2507  * layer, then the attribute in the result feature will get the value
2508  * from the feature of the method layer (even if it is undefined).
2509  *
2510  * \note For best performance use the minimum amount of features in
2511  * the method layer and copy it into a memory layer.
2512  *
2513  * \note This method relies on GEOS support. Do not use unless the
2514  * GEOS support is compiled in.
2515  *
2516  * The recognized list of options is :
2517  * <ul>
2518  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2519  *     feature could not be inserted.
2520  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2521  *     into MultiPolygons, or LineStrings to MultiLineStrings.
2522  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2523  *     will be created from the fields of the input layer.
2524  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2525  *     will be created from the fields of the method layer.
2526  * </ul>
2527  *
2528  * This function is the same as the C++ method OGRLayer::Union().
2529  *
2530  * @param pLayerInput the input layer. Should not be NULL.
2531  *
2532  * @param pLayerMethod the method layer. Should not be NULL.
2533  *
2534  * @param pLayerResult the layer where the features resulting from the
2535  * operation are inserted. Should not be NULL. See above the note
2536  * about the schema.
2537  *
2538  * @param papszOptions NULL terminated list of options (may be NULL).
2539  *
2540  * @param pfnProgress a GDALProgressFunc() compatible callback function for
2541  * reporting progress or NULL.
2542  *
2543  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2544  *
2545  * @return an error code if there was an error or the execution was
2546  * interrupted, OGRERR_NONE otherwise.
2547  *
2548  * @since OGR 1.10
2549  */
2550 
OGR_L_Union(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2551 OGRErr OGR_L_Union( OGRLayerH pLayerInput,
2552                     OGRLayerH pLayerMethod,
2553                     OGRLayerH pLayerResult,
2554                     char** papszOptions,
2555                     GDALProgressFunc pfnProgress,
2556                     void * pProgressArg )
2557 
2558 {
2559     VALIDATE_POINTER1( pLayerInput, "OGR_L_Union", OGRERR_INVALID_HANDLE );
2560     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Union", OGRERR_INVALID_HANDLE );
2561     VALIDATE_POINTER1( pLayerResult, "OGR_L_Union", OGRERR_INVALID_HANDLE );
2562 
2563     return ((OGRLayer *)pLayerInput)->Union( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
2564 }
2565 
2566 /************************************************************************/
2567 /*                          SymDifference()                             */
2568 /************************************************************************/
2569 
2570 /**
2571  * \brief Symmetrical difference of two layers.
2572  *
2573  * The result layer contains features whose geometries represent areas
2574  * that are in either in the input layer or in the method layer but
2575  * not in both. The features in the result layer have attributes from
2576  * both input and method layers. For features which represent areas
2577  * that are only in the input or in the method layer the respective
2578  * attributes have undefined values. The schema of the result layer
2579  * can be set by the user or, if it is empty, is initialized to
2580  * contain all fields in the input and method layers.
2581  *
2582  * \note If the schema of the result is set by user and contains
2583  * fields that have the same name as a field in input and in method
2584  * layer, then the attribute in the result feature will get the value
2585  * from the feature of the method layer (even if it is undefined).
2586  *
2587  * \note For best performance use the minimum amount of features in
2588  * the method layer and copy it into a memory layer.
2589  *
2590  * \note This method relies on GEOS support. Do not use unless the
2591  * GEOS support is compiled in.
2592  *
2593  * The recognized list of options is :
2594  * <ul>
2595  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2596  *     feature could not be inserted.
2597  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2598  *     into MultiPolygons, or LineStrings to MultiLineStrings.
2599  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2600  *     will be created from the fields of the input layer.
2601  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2602  *     will be created from the fields of the method layer.
2603  * </ul>
2604  *
2605  * This method is the same as the C function OGR_L_SymDifference().
2606  *
2607  * @param pLayerMethod the method layer. Should not be NULL.
2608  *
2609  * @param pLayerResult the layer where the features resulting from the
2610  * operation are inserted. Should not be NULL. See above the note
2611  * about the schema.
2612  *
2613  * @param papszOptions NULL terminated list of options (may be NULL).
2614  *
2615  * @param pfnProgress a GDALProgressFunc() compatible callback function for
2616  * reporting progress or NULL.
2617  *
2618  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2619  *
2620  * @return an error code if there was an error or the execution was
2621  * interrupted, OGRERR_NONE otherwise.
2622  *
2623  * @since OGR 1.10
2624  */
2625 
SymDifference(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2626 OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod,
2627                                 OGRLayer *pLayerResult,
2628                                 char** papszOptions,
2629                                 GDALProgressFunc pfnProgress,
2630                                 void * pProgressArg )
2631 {
2632     OGRErr ret = OGRERR_NONE;
2633     OGRFeatureDefn *poDefnInput = GetLayerDefn();
2634     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2635     OGRFeatureDefn *poDefnResult = NULL;
2636     OGRGeometry *pGeometryMethodFilter = NULL;
2637     OGRGeometry *pGeometryInputFilter = NULL;
2638     int *mapInput = NULL;
2639     int *mapMethod = NULL;
2640     double progress_max = (double) GetFeatureCount(0) + (double) pLayerMethod->GetFeatureCount(0);
2641     double progress_counter = 0;
2642     double progress_ticker = 0;
2643     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
2644     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
2645 
2646     // check for GEOS
2647     if (!OGRGeometryFactory::haveGEOS()) {
2648         return OGRERR_UNSUPPORTED_OPERATION;
2649     }
2650 
2651     // get resources
2652     ret = clone_spatial_filter(this, &pGeometryInputFilter);
2653     if (ret != OGRERR_NONE) goto done;
2654     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2655     if (ret != OGRERR_NONE) goto done;
2656     ret = create_field_map(poDefnInput, &mapInput);
2657     if (ret != OGRERR_NONE) goto done;
2658     ret = create_field_map(poDefnMethod, &mapMethod);
2659     if (ret != OGRERR_NONE) goto done;
2660     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
2661     if (ret != OGRERR_NONE) goto done;
2662     poDefnResult = pLayerResult->GetLayerDefn();
2663 
2664     // add features based on input layer
2665     ResetReading();
2666     while (OGRFeature *x = GetNextFeature()) {
2667 
2668         if (pfnProgress) {
2669             double p = progress_counter/progress_max;
2670             if (p > progress_ticker) {
2671                 if (!pfnProgress(p, "", pProgressArg)) {
2672                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2673                     ret = OGRERR_FAILURE;
2674                     delete x;
2675                     goto done;
2676                 }
2677             }
2678             progress_counter += 1.0;
2679         }
2680 
2681         // set up the filter on method layer
2682         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2683         if (!x_geom) {
2684             delete x;
2685             continue;
2686         }
2687 
2688         OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
2689         pLayerMethod->ResetReading();
2690         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2691             OGRGeometry *y_geom = y->GetGeometryRef();
2692             if (!y_geom) {delete y; continue;}
2693             OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
2694             if (geom) delete geom;
2695             geom = geom_new;
2696             delete y;
2697             if (geom && geom->IsEmpty()) break;
2698         }
2699 
2700         OGRFeature *z = NULL;
2701         if (geom && !geom->IsEmpty()) {
2702             z = new OGRFeature(poDefnResult);
2703             z->SetFieldsFrom(x, mapInput);
2704             if( bPromoteToMulti )
2705                 geom = promote_to_multi(geom);
2706             z->SetGeometryDirectly(geom);
2707         } else {
2708             if (geom) delete geom;
2709         }
2710         delete x;
2711         if (z) {
2712             ret = pLayerResult->CreateFeature(z);
2713             delete z;
2714             if (ret != OGRERR_NONE) {
2715                 if (!bSkipFailures) {
2716                     goto done;
2717                 } else {
2718                     CPLErrorReset();
2719                     ret = OGRERR_NONE;
2720                 }
2721             }
2722         }
2723     }
2724 
2725     // restore filter on method layer and add features based on it
2726     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2727     pLayerMethod->ResetReading();
2728     while (OGRFeature *x = pLayerMethod->GetNextFeature()) {
2729 
2730         if (pfnProgress) {
2731             double p = progress_counter/progress_max;
2732             if (p > progress_ticker) {
2733                 if (!pfnProgress(p, "", pProgressArg)) {
2734                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2735                     ret = OGRERR_FAILURE;
2736                     delete x;
2737                     goto done;
2738                 }
2739             }
2740             progress_counter += 1.0;
2741         }
2742 
2743         // set up the filter on input layer
2744         OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
2745         if (!x_geom) {
2746             delete x;
2747             continue;
2748         }
2749 
2750         OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
2751         ResetReading();
2752         while (OGRFeature *y = GetNextFeature()) {
2753             OGRGeometry *y_geom = y->GetGeometryRef();
2754             if (!y_geom) {delete y; continue;}
2755             OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
2756             if (geom) delete geom;
2757             geom = geom_new;
2758             delete y;
2759             if (geom == NULL || geom->IsEmpty()) break;
2760         }
2761 
2762         OGRFeature *z = NULL;
2763         if (geom && !geom->IsEmpty()) {
2764             z = new OGRFeature(poDefnResult);
2765             z->SetFieldsFrom(x, mapMethod);
2766             if( bPromoteToMulti )
2767                 geom = promote_to_multi(geom);
2768             z->SetGeometryDirectly(geom);
2769         } else {
2770             if (geom) delete geom;
2771         }
2772         delete x;
2773         if (z) {
2774             ret = pLayerResult->CreateFeature(z);
2775             delete z;
2776             if (ret != OGRERR_NONE) {
2777                 if (!bSkipFailures) {
2778                     goto done;
2779                 } else {
2780                     CPLErrorReset();
2781                     ret = OGRERR_NONE;
2782                 }
2783             }
2784         }
2785     }
2786     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
2787       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2788       ret = OGRERR_FAILURE;
2789       goto done;
2790     }
2791 done:
2792     // release resources
2793     SetSpatialFilter(pGeometryInputFilter);
2794     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
2795     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
2796     if (pGeometryInputFilter) delete pGeometryInputFilter;
2797     if (mapInput) VSIFree(mapInput);
2798     if (mapMethod) VSIFree(mapMethod);
2799     return ret;
2800 }
2801 
2802 /************************************************************************/
2803 /*                        OGR_L_SymDifference()                         */
2804 /************************************************************************/
2805 
2806 /**
2807  * \brief Symmetrical difference of two layers.
2808  *
2809  * The result layer contains features whose geometries represent areas
2810  * that are in either in the input layer or in the method layer but
2811  * not in both. The features in the result layer have attributes from
2812  * both input and method layers. For features which represent areas
2813  * that are only in the input or in the method layer the respective
2814  * attributes have undefined values. The schema of the result layer
2815  * can be set by the user or, if it is empty, is initialized to
2816  * contain all fields in the input and method layers.
2817  *
2818  * \note If the schema of the result is set by user and contains
2819  * fields that have the same name as a field in input and in method
2820  * layer, then the attribute in the result feature will get the value
2821  * from the feature of the method layer (even if it is undefined).
2822  *
2823  * \note For best performance use the minimum amount of features in
2824  * the method layer and copy it into a memory layer.
2825  *
2826  * \note This method relies on GEOS support. Do not use unless the
2827  * GEOS support is compiled in.
2828  *
2829  * The recognized list of options is :
2830  * <ul>
2831  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2832  *     feature could not be inserted.
2833  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2834  *     into MultiPolygons, or LineStrings to MultiLineStrings.
2835  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2836  *     will be created from the fields of the input layer.
2837  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2838  *     will be created from the fields of the method layer.
2839  * </ul>
2840  *
2841  * This function is the same as the C++ method OGRLayer::SymDifference().
2842  *
2843  * @param pLayerInput the input layer. Should not be NULL.
2844  *
2845  * @param pLayerMethod the method layer. Should not be NULL.
2846  *
2847  * @param pLayerResult the layer where the features resulting from the
2848  * operation are inserted. Should not be NULL. See above the note
2849  * about the schema.
2850  *
2851  * @param papszOptions NULL terminated list of options (may be NULL).
2852  *
2853  * @param pfnProgress a GDALProgressFunc() compatible callback function for
2854  * reporting progress or NULL.
2855  *
2856  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2857  *
2858  * @return an error code if there was an error or the execution was
2859  * interrupted, OGRERR_NONE otherwise.
2860  *
2861  * @since OGR 1.10
2862  */
2863 
OGR_L_SymDifference(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2864 OGRErr OGR_L_SymDifference( OGRLayerH pLayerInput,
2865                             OGRLayerH pLayerMethod,
2866                             OGRLayerH pLayerResult,
2867                             char** papszOptions,
2868                             GDALProgressFunc pfnProgress,
2869                             void * pProgressArg )
2870 
2871 {
2872     VALIDATE_POINTER1( pLayerInput, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
2873     VALIDATE_POINTER1( pLayerMethod, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
2874     VALIDATE_POINTER1( pLayerResult, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
2875 
2876     return ((OGRLayer *)pLayerInput)->SymDifference( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
2877 }
2878 
2879 /************************************************************************/
2880 /*                            Identity()                                */
2881 /************************************************************************/
2882 
2883 /**
2884  * \brief Identify the features of this layer with the ones from the
2885  * identity layer.
2886  *
2887  * The result layer contains features whose geometries represent areas
2888  * that are in the input layer. The features in the result layer have
2889  * attributes from both input and method layers. The schema of the
2890  * result layer can be set by the user or, if it is empty, is
2891  * initialized to contain all fields in input and method layers.
2892  *
2893  * \note If the schema of the result is set by user and contains
2894  * fields that have the same name as a field in input and in method
2895  * layer, then the attribute in the result feature will get the value
2896  * from the feature of the method layer (even if it is undefined).
2897  *
2898  * \note For best performance use the minimum amount of features in
2899  * the method layer and copy it into a memory layer.
2900  *
2901  * \note This method relies on GEOS support. Do not use unless the
2902  * GEOS support is compiled in.
2903  *
2904  * The recognized list of options is :
2905  * <ul>
2906  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
2907  *     feature could not be inserted.
2908  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
2909  *     into MultiPolygons, or LineStrings to MultiLineStrings.
2910  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
2911  *     will be created from the fields of the input layer.
2912  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
2913  *     will be created from the fields of the method layer.
2914  * </ul>
2915  *
2916  * This method is the same as the C function OGR_L_Identity().
2917  *
2918  * @param pLayerMethod the method layer. Should not be NULL.
2919  *
2920  * @param pLayerResult the layer where the features resulting from the
2921  * operation are inserted. Should not be NULL. See above the note
2922  * about the schema.
2923  *
2924  * @param papszOptions NULL terminated list of options (may be NULL).
2925  *
2926  * @param pfnProgress a GDALProgressFunc() compatible callback function for
2927  * reporting progress or NULL.
2928  *
2929  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
2930  *
2931  * @return an error code if there was an error or the execution was
2932  * interrupted, OGRERR_NONE otherwise.
2933  *
2934  * @since OGR 1.10
2935  */
2936 
Identity(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)2937 OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod,
2938                            OGRLayer *pLayerResult,
2939                            char** papszOptions,
2940                            GDALProgressFunc pfnProgress,
2941                            void * pProgressArg )
2942 {
2943     OGRErr ret = OGRERR_NONE;
2944     OGRFeatureDefn *poDefnInput = GetLayerDefn();
2945     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
2946     OGRFeatureDefn *poDefnResult = NULL;
2947     OGRGeometry *pGeometryMethodFilter = NULL;
2948     int *mapInput = NULL;
2949     int *mapMethod = NULL;
2950     double progress_max = (double) GetFeatureCount(0);
2951     double progress_counter = 0;
2952     double progress_ticker = 0;
2953     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
2954     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
2955 
2956     // check for GEOS
2957     if (!OGRGeometryFactory::haveGEOS()) {
2958         return OGRERR_UNSUPPORTED_OPERATION;
2959     }
2960 
2961     // get resources
2962     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
2963     if (ret != OGRERR_NONE) goto done;
2964     ret = create_field_map(poDefnInput, &mapInput);
2965     if (ret != OGRERR_NONE) goto done;
2966     ret = create_field_map(poDefnMethod, &mapMethod);
2967     if (ret != OGRERR_NONE) goto done;
2968     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
2969     if (ret != OGRERR_NONE) goto done;
2970     poDefnResult = pLayerResult->GetLayerDefn();
2971 
2972     // split the features in input layer to the result layer
2973     ResetReading();
2974     while (OGRFeature *x = GetNextFeature()) {
2975 
2976         if (pfnProgress) {
2977             double p = progress_counter/progress_max;
2978             if (p > progress_ticker) {
2979                 if (!pfnProgress(p, "", pProgressArg)) {
2980                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
2981                     ret = OGRERR_FAILURE;
2982                     delete x;
2983                     goto done;
2984                 }
2985             }
2986             progress_counter += 1.0;
2987         }
2988 
2989         // set up the filter on method layer
2990         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
2991         if (!x_geom) {
2992             delete x;
2993             continue;
2994         }
2995 
2996         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
2997         pLayerMethod->ResetReading();
2998         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
2999             OGRGeometry *y_geom = y->GetGeometryRef();
3000             if (!y_geom) {delete y; continue;}
3001             OGRGeometry* poIntersection = x_geom->Intersection(y_geom);
3002             if( poIntersection == NULL || poIntersection->IsEmpty() ||
3003                 (x_geom->getDimension() == 2 &&
3004                 y_geom->getDimension() == 2 &&
3005                 poIntersection->getDimension() < 2) )
3006             {
3007                 delete poIntersection;
3008                 delete y;
3009             }
3010             else
3011             {
3012                 OGRFeature *z = new OGRFeature(poDefnResult);
3013                 z->SetFieldsFrom(x, mapInput);
3014                 z->SetFieldsFrom(y, mapMethod);
3015                 if( bPromoteToMulti )
3016                     poIntersection = promote_to_multi(poIntersection);
3017                 z->SetGeometryDirectly(poIntersection);
3018                 OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
3019                 if (x_geom_diff) delete x_geom_diff;
3020                 x_geom_diff = x_geom_diff_new;
3021                 delete y;
3022                 ret = pLayerResult->CreateFeature(z);
3023                 delete z;
3024                 if (ret != OGRERR_NONE) {
3025                     if (!bSkipFailures) {
3026                         delete x;
3027                         delete x_geom_diff;
3028                         goto done;
3029                     } else {
3030                         CPLErrorReset();
3031                         ret = OGRERR_NONE;
3032                     }
3033                 }
3034             }
3035         }
3036 
3037         if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
3038         {
3039             delete x_geom_diff;
3040             delete x;
3041         }
3042         else
3043         {
3044             OGRFeature *z = new OGRFeature(poDefnResult);
3045             z->SetFieldsFrom(x, mapInput);
3046             if( bPromoteToMulti )
3047                 x_geom_diff = promote_to_multi(x_geom_diff);
3048             z->SetGeometryDirectly(x_geom_diff);
3049             delete x;
3050             ret = pLayerResult->CreateFeature(z);
3051             delete z;
3052             if (ret != OGRERR_NONE) {
3053                 if (!bSkipFailures) {
3054                     goto done;
3055                 } else {
3056                     CPLErrorReset();
3057                     ret = OGRERR_NONE;
3058                 }
3059             }
3060         }
3061     }
3062     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
3063       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3064       ret = OGRERR_FAILURE;
3065       goto done;
3066     }
3067 done:
3068     // release resources
3069     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3070     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
3071     if (mapInput) VSIFree(mapInput);
3072     if (mapMethod) VSIFree(mapMethod);
3073     return ret;
3074 }
3075 
3076 /************************************************************************/
3077 /*                         OGR_L_Identity()                             */
3078 /************************************************************************/
3079 
3080 /**
3081  * \brief Identify the features of this layer with the ones from the
3082  * identity layer.
3083  *
3084  * The result layer contains features whose geometries represent areas
3085  * that are in the input layer. The features in the result layer have
3086  * attributes from both input and method layers. The schema of the
3087  * result layer can be set by the user or, if it is empty, is
3088  * initialized to contain all fields in input and method layers.
3089  *
3090  * \note If the schema of the result is set by user and contains
3091  * fields that have the same name as a field in input and in method
3092  * layer, then the attribute in the result feature will get the value
3093  * from the feature of the method layer (even if it is undefined).
3094  *
3095  * \note For best performance use the minimum amount of features in
3096  * the method layer and copy it into a memory layer.
3097  *
3098  * \note This method relies on GEOS support. Do not use unless the
3099  * GEOS support is compiled in.
3100  *
3101  * The recognized list of options is :
3102  * <ul>
3103  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3104  *     feature could not be inserted.
3105  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3106  *     into MultiPolygons, or LineStrings to MultiLineStrings.
3107  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3108  *     will be created from the fields of the input layer.
3109  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3110  *     will be created from the fields of the method layer.
3111  * </ul>
3112  *
3113  * This function is the same as the C++ method OGRLayer::Identity().
3114  *
3115  * @param pLayerInput the input layer. Should not be NULL.
3116  *
3117  * @param pLayerMethod the method layer. Should not be NULL.
3118  *
3119  * @param pLayerResult the layer where the features resulting from the
3120  * operation are inserted. Should not be NULL. See above the note
3121  * about the schema.
3122  *
3123  * @param papszOptions NULL terminated list of options (may be NULL).
3124  *
3125  * @param pfnProgress a GDALProgressFunc() compatible callback function for
3126  * reporting progress or NULL.
3127  *
3128  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3129  *
3130  * @return an error code if there was an error or the execution was
3131  * interrupted, OGRERR_NONE otherwise.
3132  *
3133  * @since OGR 1.10
3134  */
3135 
OGR_L_Identity(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3136 OGRErr OGR_L_Identity( OGRLayerH pLayerInput,
3137                        OGRLayerH pLayerMethod,
3138                        OGRLayerH pLayerResult,
3139                        char** papszOptions,
3140                        GDALProgressFunc pfnProgress,
3141                        void * pProgressArg )
3142 
3143 {
3144     VALIDATE_POINTER1( pLayerInput, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
3145     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
3146     VALIDATE_POINTER1( pLayerResult, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
3147 
3148     return ((OGRLayer *)pLayerInput)->Identity( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
3149 }
3150 
3151 /************************************************************************/
3152 /*                             Update()                                 */
3153 /************************************************************************/
3154 
3155 /**
3156  * \brief Update this layer with features from the update layer.
3157  *
3158  * The result layer contains features whose geometries represent areas
3159  * that are either in the input layer or in the method layer. The
3160  * features in the result layer have areas of the features of the
3161  * method layer or those ares of the features of the input layer that
3162  * are not covered by the method layer. The features of the result
3163  * layer get their attributes from the input layer. The schema of the
3164  * result layer can be set by the user or, if it is empty, is
3165  * initialized to contain all fields in the input layer.
3166  *
3167  * \note If the schema of the result is set by user and contains
3168  * fields that have the same name as a field in the method layer, then
3169  * the attribute in the result feature the originates from the method
3170  * layer will get the value from the feature of the method layer.
3171  *
3172  * \note For best performance use the minimum amount of features in
3173  * the method layer and copy it into a memory layer.
3174  *
3175  * \note This method relies on GEOS support. Do not use unless the
3176  * GEOS support is compiled in.
3177  *
3178  * The recognized list of options is :
3179  * <ul>
3180  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3181  *     feature could not be inserted.
3182  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3183  *     into MultiPolygons, or LineStrings to MultiLineStrings.
3184  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3185  *     will be created from the fields of the input layer.
3186  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3187  *     will be created from the fields of the method layer.
3188  * </ul>
3189  *
3190  * This method is the same as the C function OGR_L_Update().
3191  *
3192  * @param pLayerMethod the method layer. Should not be NULL.
3193  *
3194  * @param pLayerResult the layer where the features resulting from the
3195  * operation are inserted. Should not be NULL. See above the note
3196  * about the schema.
3197  *
3198  * @param papszOptions NULL terminated list of options (may be NULL).
3199  *
3200  * @param pfnProgress a GDALProgressFunc() compatible callback function for
3201  * reporting progress or NULL.
3202  *
3203  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3204  *
3205  * @return an error code if there was an error or the execution was
3206  * interrupted, OGRERR_NONE otherwise.
3207  *
3208  * @since OGR 1.10
3209  */
3210 
Update(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3211 OGRErr OGRLayer::Update( OGRLayer *pLayerMethod,
3212                          OGRLayer *pLayerResult,
3213                          char** papszOptions,
3214                          GDALProgressFunc pfnProgress,
3215                          void * pProgressArg )
3216 {
3217     OGRErr ret = OGRERR_NONE;
3218     OGRFeatureDefn *poDefnInput = GetLayerDefn();
3219     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
3220     OGRFeatureDefn *poDefnResult = NULL;
3221     OGRGeometry *pGeometryMethodFilter = NULL;
3222     int *mapInput = NULL;
3223     int *mapMethod = NULL;
3224     double progress_max = (double) GetFeatureCount(0) + (double) pLayerMethod->GetFeatureCount(0);
3225     double progress_counter = 0;
3226     double progress_ticker = 0;
3227     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
3228     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
3229 
3230     // check for GEOS
3231     if (!OGRGeometryFactory::haveGEOS()) {
3232         return OGRERR_UNSUPPORTED_OPERATION;
3233     }
3234 
3235     // get resources
3236     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
3237     if (ret != OGRERR_NONE) goto done;
3238     ret = create_field_map(poDefnInput, &mapInput);
3239     if (ret != OGRERR_NONE) goto done;
3240     ret = create_field_map(poDefnMethod, &mapMethod);
3241     if (ret != OGRERR_NONE) goto done;
3242     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 0, papszOptions);
3243     if (ret != OGRERR_NONE) goto done;
3244     poDefnResult = pLayerResult->GetLayerDefn();
3245 
3246     // add clipped features from the input layer
3247     ResetReading();
3248     while (OGRFeature *x = GetNextFeature()) {
3249 
3250         if (pfnProgress) {
3251             double p = progress_counter/progress_max;
3252             if (p > progress_ticker) {
3253                 if (!pfnProgress(p, "", pProgressArg)) {
3254                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3255                     ret = OGRERR_FAILURE;
3256                     delete x;
3257                     goto done;
3258                 }
3259             }
3260             progress_counter += 1.0;
3261         }
3262 
3263         // set up the filter on method layer
3264         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
3265         if (!x_geom) {
3266             delete x;
3267             continue;
3268         }
3269 
3270         OGRGeometry *x_geom_diff = x_geom->clone(); //this will be the geometry of a result feature
3271         pLayerMethod->ResetReading();
3272         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
3273             OGRGeometry *y_geom = y->GetGeometryRef();
3274             if (!y_geom) {delete y; continue;}
3275             OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
3276             if (x_geom_diff) delete x_geom_diff;
3277             x_geom_diff = x_geom_diff_new;
3278             delete y;
3279         }
3280 
3281         if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
3282         {
3283             delete x_geom_diff;
3284             delete x;
3285         }
3286         else
3287         {
3288             OGRFeature *z = new OGRFeature(poDefnResult);
3289             z->SetFieldsFrom(x, mapInput);
3290             if( bPromoteToMulti )
3291                 x_geom_diff = promote_to_multi(x_geom_diff);
3292             z->SetGeometryDirectly(x_geom_diff);
3293             delete x;
3294             ret = pLayerResult->CreateFeature(z);
3295             delete z;
3296             if (ret != OGRERR_NONE) {
3297                 if (!bSkipFailures) {
3298                     goto done;
3299                 } else {
3300                     CPLErrorReset();
3301                     ret = OGRERR_NONE;
3302                 }
3303             }
3304         }
3305     }
3306 
3307     // restore the original filter and add features from the update layer
3308     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3309     pLayerMethod->ResetReading();
3310     while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
3311 
3312         if (pfnProgress) {
3313             double p = progress_counter/progress_max;
3314             if (p > progress_ticker) {
3315                 if (!pfnProgress(p, "", pProgressArg)) {
3316                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3317                     ret = OGRERR_FAILURE;
3318                     delete y;
3319                     goto done;
3320                 }
3321             }
3322             progress_counter += 1.0;
3323         }
3324 
3325         OGRGeometry *y_geom = y->GetGeometryRef();
3326         if (!y_geom) {delete y; continue;}
3327         OGRFeature *z = new OGRFeature(poDefnResult);
3328         if (mapMethod) z->SetFieldsFrom(y, mapMethod);
3329         z->SetGeometry(y_geom);
3330         delete y;
3331         ret = pLayerResult->CreateFeature(z);
3332         delete z;
3333         if (ret != OGRERR_NONE) {
3334             if (!bSkipFailures) {
3335                 goto done;
3336             } else {
3337                 CPLErrorReset();
3338                 ret = OGRERR_NONE;
3339             }
3340         }
3341     }
3342     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
3343       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3344       ret = OGRERR_FAILURE;
3345       goto done;
3346     }
3347 done:
3348     // release resources
3349     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3350     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
3351     if (mapInput) VSIFree(mapInput);
3352     if (mapMethod) VSIFree(mapMethod);
3353     return ret;
3354 }
3355 
3356 /************************************************************************/
3357 /*                          OGR_L_Update()                              */
3358 /************************************************************************/
3359 
3360 /**
3361  * \brief Update this layer with features from the update layer.
3362  *
3363  * The result layer contains features whose geometries represent areas
3364  * that are either in the input layer or in the method layer. The
3365  * features in the result layer have areas of the features of the
3366  * method layer or those ares of the features of the input layer that
3367  * are not covered by the method layer. The features of the result
3368  * layer get their attributes from the input layer. The schema of the
3369  * result layer can be set by the user or, if it is empty, is
3370  * initialized to contain all fields in the input layer.
3371  *
3372  * \note If the schema of the result is set by user and contains
3373  * fields that have the same name as a field in the method layer, then
3374  * the attribute in the result feature the originates from the method
3375  * layer will get the value from the feature of the method layer.
3376  *
3377  * \note For best performance use the minimum amount of features in
3378  * the method layer and copy it into a memory layer.
3379  *
3380  * \note This method relies on GEOS support. Do not use unless the
3381  * GEOS support is compiled in.
3382  *
3383  * The recognized list of options is :
3384  * <ul>
3385  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3386  *     feature could not be inserted.
3387  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3388  *     into MultiPolygons, or LineStrings to MultiLineStrings.
3389  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3390  *     will be created from the fields of the input layer.
3391  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3392  *     will be created from the fields of the method layer.
3393  * </ul>
3394  *
3395  * This function is the same as the C++ method OGRLayer::Update().
3396  *
3397  * @param pLayerInput the input layer. Should not be NULL.
3398  *
3399  * @param pLayerMethod the method layer. Should not be NULL.
3400  *
3401  * @param pLayerResult the layer where the features resulting from the
3402  * operation are inserted. Should not be NULL. See above the note
3403  * about the schema.
3404  *
3405  * @param papszOptions NULL terminated list of options (may be NULL).
3406  *
3407  * @param pfnProgress a GDALProgressFunc() compatible callback function for
3408  * reporting progress or NULL.
3409  *
3410  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3411  *
3412  * @return an error code if there was an error or the execution was
3413  * interrupted, OGRERR_NONE otherwise.
3414  *
3415  * @since OGR 1.10
3416  */
3417 
OGR_L_Update(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3418 OGRErr OGR_L_Update( OGRLayerH pLayerInput,
3419                      OGRLayerH pLayerMethod,
3420                      OGRLayerH pLayerResult,
3421                      char** papszOptions,
3422                      GDALProgressFunc pfnProgress,
3423                      void * pProgressArg )
3424 
3425 {
3426     VALIDATE_POINTER1( pLayerInput, "OGR_L_Update", OGRERR_INVALID_HANDLE );
3427     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Update", OGRERR_INVALID_HANDLE );
3428     VALIDATE_POINTER1( pLayerResult, "OGR_L_Update", OGRERR_INVALID_HANDLE );
3429 
3430     return ((OGRLayer *)pLayerInput)->Update( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
3431 }
3432 
3433 /************************************************************************/
3434 /*                              Clip()                                  */
3435 /************************************************************************/
3436 
3437 /**
3438  * \brief Clip off areas that are not covered by the method layer.
3439  *
3440  * The result layer contains features whose geometries represent areas
3441  * that are in the input layer and in the method layer. The features
3442  * in the result layer have the (possibly clipped) areas of features
3443  * in the input layer and the attributes from the same features. The
3444  * schema of the result layer can be set by the user or, if it is
3445  * empty, is initialized to contain all fields in the input layer.
3446  *
3447  * \note For best performance use the minimum amount of features in
3448  * the method layer and copy it into a memory layer.
3449  *
3450  * \note This method relies on GEOS support. Do not use unless the
3451  * GEOS support is compiled in.
3452  *
3453  * The recognized list of options is :
3454  * <ul>
3455  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3456  *     feature could not be inserted.
3457  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3458  *     into MultiPolygons, or LineStrings to MultiLineStrings.
3459  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3460  *     will be created from the fields of the input layer.
3461  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3462  *     will be created from the fields of the method layer.
3463  * </ul>
3464  *
3465  * This method is the same as the C function OGR_L_Clip().
3466  *
3467  * @param pLayerMethod the method layer. Should not be NULL.
3468  *
3469  * @param pLayerResult the layer where the features resulting from the
3470  * operation are inserted. Should not be NULL. See above the note
3471  * about the schema.
3472  *
3473  * @param papszOptions NULL terminated list of options (may be NULL).
3474  *
3475  * @param pfnProgress a GDALProgressFunc() compatible callback function for
3476  * reporting progress or NULL.
3477  *
3478  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3479  *
3480  * @return an error code if there was an error or the execution was
3481  * interrupted, OGRERR_NONE otherwise.
3482  *
3483  * @since OGR 1.10
3484  */
3485 
Clip(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3486 OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod,
3487                        OGRLayer *pLayerResult,
3488                        char** papszOptions,
3489                        GDALProgressFunc pfnProgress,
3490                        void * pProgressArg )
3491 {
3492     OGRErr ret = OGRERR_NONE;
3493     OGRFeatureDefn *poDefnInput = GetLayerDefn();
3494     OGRFeatureDefn *poDefnResult = NULL;
3495     OGRGeometry *pGeometryMethodFilter = NULL;
3496     int *mapInput = NULL;
3497     double progress_max = (double) GetFeatureCount(0);
3498     double progress_counter = 0;
3499     double progress_ticker = 0;
3500     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
3501     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
3502 
3503     // check for GEOS
3504     if (!OGRGeometryFactory::haveGEOS()) {
3505         return OGRERR_UNSUPPORTED_OPERATION;
3506     }
3507 
3508     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
3509     if (ret != OGRERR_NONE) goto done;
3510     ret = create_field_map(poDefnInput, &mapInput);
3511     if (ret != OGRERR_NONE) goto done;
3512     ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0, papszOptions);
3513     if (ret != OGRERR_NONE) goto done;
3514 
3515     poDefnResult = pLayerResult->GetLayerDefn();
3516     ResetReading();
3517     while (OGRFeature *x = GetNextFeature()) {
3518 
3519         if (pfnProgress) {
3520             double p = progress_counter/progress_max;
3521             if (p > progress_ticker) {
3522                 if (!pfnProgress(p, "", pProgressArg)) {
3523                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3524                     ret = OGRERR_FAILURE;
3525                     delete x;
3526                     goto done;
3527                 }
3528             }
3529             progress_counter += 1.0;
3530         }
3531 
3532         // set up the filter on method layer
3533         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
3534         if (!x_geom) {
3535             delete x;
3536             continue;
3537         }
3538 
3539         OGRGeometry *geom = NULL; // this will be the geometry of the result feature
3540         pLayerMethod->ResetReading();
3541         // incrementally add area from y to geom
3542         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
3543             OGRGeometry *y_geom = y->GetGeometryRef();
3544             if (!y_geom) {delete y; continue;}
3545             if (!geom) {
3546                 geom = y_geom->clone();
3547             } else {
3548                 OGRGeometry *geom_new = geom->Union(y_geom);
3549                 delete geom;
3550                 geom = geom_new;
3551             }
3552             delete y;
3553         }
3554 
3555         // possibly add a new feature with area x intersection sum of y
3556         OGRFeature *z = NULL;
3557         if (geom) {
3558             OGRGeometry* poIntersection = x_geom->Intersection(geom);
3559             if( poIntersection != NULL && !poIntersection->IsEmpty() )
3560             {
3561                 z = new OGRFeature(poDefnResult);
3562                 z->SetFieldsFrom(x, mapInput);
3563                 if( bPromoteToMulti )
3564                     poIntersection = promote_to_multi(poIntersection);
3565                 z->SetGeometryDirectly(poIntersection);
3566             }
3567             else
3568                 delete poIntersection;
3569             delete geom;
3570         }
3571         delete x;
3572         if (z) {
3573             if (z->GetGeometryRef() != NULL && !z->GetGeometryRef()->IsEmpty())
3574                 ret = pLayerResult->CreateFeature(z);
3575             delete z;
3576             if (ret != OGRERR_NONE) {
3577                 if (!bSkipFailures) {
3578                     goto done;
3579                 } else {
3580                     CPLErrorReset();
3581                     ret = OGRERR_NONE;
3582                 }
3583             }
3584         }
3585     }
3586     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
3587       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3588       ret = OGRERR_FAILURE;
3589       goto done;
3590     }
3591 done:
3592     // release resources
3593     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3594     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
3595     if (mapInput) VSIFree(mapInput);
3596     return ret;
3597 }
3598 
3599 /************************************************************************/
3600 /*                           OGR_L_Clip()                               */
3601 /************************************************************************/
3602 
3603 /**
3604  * \brief Clip off areas that are not covered by the method layer.
3605  *
3606  * The result layer contains features whose geometries represent areas
3607  * that are in the input layer and in the method layer. The features
3608  * in the result layer have the (possibly clipped) areas of features
3609  * in the input layer and the attributes from the same features. The
3610  * schema of the result layer can be set by the user or, if it is
3611  * empty, is initialized to contain all fields in the input layer.
3612  *
3613  * \note For best performance use the minimum amount of features in
3614  * the method layer and copy it into a memory layer.
3615  *
3616  * \note This method relies on GEOS support. Do not use unless the
3617  * GEOS support is compiled in.
3618  *
3619  * The recognized list of options is :
3620  * <ul>
3621  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3622  *     feature could not be inserted.
3623  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3624  *     into MultiPolygons, or LineStrings to MultiLineStrings.
3625  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3626  *     will be created from the fields of the input layer.
3627  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3628  *     will be created from the fields of the method layer.
3629  * </ul>
3630  *
3631  * This function is the same as the C++ method OGRLayer::Clip().
3632  *
3633  * @param pLayerInput the input layer. Should not be NULL.
3634  *
3635  * @param pLayerMethod the method layer. Should not be NULL.
3636  *
3637  * @param pLayerResult the layer where the features resulting from the
3638  * operation are inserted. Should not be NULL. See above the note
3639  * about the schema.
3640  *
3641  * @param papszOptions NULL terminated list of options (may be NULL).
3642  *
3643  * @param pfnProgress a GDALProgressFunc() compatible callback function for
3644  * reporting progress or NULL.
3645  *
3646  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3647  *
3648  * @return an error code if there was an error or the execution was
3649  * interrupted, OGRERR_NONE otherwise.
3650  *
3651  * @since OGR 1.10
3652  */
3653 
OGR_L_Clip(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3654 OGRErr OGR_L_Clip( OGRLayerH pLayerInput,
3655                    OGRLayerH pLayerMethod,
3656                    OGRLayerH pLayerResult,
3657                    char** papszOptions,
3658                    GDALProgressFunc pfnProgress,
3659                    void * pProgressArg )
3660 
3661 {
3662     VALIDATE_POINTER1( pLayerInput, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
3663     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
3664     VALIDATE_POINTER1( pLayerResult, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
3665 
3666     return ((OGRLayer *)pLayerInput)->Clip( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
3667 }
3668 
3669 /************************************************************************/
3670 /*                              Erase()                                 */
3671 /************************************************************************/
3672 
3673 /**
3674  * \brief Remove areas that are covered by the method layer.
3675  *
3676  * The result layer contains features whose geometries represent areas
3677  * that are in the input layer but not in the method layer. The
3678  * features in the result layer have attributes from the input
3679  * layer. The schema of the result layer can be set by the user or, if
3680  * it is empty, is initialized to contain all fields in the input
3681  * layer.
3682  *
3683  * \note For best performance use the minimum amount of features in
3684  * the method layer and copy it into a memory layer.
3685  *
3686  * \note This method relies on GEOS support. Do not use unless the
3687  * GEOS support is compiled in.
3688  *
3689  * The recognized list of options is :
3690  * <ul>
3691  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3692  *     feature could not be inserted.
3693  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3694  *     into MultiPolygons, or LineStrings to MultiLineStrings.
3695  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3696  *     will be created from the fields of the input layer.
3697  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3698  *     will be created from the fields of the method layer.
3699  * </ul>
3700  *
3701  * This method is the same as the C function OGR_L_Erase().
3702  *
3703  * @param pLayerMethod the method layer. Should not be NULL.
3704  *
3705  * @param pLayerResult the layer where the features resulting from the
3706  * operation are inserted. Should not be NULL. See above the note
3707  * about the schema.
3708  *
3709  * @param papszOptions NULL terminated list of options (may be NULL).
3710  *
3711  * @param pfnProgress a GDALProgressFunc() compatible callback function for
3712  * reporting progress or NULL.
3713  *
3714  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3715  *
3716  * @return an error code if there was an error or the execution was
3717  * interrupted, OGRERR_NONE otherwise.
3718  *
3719  * @since OGR 1.10
3720  */
3721 
Erase(OGRLayer * pLayerMethod,OGRLayer * pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3722 OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod,
3723                         OGRLayer *pLayerResult,
3724                         char** papszOptions,
3725                         GDALProgressFunc pfnProgress,
3726                         void * pProgressArg )
3727 {
3728     OGRErr ret = OGRERR_NONE;
3729     OGRFeatureDefn *poDefnInput = GetLayerDefn();
3730     OGRFeatureDefn *poDefnResult = NULL;
3731     OGRGeometry *pGeometryMethodFilter = NULL;
3732     int *mapInput = NULL;
3733     double progress_max = (double) GetFeatureCount(0);
3734     double progress_counter = 0;
3735     double progress_ticker = 0;
3736     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
3737     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
3738 
3739     // check for GEOS
3740     if (!OGRGeometryFactory::haveGEOS()) {
3741         return OGRERR_UNSUPPORTED_OPERATION;
3742     }
3743 
3744     // get resources
3745     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
3746     if (ret != OGRERR_NONE) goto done;
3747     ret = create_field_map(poDefnInput, &mapInput);
3748     if (ret != OGRERR_NONE) goto done;
3749     ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0, papszOptions);
3750     if (ret != OGRERR_NONE) goto done;
3751     poDefnResult = pLayerResult->GetLayerDefn();
3752 
3753     ResetReading();
3754     while (OGRFeature *x = GetNextFeature()) {
3755 
3756         if (pfnProgress) {
3757             double p = progress_counter/progress_max;
3758             if (p > progress_ticker) {
3759                 if (!pfnProgress(p, "", pProgressArg)) {
3760                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3761                     ret = OGRERR_FAILURE;
3762                     delete x;
3763                     goto done;
3764                 }
3765             }
3766             progress_counter += 1.0;
3767         }
3768 
3769         // set up the filter on the method layer
3770         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
3771         if (!x_geom) {
3772             delete x;
3773             continue;
3774         }
3775 
3776         OGRGeometry *geom = NULL; // this will be the geometry of the result feature
3777         pLayerMethod->ResetReading();
3778         // incrementally add area from y to geom
3779         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
3780             OGRGeometry *y_geom = y->GetGeometryRef();
3781             if (!y_geom) {delete y; continue;}
3782             if (!geom) {
3783                 geom = y_geom->clone();
3784             } else {
3785                 OGRGeometry *geom_new = geom->Union(y_geom);
3786                 delete geom;
3787                 geom = geom_new;
3788             }
3789             delete y;
3790         }
3791 
3792         // possibly add a new feature with area x minus sum of y
3793         OGRFeature *z = NULL;
3794         if (geom) {
3795             OGRGeometry* x_geom_diff = x_geom->Difference(geom);
3796             if( x_geom_diff != NULL && !x_geom_diff->IsEmpty() )
3797             {
3798                 z = new OGRFeature(poDefnResult);
3799                 z->SetFieldsFrom(x, mapInput);
3800                 if( bPromoteToMulti )
3801                     x_geom_diff = promote_to_multi(x_geom_diff);
3802                 z->SetGeometryDirectly(x_geom_diff);
3803             }
3804             else
3805                 delete x_geom_diff;
3806             delete geom;
3807         }
3808         delete x;
3809         if (z) {
3810             if (z->GetGeometryRef() != NULL && !z->GetGeometryRef()->IsEmpty())
3811                 ret = pLayerResult->CreateFeature(z);
3812             delete z;
3813             if (ret != OGRERR_NONE) {
3814                 if (!bSkipFailures) {
3815                     goto done;
3816                 } else {
3817                     CPLErrorReset();
3818                     ret = OGRERR_NONE;
3819                 }
3820             }
3821         }
3822     }
3823     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
3824       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
3825       ret = OGRERR_FAILURE;
3826       goto done;
3827     }
3828 done:
3829     // release resources
3830     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
3831     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
3832     if (mapInput) VSIFree(mapInput);
3833     return ret;
3834 }
3835 
3836 /************************************************************************/
3837 /*                           OGR_L_Erase()                              */
3838 /************************************************************************/
3839 
3840 /**
3841  * \brief Remove areas that are covered by the method layer.
3842  *
3843  * The result layer contains features whose geometries represent areas
3844  * that are in the input layer but not in the method layer. The
3845  * features in the result layer have attributes from the input
3846  * layer. The schema of the result layer can be set by the user or, if
3847  * it is empty, is initialized to contain all fields in the input
3848  * layer.
3849  *
3850  * \note For best performance use the minimum amount of features in
3851  * the method layer and copy it into a memory layer.
3852  *
3853  * \note This method relies on GEOS support. Do not use unless the
3854  * GEOS support is compiled in.
3855  *
3856  * The recognized list of options is :
3857  * <ul>
3858  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
3859  *     feature could not be inserted.
3860  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
3861  *     into MultiPolygons, or LineStrings to MultiLineStrings.
3862  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
3863  *     will be created from the fields of the input layer.
3864  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
3865  *     will be created from the fields of the method layer.
3866  * </ul>
3867  *
3868  * This function is the same as the C++ method OGRLayer::Erase().
3869  *
3870  * @param pLayerInput the input layer. Should not be NULL.
3871  *
3872  * @param pLayerMethod the method layer. Should not be NULL.
3873  *
3874  * @param pLayerResult the layer where the features resulting from the
3875  * operation are inserted. Should not be NULL. See above the note
3876  * about the schema.
3877  *
3878  * @param papszOptions NULL terminated list of options (may be NULL).
3879  *
3880  * @param pfnProgress a GDALProgressFunc() compatible callback function for
3881  * reporting progress or NULL.
3882  *
3883  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
3884  *
3885  * @return an error code if there was an error or the execution was
3886  * interrupted, OGRERR_NONE otherwise.
3887  *
3888  * @since OGR 1.10
3889  */
3890 
OGR_L_Erase(OGRLayerH pLayerInput,OGRLayerH pLayerMethod,OGRLayerH pLayerResult,char ** papszOptions,GDALProgressFunc pfnProgress,void * pProgressArg)3891 OGRErr OGR_L_Erase( OGRLayerH pLayerInput,
3892                     OGRLayerH pLayerMethod,
3893                     OGRLayerH pLayerResult,
3894                     char** papszOptions,
3895                     GDALProgressFunc pfnProgress,
3896                     void * pProgressArg )
3897 
3898 {
3899     VALIDATE_POINTER1( pLayerInput, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
3900     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
3901     VALIDATE_POINTER1( pLayerResult, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
3902 
3903     return ((OGRLayer *)pLayerInput)->Erase( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
3904 }
3905