LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/generic - ogrlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1077 837 77.7 %
Date: 2012-12-26 Functions: 98 74 75.5 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrlayer.cpp 25268 2012-11-29 20:21:41Z 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                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogrsf_frmts.h"
      31                 : #include "ogr_api.h"
      32                 : #include "ogr_p.h"
      33                 : #include "ogr_attrind.h"
      34                 : #include "swq.h"
      35                 : 
      36                 : CPL_CVSID("$Id: ogrlayer.cpp 25268 2012-11-29 20:21:41Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                              OGRLayer()                              */
      40                 : /************************************************************************/
      41                 : 
      42           26188 : OGRLayer::OGRLayer()
      43                 : 
      44                 : {
      45           26188 :     m_poStyleTable = NULL;
      46           26188 :     m_poAttrQuery = NULL;
      47           26188 :     m_poAttrIndex = NULL;
      48           26188 :     m_nRefCount = 0;
      49                 : 
      50           26188 :     m_nFeaturesRead = 0;
      51                 : 
      52           26188 :     m_poFilterGeom = NULL;
      53           26188 :     m_bFilterIsEnvelope = FALSE;
      54           26188 :     m_pPreparedFilterGeom = NULL;
      55           26188 : }
      56                 : 
      57                 : /************************************************************************/
      58                 : /*                             ~OGRLayer()                              */
      59                 : /************************************************************************/
      60                 : 
      61           26188 : OGRLayer::~OGRLayer()
      62                 : 
      63                 : {
      64           26188 :     if ( m_poStyleTable )
      65                 :     {
      66               3 :         delete m_poStyleTable;
      67               3 :         m_poStyleTable = NULL;
      68                 :     }
      69                 : 
      70           26188 :     if( m_poAttrIndex != NULL )
      71                 :     {
      72              47 :         delete m_poAttrIndex;
      73              47 :         m_poAttrIndex = NULL;
      74                 :     }
      75                 : 
      76           26188 :     if( m_poAttrQuery != NULL )
      77                 :     {
      78              58 :         delete m_poAttrQuery;
      79              58 :         m_poAttrQuery = NULL;
      80                 :     }
      81                 : 
      82           26188 :     if( m_poFilterGeom )
      83                 :     {
      84              86 :         delete m_poFilterGeom;
      85              86 :         m_poFilterGeom = NULL;
      86                 :     }
      87                 : 
      88           26188 :     if( m_pPreparedFilterGeom != NULL )
      89                 :     {
      90              86 :         OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
      91              86 :         m_pPreparedFilterGeom = NULL;
      92                 :     }
      93           26188 : }
      94                 : 
      95                 : /************************************************************************/
      96                 : /*                             Reference()                              */
      97                 : /************************************************************************/
      98                 : 
      99               0 : int OGRLayer::Reference()
     100                 : 
     101                 : {
     102               0 :     return ++m_nRefCount;
     103                 : }
     104                 : 
     105                 : /************************************************************************/
     106                 : /*                          OGR_L_Reference()                           */
     107                 : /************************************************************************/
     108                 : 
     109               0 : int OGR_L_Reference( OGRLayerH hLayer )
     110                 : 
     111                 : {
     112               0 :     VALIDATE_POINTER1( hLayer, "OGR_L_Reference", 0 );
     113                 : 
     114               0 :     return ((OGRLayer *) hLayer)->Reference();
     115                 : }
     116                 : 
     117                 : /************************************************************************/
     118                 : /*                            Dereference()                             */
     119                 : /************************************************************************/
     120                 : 
     121               0 : int OGRLayer::Dereference()
     122                 : 
     123                 : {
     124               0 :     return --m_nRefCount;
     125                 : }
     126                 : 
     127                 : /************************************************************************/
     128                 : /*                         OGR_L_Dereference()                          */
     129                 : /************************************************************************/
     130                 : 
     131               0 : int OGR_L_Dereference( OGRLayerH hLayer )
     132                 : 
     133                 : {
     134               0 :     VALIDATE_POINTER1( hLayer, "OGR_L_Dereference", 0 );
     135                 : 
     136               0 :     return ((OGRLayer *) hLayer)->Dereference();
     137                 : }
     138                 : 
     139                 : /************************************************************************/
     140                 : /*                            GetRefCount()                             */
     141                 : /************************************************************************/
     142                 : 
     143              19 : int OGRLayer::GetRefCount() const
     144                 : 
     145                 : {
     146              19 :     return m_nRefCount;
     147                 : }
     148                 : 
     149                 : /************************************************************************/
     150                 : /*                         OGR_L_GetRefCount()                          */
     151                 : /************************************************************************/
     152                 : 
     153               0 : int OGR_L_GetRefCount( OGRLayerH hLayer )
     154                 : 
     155                 : {
     156               0 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetRefCount", 0 );
     157                 : 
     158               0 :     return ((OGRLayer *) hLayer)->GetRefCount();
     159                 : }
     160                 : 
     161                 : /************************************************************************/
     162                 : /*                          GetFeatureCount()                           */
     163                 : /************************************************************************/
     164                 : 
     165             536 : int OGRLayer::GetFeatureCount( int bForce )
     166                 : 
     167                 : {
     168                 :     OGRFeature     *poFeature;
     169             536 :     int            nFeatureCount = 0;
     170                 : 
     171             536 :     if( !bForce )
     172               0 :         return -1;
     173                 : 
     174             536 :     ResetReading();
     175          214063 :     while( (poFeature = GetNextFeature()) != NULL )
     176                 :     {
     177          212991 :         nFeatureCount++;
     178          212991 :         delete poFeature;
     179                 :     }
     180             536 :     ResetReading();
     181                 : 
     182             536 :     return nFeatureCount;
     183                 : }
     184                 : 
     185                 : /************************************************************************/
     186                 : /*                       OGR_L_GetFeatureCount()                        */
     187                 : /************************************************************************/
     188                 : 
     189             710 : int OGR_L_GetFeatureCount( OGRLayerH hLayer, int bForce )
     190                 : 
     191                 : {
     192             710 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetFeature", 0 );
     193                 : 
     194             710 :     return ((OGRLayer *) hLayer)->GetFeatureCount(bForce);
     195                 : }
     196                 : 
     197                 : /************************************************************************/
     198                 : /*                             GetExtent()                              */
     199                 : /************************************************************************/
     200                 : 
     201             210 : OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce )
     202                 : 
     203                 : {
     204                 :     OGRFeature  *poFeature;
     205             210 :     OGREnvelope oEnv;
     206             210 :     GBool       bExtentSet = FALSE;
     207                 : 
     208             210 :     psExtent->MinX = 0.0;
     209             210 :     psExtent->MaxX = 0.0;
     210             210 :     psExtent->MinY = 0.0;
     211             210 :     psExtent->MaxY = 0.0;
     212                 : 
     213                 : /* -------------------------------------------------------------------- */
     214                 : /*      If this layer has a none geometry type, then we can             */
     215                 : /*      reasonably assume there are not extents available.              */
     216                 : /* -------------------------------------------------------------------- */
     217             210 :     if( GetLayerDefn()->GetGeomType() == wkbNone )
     218              68 :         return OGRERR_FAILURE;
     219                 : 
     220                 : /* -------------------------------------------------------------------- */
     221                 : /*      If not forced, we should avoid having to scan all the           */
     222                 : /*      features and just return a failure.                             */
     223                 : /* -------------------------------------------------------------------- */
     224             142 :     if( !bForce )
     225               0 :         return OGRERR_FAILURE;
     226                 : 
     227                 : /* -------------------------------------------------------------------- */
     228                 : /*      OK, we hate to do this, but go ahead and read through all       */
     229                 : /*      the features to collect geometries and build extents.           */
     230                 : /* -------------------------------------------------------------------- */
     231             142 :     ResetReading();
     232           70732 :     while( (poFeature = GetNextFeature()) != NULL )
     233                 :     {
     234           70448 :         OGRGeometry *poGeom = poFeature->GetGeometryRef();
     235           70448 :         if (poGeom == NULL || poGeom->IsEmpty())
     236                 :         {
     237                 :             /* Do nothing */
     238                 :         }
     239           70026 :         else if (!bExtentSet)
     240                 :         {
     241             130 :             poGeom->getEnvelope(psExtent);
     242             130 :             bExtentSet = TRUE;
     243                 :         }
     244                 :         else
     245                 :         {
     246           69896 :             poGeom->getEnvelope(&oEnv);
     247           69896 :             if (oEnv.MinX < psExtent->MinX) 
     248             203 :                 psExtent->MinX = oEnv.MinX;
     249           69896 :             if (oEnv.MinY < psExtent->MinY) 
     250            2063 :                 psExtent->MinY = oEnv.MinY;
     251           69896 :             if (oEnv.MaxX > psExtent->MaxX) 
     252             306 :                 psExtent->MaxX = oEnv.MaxX;
     253           69896 :             if (oEnv.MaxY > psExtent->MaxY) 
     254             177 :                 psExtent->MaxY = oEnv.MaxY;
     255                 :         }
     256           70448 :         delete poFeature;
     257                 :     }
     258             142 :     ResetReading();
     259                 : 
     260             142 :     return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
     261                 : }
     262                 : 
     263                 : /************************************************************************/
     264                 : /*                          OGR_L_GetExtent()                           */
     265                 : /************************************************************************/
     266                 : 
     267             121 : OGRErr OGR_L_GetExtent( OGRLayerH hLayer, OGREnvelope *psExtent, int bForce )
     268                 : 
     269                 : {
     270             121 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetExtent", OGRERR_INVALID_HANDLE );
     271                 : 
     272             121 :     return ((OGRLayer *) hLayer)->GetExtent( psExtent, bForce );
     273                 : }
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                         SetAttributeFilter()                         */
     277                 : /************************************************************************/
     278                 : 
     279            2086 : OGRErr OGRLayer::SetAttributeFilter( const char *pszQuery )
     280                 : 
     281                 : {
     282                 : /* -------------------------------------------------------------------- */
     283                 : /*      Are we just clearing any existing query?                        */
     284                 : /* -------------------------------------------------------------------- */
     285            2086 :     if( pszQuery == NULL || strlen(pszQuery) == 0 )
     286                 :     {
     287            1240 :         if( m_poAttrQuery )
     288                 :         {
     289             385 :             delete m_poAttrQuery;
     290             385 :             m_poAttrQuery = NULL;
     291             385 :             ResetReading();
     292                 :         }
     293            1240 :         return OGRERR_NONE;
     294                 :     }
     295                 : 
     296                 : /* -------------------------------------------------------------------- */
     297                 : /*      Or are we installing a new query?                               */
     298                 : /* -------------------------------------------------------------------- */
     299                 :     OGRErr      eErr;
     300                 : 
     301             846 :     if( !m_poAttrQuery )
     302             443 :         m_poAttrQuery = new OGRFeatureQuery();
     303                 : 
     304             846 :     eErr = m_poAttrQuery->Compile( GetLayerDefn(), pszQuery );
     305             846 :     if( eErr != OGRERR_NONE )
     306                 :     {
     307               0 :         delete m_poAttrQuery;
     308               0 :         m_poAttrQuery = NULL;
     309                 :     }
     310                 : 
     311             846 :     ResetReading();
     312                 : 
     313             846 :     return eErr;
     314                 : }
     315                 : 
     316                 : /************************************************************************/
     317                 : /*                        ContainGeomSpecialField()                     */
     318                 : /************************************************************************/
     319                 : 
     320             918 : static int ContainGeomSpecialField(swq_expr_node* expr,
     321                 :                                    int nLayerFieldCount)
     322                 : {
     323             918 :     if (expr->eNodeType == SNT_COLUMN)
     324                 :     {
     325             149 :         if( expr->table_index == 0 && expr->field_index != -1 )
     326                 :         {
     327                 :             int nSpecialFieldIdx = expr->field_index -
     328             149 :                                     nLayerFieldCount;
     329                 :             return nSpecialFieldIdx == SPF_OGR_GEOMETRY ||
     330                 :                    nSpecialFieldIdx == SPF_OGR_GEOM_WKT ||
     331             149 :                    nSpecialFieldIdx == SPF_OGR_GEOM_AREA;
     332                 :         }
     333                 :     }
     334             769 :     else if (expr->eNodeType == SNT_OPERATION)
     335                 :     {
     336            1152 :         for( int i = 0; i < expr->nSubExprCount; i++ )
     337                 :         {
     338             773 :             if (ContainGeomSpecialField(expr->papoSubExpr[i],
     339                 :                                         nLayerFieldCount))
     340               0 :                 return TRUE;
     341                 :         }
     342                 :     }
     343             769 :     return FALSE;
     344                 : }
     345                 : 
     346                 : /************************************************************************/
     347                 : /*                AttributeFilterEvaluationNeedsGeometry()              */
     348                 : /************************************************************************/
     349                 : 
     350             145 : int OGRLayer::AttributeFilterEvaluationNeedsGeometry()
     351                 : {
     352             145 :     if( !m_poAttrQuery )
     353               0 :         return FALSE;
     354                 : 
     355             145 :     swq_expr_node* expr = (swq_expr_node *) m_poAttrQuery->GetSWGExpr();
     356             145 :     int nLayerFieldCount = GetLayerDefn()->GetFieldCount();
     357                 : 
     358             145 :     return ContainGeomSpecialField(expr, nLayerFieldCount);
     359                 : }
     360                 : 
     361                 : /************************************************************************/
     362                 : /*                      OGR_L_SetAttributeFilter()                      */
     363                 : /************************************************************************/
     364                 : 
     365             240 : OGRErr OGR_L_SetAttributeFilter( OGRLayerH hLayer, const char *pszQuery )
     366                 : 
     367                 : {
     368             240 :     VALIDATE_POINTER1( hLayer, "OGR_L_SetAttributeFilter", OGRERR_INVALID_HANDLE );
     369                 : 
     370             240 :     return ((OGRLayer *) hLayer)->SetAttributeFilter( pszQuery );
     371                 : }
     372                 : 
     373                 : /************************************************************************/
     374                 : /*                             GetFeature()                             */
     375                 : /************************************************************************/
     376                 : 
     377              87 : OGRFeature *OGRLayer::GetFeature( long nFID )
     378                 : 
     379                 : {
     380                 :     OGRFeature *poFeature;
     381                 : 
     382              87 :     ResetReading();
     383           48332 :     while( (poFeature = GetNextFeature()) != NULL )
     384                 :     {
     385           48171 :         if( poFeature->GetFID() == nFID )
     386              13 :             return poFeature;
     387                 :         else
     388           48158 :             delete poFeature;
     389                 :     }
     390                 :     
     391              74 :     return NULL;
     392                 : }
     393                 : 
     394                 : /************************************************************************/
     395                 : /*                          OGR_L_GetFeature()                          */
     396                 : /************************************************************************/
     397                 : 
     398              97 : OGRFeatureH OGR_L_GetFeature( OGRLayerH hLayer, long nFeatureId )
     399                 : 
     400                 : {
     401              97 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetFeature", NULL );
     402                 : 
     403              97 :     return (OGRFeatureH) ((OGRLayer *)hLayer)->GetFeature( nFeatureId );
     404                 : }
     405                 : 
     406                 : /************************************************************************/
     407                 : /*                           SetNextByIndex()                           */
     408                 : /************************************************************************/
     409                 : 
     410             197 : OGRErr OGRLayer::SetNextByIndex( long nIndex )
     411                 : 
     412                 : {
     413                 :     OGRFeature *poFeature;
     414                 : 
     415             197 :     if( nIndex < 0 )
     416              85 :         return OGRERR_FAILURE;
     417                 : 
     418             112 :     ResetReading();
     419          145790 :     while( nIndex-- > 0 )
     420                 :     {
     421          145651 :         poFeature = GetNextFeature();
     422          145651 :         if( poFeature == NULL )
     423              85 :             return OGRERR_FAILURE;
     424                 : 
     425          145566 :         delete poFeature;
     426                 :     }
     427                 : 
     428              27 :     return OGRERR_NONE;
     429                 : }
     430                 : 
     431                 : /************************************************************************/
     432                 : /*                        OGR_L_SetNextByIndex()                        */
     433                 : /************************************************************************/
     434                 : 
     435              10 : OGRErr OGR_L_SetNextByIndex( OGRLayerH hLayer, long nIndex )
     436                 : 
     437                 : {
     438              10 :     VALIDATE_POINTER1( hLayer, "OGR_L_SetNextByIndex", OGRERR_INVALID_HANDLE );
     439                 : 
     440              10 :     return ((OGRLayer *)hLayer)->SetNextByIndex( nIndex );
     441                 : }
     442                 : 
     443                 : /************************************************************************/
     444                 : /*                        OGR_L_GetNextFeature()                        */
     445                 : /************************************************************************/
     446                 : 
     447           87206 : OGRFeatureH OGR_L_GetNextFeature( OGRLayerH hLayer )
     448                 : 
     449                 : {
     450           87206 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetNextFeature", NULL );
     451                 : 
     452           87206 :     return (OGRFeatureH) ((OGRLayer *)hLayer)->GetNextFeature();
     453                 : }
     454                 : 
     455                 : /************************************************************************/
     456                 : /*                             SetFeature()                             */
     457                 : /************************************************************************/
     458                 : 
     459               0 : OGRErr OGRLayer::SetFeature( OGRFeature * )
     460                 : 
     461                 : {
     462               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     463                 : }
     464                 : 
     465                 : /************************************************************************/
     466                 : /*                          OGR_L_SetFeature()                          */
     467                 : /************************************************************************/
     468                 : 
     469            2057 : OGRErr OGR_L_SetFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
     470                 : 
     471                 : {
     472            2057 :     VALIDATE_POINTER1( hLayer, "OGR_L_SetFeature", OGRERR_INVALID_HANDLE );
     473            2057 :     VALIDATE_POINTER1( hFeat, "OGR_L_SetFeature", OGRERR_INVALID_HANDLE );
     474                 : 
     475            2057 :     return ((OGRLayer *)hLayer)->SetFeature( (OGRFeature *) hFeat );
     476                 : }
     477                 : 
     478                 : /************************************************************************/
     479                 : /*                           CreateFeature()                            */
     480                 : /************************************************************************/
     481                 : 
     482               0 : OGRErr OGRLayer::CreateFeature( OGRFeature * )
     483                 : 
     484                 : {
     485               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     486                 : }
     487                 : 
     488                 : /************************************************************************/
     489                 : /*                        OGR_L_CreateFeature()                         */
     490                 : /************************************************************************/
     491                 : 
     492           33973 : OGRErr OGR_L_CreateFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
     493                 : 
     494                 : {
     495           33973 :     VALIDATE_POINTER1( hLayer, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE );
     496           33973 :     VALIDATE_POINTER1( hFeat, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE );
     497                 : 
     498           33973 :     return ((OGRLayer *) hLayer)->CreateFeature( (OGRFeature *) hFeat );
     499                 : }
     500                 : 
     501                 : /************************************************************************/
     502                 : /*                              GetInfo()                               */
     503                 : /************************************************************************/
     504                 : 
     505               0 : const char *OGRLayer::GetInfo( const char * pszTag )
     506                 : 
     507                 : {
     508                 :     (void) pszTag;
     509               0 :     return NULL;
     510                 : }
     511                 : 
     512                 : /************************************************************************/
     513                 : /*                            CreateField()                             */
     514                 : /************************************************************************/
     515                 : 
     516               0 : OGRErr OGRLayer::CreateField( OGRFieldDefn * poField, int bApproxOK )
     517                 : 
     518                 : {
     519                 :     (void) poField;
     520                 :     (void) bApproxOK;
     521                 : 
     522                 :     CPLError( CE_Failure, CPLE_NotSupported,
     523               0 :               "CreateField() not supported by this layer.\n" );
     524                 :               
     525               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     526                 : }
     527                 : 
     528                 : /************************************************************************/
     529                 : /*                         OGR_L_CreateField()                          */
     530                 : /************************************************************************/
     531                 : 
     532            4754 : OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField, 
     533                 :                           int bApproxOK )
     534                 : 
     535                 : {
     536            4754 :     VALIDATE_POINTER1( hLayer, "OGR_L_CreateField", OGRERR_INVALID_HANDLE );
     537            4754 :     VALIDATE_POINTER1( hField, "OGR_L_CreateField", OGRERR_INVALID_HANDLE );
     538                 : 
     539                 :     return ((OGRLayer *) hLayer)->CreateField( (OGRFieldDefn *) hField, 
     540            4754 :                                                bApproxOK );
     541                 : }
     542                 : 
     543                 : /************************************************************************/
     544                 : /*                            DeleteField()                             */
     545                 : /************************************************************************/
     546                 : 
     547               0 : OGRErr OGRLayer::DeleteField( int iField )
     548                 : 
     549                 : {
     550                 :     (void) iField;
     551                 : 
     552                 :     CPLError( CE_Failure, CPLE_NotSupported,
     553               0 :               "DeleteField() not supported by this layer.\n" );
     554                 : 
     555               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     556                 : }
     557                 : 
     558                 : /************************************************************************/
     559                 : /*                         OGR_L_DeleteField()                          */
     560                 : /************************************************************************/
     561                 : 
     562              29 : OGRErr OGR_L_DeleteField( OGRLayerH hLayer, int iField )
     563                 : 
     564                 : {
     565              29 :     VALIDATE_POINTER1( hLayer, "OGR_L_DeleteField", OGRERR_INVALID_HANDLE );
     566                 : 
     567              29 :     return ((OGRLayer *) hLayer)->DeleteField( iField );
     568                 : }
     569                 : 
     570                 : /************************************************************************/
     571                 : /*                           ReorderFields()                            */
     572                 : /************************************************************************/
     573                 : 
     574               0 : OGRErr OGRLayer::ReorderFields( int* panMap )
     575                 : 
     576                 : {
     577                 :     (void) panMap;
     578                 : 
     579                 :     CPLError( CE_Failure, CPLE_NotSupported,
     580               0 :               "ReorderFields() not supported by this layer.\n" );
     581                 : 
     582               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     583                 : }
     584                 : 
     585                 : /************************************************************************/
     586                 : /*                       OGR_L_ReorderFields()                          */
     587                 : /************************************************************************/
     588                 : 
     589              15 : OGRErr OGR_L_ReorderFields( OGRLayerH hLayer, int* panMap )
     590                 : 
     591                 : {
     592              15 :     VALIDATE_POINTER1( hLayer, "OGR_L_ReorderFields", OGRERR_INVALID_HANDLE );
     593                 : 
     594              15 :     return ((OGRLayer *) hLayer)->ReorderFields( panMap );
     595                 : }
     596                 : 
     597                 : /************************************************************************/
     598                 : /*                            ReorderField()                            */
     599                 : /************************************************************************/
     600                 : 
     601              24 : OGRErr OGRLayer::ReorderField( int iOldFieldPos, int iNewFieldPos )
     602                 : 
     603                 : {
     604                 :     OGRErr eErr;
     605                 : 
     606              24 :     int nFieldCount = GetLayerDefn()->GetFieldCount();
     607                 : 
     608              24 :     if (iOldFieldPos < 0 || iOldFieldPos >= nFieldCount)
     609                 :     {
     610                 :         CPLError( CE_Failure, CPLE_NotSupported,
     611               0 :                   "Invalid field index");
     612               0 :         return OGRERR_FAILURE;
     613                 :     }
     614              24 :     if (iNewFieldPos < 0 || iNewFieldPos >= nFieldCount)
     615                 :     {
     616                 :         CPLError( CE_Failure, CPLE_NotSupported,
     617               0 :                   "Invalid field index");
     618               0 :         return OGRERR_FAILURE;
     619                 :     }
     620              24 :     if (iNewFieldPos == iOldFieldPos)
     621               0 :         return OGRERR_NONE;
     622                 : 
     623              24 :     int* panMap = (int*) CPLMalloc(sizeof(int) * nFieldCount);
     624                 :     int i;
     625              24 :     if (iOldFieldPos < iNewFieldPos)
     626                 :     {
     627                 :         /* "0","1","2","3","4" (1,3) -> "0","2","3","1","4" */
     628              12 :         for(i=0;i<iOldFieldPos;i++)
     629               3 :             panMap[i] = i;
     630              24 :         for(;i<iNewFieldPos;i++)
     631              15 :             panMap[i] = i + 1;
     632               9 :         panMap[iNewFieldPos] = iOldFieldPos;
     633              18 :         for(i=iNewFieldPos+1;i<nFieldCount;i++)
     634               9 :             panMap[i] = i;
     635                 :     }
     636                 :     else
     637                 :     {
     638                 :         /* "0","1","2","3","4" (3,1) -> "0","3","1","2","4" */
     639              18 :         for(i=0;i<iNewFieldPos;i++)
     640               3 :             panMap[i] = i;
     641              15 :         panMap[iNewFieldPos] = iOldFieldPos;
     642              54 :         for(i=iNewFieldPos+1;i<=iOldFieldPos;i++)
     643              39 :             panMap[i] = i - 1;
     644              24 :         for(;i<nFieldCount;i++)
     645               9 :             panMap[i] = i;
     646                 :     }
     647                 : 
     648              24 :     eErr = ReorderFields(panMap);
     649                 : 
     650              24 :     CPLFree(panMap);
     651                 : 
     652              24 :     return eErr;
     653                 : }
     654                 : 
     655                 : /************************************************************************/
     656                 : /*                        OGR_L_ReorderField()                          */
     657                 : /************************************************************************/
     658                 : 
     659              24 : OGRErr OGR_L_ReorderField( OGRLayerH hLayer, int iOldFieldPos, int iNewFieldPos )
     660                 : 
     661                 : {
     662              24 :     VALIDATE_POINTER1( hLayer, "OGR_L_ReorderField", OGRERR_INVALID_HANDLE );
     663                 : 
     664              24 :     return ((OGRLayer *) hLayer)->ReorderField( iOldFieldPos, iNewFieldPos );
     665                 : }
     666                 : 
     667                 : /************************************************************************/
     668                 : /*                           AlterFieldDefn()                           */
     669                 : /************************************************************************/
     670                 : 
     671               0 : OGRErr OGRLayer::AlterFieldDefn( int iField, OGRFieldDefn* poNewFieldDefn,
     672                 :                                  int nFlags )
     673                 : 
     674                 : {
     675                 :     (void) iField;
     676                 :     (void) poNewFieldDefn;
     677                 :     (void) nFlags;
     678                 : 
     679                 :     CPLError( CE_Failure, CPLE_NotSupported,
     680               0 :               "AlterFieldDefn() not supported by this layer.\n" );
     681                 : 
     682               0 :     return OGRERR_UNSUPPORTED_OPERATION;
     683                 : }
     684                 : 
     685                 : /************************************************************************/
     686                 : /*                        OGR_L_AlterFieldDefn()                        */
     687                 : /************************************************************************/
     688                 : 
     689              34 : OGRErr OGR_L_AlterFieldDefn( OGRLayerH hLayer, int iField, OGRFieldDefnH hNewFieldDefn,
     690                 :                              int nFlags )
     691                 : 
     692                 : {
     693              34 :     VALIDATE_POINTER1( hLayer, "OGR_L_AlterFieldDefn", OGRERR_INVALID_HANDLE );
     694              34 :     VALIDATE_POINTER1( hNewFieldDefn, "OGR_L_AlterFieldDefn", OGRERR_INVALID_HANDLE );
     695                 : 
     696              34 :     return ((OGRLayer *) hLayer)->AlterFieldDefn( iField, (OGRFieldDefn*) hNewFieldDefn, nFlags );
     697                 : }
     698                 : 
     699                 : /************************************************************************/
     700                 : /*                          StartTransaction()                          */
     701                 : /************************************************************************/
     702                 : 
     703             807 : OGRErr OGRLayer::StartTransaction()
     704                 : 
     705                 : {
     706             807 :     return OGRERR_NONE;
     707                 : }
     708                 : 
     709                 : /************************************************************************/
     710                 : /*                       OGR_L_StartTransaction()                       */
     711                 : /************************************************************************/
     712                 : 
     713              71 : OGRErr OGR_L_StartTransaction( OGRLayerH hLayer )
     714                 : 
     715                 : {
     716              71 :     VALIDATE_POINTER1( hLayer, "OGR_L_StartTransaction", OGRERR_INVALID_HANDLE );
     717                 : 
     718              71 :     return ((OGRLayer *)hLayer)->StartTransaction();
     719                 : }
     720                 : 
     721                 : /************************************************************************/
     722                 : /*                         CommitTransaction()                          */
     723                 : /************************************************************************/
     724                 : 
     725             784 : OGRErr OGRLayer::CommitTransaction()
     726                 : 
     727                 : {
     728             784 :     return OGRERR_NONE;
     729                 : }
     730                 : 
     731                 : /************************************************************************/
     732                 : /*                       OGR_L_CommitTransaction()                      */
     733                 : /************************************************************************/
     734                 : 
     735              68 : OGRErr OGR_L_CommitTransaction( OGRLayerH hLayer )
     736                 : 
     737                 : {
     738              68 :     VALIDATE_POINTER1( hLayer, "OGR_L_CommitTransaction", OGRERR_INVALID_HANDLE );
     739                 : 
     740              68 :     return ((OGRLayer *)hLayer)->CommitTransaction();
     741                 : }
     742                 : 
     743                 : /************************************************************************/
     744                 : /*                        RollbackTransaction()                         */
     745                 : /************************************************************************/
     746                 : 
     747              23 : OGRErr OGRLayer::RollbackTransaction()
     748                 : 
     749                 : {
     750              23 :     return OGRERR_UNSUPPORTED_OPERATION;
     751                 : }
     752                 : 
     753                 : /************************************************************************/
     754                 : /*                     OGR_L_RollbackTransaction()                      */
     755                 : /************************************************************************/
     756                 : 
     757               4 : OGRErr OGR_L_RollbackTransaction( OGRLayerH hLayer )
     758                 : 
     759                 : {
     760               4 :     VALIDATE_POINTER1( hLayer, "OGR_L_RollbackTransaction", OGRERR_INVALID_HANDLE );
     761                 : 
     762               4 :     return ((OGRLayer *)hLayer)->RollbackTransaction();
     763                 : }
     764                 : 
     765                 : /************************************************************************/
     766                 : /*                         OGR_L_GetLayerDefn()                         */
     767                 : /************************************************************************/
     768                 : 
     769           33274 : OGRFeatureDefnH OGR_L_GetLayerDefn( OGRLayerH hLayer )
     770                 : 
     771                 : {
     772           33274 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetLayerDefn", NULL );
     773                 : 
     774           33274 :     return (OGRFeatureDefnH) ((OGRLayer *)hLayer)->GetLayerDefn();
     775                 : }
     776                 : 
     777                 : /************************************************************************/
     778                 : /*                        OGR_L_GetSpatialRef()                         */
     779                 : /************************************************************************/
     780                 : 
     781             322 : OGRSpatialReferenceH OGR_L_GetSpatialRef( OGRLayerH hLayer )
     782                 : 
     783                 : {
     784             322 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetSpatialRef", NULL );
     785                 : 
     786             322 :     return (OGRSpatialReferenceH) ((OGRLayer *) hLayer)->GetSpatialRef();
     787                 : }
     788                 : 
     789                 : /************************************************************************/
     790                 : /*                        OGR_L_TestCapability()                        */
     791                 : /************************************************************************/
     792                 : 
     793             129 : int OGR_L_TestCapability( OGRLayerH hLayer, const char *pszCap )
     794                 : 
     795                 : {
     796             129 :     VALIDATE_POINTER1( hLayer, "OGR_L_TestCapability", 0 );
     797             129 :     VALIDATE_POINTER1( pszCap, "OGR_L_TestCapability", 0 );
     798                 : 
     799             129 :     return ((OGRLayer *) hLayer)->TestCapability( pszCap );
     800                 : }
     801                 : 
     802                 : /************************************************************************/
     803                 : /*                          GetSpatialFilter()                          */
     804                 : /************************************************************************/
     805                 : 
     806             119 : OGRGeometry *OGRLayer::GetSpatialFilter()
     807                 : 
     808                 : {
     809             119 :     return m_poFilterGeom;
     810                 : }
     811                 : 
     812                 : /************************************************************************/
     813                 : /*                       OGR_L_GetSpatialFilter()                       */
     814                 : /************************************************************************/
     815                 : 
     816               0 : OGRGeometryH OGR_L_GetSpatialFilter( OGRLayerH hLayer )
     817                 : 
     818                 : {
     819               0 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetSpatialFilter", NULL );
     820                 : 
     821               0 :     return (OGRGeometryH) ((OGRLayer *) hLayer)->GetSpatialFilter();
     822                 : }
     823                 : 
     824                 : /************************************************************************/
     825                 : /*                          SetSpatialFilter()                          */
     826                 : /************************************************************************/
     827                 : 
     828           19326 : void OGRLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
     829                 : 
     830                 : {
     831           19326 :     if( InstallFilter( poGeomIn ) )
     832           17774 :         ResetReading();
     833           19326 : }
     834                 : 
     835                 : /************************************************************************/
     836                 : /*                       OGR_L_SetSpatialFilter()                       */
     837                 : /************************************************************************/
     838                 : 
     839              65 : void OGR_L_SetSpatialFilter( OGRLayerH hLayer, OGRGeometryH hGeom )
     840                 : 
     841                 : {
     842              65 :     VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilter" );
     843                 : 
     844              65 :     ((OGRLayer *) hLayer)->SetSpatialFilter( (OGRGeometry *) hGeom );
     845                 : }
     846                 : 
     847                 : /************************************************************************/
     848                 : /*                        SetSpatialFilterRect()                        */
     849                 : /************************************************************************/
     850                 : 
     851           17530 : void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY, 
     852                 :                                      double dfMaxX, double dfMaxY )
     853                 : 
     854                 : {
     855           17530 :     OGRLinearRing  oRing;
     856           17530 :     OGRPolygon oPoly;
     857                 : 
     858           17530 :     oRing.addPoint( dfMinX, dfMinY );
     859           17530 :     oRing.addPoint( dfMinX, dfMaxY );
     860           17530 :     oRing.addPoint( dfMaxX, dfMaxY );
     861           17530 :     oRing.addPoint( dfMaxX, dfMinY );
     862           17530 :     oRing.addPoint( dfMinX, dfMinY );
     863                 : 
     864           17530 :     oPoly.addRing( &oRing );
     865                 : 
     866           17530 :     SetSpatialFilter( &oPoly );
     867           17530 : }
     868                 : 
     869                 : /************************************************************************/
     870                 : /*                     OGR_L_SetSpatialFilterRect()                     */
     871                 : /************************************************************************/
     872                 : 
     873           17522 : void OGR_L_SetSpatialFilterRect( OGRLayerH hLayer, 
     874                 :                                  double dfMinX, double dfMinY, 
     875                 :                                  double dfMaxX, double dfMaxY )
     876                 : 
     877                 : {
     878           17522 :     VALIDATE_POINTER0( hLayer, "OGR_L_SetSpatialFilterRect" );
     879                 : 
     880                 :     ((OGRLayer *) hLayer)->SetSpatialFilterRect( dfMinX, dfMinY, 
     881           17522 :                                                  dfMaxX, dfMaxY );
     882                 : }
     883                 : 
     884                 : /************************************************************************/
     885                 : /*                           InstallFilter()                            */
     886                 : /*                                                                      */
     887                 : /*      This method is only intended to be used from within             */
     888                 : /*      drivers, normally from the SetSpatialFilter() method.           */
     889                 : /*      It installs a filter, and also tests it to see if it is         */
     890                 : /*      rectangular.  If so, it this is kept track of alongside the     */
     891                 : /*      filter geometry itself so we can do cheaper comparisons in      */
     892                 : /*      the FilterGeometry() call.                                      */
     893                 : /*                                                                      */
     894                 : /*      Returns TRUE if the newly installed filter differs in some      */
     895                 : /*      way from the current one.                                       */
     896                 : /************************************************************************/
     897                 : 
     898           19524 : int OGRLayer::InstallFilter( OGRGeometry * poFilter )
     899                 : 
     900                 : {
     901           19524 :     if( m_poFilterGeom == NULL && poFilter == NULL )
     902            1656 :         return FALSE;
     903                 : 
     904                 : /* -------------------------------------------------------------------- */
     905                 : /*      Replace the existing filter.                                    */
     906                 : /* -------------------------------------------------------------------- */
     907           17868 :     if( m_poFilterGeom != NULL )
     908                 :     {
     909           17680 :         delete m_poFilterGeom;
     910           17680 :         m_poFilterGeom = NULL;
     911                 :     }
     912                 : 
     913           17868 :     if( m_pPreparedFilterGeom != NULL )
     914                 :     {
     915           17680 :         OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
     916           17680 :         m_pPreparedFilterGeom = NULL;
     917                 :     }
     918                 : 
     919           17868 :     if( poFilter != NULL )
     920           17766 :         m_poFilterGeom = poFilter->clone();
     921                 : 
     922           17868 :     m_bFilterIsEnvelope = FALSE;
     923                 : 
     924           17868 :     if( m_poFilterGeom == NULL )
     925             102 :         return TRUE;
     926                 : 
     927           17766 :     if( m_poFilterGeom != NULL )
     928           17766 :         m_poFilterGeom->getEnvelope( &m_sFilterEnvelope );
     929                 : 
     930                 :     /* Compile geometry filter as a prepared geometry */
     931           17766 :     m_pPreparedFilterGeom = OGRCreatePreparedGeometry(m_poFilterGeom);
     932                 : 
     933                 : /* -------------------------------------------------------------------- */
     934                 : /*      Now try to determine if the filter is really a rectangle.       */
     935                 : /* -------------------------------------------------------------------- */
     936           17766 :     if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
     937              12 :         return TRUE;
     938                 : 
     939           17754 :     OGRPolygon *poPoly = (OGRPolygon *) m_poFilterGeom;
     940                 : 
     941           17754 :     if( poPoly->getNumInteriorRings() != 0 )
     942               0 :         return TRUE;
     943                 : 
     944           17754 :     OGRLinearRing *poRing = poPoly->getExteriorRing();
     945           17754 :     if (poRing == NULL)
     946               0 :         return TRUE;
     947                 : 
     948           17754 :     if( poRing->getNumPoints() > 5 || poRing->getNumPoints() < 4 )
     949               0 :         return TRUE;
     950                 : 
     951                 :     // If the ring has 5 points, the last should be the first. 
     952           17754 :     if( poRing->getNumPoints() == 5 
     953                 :         && ( poRing->getX(0) != poRing->getX(4)
     954                 :              || poRing->getY(0) != poRing->getY(4) ) )
     955               0 :         return TRUE;
     956                 : 
     957                 :     // Polygon with first segment in "y" direction. 
     958           17754 :     if( poRing->getX(0) == poRing->getX(1)
     959                 :         && poRing->getY(1) == poRing->getY(2)
     960                 :         && poRing->getX(2) == poRing->getX(3)
     961                 :         && poRing->getY(3) == poRing->getY(0) )
     962           17669 :         m_bFilterIsEnvelope = TRUE;
     963                 : 
     964                 :     // Polygon with first segment in "x" direction. 
     965           17754 :     if( poRing->getY(0) == poRing->getY(1)
     966                 :         && poRing->getX(1) == poRing->getX(2)
     967                 :         && poRing->getY(2) == poRing->getY(3)
     968                 :         && poRing->getX(3) == poRing->getX(0) )
     969            1146 :         m_bFilterIsEnvelope = TRUE;
     970                 : 
     971           17754 :     return TRUE;
     972                 : }
     973                 : 
     974                 : /************************************************************************/
     975                 : /*                           FilterGeometry()                           */
     976                 : /*                                                                      */
     977                 : /*      Compare the passed in geometry to the currently installed       */
     978                 : /*      filter.  Optimize for case where filter is just an              */
     979                 : /*      envelope.                                                       */
     980                 : /************************************************************************/
     981                 : 
     982          178502 : int OGRLayer::FilterGeometry( OGRGeometry *poGeometry )
     983                 : 
     984                 : {
     985                 : /* -------------------------------------------------------------------- */
     986                 : /*      In trivial cases of new filter or target geometry, we accept    */
     987                 : /*      an intersection.  No geometry is taken to mean "the whole       */
     988                 : /*      world".                                                         */
     989                 : /* -------------------------------------------------------------------- */
     990          178502 :     if( m_poFilterGeom == NULL )
     991              28 :         return TRUE;
     992                 : 
     993          178474 :     if( poGeometry == NULL )
     994             427 :         return TRUE;
     995                 : 
     996                 : /* -------------------------------------------------------------------- */
     997                 : /*      Compute the target geometry envelope, and if there is no        */
     998                 : /*      intersection between the envelopes we are sure not to have      */
     999                 : /*      any intersection.                                               */
    1000                 : /* -------------------------------------------------------------------- */
    1001          178047 :     OGREnvelope sGeomEnv;
    1002                 : 
    1003          178047 :     poGeometry->getEnvelope( &sGeomEnv );
    1004                 : 
    1005          178047 :     if( sGeomEnv.MaxX < m_sFilterEnvelope.MinX
    1006                 :         || sGeomEnv.MaxY < m_sFilterEnvelope.MinY
    1007                 :         || m_sFilterEnvelope.MaxX < sGeomEnv.MinX
    1008                 :         || m_sFilterEnvelope.MaxY < sGeomEnv.MinY )
    1009          108598 :         return FALSE;
    1010                 : 
    1011                 : 
    1012                 : /* -------------------------------------------------------------------- */
    1013                 : /*      If the filter geometry is its own envelope and if the           */
    1014                 : /*      envelope of the geometry is inside the filter geometry,         */
    1015                 : /*      the geometry itself is inside the filter geometry               */
    1016                 : /* -------------------------------------------------------------------- */
    1017           69449 :     if( m_bFilterIsEnvelope &&
    1018                 :         sGeomEnv.MinX >= m_sFilterEnvelope.MinX &&
    1019                 :         sGeomEnv.MinY >= m_sFilterEnvelope.MinY &&
    1020                 :         sGeomEnv.MaxX <= m_sFilterEnvelope.MaxX &&
    1021                 :         sGeomEnv.MaxY <= m_sFilterEnvelope.MaxY)
    1022                 :     {
    1023           56041 :         return TRUE;
    1024                 :     }
    1025                 :     else
    1026                 :     {
    1027                 : /* -------------------------------------------------------------------- */
    1028                 : /*      If the filter geometry is its own envelope and if the           */
    1029                 : /*      the geometry (line, or polygon without hole) h has at least one */
    1030                 : /*      point inside the filter geometry, the geometry itself is inside */
    1031                 : /*      the filter geometry.                                            */
    1032                 : /* -------------------------------------------------------------------- */
    1033           13408 :         if( m_bFilterIsEnvelope )
    1034                 :         {
    1035           13394 :             OGRLineString* poLS = NULL;
    1036                 : 
    1037           13394 :             switch( wkbFlatten(poGeometry->getGeometryType()) )
    1038                 :             {
    1039                 :                 case wkbPolygon:
    1040                 :                 {
    1041            5767 :                     OGRPolygon* poPoly = (OGRPolygon* )poGeometry;
    1042            5767 :                     OGRLinearRing* poRing = poPoly->getExteriorRing();
    1043            5767 :                     if (poRing != NULL && poPoly->getNumInteriorRings() == 0)
    1044                 :                     {
    1045            5444 :                         poLS = poRing;
    1046                 :                     }
    1047            5767 :                     break;
    1048                 :                 }
    1049                 : 
    1050                 :                 case wkbLineString:
    1051            7626 :                     poLS = (OGRLineString* )poGeometry;
    1052                 :                     break;
    1053                 : 
    1054                 :                 default:
    1055                 :                     break;
    1056                 :             }
    1057                 : 
    1058           13394 :             if( poLS != NULL )
    1059                 :             {
    1060           13070 :                 int nNumPoints = poLS->getNumPoints();
    1061          426447 :                 for(int i = 0; i < nNumPoints; i++)
    1062                 :                 {
    1063          424453 :                     double x = poLS->getX(i);
    1064          424453 :                     double y = poLS->getY(i);
    1065          424453 :                     if (x >= m_sFilterEnvelope.MinX &&
    1066                 :                         y >= m_sFilterEnvelope.MinY &&
    1067                 :                         x <= m_sFilterEnvelope.MaxX &&
    1068                 :                         y <= m_sFilterEnvelope.MaxY)
    1069                 :                     {
    1070           11076 :                         return TRUE;
    1071                 :                     }
    1072                 :                 }
    1073                 :             }
    1074                 :         }
    1075                 : 
    1076                 : /* -------------------------------------------------------------------- */
    1077                 : /*      Fallback to full intersect test (using GEOS) if we still        */
    1078                 : /*      don't know for sure.                                            */
    1079                 : /* -------------------------------------------------------------------- */
    1080            2332 :         if( OGRGeometryFactory::haveGEOS() )
    1081                 :         {
    1082                 :             //CPLDebug("OGRLayer", "GEOS intersection");
    1083            2332 :             if( m_pPreparedFilterGeom != NULL )
    1084                 :                 return OGRPreparedGeometryIntersects(m_pPreparedFilterGeom,
    1085            2332 :                                                      poGeometry);
    1086                 :             else
    1087               0 :                 return m_poFilterGeom->Intersects( poGeometry );
    1088                 :         }
    1089                 :         else
    1090               0 :             return TRUE;
    1091                 :     }
    1092                 : }
    1093                 : 
    1094                 : /************************************************************************/
    1095                 : /*                         OGR_L_ResetReading()                         */
    1096                 : /************************************************************************/
    1097                 : 
    1098           18975 : void OGR_L_ResetReading( OGRLayerH hLayer )
    1099                 : 
    1100                 : {
    1101           18975 :     VALIDATE_POINTER0( hLayer, "OGR_L_ResetReading" );
    1102                 : 
    1103           18975 :     ((OGRLayer *) hLayer)->ResetReading();
    1104                 : }
    1105                 : 
    1106                 : /************************************************************************/
    1107                 : /*                       InitializeIndexSupport()                       */
    1108                 : /*                                                                      */
    1109                 : /*      This is only intended to be called by driver layer              */
    1110                 : /*      implementations but we don't make it protected so that the      */
    1111                 : /*      datasources can do it too if that is more appropriate.          */
    1112                 : /************************************************************************/
    1113                 : 
    1114             477 : OGRErr OGRLayer::InitializeIndexSupport( const char *pszFilename )
    1115                 : 
    1116                 : {
    1117                 :     OGRErr eErr;
    1118                 : 
    1119             477 :     if (m_poAttrIndex != NULL)
    1120             430 :         return OGRERR_NONE;
    1121                 : 
    1122              47 :     m_poAttrIndex = OGRCreateDefaultLayerIndex();
    1123                 : 
    1124              47 :     eErr = m_poAttrIndex->Initialize( pszFilename, this );
    1125              47 :     if( eErr != OGRERR_NONE )
    1126                 :     {
    1127               0 :         delete m_poAttrIndex;
    1128               0 :         m_poAttrIndex = NULL;
    1129                 :     }
    1130                 : 
    1131              47 :     return eErr;
    1132                 : }
    1133                 : 
    1134                 : /************************************************************************/
    1135                 : /*                             SyncToDisk()                             */
    1136                 : /************************************************************************/
    1137                 : 
    1138               0 : OGRErr OGRLayer::SyncToDisk()
    1139                 : 
    1140                 : {
    1141               0 :     return OGRERR_NONE;
    1142                 : }
    1143                 : 
    1144                 : /************************************************************************/
    1145                 : /*                          OGR_L_SyncToDisk()                          */
    1146                 : /************************************************************************/
    1147                 : 
    1148               3 : OGRErr OGR_L_SyncToDisk( OGRLayerH hDS )
    1149                 : 
    1150                 : {
    1151               3 :     VALIDATE_POINTER1( hDS, "OGR_L_SyncToDisk", OGRERR_INVALID_HANDLE );
    1152                 : 
    1153               3 :     return ((OGRLayer *) hDS)->SyncToDisk();
    1154                 : }
    1155                 : 
    1156                 : /************************************************************************/
    1157                 : /*                           DeleteFeature()                            */
    1158                 : /************************************************************************/
    1159                 : 
    1160               0 : OGRErr OGRLayer::DeleteFeature( long nFID )
    1161                 : 
    1162                 : {
    1163               0 :     return OGRERR_UNSUPPORTED_OPERATION;
    1164                 : }
    1165                 : 
    1166                 : /************************************************************************/
    1167                 : /*                        OGR_L_DeleteFeature()                         */
    1168                 : /************************************************************************/
    1169                 : 
    1170              38 : OGRErr OGR_L_DeleteFeature( OGRLayerH hDS, long nFID )
    1171                 : 
    1172                 : {
    1173              38 :     VALIDATE_POINTER1( hDS, "OGR_L_DeleteFeature", OGRERR_INVALID_HANDLE );
    1174                 : 
    1175              38 :     return ((OGRLayer *) hDS)->DeleteFeature( nFID );
    1176                 : }
    1177                 : 
    1178                 : /************************************************************************/
    1179                 : /*                          GetFeaturesRead()                           */
    1180                 : /************************************************************************/
    1181                 : 
    1182               0 : GIntBig OGRLayer::GetFeaturesRead()
    1183                 : 
    1184                 : {
    1185               0 :     return m_nFeaturesRead;
    1186                 : }
    1187                 : 
    1188                 : /************************************************************************/
    1189                 : /*                       OGR_L_GetFeaturesRead()                        */
    1190                 : /************************************************************************/
    1191                 : 
    1192               0 : GIntBig OGR_L_GetFeaturesRead( OGRLayerH hLayer )
    1193                 : 
    1194                 : {
    1195               0 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetFeaturesRead", 0 );
    1196                 : 
    1197               0 :     return ((OGRLayer *) hLayer)->GetFeaturesRead();
    1198                 : }
    1199                 : 
    1200                 : /************************************************************************/
    1201                 : /*                             GetFIDColumn                             */
    1202                 : /************************************************************************/
    1203                 : 
    1204              19 : const char *OGRLayer::GetFIDColumn()
    1205                 : 
    1206                 : {
    1207              19 :     return "";
    1208                 : }
    1209                 : 
    1210                 : /************************************************************************/
    1211                 : /*                         OGR_L_GetFIDColumn()                         */
    1212                 : /************************************************************************/
    1213                 : 
    1214              21 : const char *OGR_L_GetFIDColumn( OGRLayerH hLayer )
    1215                 : 
    1216                 : {
    1217              21 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetFIDColumn", NULL );
    1218                 : 
    1219              21 :     return ((OGRLayer *) hLayer)->GetFIDColumn();
    1220                 : }
    1221                 : 
    1222                 : /************************************************************************/
    1223                 : /*                         GetGeometryColumn()                          */
    1224                 : /************************************************************************/
    1225                 : 
    1226             759 : const char *OGRLayer::GetGeometryColumn()
    1227                 : 
    1228                 : {
    1229             759 :     return "";
    1230                 : }
    1231                 : 
    1232                 : /************************************************************************/
    1233                 : /*                      OGR_L_GetGeometryColumn()                       */
    1234                 : /************************************************************************/
    1235                 : 
    1236              29 : const char *OGR_L_GetGeometryColumn( OGRLayerH hLayer )
    1237                 : 
    1238                 : {
    1239              29 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetGeometryColumn", NULL );
    1240                 : 
    1241              29 :     return ((OGRLayer *) hLayer)->GetGeometryColumn();
    1242                 : }
    1243                 : 
    1244                 : /************************************************************************/
    1245                 : /*                            GetStyleTable()                           */
    1246                 : /************************************************************************/
    1247                 : 
    1248             124 : OGRStyleTable *OGRLayer::GetStyleTable()
    1249                 : {
    1250             124 :     return m_poStyleTable;
    1251                 : }
    1252                 : 
    1253                 : /************************************************************************/
    1254                 : /*                         SetStyleTableDirectly()                      */
    1255                 : /************************************************************************/
    1256                 : 
    1257               0 : void OGRLayer::SetStyleTableDirectly( OGRStyleTable *poStyleTable )
    1258                 : {
    1259               0 :     if ( m_poStyleTable )
    1260               0 :         delete m_poStyleTable;
    1261               0 :     m_poStyleTable = poStyleTable;
    1262               0 : }
    1263                 : 
    1264                 : /************************************************************************/
    1265                 : /*                            SetStyleTable()                           */
    1266                 : /************************************************************************/
    1267                 : 
    1268             124 : void OGRLayer::SetStyleTable(OGRStyleTable *poStyleTable)
    1269                 : {
    1270             124 :     if ( m_poStyleTable )
    1271               0 :         delete m_poStyleTable;
    1272             124 :     if ( poStyleTable )
    1273               0 :         m_poStyleTable = poStyleTable->Clone();
    1274             124 : }
    1275                 : 
    1276                 : /************************************************************************/
    1277                 : /*                         OGR_L_GetStyleTable()                        */
    1278                 : /************************************************************************/
    1279                 : 
    1280               0 : OGRStyleTableH OGR_L_GetStyleTable( OGRLayerH hLayer )
    1281                 : 
    1282                 : {
    1283               0 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetStyleTable", NULL );
    1284                 :     
    1285               0 :     return (OGRStyleTableH) ((OGRLayer *) hLayer)->GetStyleTable( );
    1286                 : }
    1287                 : 
    1288                 : /************************************************************************/
    1289                 : /*                         OGR_L_SetStyleTableDirectly()                */
    1290                 : /************************************************************************/
    1291                 : 
    1292               0 : void OGR_L_SetStyleTableDirectly( OGRLayerH hLayer,
    1293                 :                                   OGRStyleTableH hStyleTable )
    1294                 : 
    1295                 : {
    1296               0 :     VALIDATE_POINTER0( hLayer, "OGR_L_SetStyleTableDirectly" );
    1297                 :     
    1298               0 :     ((OGRLayer *) hLayer)->SetStyleTableDirectly( (OGRStyleTable *) hStyleTable);
    1299                 : }
    1300                 : 
    1301                 : /************************************************************************/
    1302                 : /*                         OGR_L_SetStyleTable()                        */
    1303                 : /************************************************************************/
    1304                 : 
    1305               0 : void OGR_L_SetStyleTable( OGRLayerH hLayer,
    1306                 :                           OGRStyleTableH hStyleTable )
    1307                 : 
    1308                 : {
    1309               0 :     VALIDATE_POINTER0( hLayer, "OGR_L_SetStyleTable" );
    1310               0 :     VALIDATE_POINTER0( hStyleTable, "OGR_L_SetStyleTable" );
    1311                 :     
    1312               0 :     ((OGRLayer *) hLayer)->SetStyleTable( (OGRStyleTable *) hStyleTable);
    1313                 : }
    1314                 : 
    1315                 : /************************************************************************/
    1316                 : /*                               GetName()                              */
    1317                 : /************************************************************************/
    1318                 : 
    1319         1059405 : const char *OGRLayer::GetName()
    1320                 : 
    1321                 : {
    1322         1059405 :     return GetLayerDefn()->GetName();
    1323                 : }
    1324                 : 
    1325                 : /************************************************************************/
    1326                 : /*                           OGR_L_GetName()                            */
    1327                 : /************************************************************************/
    1328                 : 
    1329            4158 : const char* OGR_L_GetName( OGRLayerH hLayer )
    1330                 : 
    1331                 : {
    1332            4158 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetName", "" );
    1333                 : 
    1334            4158 :     return ((OGRLayer *) hLayer)->GetName();
    1335                 : }
    1336                 : 
    1337                 : /************************************************************************/
    1338                 : /*                            GetGeomType()                             */
    1339                 : /************************************************************************/
    1340                 : 
    1341            1937 : OGRwkbGeometryType OGRLayer::GetGeomType()
    1342                 : {
    1343            1937 :     return GetLayerDefn()->GetGeomType();
    1344                 : }
    1345                 : /************************************************************************/
    1346                 : /*                         OGR_L_GetGeomType()                          */
    1347                 : /************************************************************************/
    1348                 : 
    1349             116 : OGRwkbGeometryType OGR_L_GetGeomType( OGRLayerH hLayer )
    1350                 : 
    1351                 : {
    1352             116 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetGeomType", wkbUnknown );
    1353                 : 
    1354             116 :     return ((OGRLayer *) hLayer)->GetGeomType();
    1355                 : }
    1356                 : 
    1357                 : /************************************************************************/
    1358                 : /*                          SetIgnoredFields()                          */
    1359                 : /************************************************************************/
    1360                 : 
    1361            1490 : OGRErr OGRLayer::SetIgnoredFields( const char **papszFields )
    1362                 : {
    1363            1490 :     OGRFeatureDefn *poDefn = GetLayerDefn();
    1364                 : 
    1365                 :     // first set everything as *not* ignored
    1366            7634 :     for( int iField = 0; iField < poDefn->GetFieldCount(); iField++ )
    1367                 :     {
    1368            6144 :         poDefn->GetFieldDefn(iField)->SetIgnored( FALSE );
    1369                 :     }
    1370            1490 :     poDefn->SetGeometryIgnored( FALSE );
    1371            1490 :     poDefn->SetStyleIgnored( FALSE );
    1372                 :     
    1373            1490 :     if ( papszFields == NULL )
    1374            1255 :         return OGRERR_NONE;
    1375                 : 
    1376                 :     // ignore some fields
    1377            1477 :     while ( *papszFields )
    1378                 :     {
    1379            1007 :         const char* pszFieldName = *papszFields;
    1380                 :         // check special fields
    1381            1007 :         if ( EQUAL(pszFieldName, "OGR_GEOMETRY") )
    1382              27 :             poDefn->SetGeometryIgnored( TRUE );
    1383             980 :         else if ( EQUAL(pszFieldName, "OGR_STYLE") )
    1384               2 :             poDefn->SetStyleIgnored( TRUE );
    1385                 :         else
    1386                 :         {
    1387                 :             // check ordinary fields
    1388             978 :             int iField = poDefn->GetFieldIndex(pszFieldName);
    1389             978 :             if ( iField == -1 )
    1390               0 :                 return OGRERR_FAILURE;
    1391                 :             else
    1392             978 :                 poDefn->GetFieldDefn(iField)->SetIgnored( TRUE );
    1393                 :         }
    1394            1007 :         papszFields++;
    1395                 :     }
    1396                 : 
    1397             235 :     return OGRERR_NONE;
    1398                 : }
    1399                 : 
    1400                 : /************************************************************************/
    1401                 : /*                       OGR_L_SetIgnoredFields()                       */
    1402                 : /************************************************************************/
    1403                 : 
    1404               4 : OGRErr OGR_L_SetIgnoredFields( OGRLayerH hLayer, const char **papszFields )
    1405                 : 
    1406                 : {
    1407               4 :     VALIDATE_POINTER1( hLayer, "OGR_L_SetIgnoredFields", OGRERR_INVALID_HANDLE );
    1408                 : 
    1409               4 :     return ((OGRLayer *) hLayer)->SetIgnoredFields( papszFields );
    1410                 : }
    1411                 : 
    1412                 : /************************************************************************/
    1413                 : /*         helper functions for layer overlay methods                   */
    1414                 : /************************************************************************/
    1415                 : 
    1416               9 : OGRErr clone_spatial_filter(OGRLayer *pLayer, OGRGeometry **ppGeometry)
    1417                 : {
    1418               9 :     OGRErr ret = OGRERR_NONE;
    1419               9 :     OGRGeometry *g = pLayer->GetSpatialFilter();
    1420               9 :     *ppGeometry = g ? g->clone() : NULL;
    1421               9 :     return ret;
    1422                 : }
    1423                 : 
    1424              12 : OGRErr create_field_map(OGRFeatureDefn *poDefn, int **map)
    1425                 : {
    1426              12 :     OGRErr ret = OGRERR_NONE;
    1427              12 :     int n = poDefn->GetFieldCount();
    1428              12 :     if (n > 0) {
    1429               0 :         *map = (int*)VSIMalloc(sizeof(int) * n);
    1430               0 :         if (!(*map)) return OGRERR_NOT_ENOUGH_MEMORY;
    1431                 :     }
    1432              12 :     return ret;
    1433                 : }
    1434                 : 
    1435               7 : OGRErr set_result_schema(OGRLayer *pLayerResult,
    1436                 :                          OGRFeatureDefn *poDefnInput, 
    1437                 :                          OGRFeatureDefn *poDefnMethod,
    1438                 :                          int *mapInput,
    1439                 :                          int *mapMethod,
    1440                 :                          int combined)
    1441                 : {
    1442               7 :     OGRErr ret = OGRERR_NONE;
    1443               7 :     OGRFeatureDefn *poDefnResult = pLayerResult->GetLayerDefn();
    1444               7 :     if (poDefnResult->GetFieldCount() > 0) {
    1445                 :         // the user has defined the schema of the output layer
    1446               0 :         for( int iField = 0; iField < poDefnInput->GetFieldCount(); iField++ ) {
    1447               0 :             mapInput[iField] = poDefnResult->GetFieldIndex(poDefnInput->GetFieldDefn(iField)->GetNameRef());
    1448                 :         }
    1449               0 :         if (!mapMethod) return ret;
    1450               0 :         for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
    1451               0 :             mapMethod[iField] = poDefnResult->GetFieldIndex(poDefnMethod->GetFieldDefn(iField)->GetNameRef());
    1452                 :         }
    1453                 :     } else {
    1454                 :         // use schema from the input layer or from input and method layers
    1455               7 :         int nFieldsInput = poDefnInput->GetFieldCount();
    1456               7 :         for( int iField = 0; iField < nFieldsInput; iField++ ) {
    1457               0 :             ret = pLayerResult->CreateField(poDefnInput->GetFieldDefn(iField));
    1458               0 :             if (ret != OGRERR_NONE) return ret;
    1459               0 :             mapInput[iField] = iField;
    1460                 :         }
    1461               7 :         if (!combined) return ret;
    1462               4 :         if (!mapMethod) return ret;
    1463               0 :         for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
    1464               0 :             ret = pLayerResult->CreateField(poDefnMethod->GetFieldDefn(iField));
    1465               0 :             if (ret != OGRERR_NONE) return ret;
    1466               0 :             mapMethod[iField] = nFieldsInput+iField;
    1467                 :         }
    1468                 :     }
    1469               0 :     return ret;
    1470                 : }
    1471                 : 
    1472              16 : OGRGeometry *set_filter_from(OGRLayer *pLayer, OGRGeometry *pGeometryExistingFilter, OGRFeature *pFeature)
    1473                 : {
    1474              16 :     OGRGeometry *geom = pFeature->GetGeometryRef();
    1475              16 :     if (!geom) return NULL;
    1476              16 :     if (pGeometryExistingFilter) {
    1477               0 :         if (!geom->Intersects(pGeometryExistingFilter)) return NULL;
    1478               0 :         OGRGeometry *intersection = geom->Intersection(pGeometryExistingFilter);
    1479               0 :         pLayer->SetSpatialFilter(intersection);
    1480               0 :         if (intersection) delete intersection;
    1481                 :     } else {
    1482              16 :         pLayer->SetSpatialFilter(geom);
    1483                 :     }
    1484              16 :     return geom;
    1485                 : }
    1486                 : 
    1487                 : /************************************************************************/
    1488                 : /*                          Intersection()                              */
    1489                 : /************************************************************************/
    1490                 : /**
    1491                 :  * \brief Intersection of two layers.
    1492                 :  *
    1493                 :  * The result layer contains features whose geometries represent areas
    1494                 :  * that are common between features in the input layer and in the
    1495                 :  * method layer. The features in the result layer have attributes from
    1496                 :  * both input and method layers. The schema of the result layer can be
    1497                 :  * set by the user or, if it is empty, is initialized to contain all
    1498                 :  * fields in the input and method layers.
    1499                 :  *
    1500                 :  * \note If the schema of the result is set by user and contains
    1501                 :  * fields that have the same name as a field in input and in method
    1502                 :  * layer, then the attribute in the result feature will get the value
    1503                 :  * from the feature of the method layer.
    1504                 :  *
    1505                 :  * \note For best performance use the minimum amount of features in
    1506                 :  * the method layer and copy it into a memory layer.
    1507                 :  *
    1508                 :  * \note This method relies on GEOS support. Do not use unless the
    1509                 :  * GEOS support is compiled in.
    1510                 :  *
    1511                 :  * This method is the same as the C function OGR_L_Intersection().
    1512                 :  *
    1513                 :  * @param pLayerMethod the method layer. Should not be NULL.
    1514                 :  *
    1515                 :  * @param pLayerResult the layer where the features resulting from the
    1516                 :  * operation are inserted. Should not be NULL. See above the note
    1517                 :  * about the schema.
    1518                 :  *
    1519                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    1520                 :  *
    1521                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    1522                 :  * reporting progress or NULL.
    1523                 :  *
    1524                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    1525                 :  *
    1526                 :  * @return an error code if there was an error or the execution was
    1527                 :  * interrupted, OGRERR_NONE otherwise.
    1528                 :  *
    1529                 :  * @since OGR 1.10
    1530                 :  */
    1531                 : 
    1532               1 : OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod, 
    1533                 :                                OGRLayer *pLayerResult, 
    1534                 :                                char** papszOptions, 
    1535                 :                                GDALProgressFunc pfnProgress, 
    1536                 :                                void * pProgressArg )
    1537                 : {
    1538               1 :     OGRErr ret = OGRERR_NONE;
    1539               1 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    1540               1 :     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
    1541               1 :     OGRFeatureDefn *poDefnResult = NULL;
    1542               1 :     OGRGeometry *pGeometryMethodFilter = NULL;
    1543               1 :     int *mapInput = NULL;
    1544               1 :     int *mapMethod = NULL;
    1545               1 :     OGREnvelope sEnvelopeMethod;
    1546                 :     GBool bEnvelopeSet;
    1547               1 :     double progress_max = GetFeatureCount(0);
    1548               1 :     double progress_counter = 0;
    1549               1 :     double progress_ticker = 0;
    1550                 : 
    1551                 :     // check for GEOS
    1552               1 :     if (!OGRGeometryFactory::haveGEOS()) {
    1553               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    1554                 :     }
    1555                 : 
    1556                 :     // get resources
    1557               1 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    1558               1 :     if (ret != OGRERR_NONE) goto done;
    1559               1 :     ret = create_field_map(poDefnInput, &mapInput);
    1560               1 :     if (ret != OGRERR_NONE) goto done;
    1561               1 :     ret = create_field_map(poDefnMethod, &mapMethod);
    1562               1 :     if (ret != OGRERR_NONE) goto done;
    1563               1 :     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1);
    1564               1 :     if (ret != OGRERR_NONE) goto done;
    1565               1 :     poDefnResult = pLayerResult->GetLayerDefn();
    1566               1 :     bEnvelopeSet = pLayerMethod->GetExtent(&sEnvelopeMethod, 1) == OGRERR_NONE;
    1567                 : 
    1568               1 :     ResetReading();
    1569               5 :     while (OGRFeature *x = GetNextFeature()) {
    1570                 : 
    1571               2 :         if (pfnProgress) {
    1572               0 :             double p = progress_counter/progress_max;
    1573               0 :             if (p > progress_ticker) {
    1574               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    1575               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    1576               0 :                     ret = OGRERR_FAILURE;
    1577               0 :                     delete x;
    1578               0 :                     goto done;
    1579                 :                 }
    1580               0 :                 progress_ticker += 0.01;
    1581                 :             }
    1582               0 :             progress_counter += 1.0;
    1583                 :         }
    1584                 : 
    1585                 :         // is it worth to proceed?
    1586               2 :         if (bEnvelopeSet) {
    1587               2 :             OGRGeometry *x_geom = x->GetGeometryRef();
    1588               2 :             if (x_geom) {
    1589               2 :                 OGREnvelope x_env;
    1590               2 :                 x_geom->getEnvelope(&x_env);
    1591               2 :                 if (x_env.MaxX < sEnvelopeMethod.MinX 
    1592                 :                     || x_env.MaxY < sEnvelopeMethod.MinY
    1593                 :                     || sEnvelopeMethod.MaxX < x_env.MinX
    1594                 :                     || sEnvelopeMethod.MaxY < x_env.MinY) {
    1595               0 :                     delete x;
    1596               0 :                     continue;
    1597                 :                 }
    1598                 :             } else {
    1599               0 :                 delete x;
    1600               0 :                 continue;
    1601                 :             }
    1602                 :         }
    1603                 : 
    1604                 :         // set up the filter for method layer
    1605               2 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    1606               2 :         if (!x_geom) {
    1607               0 :             delete x;
    1608               0 :             continue;
    1609                 :         }
    1610                 : 
    1611               2 :         pLayerMethod->ResetReading();
    1612               6 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    1613               2 :             OGRGeometry *y_geom = y->GetGeometryRef();
    1614               2 :             if (!y_geom) {delete y; continue;}
    1615               2 :             OGRFeature *z = new OGRFeature(poDefnResult);
    1616               2 :             z->SetFieldsFrom(x, mapInput);
    1617               2 :             z->SetFieldsFrom(y, mapMethod);
    1618               2 :             z->SetGeometryDirectly(x_geom->Intersection(y_geom));
    1619               4 :             delete y;
    1620               2 :             ret = pLayerResult->CreateFeature(z);
    1621               2 :             delete z;
    1622               2 :             if (ret != OGRERR_NONE) {delete x; goto done;}
    1623                 :         }
    1624                 : 
    1625               4 :         delete x;
    1626                 :     }
    1627               1 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    1628               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    1629               0 :       ret = OGRERR_FAILURE;
    1630                 :       goto done;
    1631                 :     }
    1632                 : done:
    1633                 :     // release resources
    1634               1 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    1635               1 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    1636               1 :     if (mapInput) VSIFree(mapInput);
    1637               1 :     if (mapMethod) VSIFree(mapMethod);
    1638               1 :     return ret;
    1639                 : }
    1640                 : 
    1641                 : /************************************************************************/
    1642                 : /*                       OGR_L_Intersection()                           */
    1643                 : /************************************************************************/
    1644                 : /**
    1645                 :  * \brief Intersection of two layers.
    1646                 :  *
    1647                 :  * The result layer contains features whose geometries represent areas
    1648                 :  * that are common between features in the input layer and in the
    1649                 :  * method layer. The features in the result layer have attributes from
    1650                 :  * both input and method layers. The schema of the result layer can be
    1651                 :  * set by the user or, if it is empty, is initialized to contain all
    1652                 :  * fields in the input and method layers.
    1653                 :  *
    1654                 :  * \note If the schema of the result is set by user and contains
    1655                 :  * fields that have the same name as a field in input and in method
    1656                 :  * layer, then the attribute in the result feature will get the value
    1657                 :  * from the feature of the method layer.
    1658                 :  *
    1659                 :  * \note For best performance use the minimum amount of features in
    1660                 :  * the method layer and copy it into a memory layer.
    1661                 :  *
    1662                 :  * \note This method relies on GEOS support. Do not use unless the
    1663                 :  * GEOS support is compiled in.
    1664                 :  *
    1665                 :  * This function is the same as the C++ method OGRLayer::Intersection().
    1666                 :  * 
    1667                 :  * @param pLayerInput the input layer. Should not be NULL.
    1668                 :  *
    1669                 :  * @param pLayerMethod the method layer. Should not be NULL.
    1670                 :  *
    1671                 :  * @param pLayerResult the layer where the features resulting from the
    1672                 :  * operation are inserted. Should not be NULL. See above the note
    1673                 :  * about the schema.
    1674                 :  *
    1675                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    1676                 :  *
    1677                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    1678                 :  * reporting progress or NULL.
    1679                 :  *
    1680                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    1681                 :  *
    1682                 :  * @return an error code if there was an error or the execution was
    1683                 :  * interrupted, OGRERR_NONE otherwise.
    1684                 :  *
    1685                 :  * @since OGR 1.10
    1686                 :  */
    1687                 : 
    1688               1 : OGRErr OGR_L_Intersection( OGRLayerH pLayerInput, 
    1689                 :                            OGRLayerH pLayerMethod, 
    1690                 :                            OGRLayerH pLayerResult, 
    1691                 :                            char** papszOptions, 
    1692                 :                            GDALProgressFunc pfnProgress, 
    1693                 :                            void * pProgressArg )
    1694                 : 
    1695                 : {
    1696               1 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
    1697               1 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
    1698               1 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
    1699                 : 
    1700               1 :     return ((OGRLayer *)pLayerInput)->Intersection( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    1701                 : }
    1702                 : 
    1703                 : /************************************************************************/
    1704                 : /*                              Union()                                 */
    1705                 : /************************************************************************/
    1706                 : 
    1707                 : /**
    1708                 :  * \brief Union of two layers.
    1709                 :  *
    1710                 :  * The result layer contains features whose geometries represent areas
    1711                 :  * that are in either in the input layer or in the method layer. The
    1712                 :  * features in the result layer have attributes from both input and
    1713                 :  * method layers. For features which represent areas that are only in
    1714                 :  * the input or in the method layer the respective attributes have
    1715                 :  * undefined values. The schema of the result layer can be set by the
    1716                 :  * user or, if it is empty, is initialized to contain all fields in
    1717                 :  * the input and method layers.
    1718                 :  *
    1719                 :  * \note If the schema of the result is set by user and contains
    1720                 :  * fields that have the same name as a field in input and in method
    1721                 :  * layer, then the attribute in the result feature will get the value
    1722                 :  * from the feature of the method layer (even if it is undefined).
    1723                 :  *
    1724                 :  * \note For best performance use the minimum amount of features in
    1725                 :  * the method layer and copy it into a memory layer.
    1726                 :  *
    1727                 :  * \note This method relies on GEOS support. Do not use unless the
    1728                 :  * GEOS support is compiled in.
    1729                 :  *
    1730                 :  * This method is the same as the C function OGR_L_Union().
    1731                 :  * 
    1732                 :  * @param pLayerMethod the method layer. Should not be NULL.
    1733                 :  *
    1734                 :  * @param pLayerResult the layer where the features resulting from the
    1735                 :  * operation are inserted. Should not be NULL. See above the note
    1736                 :  * about the schema.
    1737                 :  *
    1738                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    1739                 :  *
    1740                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    1741                 :  * reporting progress or NULL.
    1742                 :  *
    1743                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    1744                 :  *
    1745                 :  * @return an error code if there was an error or the execution was
    1746                 :  * interrupted, OGRERR_NONE otherwise.
    1747                 :  *
    1748                 :  * @since OGR 1.10
    1749                 :  */
    1750                 : 
    1751               1 : OGRErr OGRLayer::Union( OGRLayer *pLayerMethod, 
    1752                 :                         OGRLayer *pLayerResult, 
    1753                 :                         char** papszOptions, 
    1754                 :                         GDALProgressFunc pfnProgress, 
    1755                 :                         void * pProgressArg )
    1756                 : {
    1757               1 :     OGRErr ret = OGRERR_NONE;
    1758               1 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    1759               1 :     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
    1760               1 :     OGRFeatureDefn *poDefnResult = NULL;
    1761               1 :     OGRGeometry *pGeometryMethodFilter = NULL;
    1762               1 :     OGRGeometry *pGeometryInputFilter = NULL;
    1763               1 :     int *mapInput = NULL;
    1764               1 :     int *mapMethod = NULL;
    1765               1 :     double progress_max = GetFeatureCount(0) + pLayerMethod->GetFeatureCount(0);
    1766               1 :     double progress_counter = 0;
    1767               1 :     double progress_ticker = 0;
    1768                 :     
    1769                 :     // check for GEOS
    1770               1 :     if (!OGRGeometryFactory::haveGEOS()) {
    1771               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    1772                 :     }
    1773                 : 
    1774                 :     // get resources
    1775               1 :     ret = clone_spatial_filter(this, &pGeometryInputFilter);
    1776               1 :     if (ret != OGRERR_NONE) goto done;
    1777               1 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    1778               1 :     if (ret != OGRERR_NONE) goto done;
    1779               1 :     ret = create_field_map(poDefnInput, &mapInput);
    1780               1 :     if (ret != OGRERR_NONE) goto done;
    1781               1 :     ret = create_field_map(poDefnMethod, &mapMethod);
    1782               1 :     if (ret != OGRERR_NONE) goto done;
    1783               1 :     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1);
    1784               1 :     if (ret != OGRERR_NONE) goto done;
    1785               1 :     poDefnResult = pLayerResult->GetLayerDefn();
    1786                 : 
    1787                 :     // add features based on input layer
    1788               1 :     ResetReading();
    1789               5 :     while (OGRFeature *x = GetNextFeature()) {
    1790                 : 
    1791               2 :         if (pfnProgress) {
    1792               0 :             double p = progress_counter/progress_max;
    1793               0 :             if (p > progress_ticker) {
    1794               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    1795               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    1796               0 :                     ret = OGRERR_FAILURE;
    1797               0 :                     delete x;
    1798               0 :                     goto done;
    1799                 :                 }
    1800               0 :                 progress_ticker += 0.01;
    1801                 :             }
    1802               0 :             progress_counter += 1.0;
    1803                 :         }
    1804                 : 
    1805                 :         // set up the filter on method layer
    1806               2 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    1807               2 :         if (!x_geom) {
    1808               0 :             delete x; 
    1809               0 :             continue;
    1810                 :         }
    1811                 :         
    1812               2 :         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
    1813               2 :         pLayerMethod->ResetReading();
    1814               6 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    1815               2 :             OGRGeometry *y_geom = y->GetGeometryRef();
    1816               2 :             if (!y_geom) {delete y; continue;}
    1817               2 :             OGRFeature *z = new OGRFeature(poDefnResult);
    1818               2 :             z->SetFieldsFrom(x, mapInput);
    1819               2 :             z->SetFieldsFrom(y, mapMethod);
    1820               2 :             z->SetGeometryDirectly(x_geom->Intersection(y_geom));
    1821               4 :             OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
    1822               2 :             if (x_geom_diff) delete x_geom_diff;
    1823               2 :             x_geom_diff = x_geom_diff_new;
    1824               2 :             delete y;
    1825               2 :             ret = pLayerResult->CreateFeature(z);
    1826               2 :             delete z;
    1827               2 :             if (ret != OGRERR_NONE) {delete x; if (x_geom_diff) delete x_geom_diff; goto done;}
    1828                 :         }
    1829                 : 
    1830               4 :         OGRFeature *z = new OGRFeature(poDefnResult);
    1831               2 :         z->SetFieldsFrom(x, mapInput);
    1832               2 :         z->SetGeometryDirectly(x_geom_diff);
    1833               4 :         delete x;
    1834               2 :         ret = pLayerResult->CreateFeature(z);
    1835               2 :         delete z;
    1836               2 :         if (ret != OGRERR_NONE) goto done;
    1837                 :     }
    1838                 : 
    1839                 :     // restore filter on method layer and add features based on it
    1840               1 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    1841               1 :     pLayerMethod->ResetReading();
    1842               3 :     while (OGRFeature *x = pLayerMethod->GetNextFeature()) {
    1843                 : 
    1844               1 :         if (pfnProgress) {
    1845               0 :             double p = progress_counter/progress_max;
    1846               0 :             if (p > progress_ticker) {
    1847               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    1848               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    1849               0 :                     ret = OGRERR_FAILURE;
    1850               0 :                     delete x;
    1851               0 :                     goto done;
    1852                 :                 }
    1853               0 :                 progress_ticker += 0.01;
    1854                 :             }
    1855               0 :             progress_counter += 1.0;
    1856                 :         }
    1857                 : 
    1858                 :         // set up the filter on input layer
    1859               1 :         OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
    1860               1 :         if (!x_geom) {
    1861               0 :             delete x; 
    1862               0 :             continue;
    1863                 :         }
    1864                 :         
    1865               1 :         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
    1866               1 :         ResetReading();
    1867               5 :         while (OGRFeature *y = GetNextFeature()) {
    1868               2 :             OGRGeometry *y_geom = y->GetGeometryRef();
    1869               2 :             if (!y_geom) {delete y; continue;}
    1870               2 :             OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
    1871               2 :             if (x_geom_diff) delete x_geom_diff;
    1872               2 :             x_geom_diff = x_geom_diff_new;
    1873               2 :             delete y;
    1874                 :         }
    1875                 : 
    1876               2 :         OGRFeature *z = new OGRFeature(poDefnResult);
    1877               1 :         z->SetFieldsFrom(x, mapMethod);
    1878               1 :         z->SetGeometryDirectly(x_geom_diff);
    1879               2 :         delete x;
    1880               1 :         ret = pLayerResult->CreateFeature(z);
    1881               1 :         delete z;
    1882               1 :         if (ret != OGRERR_NONE) goto done;
    1883                 :     }
    1884               1 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    1885               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    1886               0 :       ret = OGRERR_FAILURE;
    1887                 :       goto done;
    1888                 :     }
    1889                 : done:
    1890                 :     // release resources
    1891               1 :     SetSpatialFilter(pGeometryInputFilter);
    1892               1 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    1893               1 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    1894               1 :     if (pGeometryInputFilter) delete pGeometryInputFilter;
    1895               1 :     if (mapInput) VSIFree(mapInput);
    1896               1 :     if (mapMethod) VSIFree(mapMethod);
    1897               1 :     return ret;
    1898                 : }
    1899                 : 
    1900                 : /************************************************************************/
    1901                 : /*                           OGR_L_Union()                              */
    1902                 : /************************************************************************/
    1903                 : 
    1904                 : /**
    1905                 :  * \brief Union of two layers.
    1906                 :  *
    1907                 :  * The result layer contains features whose geometries represent areas
    1908                 :  * that are in either in the input layer or in the method layer. The
    1909                 :  * features in the result layer have attributes from both input and
    1910                 :  * method layers. For features which represent areas that are only in
    1911                 :  * the input or in the method layer the respective attributes have
    1912                 :  * undefined values. The schema of the result layer can be set by the
    1913                 :  * user or, if it is empty, is initialized to contain all fields in
    1914                 :  * the input and method layers.
    1915                 :  *
    1916                 :  * \note If the schema of the result is set by user and contains
    1917                 :  * fields that have the same name as a field in input and in method
    1918                 :  * layer, then the attribute in the result feature will get the value
    1919                 :  * from the feature of the method layer (even if it is undefined).
    1920                 :  *
    1921                 :  * \note For best performance use the minimum amount of features in
    1922                 :  * the method layer and copy it into a memory layer.
    1923                 :  *
    1924                 :  * \note This method relies on GEOS support. Do not use unless the
    1925                 :  * GEOS support is compiled in.
    1926                 :  *
    1927                 :  * This function is the same as the C++ method OGRLayer::Union().
    1928                 :  * 
    1929                 :  * @param pLayerInput the input layer. Should not be NULL.
    1930                 :  *
    1931                 :  * @param pLayerMethod the method layer. Should not be NULL.
    1932                 :  *
    1933                 :  * @param pLayerResult the layer where the features resulting from the
    1934                 :  * operation are inserted. Should not be NULL. See above the note
    1935                 :  * about the schema.
    1936                 :  *
    1937                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    1938                 :  *
    1939                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    1940                 :  * reporting progress or NULL.
    1941                 :  *
    1942                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    1943                 :  *
    1944                 :  * @return an error code if there was an error or the execution was
    1945                 :  * interrupted, OGRERR_NONE otherwise.
    1946                 :  *
    1947                 :  * @since OGR 1.10 
    1948                 :  */
    1949                 : 
    1950               1 : OGRErr OGR_L_Union( OGRLayerH pLayerInput, 
    1951                 :                     OGRLayerH pLayerMethod, 
    1952                 :                     OGRLayerH pLayerResult, 
    1953                 :                     char** papszOptions, 
    1954                 :                     GDALProgressFunc pfnProgress, 
    1955                 :                     void * pProgressArg )
    1956                 : 
    1957                 : {
    1958               1 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Union", OGRERR_INVALID_HANDLE );
    1959               1 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Union", OGRERR_INVALID_HANDLE );
    1960               1 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Union", OGRERR_INVALID_HANDLE );
    1961                 : 
    1962               1 :     return ((OGRLayer *)pLayerInput)->Union( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    1963                 : }
    1964                 : 
    1965                 : /************************************************************************/
    1966                 : /*                          SymDifference()                             */
    1967                 : /************************************************************************/
    1968                 : 
    1969                 : /**
    1970                 :  * \brief Symmetrical difference of two layers.
    1971                 :  *
    1972                 :  * The result layer contains features whose geometries represent areas
    1973                 :  * that are in either in the input layer or in the method layer but
    1974                 :  * not in both. The features in the result layer have attributes from
    1975                 :  * both input and method layers. For features which represent areas
    1976                 :  * that are only in the input or in the method layer the respective
    1977                 :  * attributes have undefined values. The schema of the result layer
    1978                 :  * can be set by the user or, if it is empty, is initialized to
    1979                 :  * contain all fields in the input and method layers.
    1980                 :  *
    1981                 :  * \note If the schema of the result is set by user and contains
    1982                 :  * fields that have the same name as a field in input and in method
    1983                 :  * layer, then the attribute in the result feature will get the value
    1984                 :  * from the feature of the method layer (even if it is undefined).
    1985                 :  *
    1986                 :  * \note For best performance use the minimum amount of features in
    1987                 :  * the method layer and copy it into a memory layer.
    1988                 :  *
    1989                 :  * \note This method relies on GEOS support. Do not use unless the
    1990                 :  * GEOS support is compiled in.
    1991                 :  *
    1992                 :  * This method is the same as the C function OGR_L_SymDifference().
    1993                 :  * 
    1994                 :  * @param pLayerMethod the method layer. Should not be NULL.
    1995                 :  *
    1996                 :  * @param pLayerResult the layer where the features resulting from the
    1997                 :  * operation are inserted. Should not be NULL. See above the note
    1998                 :  * about the schema.
    1999                 :  *
    2000                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2001                 :  *
    2002                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2003                 :  * reporting progress or NULL.
    2004                 :  *
    2005                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2006                 :  *
    2007                 :  * @return an error code if there was an error or the execution was
    2008                 :  * interrupted, OGRERR_NONE otherwise.
    2009                 :  *
    2010                 :  * @since OGR 1.10
    2011                 :  */
    2012                 : 
    2013               1 : OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod, 
    2014                 :                                 OGRLayer *pLayerResult, 
    2015                 :                                 char** papszOptions, 
    2016                 :                                 GDALProgressFunc pfnProgress, 
    2017                 :                                 void * pProgressArg )
    2018                 : {
    2019               1 :     OGRErr ret = OGRERR_NONE;
    2020               1 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    2021               1 :     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
    2022               1 :     OGRFeatureDefn *poDefnResult = NULL;
    2023               1 :     OGRGeometry *pGeometryMethodFilter = NULL;
    2024               1 :     OGRGeometry *pGeometryInputFilter = NULL;
    2025               1 :     int *mapInput = NULL;
    2026               1 :     int *mapMethod = NULL;
    2027               1 :     double progress_max = GetFeatureCount(0) + pLayerMethod->GetFeatureCount(0);
    2028               1 :     double progress_counter = 0;
    2029               1 :     double progress_ticker = 0;
    2030                 : 
    2031                 :     // check for GEOS
    2032               1 :     if (!OGRGeometryFactory::haveGEOS()) {
    2033               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    2034                 :     }
    2035                 : 
    2036                 :     // get resources
    2037               1 :     ret = clone_spatial_filter(this, &pGeometryInputFilter);
    2038               1 :     if (ret != OGRERR_NONE) goto done;
    2039               1 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    2040               1 :     if (ret != OGRERR_NONE) goto done;
    2041               1 :     ret = create_field_map(poDefnInput, &mapInput);
    2042               1 :     if (ret != OGRERR_NONE) goto done;
    2043               1 :     ret = create_field_map(poDefnMethod, &mapMethod);
    2044               1 :     if (ret != OGRERR_NONE) goto done;
    2045               1 :     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1);
    2046               1 :     if (ret != OGRERR_NONE) goto done;
    2047               1 :     poDefnResult = pLayerResult->GetLayerDefn();
    2048                 : 
    2049                 :     // add features based on input layer
    2050               1 :     ResetReading();
    2051               5 :     while (OGRFeature *x = GetNextFeature()) {
    2052                 : 
    2053               2 :         if (pfnProgress) {
    2054               0 :             double p = progress_counter/progress_max;
    2055               0 :             if (p > progress_ticker) {
    2056               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2057               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2058               0 :                     ret = OGRERR_FAILURE;
    2059               0 :                     delete x;
    2060               0 :                     goto done;
    2061                 :                 }
    2062               0 :                 progress_ticker += 0.01;
    2063                 :             }
    2064               0 :             progress_counter += 1.0;
    2065                 :         }
    2066                 : 
    2067                 :         // set up the filter on method layer
    2068               2 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    2069               2 :         if (!x_geom) {
    2070               0 :             delete x; 
    2071               0 :             continue;
    2072                 :         }
    2073                 :         
    2074               2 :         OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
    2075               2 :         pLayerMethod->ResetReading();
    2076               6 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    2077               2 :             OGRGeometry *y_geom = y->GetGeometryRef();
    2078               2 :             if (!y_geom) {delete y; continue;}
    2079               2 :             OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
    2080               2 :             if (geom) delete geom;
    2081               2 :             geom = geom_new;
    2082               2 :             delete y;
    2083               2 :             if (geom && geom->IsEmpty()) break;
    2084                 :         }
    2085                 : 
    2086               2 :         OGRFeature *z = NULL;
    2087               2 :         if (geom && !geom->IsEmpty()) {
    2088               2 :             z = new OGRFeature(poDefnResult);
    2089               2 :             z->SetFieldsFrom(x, mapInput);
    2090               2 :             z->SetGeometryDirectly(geom);
    2091                 :         } else {
    2092               0 :             if (geom) delete geom;
    2093                 :         }
    2094               2 :         delete x;
    2095               2 :         if (z) {
    2096               2 :             ret = pLayerResult->CreateFeature(z);
    2097               2 :             delete z;
    2098               2 :             if (ret != OGRERR_NONE) goto done;
    2099                 :         }
    2100                 :     }
    2101                 : 
    2102                 :     // restore filter on method layer and add features based on it
    2103               1 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2104               1 :     pLayerMethod->ResetReading();
    2105               3 :     while (OGRFeature *x = pLayerMethod->GetNextFeature()) {
    2106                 : 
    2107               1 :         if (pfnProgress) {
    2108               0 :             double p = progress_counter/progress_max;
    2109               0 :             if (p > progress_ticker) {
    2110               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2111               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2112               0 :                     ret = OGRERR_FAILURE;
    2113               0 :                     delete x;
    2114               0 :                     goto done;
    2115                 :                 }
    2116               0 :                 progress_ticker += 0.01;
    2117                 :             }
    2118               0 :             progress_counter += 1.0;
    2119                 :         }
    2120                 : 
    2121                 :         // set up the filter on input layer
    2122               1 :         OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
    2123               1 :         if (!x_geom) {
    2124               0 :             delete x; 
    2125               0 :             continue;
    2126                 :         }
    2127                 :         
    2128               1 :         OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
    2129               1 :         ResetReading();
    2130               5 :         while (OGRFeature *y = GetNextFeature()) {
    2131               2 :             OGRGeometry *y_geom = y->GetGeometryRef();
    2132               2 :             if (!y_geom) {delete y; continue;}
    2133               2 :             OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
    2134               2 :             if (geom) delete geom;
    2135               2 :             geom = geom_new;
    2136               2 :             delete y;
    2137               2 :             if (geom->IsEmpty()) break;
    2138                 :         }
    2139                 : 
    2140               1 :         OGRFeature *z = NULL;
    2141               1 :         if (geom && !geom->IsEmpty()) {
    2142               1 :             z = new OGRFeature(poDefnResult);
    2143               1 :             z->SetFieldsFrom(x, mapMethod);
    2144               1 :             z->SetGeometryDirectly(geom);
    2145                 :         } else {
    2146               0 :             if (geom) delete geom;
    2147                 :         }
    2148               1 :         delete x;
    2149               1 :         if (z) {
    2150               1 :             ret = pLayerResult->CreateFeature(z);
    2151               1 :             delete z;
    2152               1 :             if (ret != OGRERR_NONE) goto done;
    2153                 :         }
    2154                 :     }
    2155               1 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    2156               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2157               0 :       ret = OGRERR_FAILURE;
    2158                 :       goto done;
    2159                 :     }
    2160                 : done:
    2161                 :     // release resources
    2162               1 :     SetSpatialFilter(pGeometryInputFilter);
    2163               1 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2164               1 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    2165               1 :     if (pGeometryInputFilter) delete pGeometryInputFilter;
    2166               1 :     if (mapInput) VSIFree(mapInput);
    2167               1 :     if (mapMethod) VSIFree(mapMethod);
    2168               1 :     return ret;
    2169                 : }
    2170                 : 
    2171                 : /************************************************************************/
    2172                 : /*                        OGR_L_SymDifference()                         */
    2173                 : /************************************************************************/
    2174                 : 
    2175                 : /**
    2176                 :  * \brief Symmetrical difference of two layers.
    2177                 :  *
    2178                 :  * The result layer contains features whose geometries represent areas
    2179                 :  * that are in either in the input layer or in the method layer but
    2180                 :  * not in both. The features in the result layer have attributes from
    2181                 :  * both input and method layers. For features which represent areas
    2182                 :  * that are only in the input or in the method layer the respective
    2183                 :  * attributes have undefined values. The schema of the result layer
    2184                 :  * can be set by the user or, if it is empty, is initialized to
    2185                 :  * contain all fields in the input and method layers.
    2186                 :  *
    2187                 :  * \note If the schema of the result is set by user and contains
    2188                 :  * fields that have the same name as a field in input and in method
    2189                 :  * layer, then the attribute in the result feature will get the value
    2190                 :  * from the feature of the method layer (even if it is undefined).
    2191                 :  *
    2192                 :  * \note For best performance use the minimum amount of features in
    2193                 :  * the method layer and copy it into a memory layer.
    2194                 :  *
    2195                 :  * \note This method relies on GEOS support. Do not use unless the
    2196                 :  * GEOS support is compiled in.
    2197                 :  *
    2198                 :  * This function is the same as the C++ method OGRLayer::SymDifference().
    2199                 :  *
    2200                 :  * @param pLayerInput the input layer. Should not be NULL.
    2201                 :  *
    2202                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2203                 :  *
    2204                 :  * @param pLayerResult the layer where the features resulting from the
    2205                 :  * operation are inserted. Should not be NULL. See above the note
    2206                 :  * about the schema.
    2207                 :  *
    2208                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2209                 :  *
    2210                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2211                 :  * reporting progress or NULL.
    2212                 :  *
    2213                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2214                 :  *
    2215                 :  * @return an error code if there was an error or the execution was
    2216                 :  * interrupted, OGRERR_NONE otherwise.
    2217                 :  *
    2218                 :  * @since OGR 1.10
    2219                 :  */
    2220                 : 
    2221               1 : OGRErr OGR_L_SymDifference( OGRLayerH pLayerInput, 
    2222                 :                             OGRLayerH pLayerMethod, 
    2223                 :                             OGRLayerH pLayerResult, 
    2224                 :                             char** papszOptions, 
    2225                 :                             GDALProgressFunc pfnProgress, 
    2226                 :                             void * pProgressArg )
    2227                 : 
    2228                 : {
    2229               1 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
    2230               1 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
    2231               1 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
    2232                 : 
    2233               1 :     return ((OGRLayer *)pLayerInput)->SymDifference( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    2234                 : }
    2235                 : 
    2236                 : /************************************************************************/
    2237                 : /*                            Identity()                                */
    2238                 : /************************************************************************/
    2239                 : 
    2240                 : /**
    2241                 :  * \brief Identify the features of this layer with the ones from the
    2242                 :  * identity layer.
    2243                 :  *
    2244                 :  * The result layer contains features whose geometries represent areas
    2245                 :  * that are in the input layer. The features in the result layer have
    2246                 :  * attributes from both input and method layers. The schema of the
    2247                 :  * result layer can be set by the user or, if it is empty, is
    2248                 :  * initialized to contain all fields in input and method layers.
    2249                 :  *
    2250                 :  * \note If the schema of the result is set by user and contains
    2251                 :  * fields that have the same name as a field in input and in method
    2252                 :  * layer, then the attribute in the result feature will get the value
    2253                 :  * from the feature of the method layer (even if it is undefined).
    2254                 :  *
    2255                 :  * \note For best performance use the minimum amount of features in
    2256                 :  * the method layer and copy it into a memory layer.
    2257                 :  *
    2258                 :  * \note This method relies on GEOS support. Do not use unless the
    2259                 :  * GEOS support is compiled in.
    2260                 :  *
    2261                 :  * This method is the same as the C function OGR_L_Identity().
    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                 : 
    2282               1 : OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod, 
    2283                 :                            OGRLayer *pLayerResult, 
    2284                 :                            char** papszOptions, 
    2285                 :                            GDALProgressFunc pfnProgress, 
    2286                 :                            void * pProgressArg )
    2287                 : {
    2288               1 :     OGRErr ret = OGRERR_NONE;
    2289               1 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    2290               1 :     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
    2291               1 :     OGRFeatureDefn *poDefnResult = NULL;
    2292               1 :     OGRGeometry *pGeometryMethodFilter = NULL;
    2293               1 :     int *mapInput = NULL;
    2294               1 :     int *mapMethod = NULL;
    2295               1 :     double progress_max = GetFeatureCount(0);
    2296               1 :     double progress_counter = 0;
    2297               1 :     double progress_ticker = 0;
    2298                 : 
    2299                 :     // check for GEOS
    2300               1 :     if (!OGRGeometryFactory::haveGEOS()) {
    2301               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    2302                 :     }
    2303                 : 
    2304                 :     // get resources
    2305               1 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    2306               1 :     if (ret != OGRERR_NONE) goto done;
    2307               1 :     ret = create_field_map(poDefnInput, &mapInput);
    2308               1 :     if (ret != OGRERR_NONE) goto done;
    2309               1 :     ret = create_field_map(poDefnMethod, &mapMethod);
    2310               1 :     if (ret != OGRERR_NONE) goto done;
    2311               1 :     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1);
    2312               1 :     if (ret != OGRERR_NONE) goto done;
    2313               1 :     poDefnResult = pLayerResult->GetLayerDefn();
    2314                 : 
    2315                 :     // split the features in input layer to the result layer
    2316               1 :     ResetReading();
    2317               5 :     while (OGRFeature *x = GetNextFeature()) {
    2318                 : 
    2319               2 :         if (pfnProgress) {
    2320               0 :             double p = progress_counter/progress_max;
    2321               0 :             if (p > progress_ticker) {
    2322               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2323               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2324               0 :                     ret = OGRERR_FAILURE;
    2325               0 :                     delete x;
    2326               0 :                     goto done;
    2327                 :                 }
    2328               0 :                 progress_ticker += 0.01;
    2329                 :             }
    2330               0 :             progress_counter += 1.0;
    2331                 :         }
    2332                 : 
    2333                 :         // set up the filter on method layer
    2334               2 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    2335               2 :         if (!x_geom) {
    2336               0 :             delete x; 
    2337               0 :             continue;
    2338                 :         }
    2339                 :         
    2340               2 :         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
    2341               2 :         pLayerMethod->ResetReading();
    2342               6 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    2343               2 :             OGRGeometry *y_geom = y->GetGeometryRef();
    2344               2 :             if (!y_geom) {delete y; continue;}
    2345               2 :             OGRFeature *z = new OGRFeature(poDefnResult);
    2346               2 :             z->SetFieldsFrom(x, mapInput);
    2347               2 :             z->SetFieldsFrom(y, mapMethod);
    2348               2 :             z->SetGeometryDirectly(x_geom->Intersection(y_geom));
    2349               4 :             OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
    2350               2 :             if (x_geom_diff) delete x_geom_diff;
    2351               2 :             x_geom_diff = x_geom_diff_new;
    2352               2 :             delete y;
    2353               2 :             ret = pLayerResult->CreateFeature(z);
    2354               2 :             delete z;
    2355               2 :             if (ret != OGRERR_NONE) {delete x; delete x_geom_diff; goto done;}
    2356                 :         }
    2357                 : 
    2358               4 :         OGRFeature *z = new OGRFeature(poDefnResult);
    2359               2 :         z->SetFieldsFrom(x, mapInput);
    2360               2 :         z->SetGeometryDirectly(x_geom_diff);
    2361               4 :         delete x;
    2362               2 :         ret = pLayerResult->CreateFeature(z);
    2363               2 :         delete z;
    2364               2 :         if (ret != OGRERR_NONE) goto done;
    2365                 :     }
    2366               1 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    2367               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2368               0 :       ret = OGRERR_FAILURE;
    2369                 :       goto done;
    2370                 :     }
    2371                 : done:
    2372                 :     // release resources
    2373               1 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2374               1 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    2375               1 :     if (mapInput) VSIFree(mapInput);
    2376               1 :     if (mapMethod) VSIFree(mapMethod);
    2377               1 :     return ret;
    2378                 : }
    2379                 : 
    2380                 : /************************************************************************/
    2381                 : /*                         OGR_L_Identity()                             */
    2382                 : /************************************************************************/
    2383                 : 
    2384                 : /**
    2385                 :  * \brief Identify the features of this layer with the ones from the
    2386                 :  * identity layer.
    2387                 :  *
    2388                 :  * The result layer contains features whose geometries represent areas
    2389                 :  * that are in the input layer. The features in the result layer have
    2390                 :  * attributes from both input and method layers. The schema of the
    2391                 :  * result layer can be set by the user or, if it is empty, is
    2392                 :  * initialized to contain all fields in input and method layers.
    2393                 :  *
    2394                 :  * \note If the schema of the result is set by user and contains
    2395                 :  * fields that have the same name as a field in input and in method
    2396                 :  * layer, then the attribute in the result feature will get the value
    2397                 :  * from the feature of the method layer (even if it is undefined).
    2398                 :  *
    2399                 :  * \note For best performance use the minimum amount of features in
    2400                 :  * the method layer and copy it into a memory layer.
    2401                 :  *
    2402                 :  * \note This method relies on GEOS support. Do not use unless the
    2403                 :  * GEOS support is compiled in.
    2404                 :  *
    2405                 :  * This function is the same as the C++ method OGRLayer::Identity().
    2406                 :  * 
    2407                 :  * @param pLayerInput the input layer. Should not be NULL.
    2408                 :  *
    2409                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2410                 :  *
    2411                 :  * @param pLayerResult the layer where the features resulting from the
    2412                 :  * operation are inserted. Should not be NULL. See above the note
    2413                 :  * about the schema.
    2414                 :  *
    2415                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2416                 :  *
    2417                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2418                 :  * reporting progress or NULL.
    2419                 :  *
    2420                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2421                 :  *
    2422                 :  * @return an error code if there was an error or the execution was
    2423                 :  * interrupted, OGRERR_NONE otherwise.
    2424                 :  *
    2425                 :  * @since OGR 1.10
    2426                 :  */
    2427                 : 
    2428               1 : OGRErr OGR_L_Identity( OGRLayerH pLayerInput, 
    2429                 :                        OGRLayerH pLayerMethod, 
    2430                 :                        OGRLayerH pLayerResult, 
    2431                 :                        char** papszOptions, 
    2432                 :                        GDALProgressFunc pfnProgress, 
    2433                 :                        void * pProgressArg )
    2434                 : 
    2435                 : {
    2436               1 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
    2437               1 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
    2438               1 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
    2439                 : 
    2440               1 :     return ((OGRLayer *)pLayerInput)->Identity( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    2441                 : }
    2442                 : 
    2443                 : /************************************************************************/
    2444                 : /*                             Update()                                 */
    2445                 : /************************************************************************/
    2446                 : 
    2447                 : /**
    2448                 :  * \brief Update this layer with features from the update layer.
    2449                 :  *
    2450                 :  * The result layer contains features whose geometries represent areas
    2451                 :  * that are either in the input layer or in the method layer. The
    2452                 :  * features in the result layer have areas of the features of the
    2453                 :  * method layer or those ares of the features of the input layer that
    2454                 :  * are not covered by the method layer. The features of the result
    2455                 :  * layer get their attributes from the input layer. The schema of the
    2456                 :  * result layer can be set by the user or, if it is empty, is
    2457                 :  * initialized to contain all fields in the input layer.
    2458                 :  *
    2459                 :  * \note If the schema of the result is set by user and contains
    2460                 :  * fields that have the same name as a field in the method layer, then
    2461                 :  * the attribute in the result feature the originates from the method
    2462                 :  * layer will get the value from the feature of the method layer.
    2463                 :  *
    2464                 :  * \note For best performance use the minimum amount of features in
    2465                 :  * the method layer and copy it into a memory layer.
    2466                 :  *
    2467                 :  * \note This method relies on GEOS support. Do not use unless the
    2468                 :  * GEOS support is compiled in.
    2469                 :  *
    2470                 :  * This method is the same as the C function OGR_L_Update().
    2471                 :  * 
    2472                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2473                 :  *
    2474                 :  * @param pLayerResult the layer where the features resulting from the
    2475                 :  * operation are inserted. Should not be NULL. See above the note
    2476                 :  * about the schema.
    2477                 :  *
    2478                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2479                 :  *
    2480                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2481                 :  * reporting progress or NULL.
    2482                 :  *
    2483                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2484                 :  *
    2485                 :  * @return an error code if there was an error or the execution was
    2486                 :  * interrupted, OGRERR_NONE otherwise.
    2487                 :  *
    2488                 :  * @since OGR 1.10
    2489                 :  */
    2490                 : 
    2491               1 : OGRErr OGRLayer::Update( OGRLayer *pLayerMethod, 
    2492                 :                          OGRLayer *pLayerResult, 
    2493                 :                          char** papszOptions, 
    2494                 :                          GDALProgressFunc pfnProgress, 
    2495                 :                          void * pProgressArg )
    2496                 : {
    2497               1 :     OGRErr ret = OGRERR_NONE;
    2498               1 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    2499               1 :     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
    2500               1 :     OGRFeatureDefn *poDefnResult = NULL;
    2501               1 :     OGRGeometry *pGeometryMethodFilter = NULL;
    2502               1 :     int *mapInput = NULL;
    2503               1 :     int *mapMethod = NULL;
    2504               1 :     double progress_max = GetFeatureCount(0) + pLayerMethod->GetFeatureCount(0);
    2505               1 :     double progress_counter = 0;
    2506               1 :     double progress_ticker = 0;
    2507                 : 
    2508                 :     // check for GEOS
    2509               1 :     if (!OGRGeometryFactory::haveGEOS()) {
    2510               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    2511                 :     }
    2512                 : 
    2513                 :     // get resources
    2514               1 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    2515               1 :     if (ret != OGRERR_NONE) goto done;
    2516               1 :     ret = create_field_map(poDefnInput, &mapInput);
    2517               1 :     if (ret != OGRERR_NONE) goto done;
    2518               1 :     ret = create_field_map(poDefnMethod, &mapMethod);
    2519               1 :     if (ret != OGRERR_NONE) goto done;
    2520               1 :     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 0);
    2521               1 :     if (ret != OGRERR_NONE) goto done;
    2522               1 :     poDefnResult = pLayerResult->GetLayerDefn();
    2523                 : 
    2524                 :     // add clipped features from the input layer
    2525               1 :     ResetReading();
    2526               5 :     while (OGRFeature *x = GetNextFeature()) {
    2527                 : 
    2528               2 :         if (pfnProgress) {
    2529               0 :             double p = progress_counter/progress_max;
    2530               0 :             if (p > progress_ticker) {
    2531               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2532               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2533               0 :                     ret = OGRERR_FAILURE;
    2534               0 :                     delete x;
    2535               0 :                     goto done;
    2536                 :                 }
    2537               0 :                 progress_ticker += 0.01;
    2538                 :             }
    2539               0 :             progress_counter += 1.0;
    2540                 :         }
    2541                 : 
    2542                 :         // set up the filter on method layer
    2543               2 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    2544               2 :         if (!x_geom) {
    2545               0 :             delete x; 
    2546               0 :             continue;
    2547                 :         }
    2548                 :         
    2549               2 :         OGRGeometry *x_geom_diff = x_geom->clone(); //this will be the geometry of a result feature
    2550               2 :         pLayerMethod->ResetReading();
    2551               6 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    2552               2 :             OGRGeometry *y_geom = y->GetGeometryRef();
    2553               2 :             if (!y_geom) {delete y; continue;}
    2554               2 :             OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
    2555               2 :             if (x_geom_diff) delete x_geom_diff;
    2556               2 :             x_geom_diff = x_geom_diff_new;
    2557               2 :             delete y;
    2558                 :         }
    2559                 : 
    2560               4 :         OGRFeature *z = new OGRFeature(poDefnResult);
    2561               2 :         z->SetFieldsFrom(x, mapInput);
    2562               2 :         z->SetGeometryDirectly(x_geom_diff);
    2563               4 :         delete x;
    2564               2 :         ret = pLayerResult->CreateFeature(z);
    2565               2 :         delete z;
    2566               2 :         if (ret != OGRERR_NONE) goto done;
    2567                 :     }
    2568                 : 
    2569                 :     // restore the original filter and add features from the update layer
    2570               1 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2571               1 :     pLayerMethod->ResetReading();
    2572               3 :     while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    2573                 : 
    2574               1 :         if (pfnProgress) {
    2575               0 :             double p = progress_counter/progress_max;
    2576               0 :             if (p > progress_ticker) {
    2577               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2578               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2579               0 :                     ret = OGRERR_FAILURE;
    2580               0 :                     delete y;
    2581               0 :                     goto done;
    2582                 :                 }
    2583               0 :                 progress_ticker += 0.01;
    2584                 :             }
    2585               0 :             progress_counter += 1.0;
    2586                 :         }
    2587                 : 
    2588               1 :         OGRGeometry *y_geom = y->GetGeometryRef();
    2589               1 :         if (!y_geom) {delete y; continue;}
    2590               1 :         OGRFeature *z = new OGRFeature(poDefnResult);
    2591               1 :         if (mapMethod) z->SetFieldsFrom(y, mapMethod);
    2592               1 :         z->SetGeometry(y_geom);
    2593               1 :         delete y;
    2594               1 :         ret = pLayerResult->CreateFeature(z);
    2595               1 :         delete z;
    2596               1 :         if (ret != OGRERR_NONE) goto done;
    2597                 :     }
    2598               1 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    2599               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2600               0 :       ret = OGRERR_FAILURE;
    2601                 :       goto done;
    2602                 :     }
    2603                 : done:
    2604                 :     // release resources
    2605               1 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2606               1 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    2607               1 :     if (mapInput) VSIFree(mapInput);
    2608               1 :     if (mapMethod) VSIFree(mapMethod);
    2609               1 :     return ret;
    2610                 : }
    2611                 : 
    2612                 : /************************************************************************/
    2613                 : /*                          OGR_L_Update()                              */
    2614                 : /************************************************************************/
    2615                 : 
    2616                 : /**
    2617                 :  * \brief Update this layer with features from the update layer.
    2618                 :  *
    2619                 :  * The result layer contains features whose geometries represent areas
    2620                 :  * that are either in the input layer or in the method layer. The
    2621                 :  * features in the result layer have areas of the features of the
    2622                 :  * method layer or those ares of the features of the input layer that
    2623                 :  * are not covered by the method layer. The features of the result
    2624                 :  * layer get their attributes from the input layer. The schema of the
    2625                 :  * result layer can be set by the user or, if it is empty, is
    2626                 :  * initialized to contain all fields in the input layer.
    2627                 :  *
    2628                 :  * \note If the schema of the result is set by user and contains
    2629                 :  * fields that have the same name as a field in the method layer, then
    2630                 :  * the attribute in the result feature the originates from the method
    2631                 :  * layer will get the value from the feature of the method layer.
    2632                 :  *
    2633                 :  * \note For best performance use the minimum amount of features in
    2634                 :  * the method layer and copy it into a memory layer.
    2635                 :  *
    2636                 :  * \note This method relies on GEOS support. Do not use unless the
    2637                 :  * GEOS support is compiled in.
    2638                 :  *
    2639                 :  * This function is the same as the C++ method OGRLayer::Update().
    2640                 :  * 
    2641                 :  * @param pLayerInput the input layer. Should not be NULL.
    2642                 :  *
    2643                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2644                 :  *
    2645                 :  * @param pLayerResult the layer where the features resulting from the
    2646                 :  * operation are inserted. Should not be NULL. See above the note
    2647                 :  * about the schema.
    2648                 :  *
    2649                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2650                 :  *
    2651                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2652                 :  * reporting progress or NULL.
    2653                 :  *
    2654                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2655                 :  *
    2656                 :  * @return an error code if there was an error or the execution was
    2657                 :  * interrupted, OGRERR_NONE otherwise.
    2658                 :  *
    2659                 :  * @since OGR 1.10
    2660                 :  */
    2661                 : 
    2662               1 : OGRErr OGR_L_Update( OGRLayerH pLayerInput, 
    2663                 :                      OGRLayerH pLayerMethod, 
    2664                 :                      OGRLayerH pLayerResult, 
    2665                 :                      char** papszOptions, 
    2666                 :                      GDALProgressFunc pfnProgress, 
    2667                 :                      void * pProgressArg )
    2668                 : 
    2669                 : {
    2670               1 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Update", OGRERR_INVALID_HANDLE );
    2671               1 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Update", OGRERR_INVALID_HANDLE );
    2672               1 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Update", OGRERR_INVALID_HANDLE );
    2673                 : 
    2674               1 :     return ((OGRLayer *)pLayerInput)->Update( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    2675                 : }
    2676                 : 
    2677                 : /************************************************************************/
    2678                 : /*                              Clip()                                  */
    2679                 : /************************************************************************/
    2680                 : 
    2681                 : /**
    2682                 :  * \brief Clip off areas that are not covered by the method layer.
    2683                 :  *
    2684                 :  * The result layer contains features whose geometries represent areas
    2685                 :  * that are in the input layer and in the method layer. The features
    2686                 :  * in the result layer have the (possibly clipped) areas of features
    2687                 :  * in the input layer and the attributes from the same features. The
    2688                 :  * schema of the result layer can be set by the user or, if it is
    2689                 :  * empty, is initialized to contain all fields in the input layer.
    2690                 :  *
    2691                 :  * \note For best performance use the minimum amount of features in
    2692                 :  * the method layer and copy it into a memory layer.
    2693                 :  *
    2694                 :  * \note This method relies on GEOS support. Do not use unless the
    2695                 :  * GEOS support is compiled in.
    2696                 :  *
    2697                 :  * This method is the same as the C function OGR_L_Clip().
    2698                 :  * 
    2699                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2700                 :  *
    2701                 :  * @param pLayerResult the layer where the features resulting from the
    2702                 :  * operation are inserted. Should not be NULL. See above the note
    2703                 :  * about the schema.
    2704                 :  *
    2705                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2706                 :  *
    2707                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2708                 :  * reporting progress or NULL.
    2709                 :  *
    2710                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2711                 :  *
    2712                 :  * @return an error code if there was an error or the execution was
    2713                 :  * interrupted, OGRERR_NONE otherwise.
    2714                 :  *
    2715                 :  * @since OGR 1.10
    2716                 :  */
    2717                 : 
    2718               1 : OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod, 
    2719                 :                        OGRLayer *pLayerResult, 
    2720                 :                        char** papszOptions, 
    2721                 :                        GDALProgressFunc pfnProgress, 
    2722                 :                        void * pProgressArg )
    2723                 : {
    2724               1 :     OGRErr ret = OGRERR_NONE;
    2725               1 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    2726               1 :     OGRFeatureDefn *poDefnResult = NULL;
    2727               1 :     OGRGeometry *pGeometryMethodFilter = NULL;
    2728               1 :     int *mapInput = NULL;
    2729               1 :     double progress_max = GetFeatureCount(0);
    2730               1 :     double progress_counter = 0;
    2731               1 :     double progress_ticker = 0;
    2732                 : 
    2733                 :     // check for GEOS
    2734               1 :     if (!OGRGeometryFactory::haveGEOS()) {
    2735               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    2736                 :     }
    2737                 : 
    2738               1 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    2739               1 :     if (ret != OGRERR_NONE) goto done;
    2740               1 :     ret = create_field_map(poDefnInput, &mapInput);
    2741               1 :     if (ret != OGRERR_NONE) goto done;
    2742               1 :     ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0);
    2743               1 :     if (ret != OGRERR_NONE) goto done;
    2744                 :     
    2745               1 :     poDefnResult = pLayerResult->GetLayerDefn();
    2746               1 :     ResetReading();
    2747               5 :     while (OGRFeature *x = GetNextFeature()) {
    2748                 : 
    2749               2 :         if (pfnProgress) {
    2750               0 :             double p = progress_counter/progress_max;
    2751               0 :             if (p > progress_ticker) {
    2752               0 :                 if (pfnProgress(p, "", pProgressArg)) {
    2753               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2754               0 :                     ret = OGRERR_FAILURE;
    2755               0 :                     delete x;
    2756               0 :                     goto done;
    2757                 :                 }
    2758               0 :                 progress_ticker += 0.01;
    2759                 :             }
    2760               0 :             progress_counter += 1.0;
    2761                 :         }
    2762                 : 
    2763                 :         // set up the filter on method layer
    2764               2 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    2765               2 :         if (!x_geom) {
    2766               0 :             delete x; 
    2767               0 :             continue;
    2768                 :         }
    2769                 :         
    2770               2 :         OGRGeometry *geom = NULL; // this will be the geometry of the result feature 
    2771               2 :         pLayerMethod->ResetReading();
    2772                 :         // incrementally add area from y to geom
    2773               6 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    2774               2 :             OGRGeometry *y_geom = y->GetGeometryRef();
    2775               2 :             if (!y_geom) {delete y; continue;}
    2776               2 :             if (!geom) {
    2777               2 :                 geom = y_geom->clone();
    2778                 :             } else {
    2779               0 :                 OGRGeometry *geom_new = geom->Union(y_geom);
    2780               0 :                 delete geom;
    2781               0 :                 geom = geom_new;
    2782                 :             }
    2783               2 :             delete y;
    2784                 :         }
    2785                 : 
    2786                 :         // possibly add a new feature with area x intersection sum of y
    2787               2 :         OGRFeature *z = NULL;
    2788               2 :         if (geom) {
    2789               2 :             z = new OGRFeature(poDefnResult);
    2790               2 :             z->SetFieldsFrom(x, mapInput);
    2791               2 :             z->SetGeometryDirectly(x_geom->Intersection(geom));
    2792               4 :             delete geom;
    2793                 :         }
    2794               2 :         delete x;
    2795               2 :         if (z) {
    2796               2 :             if (!z->GetGeometryRef()->IsEmpty())
    2797               2 :                 ret = pLayerResult->CreateFeature(z);
    2798               2 :             delete z;
    2799               2 :             if (ret != OGRERR_NONE) goto done;
    2800                 :         }
    2801                 :     }
    2802               1 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    2803               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2804               0 :       ret = OGRERR_FAILURE;
    2805                 :       goto done;
    2806                 :     }
    2807                 : done:
    2808                 :     // release resources
    2809               1 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2810               1 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    2811               1 :     if (mapInput) VSIFree(mapInput);
    2812               1 :     return ret;
    2813                 : }
    2814                 : 
    2815                 : /************************************************************************/
    2816                 : /*                           OGR_L_Clip()                               */
    2817                 : /************************************************************************/
    2818                 : 
    2819                 : /**
    2820                 :  * \brief Clip off areas that are not covered by the method layer.
    2821                 :  *
    2822                 :  * The result layer contains features whose geometries represent areas
    2823                 :  * that are in the input layer and in the method layer. The features
    2824                 :  * in the result layer have the (possibly clipped) areas of features
    2825                 :  * in the input layer and the attributes from the same features. The
    2826                 :  * schema of the result layer can be set by the user or, if it is
    2827                 :  * empty, is initialized to contain all fields in the input layer.
    2828                 :  *
    2829                 :  * \note For best performance use the minimum amount of features in
    2830                 :  * the method layer and copy it into a memory layer.
    2831                 :  *
    2832                 :  * \note This method relies on GEOS support. Do not use unless the
    2833                 :  * GEOS support is compiled in.
    2834                 :  *
    2835                 :  * This function is the same as the C++ method OGRLayer::Clip().
    2836                 :  * 
    2837                 :  * @param pLayerInput the input layer. Should not be NULL.
    2838                 :  *
    2839                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2840                 :  *
    2841                 :  * @param pLayerResult the layer where the features resulting from the
    2842                 :  * operation are inserted. Should not be NULL. See above the note
    2843                 :  * about the schema.
    2844                 :  *
    2845                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2846                 :  *
    2847                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2848                 :  * reporting progress or NULL.
    2849                 :  *
    2850                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2851                 :  *
    2852                 :  * @return an error code if there was an error or the execution was
    2853                 :  * interrupted, OGRERR_NONE otherwise.
    2854                 :  *
    2855                 :  * @since OGR 1.10
    2856                 :  */
    2857                 : 
    2858               1 : OGRErr OGR_L_Clip( OGRLayerH pLayerInput, 
    2859                 :                    OGRLayerH pLayerMethod, 
    2860                 :                    OGRLayerH pLayerResult, 
    2861                 :                    char** papszOptions, 
    2862                 :                    GDALProgressFunc pfnProgress, 
    2863                 :                    void * pProgressArg )
    2864                 : 
    2865                 : {
    2866               1 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
    2867               1 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
    2868               1 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
    2869                 : 
    2870               1 :     return ((OGRLayer *)pLayerInput)->Clip( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    2871                 : }
    2872                 : 
    2873                 : /************************************************************************/
    2874                 : /*                              Erase()                                 */
    2875                 : /************************************************************************/
    2876                 : 
    2877                 : /**
    2878                 :  * \brief Remove areas that are covered by the method layer.
    2879                 :  *
    2880                 :  * The result layer contains features whose geometries represent areas
    2881                 :  * that are in the input layer but not in the method layer. The
    2882                 :  * features in the result layer have attributes from the input
    2883                 :  * layer. The schema of the result layer can be set by the user or, if
    2884                 :  * it is empty, is initialized to contain all fields in the input
    2885                 :  * layer.
    2886                 :  *
    2887                 :  * \note For best performance use the minimum amount of features in
    2888                 :  * the method layer and copy it into a memory layer.
    2889                 :  *
    2890                 :  * \note This method relies on GEOS support. Do not use unless the
    2891                 :  * GEOS support is compiled in.
    2892                 :  *
    2893                 :  * This method is the same as the C function OGR_L_Erase().
    2894                 :  *
    2895                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2896                 :  *
    2897                 :  * @param pLayerResult the layer where the features resulting from the
    2898                 :  * operation are inserted. Should not be NULL. See above the note
    2899                 :  * about the schema.
    2900                 :  *
    2901                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2902                 :  *
    2903                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2904                 :  * reporting progress or NULL.
    2905                 :  *
    2906                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2907                 :  *
    2908                 :  * @return an error code if there was an error or the execution was
    2909                 :  * interrupted, OGRERR_NONE otherwise.
    2910                 :  *
    2911                 :  * @since OGR 1.10
    2912                 :  */
    2913                 : 
    2914               1 : OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod, 
    2915                 :                         OGRLayer *pLayerResult, 
    2916                 :                         char** papszOptions, 
    2917                 :                         GDALProgressFunc pfnProgress, 
    2918                 :                         void * pProgressArg )
    2919                 : {
    2920               1 :     OGRErr ret = OGRERR_NONE;
    2921               1 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    2922               1 :     OGRFeatureDefn *poDefnResult = NULL;
    2923               1 :     OGRGeometry *pGeometryMethodFilter = NULL;
    2924               1 :     int *mapInput = NULL;
    2925               1 :     double progress_max = GetFeatureCount(0);
    2926               1 :     double progress_counter = 0;
    2927               1 :     double progress_ticker = 0;
    2928                 : 
    2929                 :     // check for GEOS
    2930               1 :     if (!OGRGeometryFactory::haveGEOS()) {
    2931               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    2932                 :     }
    2933                 : 
    2934                 :     // get resources
    2935               1 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    2936               1 :     if (ret != OGRERR_NONE) goto done;
    2937               1 :     ret = create_field_map(poDefnInput, &mapInput);
    2938               1 :     if (ret != OGRERR_NONE) goto done;
    2939               1 :     ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0);
    2940               1 :     if (ret != OGRERR_NONE) goto done;
    2941               1 :     poDefnResult = pLayerResult->GetLayerDefn();
    2942                 : 
    2943               1 :     ResetReading();
    2944               5 :     while (OGRFeature *x = GetNextFeature()) {
    2945                 : 
    2946               2 :         if (pfnProgress) {
    2947               0 :             double p = progress_counter/progress_max;
    2948               0 :             if (p > progress_ticker) {
    2949               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2950               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2951               0 :                     ret = OGRERR_FAILURE;
    2952               0 :                     delete x;
    2953               0 :                     goto done;
    2954                 :                 }
    2955               0 :                 progress_ticker += 0.01;
    2956                 :             }
    2957               0 :             progress_counter += 1.0;
    2958                 :         }
    2959                 : 
    2960                 :         // set up the filter on the method layer
    2961               2 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    2962               2 :         if (!x_geom) {
    2963               0 :             delete x; 
    2964               0 :             continue;
    2965                 :         }
    2966                 : 
    2967               2 :         OGRGeometry *geom = NULL; // this will be the geometry of the result feature
    2968               2 :         pLayerMethod->ResetReading();
    2969                 :         // incrementally add area from y to geom
    2970               6 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    2971               2 :             OGRGeometry *y_geom = y->GetGeometryRef();
    2972               2 :             if (!y_geom) {delete y; continue;}
    2973               2 :             if (!geom) {
    2974               2 :                 geom = y_geom->clone();
    2975                 :             } else {
    2976               0 :                 OGRGeometry *geom_new = geom->Union(y_geom);
    2977               0 :                 delete geom;
    2978               0 :                 geom = geom_new;
    2979                 :             }
    2980               2 :             delete y;
    2981                 :         }
    2982                 : 
    2983                 :         // possibly add a new feature with area x minus sum of y
    2984               2 :         OGRFeature *z = NULL;
    2985               2 :         if (geom) {
    2986               2 :             z = new OGRFeature(poDefnResult);
    2987               2 :             z->SetFieldsFrom(x, mapInput);
    2988               2 :             z->SetGeometryDirectly(x_geom->Difference(geom));
    2989               4 :             delete geom;
    2990                 :         }
    2991               2 :         delete x;
    2992               2 :         if (z) {
    2993               2 :             if (!z->GetGeometryRef()->IsEmpty())
    2994               2 :                 ret = pLayerResult->CreateFeature(z);
    2995               2 :             delete z;
    2996               2 :             if (ret != OGRERR_NONE) goto done;
    2997                 :         }
    2998                 :     }
    2999               1 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    3000               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    3001               0 :       ret = OGRERR_FAILURE;
    3002                 :       goto done;
    3003                 :     }
    3004                 : done:
    3005                 :     // release resources
    3006               1 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    3007               1 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    3008               1 :     if (mapInput) VSIFree(mapInput);
    3009               1 :     return ret;
    3010                 : }
    3011                 : 
    3012                 : /************************************************************************/
    3013                 : /*                           OGR_L_Erase()                              */
    3014                 : /************************************************************************/
    3015                 : 
    3016                 : /**
    3017                 :  * \brief Remove areas that are covered by the method layer.
    3018                 :  *
    3019                 :  * The result layer contains features whose geometries represent areas
    3020                 :  * that are in the input layer but not in the method layer. The
    3021                 :  * features in the result layer have attributes from the input
    3022                 :  * layer. The schema of the result layer can be set by the user or, if
    3023                 :  * it is empty, is initialized to contain all fields in the input
    3024                 :  * layer.
    3025                 :  *
    3026                 :  * \note For best performance use the minimum amount of features in
    3027                 :  * the method layer and copy it into a memory layer.
    3028                 :  *
    3029                 :  * \note This method relies on GEOS support. Do not use unless the
    3030                 :  * GEOS support is compiled in.
    3031                 :  *
    3032                 :  * This function is the same as the C++ method OGRLayer::Erase().
    3033                 :  * 
    3034                 :  * @param pLayerInput the input layer. Should not be NULL.
    3035                 :  *
    3036                 :  * @param pLayerMethod the method layer. Should not be NULL.
    3037                 :  *
    3038                 :  * @param pLayerResult the layer where the features resulting from the
    3039                 :  * operation are inserted. Should not be NULL. See above the note
    3040                 :  * about the schema.
    3041                 :  *
    3042                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    3043                 :  *
    3044                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    3045                 :  * reporting progress or NULL.
    3046                 :  *
    3047                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    3048                 :  *
    3049                 :  * @return an error code if there was an error or the execution was
    3050                 :  * interrupted, OGRERR_NONE otherwise.
    3051                 :  *
    3052                 :  * @since OGR 1.10
    3053                 :  */
    3054                 : 
    3055               1 : OGRErr OGR_L_Erase( OGRLayerH pLayerInput, 
    3056                 :                     OGRLayerH pLayerMethod, 
    3057                 :                     OGRLayerH pLayerResult, 
    3058                 :                     char** papszOptions, 
    3059                 :                     GDALProgressFunc pfnProgress, 
    3060                 :                     void * pProgressArg )
    3061                 : 
    3062                 : {
    3063               1 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
    3064               1 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
    3065               1 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
    3066                 : 
    3067               1 :     return ((OGRLayer *)pLayerInput)->Erase( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    3068                 : }

Generated by: LCOV version 1.7