1 /******************************************************************************
2  *
3  * Project:  OpenGIS Simple Features Reference Implementation
4  * Purpose:  Implements OGRUnionLayer class
5  * Author:   Even Rouault, even dot rouault at spatialys.com
6  *
7  ******************************************************************************
8  * Copyright (c) 2012-2014, Even Rouault <even dot rouault at spatialys.com>
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining a
11  * copy of this software and associated documentation files (the "Software"),
12  * to deal in the Software without restriction, including without limitation
13  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
14  * and/or sell copies of the Software, and to permit persons to whom the
15  * Software is furnished to do so, subject to the following conditions:
16  *
17  * The above copyright notice and this permission notice shall be included
18  * in all copies or substantial portions of the Software.
19  *
20  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
23  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
25  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26  * DEALINGS IN THE SOFTWARE.
27  ****************************************************************************/
28 
29 #ifndef DOXYGEN_SKIP
30 
31 #include "ogrunionlayer.h"
32 #include "ogrwarpedlayer.h"
33 #include "ogr_p.h"
34 
35 CPL_CVSID("$Id: ogrunionlayer.cpp 355b41831cd2685c85d1aabe5b95665a2c6e99b7 2019-06-19 17:07:04 +0200 Even Rouault $")
36 
37 /************************************************************************/
38 /*                      OGRUnionLayerGeomFieldDefn()                    */
39 /************************************************************************/
40 
OGRUnionLayerGeomFieldDefn(const char * pszNameIn,OGRwkbGeometryType eType)41 OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
42     const char* pszNameIn,
43     OGRwkbGeometryType eType) :
44     OGRGeomFieldDefn(pszNameIn, eType)
45 {}
46 
47 /************************************************************************/
48 /*                      OGRUnionLayerGeomFieldDefn()                    */
49 /************************************************************************/
50 
OGRUnionLayerGeomFieldDefn(OGRGeomFieldDefn * poSrc)51 OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
52     OGRGeomFieldDefn* poSrc) :
53     OGRGeomFieldDefn(poSrc->GetNameRef(), poSrc->GetType())
54 {
55     SetSpatialRef(poSrc->GetSpatialRef());
56 }
57 
58 /************************************************************************/
59 /*                      OGRUnionLayerGeomFieldDefn()                    */
60 /************************************************************************/
61 
OGRUnionLayerGeomFieldDefn(OGRUnionLayerGeomFieldDefn * poSrc)62 OGRUnionLayerGeomFieldDefn::OGRUnionLayerGeomFieldDefn(
63     OGRUnionLayerGeomFieldDefn* poSrc) :
64     OGRGeomFieldDefn(poSrc->GetNameRef(), poSrc->GetType()),
65     bGeomTypeSet(poSrc->bGeomTypeSet),
66     bSRSSet(poSrc->bSRSSet)
67 {
68     SetSpatialRef(poSrc->GetSpatialRef());
69     sStaticEnvelope = poSrc->sStaticEnvelope;
70 }
71 
72 /************************************************************************/
73 /*                     ~OGRUnionLayerGeomFieldDefn()                    */
74 /************************************************************************/
75 
~OGRUnionLayerGeomFieldDefn()76 OGRUnionLayerGeomFieldDefn::~OGRUnionLayerGeomFieldDefn() {}
77 
78 /************************************************************************/
79 /*                          OGRUnionLayer()                             */
80 /************************************************************************/
81 
OGRUnionLayer(const char * pszName,int nSrcLayersIn,OGRLayer ** papoSrcLayersIn,int bTakeLayerOwnership)82 OGRUnionLayer::OGRUnionLayer( const char* pszName,
83                               int nSrcLayersIn,
84                               OGRLayer** papoSrcLayersIn,
85                               int bTakeLayerOwnership ) :
86     osName(pszName),
87     nSrcLayers(nSrcLayersIn),
88     papoSrcLayers(papoSrcLayersIn),
89     bHasLayerOwnership(bTakeLayerOwnership),
90     poFeatureDefn(nullptr),
91     nFields(0),
92     papoFields(nullptr),
93     nGeomFields(0),
94     papoGeomFields(nullptr),
95     eFieldStrategy(FIELD_UNION_ALL_LAYERS),
96     bPreserveSrcFID(FALSE),
97     nFeatureCount(-1),
98     iCurLayer(-1),
99     pszAttributeFilter(nullptr),
100     nNextFID(0),
101     panMap(nullptr),
102     papszIgnoredFields(nullptr),
103     bAttrFilterPassThroughValue(-1),
104     pabModifiedLayers(static_cast<int*>(CPLCalloc(sizeof(int), nSrcLayers))),
105     pabCheckIfAutoWrap(static_cast<int*>(CPLCalloc(sizeof(int), nSrcLayers))),
106     poGlobalSRS(nullptr)
107 {
108     CPLAssert(nSrcLayersIn > 0);
109 
110     SetDescription( pszName );
111 }
112 
113 /************************************************************************/
114 /*                         ~OGRUnionLayer()                             */
115 /************************************************************************/
116 
~OGRUnionLayer()117 OGRUnionLayer::~OGRUnionLayer()
118 {
119     if( bHasLayerOwnership )
120     {
121         for(int i = 0; i < nSrcLayers; i++)
122             delete papoSrcLayers[i];
123     }
124     CPLFree(papoSrcLayers);
125 
126     for(int i = 0; i < nFields; i++)
127         delete papoFields[i];
128     CPLFree(papoFields);
129     for(int i = 0; i < nGeomFields; i++)
130         delete papoGeomFields[i];
131     CPLFree(papoGeomFields);
132 
133     CPLFree(pszAttributeFilter);
134     CPLFree(panMap);
135     CSLDestroy(papszIgnoredFields);
136     CPLFree(pabModifiedLayers);
137     CPLFree(pabCheckIfAutoWrap);
138 
139     if( poFeatureDefn )
140         poFeatureDefn->Release();
141     if( poGlobalSRS != nullptr )
142         poGlobalSRS->Release();
143 }
144 
145 /************************************************************************/
146 /*                              SetFields()                             */
147 /************************************************************************/
148 
SetFields(FieldUnionStrategy eFieldStrategyIn,int nFieldsIn,OGRFieldDefn ** papoFieldsIn,int nGeomFieldsIn,OGRUnionLayerGeomFieldDefn ** papoGeomFieldsIn)149 void OGRUnionLayer::SetFields(FieldUnionStrategy eFieldStrategyIn,
150                               int nFieldsIn,
151                               OGRFieldDefn** papoFieldsIn,
152                               int nGeomFieldsIn,
153                               OGRUnionLayerGeomFieldDefn** papoGeomFieldsIn)
154 {
155     CPLAssert(nFields == 0);
156     CPLAssert(poFeatureDefn == nullptr);
157 
158     eFieldStrategy = eFieldStrategyIn;
159     if( nFieldsIn )
160     {
161         nFields = nFieldsIn;
162         papoFields = static_cast<OGRFieldDefn**>(CPLMalloc(nFields * sizeof(OGRFieldDefn*)));
163         for(int i=0;i<nFields;i++)
164             papoFields[i] = new OGRFieldDefn(papoFieldsIn[i]);
165     }
166     nGeomFields = nGeomFieldsIn;
167     if( nGeomFields > 0 )
168     {
169         papoGeomFields = static_cast<OGRUnionLayerGeomFieldDefn** >(CPLMalloc(
170                             nGeomFields * sizeof(OGRUnionLayerGeomFieldDefn*)));
171         for(int i=0;i<nGeomFields;i++)
172             papoGeomFields[i] = new OGRUnionLayerGeomFieldDefn(papoGeomFieldsIn[i]);
173     }
174 }
175 
176 /************************************************************************/
177 /*                        SetSourceLayerFieldName()                     */
178 /************************************************************************/
179 
SetSourceLayerFieldName(const char * pszSourceLayerFieldName)180 void OGRUnionLayer::SetSourceLayerFieldName(const char* pszSourceLayerFieldName)
181 {
182     CPLAssert(poFeatureDefn == nullptr);
183 
184     CPLAssert(osSourceLayerFieldName.empty());
185     if( pszSourceLayerFieldName != nullptr )
186         osSourceLayerFieldName = pszSourceLayerFieldName;
187 }
188 
189 /************************************************************************/
190 /*                           SetPreserveSrcFID()                        */
191 /************************************************************************/
192 
SetPreserveSrcFID(int bPreserveSrcFIDIn)193 void OGRUnionLayer::SetPreserveSrcFID(int bPreserveSrcFIDIn)
194 {
195     CPLAssert(poFeatureDefn == nullptr);
196 
197     bPreserveSrcFID = bPreserveSrcFIDIn;
198 }
199 
200 /************************************************************************/
201 /*                          SetFeatureCount()                           */
202 /************************************************************************/
203 
SetFeatureCount(int nFeatureCountIn)204 void OGRUnionLayer::SetFeatureCount(int nFeatureCountIn)
205 {
206     CPLAssert(poFeatureDefn == nullptr);
207 
208     nFeatureCount = nFeatureCountIn;
209 }
210 
211 /************************************************************************/
212 /*                         MergeFieldDefn()                             */
213 /************************************************************************/
214 
MergeFieldDefn(OGRFieldDefn * poFieldDefn,OGRFieldDefn * poSrcFieldDefn)215 static void MergeFieldDefn(OGRFieldDefn* poFieldDefn,
216                            OGRFieldDefn* poSrcFieldDefn)
217 {
218     if( poFieldDefn->GetType() != poSrcFieldDefn->GetType() )
219     {
220         if( poSrcFieldDefn->GetType() == OFTReal &&
221             (poFieldDefn->GetType() == OFTInteger ||
222              poFieldDefn->GetType() == OFTInteger64) )
223             poFieldDefn->SetType(OFTReal);
224         if( poFieldDefn->GetType() == OFTReal &&
225             (poSrcFieldDefn->GetType() == OFTInteger ||
226              poSrcFieldDefn->GetType() == OFTInteger64) )
227             poFieldDefn->SetType(OFTReal);
228         else if( poSrcFieldDefn->GetType() == OFTInteger64 &&
229                  poFieldDefn->GetType() == OFTInteger)
230             poFieldDefn->SetType(OFTInteger64);
231         else if( poFieldDefn->GetType() == OFTInteger64 &&
232                  poSrcFieldDefn->GetType() == OFTInteger)
233             poFieldDefn->SetType(OFTInteger64);
234         else
235             poFieldDefn->SetType(OFTString);
236     }
237 
238     if( poFieldDefn->GetWidth() != poSrcFieldDefn->GetWidth() ||
239         poFieldDefn->GetPrecision() != poSrcFieldDefn->GetPrecision() )
240     {
241         poFieldDefn->SetWidth(0);
242         poFieldDefn->SetPrecision(0);
243     }
244 }
245 
246 /************************************************************************/
247 /*                             GetLayerDefn()                           */
248 /************************************************************************/
249 
GetLayerDefn()250 OGRFeatureDefn *OGRUnionLayer::GetLayerDefn()
251 {
252     if( poFeatureDefn != nullptr )
253         return poFeatureDefn;
254 
255     poFeatureDefn = new OGRFeatureDefn( osName );
256     poFeatureDefn->Reference();
257     poFeatureDefn->SetGeomType(wkbNone);
258 
259     int iCompareFirstIndex = 0;
260     if( !osSourceLayerFieldName.empty() )
261     {
262         OGRFieldDefn oField(osSourceLayerFieldName, OFTString);
263         poFeatureDefn->AddFieldDefn(&oField);
264         iCompareFirstIndex = 1;
265     }
266 
267     if( eFieldStrategy == FIELD_SPECIFIED )
268     {
269         for( int i = 0; i < nFields; i++ )
270             poFeatureDefn->AddFieldDefn(papoFields[i]);
271         for( int i = 0; i < nGeomFields; i++ )
272         {
273             poFeatureDefn->AddGeomFieldDefn(
274                 new OGRUnionLayerGeomFieldDefn(papoGeomFields[i]), FALSE);
275             OGRUnionLayerGeomFieldDefn* poGeomFieldDefn =
276                 cpl::down_cast<OGRUnionLayerGeomFieldDefn*>(poFeatureDefn->GetGeomFieldDefn(i));
277 
278             if( poGeomFieldDefn->bGeomTypeSet == FALSE ||
279                 poGeomFieldDefn->bSRSSet == FALSE )
280             {
281                 for( int iLayer = 0; iLayer < nSrcLayers; iLayer++ )
282                 {
283                     OGRFeatureDefn* poSrcFeatureDefn =
284                                 papoSrcLayers[iLayer]->GetLayerDefn();
285                     int nIndex =
286                         poSrcFeatureDefn->GetGeomFieldIndex(poGeomFieldDefn->GetNameRef());
287                     if( nIndex >= 0 )
288                     {
289                         OGRGeomFieldDefn* poSrcGeomFieldDefn =
290                             poSrcFeatureDefn->GetGeomFieldDefn(nIndex);
291                         if( poGeomFieldDefn->bGeomTypeSet == FALSE )
292                         {
293                             poGeomFieldDefn->bGeomTypeSet = TRUE;
294                             poGeomFieldDefn->SetType(poSrcGeomFieldDefn->GetType());
295                         }
296                         if( poGeomFieldDefn->bSRSSet == FALSE )
297                         {
298                             poGeomFieldDefn->bSRSSet = TRUE;
299                             poGeomFieldDefn->SetSpatialRef(poSrcGeomFieldDefn->GetSpatialRef());
300                             if( i == 0 && poGlobalSRS == nullptr )
301                             {
302                                 poGlobalSRS = poSrcGeomFieldDefn->GetSpatialRef();
303                                 if( poGlobalSRS != nullptr )
304                                     poGlobalSRS->Reference();
305                             }
306                         }
307                         break;
308                     }
309                 }
310             }
311         }
312     }
313     else if( eFieldStrategy == FIELD_FROM_FIRST_LAYER )
314     {
315         OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[0]->GetLayerDefn();
316         for( int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++)
317             poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
318         for( int i = 0;
319              nGeomFields != - 1 && i < poSrcFeatureDefn->GetGeomFieldCount();
320              i++ )
321         {
322             OGRGeomFieldDefn* poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
323             poFeatureDefn->AddGeomFieldDefn(
324                 new OGRUnionLayerGeomFieldDefn(poFldDefn), FALSE);
325         }
326     }
327     else if (eFieldStrategy == FIELD_UNION_ALL_LAYERS )
328     {
329         if( nGeomFields == 1 )
330         {
331             poFeatureDefn->AddGeomFieldDefn(
332                         new OGRUnionLayerGeomFieldDefn(papoGeomFields[0]), FALSE);
333         }
334 
335         for(int iLayer = 0; iLayer < nSrcLayers; iLayer++)
336         {
337             OGRFeatureDefn* poSrcFeatureDefn =
338                                 papoSrcLayers[iLayer]->GetLayerDefn();
339 
340             /* Add any field that is found in the source layers */
341             for( int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++ )
342             {
343                 OGRFieldDefn* poSrcFieldDefn = poSrcFeatureDefn->GetFieldDefn(i);
344                 int nIndex =
345                     poFeatureDefn->GetFieldIndex(poSrcFieldDefn->GetNameRef());
346                 if( nIndex < 0 )
347                     poFeatureDefn->AddFieldDefn(poSrcFieldDefn);
348                 else
349                 {
350                     OGRFieldDefn* poFieldDefn =
351                                         poFeatureDefn->GetFieldDefn(nIndex);
352                     MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
353                 }
354             }
355 
356             for( int i = 0;
357                  nGeomFields != - 1 &&
358                  i < poSrcFeatureDefn->GetGeomFieldCount();
359                  i++)
360             {
361                 OGRGeomFieldDefn* poSrcFieldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
362                 int nIndex =
363                     poFeatureDefn->GetGeomFieldIndex(poSrcFieldDefn->GetNameRef());
364                 if( nIndex < 0 )
365                 {
366                     poFeatureDefn->AddGeomFieldDefn(
367                         new OGRUnionLayerGeomFieldDefn(poSrcFieldDefn), FALSE);
368                     if( poFeatureDefn->GetGeomFieldCount() == 1 && nGeomFields == 0 &&
369                         GetSpatialRef() != nullptr )
370                     {
371                         OGRUnionLayerGeomFieldDefn* poGeomFieldDefn =
372                             cpl::down_cast<OGRUnionLayerGeomFieldDefn*>(poFeatureDefn->GetGeomFieldDefn(0));
373                         poGeomFieldDefn->bSRSSet = TRUE;
374                         poGeomFieldDefn->SetSpatialRef(GetSpatialRef());
375                     }
376                 }
377                 else
378                 {
379                     if( nIndex == 0 && nGeomFields == 1 )
380                     {
381                         OGRUnionLayerGeomFieldDefn* poGeomFieldDefn =
382                             cpl::down_cast<OGRUnionLayerGeomFieldDefn*>(poFeatureDefn->GetGeomFieldDefn(0));
383                         if( poGeomFieldDefn->bGeomTypeSet == FALSE )
384                         {
385                             poGeomFieldDefn->bGeomTypeSet = TRUE;
386                             poGeomFieldDefn->SetType(poSrcFieldDefn->GetType());
387                         }
388                         if( poGeomFieldDefn->bSRSSet == FALSE )
389                         {
390                             poGeomFieldDefn->bSRSSet = TRUE;
391                             poGeomFieldDefn->SetSpatialRef(poSrcFieldDefn->GetSpatialRef());
392                         }
393                     }
394                     /* TODO: merge type, SRS, extent ? */
395                 }
396             }
397         }
398     }
399     else if (eFieldStrategy == FIELD_INTERSECTION_ALL_LAYERS )
400     {
401         OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[0]->GetLayerDefn();
402         for( int i = 0; i < poSrcFeatureDefn->GetFieldCount(); i++ )
403             poFeatureDefn->AddFieldDefn(poSrcFeatureDefn->GetFieldDefn(i));
404         for( int i = 0; i < poSrcFeatureDefn->GetGeomFieldCount(); i++ )
405         {
406             OGRGeomFieldDefn* poFldDefn = poSrcFeatureDefn->GetGeomFieldDefn(i);
407             poFeatureDefn->AddGeomFieldDefn(
408                 new OGRUnionLayerGeomFieldDefn(poFldDefn), FALSE);
409         }
410 
411         /* Remove any field that is not found in the source layers */
412         for( int iLayer = 1; iLayer < nSrcLayers; iLayer++ )
413         {
414             OGRFeatureDefn* l_poSrcFeatureDefn =
415                                         papoSrcLayers[iLayer]->GetLayerDefn();
416             for( int i = iCompareFirstIndex;
417                  i < poFeatureDefn->GetFieldCount();
418                  // No increment.
419                  )
420             {
421                 OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(i);
422                 int nSrcIndex = l_poSrcFeatureDefn->GetFieldIndex(
423                                                     poFieldDefn->GetNameRef());
424                 if( nSrcIndex < 0 )
425                 {
426                     poFeatureDefn->DeleteFieldDefn(i);
427                 }
428                 else
429                 {
430                     OGRFieldDefn* poSrcFieldDefn =
431                         l_poSrcFeatureDefn->GetFieldDefn(nSrcIndex);
432                     MergeFieldDefn(poFieldDefn, poSrcFieldDefn);
433 
434                     i++;
435                 }
436             }
437             for( int i = 0;
438                  i < poFeatureDefn->GetGeomFieldCount();
439                  // No increment.
440                  )
441             {
442                 OGRGeomFieldDefn* poFieldDefn = poFeatureDefn->GetGeomFieldDefn(i);
443                 int nSrcIndex = l_poSrcFeatureDefn->GetGeomFieldIndex(
444                                                     poFieldDefn->GetNameRef());
445                 if( nSrcIndex < 0 )
446                 {
447                     poFeatureDefn->DeleteGeomFieldDefn(i);
448                 }
449                 else
450                 {
451                     /* TODO: merge type, SRS, extent ? */
452 
453                     i++;
454                 }
455             }
456         }
457     }
458 
459     return poFeatureDefn;
460 }
461 
462 /************************************************************************/
463 /*                             GetGeomType()                            */
464 /************************************************************************/
465 
GetGeomType()466 OGRwkbGeometryType OGRUnionLayer::GetGeomType()
467 {
468     if( nGeomFields < 0 )
469         return wkbNone;
470     if( nGeomFields >= 1 && papoGeomFields[0]->bGeomTypeSet )
471     {
472         return papoGeomFields[0]->GetType();
473     }
474 
475     return OGRLayer::GetGeomType();
476 }
477 
478 /************************************************************************/
479 /*                    SetSpatialFilterToSourceLayer()                   */
480 /************************************************************************/
481 
SetSpatialFilterToSourceLayer(OGRLayer * poSrcLayer)482 void OGRUnionLayer::SetSpatialFilterToSourceLayer(OGRLayer* poSrcLayer)
483 {
484     if( m_iGeomFieldFilter >= 0 &&
485         m_iGeomFieldFilter < GetLayerDefn()->GetGeomFieldCount() )
486     {
487         int iSrcGeomField = poSrcLayer->GetLayerDefn()->GetGeomFieldIndex(
488             GetLayerDefn()->GetGeomFieldDefn(m_iGeomFieldFilter)->GetNameRef());
489         if( iSrcGeomField >= 0 )
490         {
491             poSrcLayer->SetSpatialFilter(iSrcGeomField, m_poFilterGeom);
492         }
493         else
494         {
495             poSrcLayer->SetSpatialFilter(nullptr);
496         }
497     }
498     else
499     {
500         poSrcLayer->SetSpatialFilter(nullptr);
501     }
502 }
503 
504 /************************************************************************/
505 /*                        ConfigureActiveLayer()                        */
506 /************************************************************************/
507 
ConfigureActiveLayer()508 void OGRUnionLayer::ConfigureActiveLayer()
509 {
510     AutoWarpLayerIfNecessary(iCurLayer);
511     ApplyAttributeFilterToSrcLayer(iCurLayer);
512     SetSpatialFilterToSourceLayer(papoSrcLayers[iCurLayer]);
513     papoSrcLayers[iCurLayer]->ResetReading();
514 
515     /* Establish map */
516     GetLayerDefn();
517     OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[iCurLayer]->GetLayerDefn();
518     CPLFree(panMap);
519     panMap = static_cast<int*>(CPLMalloc(poSrcFeatureDefn->GetFieldCount() * sizeof(int)));
520     for(int i=0; i < poSrcFeatureDefn->GetFieldCount(); i++)
521     {
522         OGRFieldDefn* poSrcFieldDefn = poSrcFeatureDefn->GetFieldDefn(i);
523         if( CSLFindString(papszIgnoredFields,
524                           poSrcFieldDefn->GetNameRef() ) == -1 )
525         {
526             panMap[i] =
527                 poFeatureDefn->GetFieldIndex(poSrcFieldDefn->GetNameRef());
528         }
529         else
530         {
531             panMap[i] = -1;
532         }
533     }
534 
535     if( papoSrcLayers[iCurLayer]->TestCapability(OLCIgnoreFields) )
536     {
537         char** papszIter = papszIgnoredFields;
538         char** papszFieldsSrc = nullptr;
539         while ( papszIter != nullptr && *papszIter != nullptr )
540         {
541             const char* pszFieldName = *papszIter;
542             if ( EQUAL(pszFieldName, "OGR_GEOMETRY") ||
543                  EQUAL(pszFieldName, "OGR_STYLE") ||
544                  poSrcFeatureDefn->GetFieldIndex(pszFieldName) >= 0 ||
545                  poSrcFeatureDefn->GetGeomFieldIndex(pszFieldName) >= 0 )
546             {
547                 papszFieldsSrc = CSLAddString(papszFieldsSrc, pszFieldName);
548             }
549             papszIter++;
550         }
551 
552         /* Attribute fields */
553         int* panSrcFieldsUsed = static_cast<int*>(CPLCalloc(sizeof(int),
554                                           poSrcFeatureDefn->GetFieldCount()));
555         for(int iField = 0;
556                 iField < poFeatureDefn->GetFieldCount(); iField++)
557         {
558             OGRFieldDefn* poFieldDefn = poFeatureDefn->GetFieldDefn(iField);
559             int iSrcField =
560                     poSrcFeatureDefn->GetFieldIndex(poFieldDefn->GetNameRef());
561             if (iSrcField >= 0)
562                 panSrcFieldsUsed[iSrcField] = TRUE;
563         }
564         for(int iSrcField = 0;
565                 iSrcField < poSrcFeatureDefn->GetFieldCount(); iSrcField ++)
566         {
567             if( !panSrcFieldsUsed[iSrcField] )
568             {
569                 OGRFieldDefn *poSrcDefn =
570                         poSrcFeatureDefn->GetFieldDefn( iSrcField );
571                 papszFieldsSrc =
572                         CSLAddString(papszFieldsSrc, poSrcDefn->GetNameRef());
573             }
574         }
575         CPLFree(panSrcFieldsUsed);
576 
577         /* geometry fields now */
578         panSrcFieldsUsed = static_cast<int*>(CPLCalloc(sizeof(int),
579                                     poSrcFeatureDefn->GetGeomFieldCount()));
580         for(int iField = 0;
581                 iField < poFeatureDefn->GetGeomFieldCount(); iField++)
582         {
583             OGRGeomFieldDefn* poFieldDefn = poFeatureDefn->GetGeomFieldDefn(iField);
584             int iSrcField =
585                     poSrcFeatureDefn->GetGeomFieldIndex(poFieldDefn->GetNameRef());
586             if (iSrcField >= 0)
587                 panSrcFieldsUsed[iSrcField] = TRUE;
588         }
589         for(int iSrcField = 0;
590                 iSrcField < poSrcFeatureDefn->GetGeomFieldCount(); iSrcField ++)
591         {
592             if( !panSrcFieldsUsed[iSrcField] )
593             {
594                 OGRGeomFieldDefn *poSrcDefn =
595                         poSrcFeatureDefn->GetGeomFieldDefn( iSrcField );
596                 papszFieldsSrc =
597                         CSLAddString(papszFieldsSrc, poSrcDefn->GetNameRef());
598             }
599         }
600         CPLFree(panSrcFieldsUsed);
601 
602         papoSrcLayers[iCurLayer]->SetIgnoredFields(
603             const_cast<const char**>(papszFieldsSrc));
604 
605         CSLDestroy(papszFieldsSrc);
606     }
607 }
608 
609 /************************************************************************/
610 /*                             ResetReading()                           */
611 /************************************************************************/
612 
ResetReading()613 void OGRUnionLayer::ResetReading()
614 {
615     iCurLayer = 0;
616     ConfigureActiveLayer();
617     nNextFID = 0;
618 }
619 
620 /************************************************************************/
621 /*                         AutoWarpLayerIfNecessary()                   */
622 /************************************************************************/
623 
AutoWarpLayerIfNecessary(int iLayer)624 void OGRUnionLayer::AutoWarpLayerIfNecessary(int iLayer)
625 {
626     if( !pabCheckIfAutoWrap[iLayer] )
627     {
628         pabCheckIfAutoWrap[iLayer] = TRUE;
629 
630         for(int i=0; i<GetLayerDefn()->GetGeomFieldCount();i++)
631         {
632             OGRSpatialReference* poSRS = GetLayerDefn()->GetGeomFieldDefn(i)->GetSpatialRef();
633             if( poSRS != nullptr )
634                 poSRS->Reference();
635 
636             OGRFeatureDefn* poSrcFeatureDefn = papoSrcLayers[iLayer]->GetLayerDefn();
637             int iSrcGeomField = poSrcFeatureDefn->GetGeomFieldIndex(
638                     GetLayerDefn()->GetGeomFieldDefn(i)->GetNameRef());
639             if( iSrcGeomField >= 0 )
640             {
641                 OGRSpatialReference* poSRS2 =
642                     poSrcFeatureDefn->GetGeomFieldDefn(iSrcGeomField)->GetSpatialRef();
643 
644                 if( (poSRS == nullptr && poSRS2 != nullptr) ||
645                     (poSRS != nullptr && poSRS2 == nullptr) )
646                 {
647                     CPLError(CE_Warning, CPLE_AppDefined,
648                             "SRS of geometry field '%s' layer %s not consistent with UnionLayer SRS",
649                             GetLayerDefn()->GetGeomFieldDefn(i)->GetNameRef(),
650                             papoSrcLayers[iLayer]->GetName());
651                 }
652                 else if (poSRS != nullptr && poSRS2 != nullptr &&
653                         poSRS != poSRS2 && !poSRS->IsSame(poSRS2))
654                 {
655                     CPLDebug("VRT", "SRS of geometry field '%s' layer %s not consistent with UnionLayer SRS. "
656                             "Trying auto warping",
657                             GetLayerDefn()->GetGeomFieldDefn(i)->GetNameRef(),
658                             papoSrcLayers[iLayer]->GetName());
659                     OGRCoordinateTransformation* poCT =
660                         OGRCreateCoordinateTransformation( poSRS2, poSRS );
661                     OGRCoordinateTransformation* poReversedCT = (poCT != nullptr) ?
662                         OGRCreateCoordinateTransformation( poSRS, poSRS2 ) : nullptr;
663                     if( poReversedCT != nullptr )
664                         papoSrcLayers[iLayer] = new OGRWarpedLayer(
665                                     papoSrcLayers[iLayer], iSrcGeomField, TRUE, poCT, poReversedCT);
666                     else
667                     {
668                         CPLError(CE_Warning, CPLE_AppDefined,
669                                  "AutoWarpLayerIfNecessary failed to create "
670                                  "poCT or poReversedCT.");
671                         if ( poCT != nullptr )
672                             delete poCT;
673                     }
674                 }
675             }
676 
677             if( poSRS != nullptr )
678                 poSRS->Release();
679         }
680     }
681 }
682 
683 /************************************************************************/
684 /*                           GetNextFeature()                           */
685 /************************************************************************/
686 
GetNextFeature()687 OGRFeature *OGRUnionLayer::GetNextFeature()
688 {
689     if( poFeatureDefn == nullptr ) GetLayerDefn();
690     if( iCurLayer < 0 )
691         ResetReading();
692 
693     if( iCurLayer == nSrcLayers )
694         return nullptr;
695 
696     while( true )
697     {
698         OGRFeature* poSrcFeature = papoSrcLayers[iCurLayer]->GetNextFeature();
699         if( poSrcFeature == nullptr )
700         {
701             iCurLayer ++;
702             if( iCurLayer < nSrcLayers )
703             {
704                 ConfigureActiveLayer();
705                 continue;
706             }
707             else
708                 break;
709         }
710 
711         OGRFeature* poFeature = TranslateFromSrcLayer(poSrcFeature);
712         delete poSrcFeature;
713 
714         if( (m_poFilterGeom == nullptr ||
715              FilterGeometry( poFeature->GetGeomFieldRef(m_iGeomFieldFilter) ) ) &&
716             (m_poAttrQuery == nullptr ||
717              m_poAttrQuery->Evaluate( poFeature )) )
718         {
719             return poFeature;
720         }
721 
722         delete poFeature;
723     }
724     return nullptr;
725 }
726 
727 /************************************************************************/
728 /*                             GetFeature()                             */
729 /************************************************************************/
730 
GetFeature(GIntBig nFeatureId)731 OGRFeature *OGRUnionLayer::GetFeature( GIntBig nFeatureId )
732 {
733     OGRFeature* poFeature = nullptr;
734 
735     if( !bPreserveSrcFID )
736     {
737         poFeature = OGRLayer::GetFeature(nFeatureId);
738     }
739     else
740     {
741         int iGeomFieldFilterSave = m_iGeomFieldFilter;
742         OGRGeometry* poGeomSave = m_poFilterGeom;
743         m_poFilterGeom = nullptr;
744         SetSpatialFilter(nullptr);
745 
746         for(int i=0;i<nSrcLayers;i++)
747         {
748             iCurLayer = i;
749             ConfigureActiveLayer();
750 
751             OGRFeature* poSrcFeature = papoSrcLayers[i]->GetFeature(nFeatureId);
752             if( poSrcFeature != nullptr )
753             {
754                 poFeature = TranslateFromSrcLayer(poSrcFeature);
755                 delete poSrcFeature;
756 
757                 break;
758             }
759         }
760 
761         SetSpatialFilter(iGeomFieldFilterSave, poGeomSave);
762         delete poGeomSave;
763 
764         ResetReading();
765     }
766 
767     return poFeature;
768 }
769 
770 /************************************************************************/
771 /*                          ICreateFeature()                             */
772 /************************************************************************/
773 
ICreateFeature(OGRFeature * poFeature)774 OGRErr OGRUnionLayer::ICreateFeature( OGRFeature* poFeature )
775 {
776     if( osSourceLayerFieldName.empty() )
777     {
778         CPLError(CE_Failure, CPLE_NotSupported,
779                  "CreateFeature() not supported when SourceLayerFieldName is not set");
780         return OGRERR_FAILURE;
781     }
782 
783     if( poFeature->GetFID() != OGRNullFID )
784     {
785         CPLError(CE_Failure, CPLE_NotSupported,
786                  "CreateFeature() not supported when FID is set");
787         return OGRERR_FAILURE;
788     }
789 
790     if( !poFeature->IsFieldSetAndNotNull(0) )
791     {
792         CPLError(CE_Failure, CPLE_NotSupported,
793                  "CreateFeature() not supported when '%s' field is not set",
794                  osSourceLayerFieldName.c_str());
795         return OGRERR_FAILURE;
796     }
797 
798     const char* pszSrcLayerName = poFeature->GetFieldAsString(0);
799     for(int i=0;i<nSrcLayers;i++)
800     {
801         if( strcmp(pszSrcLayerName, papoSrcLayers[i]->GetName()) == 0)
802         {
803             pabModifiedLayers[i] = TRUE;
804 
805             OGRFeature* poSrcFeature =
806                         new OGRFeature(papoSrcLayers[i]->GetLayerDefn());
807             poSrcFeature->SetFrom(poFeature, TRUE);
808             OGRErr eErr = papoSrcLayers[i]->CreateFeature(poSrcFeature);
809             if( eErr == OGRERR_NONE )
810                 poFeature->SetFID(poSrcFeature->GetFID());
811             delete poSrcFeature;
812             return eErr;
813         }
814     }
815 
816     CPLError(CE_Failure, CPLE_NotSupported,
817              "CreateFeature() not supported : '%s' source layer does not exist",
818              pszSrcLayerName);
819     return OGRERR_FAILURE;
820 }
821 
822 /************************************************************************/
823 /*                             ISetFeature()                             */
824 /************************************************************************/
825 
ISetFeature(OGRFeature * poFeature)826 OGRErr OGRUnionLayer::ISetFeature( OGRFeature* poFeature )
827 {
828     if( !bPreserveSrcFID )
829     {
830         CPLError(CE_Failure, CPLE_NotSupported,
831                  "SetFeature() not supported when PreserveSrcFID is OFF");
832         return OGRERR_FAILURE;
833     }
834 
835     if( osSourceLayerFieldName.empty() )
836     {
837         CPLError(CE_Failure, CPLE_NotSupported,
838                  "SetFeature() not supported when SourceLayerFieldName is not set");
839         return OGRERR_FAILURE;
840     }
841 
842     if( poFeature->GetFID() == OGRNullFID )
843     {
844         CPLError(CE_Failure, CPLE_NotSupported,
845                  "SetFeature() not supported when FID is not set");
846         return OGRERR_FAILURE;
847     }
848 
849     if( !poFeature->IsFieldSetAndNotNull(0) )
850     {
851         CPLError(CE_Failure, CPLE_NotSupported,
852                  "SetFeature() not supported when '%s' field is not set",
853                  osSourceLayerFieldName.c_str());
854         return OGRERR_FAILURE;
855     }
856 
857     const char* pszSrcLayerName = poFeature->GetFieldAsString(0);
858     for(int i=0;i<nSrcLayers;i++)
859     {
860         if( strcmp(pszSrcLayerName, papoSrcLayers[i]->GetName()) == 0)
861         {
862             pabModifiedLayers[i] = TRUE;
863 
864             OGRFeature* poSrcFeature =
865                         new OGRFeature(papoSrcLayers[i]->GetLayerDefn());
866             poSrcFeature->SetFrom(poFeature, TRUE);
867             poSrcFeature->SetFID(poFeature->GetFID());
868             OGRErr eErr = papoSrcLayers[i]->SetFeature(poSrcFeature);
869             delete poSrcFeature;
870             return eErr;
871         }
872     }
873 
874     CPLError(CE_Failure, CPLE_NotSupported,
875              "SetFeature() not supported : '%s' source layer does not exist",
876              pszSrcLayerName);
877     return OGRERR_FAILURE;
878 }
879 
880 /************************************************************************/
881 /*                           GetSpatialRef()                            */
882 /************************************************************************/
883 
GetSpatialRef()884 OGRSpatialReference *OGRUnionLayer::GetSpatialRef()
885 {
886     if( nGeomFields < 0 )
887         return nullptr;
888     if( nGeomFields >= 1 &&
889         papoGeomFields[0]->bSRSSet )
890         return papoGeomFields[0]->GetSpatialRef();
891 
892     if( poGlobalSRS == nullptr )
893     {
894         poGlobalSRS = papoSrcLayers[0]->GetSpatialRef();
895         if( poGlobalSRS != nullptr )
896             poGlobalSRS->Reference();
897     }
898     return poGlobalSRS;
899 }
900 
901 /************************************************************************/
902 /*                      GetAttrFilterPassThroughValue()                 */
903 /************************************************************************/
904 
GetAttrFilterPassThroughValue()905 int OGRUnionLayer::GetAttrFilterPassThroughValue()
906 {
907     if( m_poAttrQuery == nullptr )
908         return TRUE;
909 
910     if( bAttrFilterPassThroughValue >= 0)
911         return bAttrFilterPassThroughValue;
912 
913     char** papszUsedFields = m_poAttrQuery->GetUsedFields();
914     int bRet = TRUE;
915 
916     for(int iLayer = 0; iLayer < nSrcLayers; iLayer++)
917     {
918         OGRFeatureDefn* poSrcFeatureDefn =
919                                 papoSrcLayers[iLayer]->GetLayerDefn();
920         char** papszIter = papszUsedFields;
921         while( papszIter != nullptr && *papszIter != nullptr )
922         {
923             int bIsSpecial = FALSE;
924             for(int i = 0; i < SPECIAL_FIELD_COUNT; i++)
925             {
926                 if( EQUAL(*papszIter, SpecialFieldNames[i]) )
927                 {
928                     bIsSpecial = TRUE;
929                     break;
930                 }
931             }
932             if( !bIsSpecial &&
933                 poSrcFeatureDefn->GetFieldIndex(*papszIter) < 0 )
934             {
935                 bRet = FALSE;
936                 break;
937             }
938             papszIter ++;
939         }
940     }
941 
942     CSLDestroy(papszUsedFields);
943 
944     bAttrFilterPassThroughValue = bRet;
945 
946     return bRet;
947 }
948 
949 /************************************************************************/
950 /*                  ApplyAttributeFilterToSrcLayer()                    */
951 /************************************************************************/
952 
ApplyAttributeFilterToSrcLayer(int iSubLayer)953 void OGRUnionLayer::ApplyAttributeFilterToSrcLayer(int iSubLayer)
954 {
955     CPLAssert(iSubLayer >= 0 && iSubLayer < nSrcLayers);
956 
957     if( GetAttrFilterPassThroughValue() )
958         papoSrcLayers[iSubLayer]->SetAttributeFilter(pszAttributeFilter);
959     else
960         papoSrcLayers[iSubLayer]->SetAttributeFilter(nullptr);
961 }
962 
963 /************************************************************************/
964 /*                          GetFeatureCount()                           */
965 /************************************************************************/
966 
GetFeatureCount(int bForce)967 GIntBig OGRUnionLayer::GetFeatureCount( int bForce )
968 {
969     if (nFeatureCount >= 0 &&
970         m_poFilterGeom == nullptr && m_poAttrQuery == nullptr)
971     {
972         return nFeatureCount;
973     }
974 
975     if( !GetAttrFilterPassThroughValue() )
976         return OGRLayer::GetFeatureCount(bForce);
977 
978     GIntBig nRet = 0;
979     for(int i = 0; i < nSrcLayers; i++)
980     {
981         AutoWarpLayerIfNecessary(i);
982         ApplyAttributeFilterToSrcLayer(i);
983         SetSpatialFilterToSourceLayer(papoSrcLayers[i]);
984         nRet += papoSrcLayers[i]->GetFeatureCount(bForce);
985     }
986     ResetReading();
987     return nRet;
988 }
989 
990 /************************************************************************/
991 /*                         SetAttributeFilter()                         */
992 /************************************************************************/
993 
SetAttributeFilter(const char * pszAttributeFilterIn)994 OGRErr OGRUnionLayer::SetAttributeFilter( const char * pszAttributeFilterIn )
995 {
996     if( pszAttributeFilterIn == nullptr && pszAttributeFilter == nullptr)
997         return OGRERR_NONE;
998     if( pszAttributeFilterIn != nullptr && pszAttributeFilter != nullptr &&
999         strcmp(pszAttributeFilterIn, pszAttributeFilter) == 0)
1000         return OGRERR_NONE;
1001 
1002     if( poFeatureDefn == nullptr ) GetLayerDefn();
1003 
1004     bAttrFilterPassThroughValue = -1;
1005 
1006     OGRErr eErr = OGRLayer::SetAttributeFilter(pszAttributeFilterIn);
1007     if( eErr != OGRERR_NONE )
1008         return eErr;
1009 
1010     CPLFree(pszAttributeFilter);
1011     pszAttributeFilter = pszAttributeFilterIn ?
1012                                 CPLStrdup(pszAttributeFilterIn) : nullptr;
1013 
1014     if( iCurLayer >= 0 && iCurLayer < nSrcLayers)
1015         ApplyAttributeFilterToSrcLayer(iCurLayer);
1016 
1017     return OGRERR_NONE;
1018 }
1019 
1020 /************************************************************************/
1021 /*                           TestCapability()                           */
1022 /************************************************************************/
1023 
TestCapability(const char * pszCap)1024 int  OGRUnionLayer::TestCapability( const char * pszCap )
1025 {
1026     if( EQUAL(pszCap, OLCFastFeatureCount ) )
1027     {
1028         if( nFeatureCount >= 0 &&
1029             m_poFilterGeom == nullptr && m_poAttrQuery == nullptr )
1030             return TRUE;
1031 
1032         if( !GetAttrFilterPassThroughValue() )
1033             return FALSE;
1034 
1035         for(int i = 0; i < nSrcLayers; i++)
1036         {
1037             AutoWarpLayerIfNecessary(i);
1038             ApplyAttributeFilterToSrcLayer(i);
1039             SetSpatialFilterToSourceLayer(papoSrcLayers[i]);
1040             if( !papoSrcLayers[i]->TestCapability(pszCap) )
1041                 return FALSE;
1042         }
1043         return TRUE;
1044     }
1045 
1046     if( EQUAL(pszCap, OLCFastGetExtent ) )
1047     {
1048         if( nGeomFields >= 1 &&
1049             papoGeomFields[0]->sStaticEnvelope.IsInit() )
1050             return TRUE;
1051 
1052         for(int i = 0; i < nSrcLayers; i++)
1053         {
1054             AutoWarpLayerIfNecessary(i);
1055             if( !papoSrcLayers[i]->TestCapability(pszCap) )
1056                 return FALSE;
1057         }
1058         return TRUE;
1059     }
1060 
1061     if( EQUAL(pszCap, OLCFastSpatialFilter) )
1062     {
1063         for(int i = 0; i < nSrcLayers; i++)
1064         {
1065             AutoWarpLayerIfNecessary(i);
1066             ApplyAttributeFilterToSrcLayer(i);
1067             if( !papoSrcLayers[i]->TestCapability(pszCap) )
1068                 return FALSE;
1069         }
1070         return TRUE;
1071     }
1072 
1073     if( EQUAL(pszCap, OLCStringsAsUTF8) )
1074     {
1075         for(int i = 0; i < nSrcLayers; i++)
1076         {
1077             if( !papoSrcLayers[i]->TestCapability(pszCap) )
1078                 return FALSE;
1079         }
1080         return TRUE;
1081     }
1082 
1083     if( EQUAL(pszCap, OLCRandomRead ) )
1084     {
1085         if( !bPreserveSrcFID )
1086             return FALSE;
1087 
1088         for(int i = 0; i < nSrcLayers; i++)
1089         {
1090             if( !papoSrcLayers[i]->TestCapability(pszCap) )
1091                 return FALSE;
1092         }
1093         return TRUE;
1094     }
1095 
1096     if( EQUAL(pszCap, OLCRandomWrite ) )
1097     {
1098         if( !bPreserveSrcFID || osSourceLayerFieldName.empty())
1099             return FALSE;
1100 
1101         for(int i = 0; i < nSrcLayers; i++)
1102         {
1103             if( !papoSrcLayers[i]->TestCapability(pszCap) )
1104                 return FALSE;
1105         }
1106         return TRUE;
1107     }
1108 
1109     if( EQUAL(pszCap, OLCSequentialWrite ) )
1110     {
1111         if( osSourceLayerFieldName.empty())
1112             return FALSE;
1113 
1114         for(int i = 0; i < nSrcLayers; i++)
1115         {
1116             if( !papoSrcLayers[i]->TestCapability(pszCap) )
1117                 return FALSE;
1118         }
1119         return TRUE;
1120     }
1121 
1122     if( EQUAL(pszCap, OLCIgnoreFields) )
1123         return TRUE;
1124 
1125     if( EQUAL(pszCap,OLCCurveGeometries) )
1126         return TRUE;
1127 
1128     return FALSE;
1129 }
1130 
1131 /************************************************************************/
1132 /*                              GetExtent()                             */
1133 /************************************************************************/
1134 
GetExtent(int iGeomField,OGREnvelope * psExtent,int bForce)1135 OGRErr OGRUnionLayer::GetExtent(int iGeomField, OGREnvelope *psExtent, int bForce)
1136 {
1137     if( iGeomField >= 0 && iGeomField < nGeomFields &&
1138         papoGeomFields[iGeomField]->sStaticEnvelope.IsInit() )
1139     {
1140         *psExtent = papoGeomFields[iGeomField]->sStaticEnvelope;
1141         return OGRERR_NONE;
1142     }
1143 
1144     if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
1145     {
1146         CPLError(CE_Failure, CPLE_AppDefined,
1147                      "Invalid geometry field index : %d", iGeomField);
1148         return OGRERR_FAILURE;
1149     }
1150 
1151     int bInit = FALSE;
1152     for(int i = 0; i < nSrcLayers; i++)
1153     {
1154         AutoWarpLayerIfNecessary(i);
1155         int iSrcGeomField = papoSrcLayers[i]->GetLayerDefn()->GetGeomFieldIndex(
1156             GetLayerDefn()->GetGeomFieldDefn(iGeomField)->GetNameRef());
1157         if( iSrcGeomField >= 0 )
1158         {
1159             if( !bInit )
1160             {
1161                 if( papoSrcLayers[i]->GetExtent(iSrcGeomField, psExtent, bForce) == OGRERR_NONE )
1162                     bInit = TRUE;
1163             }
1164             else
1165             {
1166                 OGREnvelope sExtent;
1167                 if( papoSrcLayers[i]->GetExtent(iSrcGeomField, &sExtent, bForce) == OGRERR_NONE )
1168                 {
1169                     psExtent->Merge(sExtent);
1170                 }
1171             }
1172         }
1173     }
1174     return (bInit) ? OGRERR_NONE : OGRERR_FAILURE;
1175 }
1176 
1177 /************************************************************************/
1178 /*                             GetExtent()                              */
1179 /************************************************************************/
1180 
GetExtent(OGREnvelope * psExtent,int bForce)1181 OGRErr OGRUnionLayer::GetExtent( OGREnvelope *psExtent, int bForce )
1182 {
1183     return GetExtent(0, psExtent, bForce);
1184 }
1185 
1186 /************************************************************************/
1187 /*                          SetSpatialFilter()                          */
1188 /************************************************************************/
1189 
SetSpatialFilter(OGRGeometry * poGeomIn)1190 void OGRUnionLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
1191 {
1192     SetSpatialFilter(0, poGeomIn);
1193 }
1194 
1195 /************************************************************************/
1196 /*                         SetSpatialFilter()                           */
1197 /************************************************************************/
1198 
SetSpatialFilter(int iGeomField,OGRGeometry * poGeom)1199 void OGRUnionLayer::SetSpatialFilter( int iGeomField, OGRGeometry *poGeom )
1200 {
1201     if( iGeomField < 0 || iGeomField >= GetLayerDefn()->GetGeomFieldCount() )
1202     {
1203         if( poGeom != nullptr )
1204         {
1205             CPLError(CE_Failure, CPLE_AppDefined,
1206                         "Invalid geometry field index : %d", iGeomField);
1207             return;
1208         }
1209     }
1210 
1211     m_iGeomFieldFilter = iGeomField;
1212     if( InstallFilter( poGeom ) )
1213         ResetReading();
1214 
1215     if( iCurLayer >= 0 && iCurLayer < nSrcLayers)
1216     {
1217         SetSpatialFilterToSourceLayer(papoSrcLayers[iCurLayer]);
1218     }
1219 }
1220 
1221 /************************************************************************/
1222 /*                        TranslateFromSrcLayer()                       */
1223 /************************************************************************/
1224 
TranslateFromSrcLayer(OGRFeature * poSrcFeature)1225 OGRFeature* OGRUnionLayer::TranslateFromSrcLayer(OGRFeature* poSrcFeature)
1226 {
1227     CPLAssert(poSrcFeature->GetFieldCount() == 0 || panMap != nullptr);
1228     CPLAssert(iCurLayer >= 0 && iCurLayer < nSrcLayers);
1229 
1230     OGRFeature* poFeature = new OGRFeature(poFeatureDefn);
1231     poFeature->SetFrom(poSrcFeature, panMap, TRUE);
1232 
1233     if( !osSourceLayerFieldName.empty() &&
1234         !poFeatureDefn->GetFieldDefn(0)->IsIgnored() )
1235     {
1236         poFeature->SetField(0, papoSrcLayers[iCurLayer]->GetName());
1237     }
1238 
1239     for(int i=0;i<poFeatureDefn->GetGeomFieldCount();i++)
1240     {
1241         if( poFeatureDefn->GetGeomFieldDefn(i)->IsIgnored() )
1242             poFeature->SetGeomFieldDirectly(i, nullptr);
1243         else
1244         {
1245             OGRGeometry* poGeom = poFeature->GetGeomFieldRef(i);
1246             if( poGeom != nullptr )
1247             {
1248                 poGeom->assignSpatialReference(
1249                     poFeatureDefn->GetGeomFieldDefn(i)->GetSpatialRef());
1250             }
1251         }
1252     }
1253 
1254     if( bPreserveSrcFID )
1255         poFeature->SetFID(poSrcFeature->GetFID());
1256     else
1257         poFeature->SetFID(nNextFID ++);
1258     return poFeature;
1259 }
1260 
1261 /************************************************************************/
1262 /*                          SetIgnoredFields()                          */
1263 /************************************************************************/
1264 
SetIgnoredFields(const char ** papszFields)1265 OGRErr OGRUnionLayer::SetIgnoredFields( const char **papszFields )
1266 {
1267     OGRErr eErr = OGRLayer::SetIgnoredFields(papszFields);
1268     if( eErr != OGRERR_NONE )
1269         return eErr;
1270 
1271     CSLDestroy(papszIgnoredFields);
1272     papszIgnoredFields = papszFields ? CSLDuplicate(papszFields) : nullptr;
1273 
1274     return eErr;
1275 }
1276 
1277 /************************************************************************/
1278 /*                             SyncToDisk()                             */
1279 /************************************************************************/
1280 
SyncToDisk()1281 OGRErr OGRUnionLayer::SyncToDisk()
1282 {
1283     for(int i = 0; i < nSrcLayers; i++)
1284     {
1285         if (pabModifiedLayers[i])
1286         {
1287             papoSrcLayers[i]->SyncToDisk();
1288             pabModifiedLayers[i] = FALSE;
1289         }
1290     }
1291 
1292     return OGRERR_NONE;
1293 }
1294 
1295 #endif /* #ifndef DOXYGEN_SKIP */
1296