LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/generic - ogrlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 1178 935 79.4 %
Date: 2013-03-30 Functions: 99 75 75.8 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrlayer.cpp 25470 2013-01-06 19:52:19Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  The generic portions of the OGRSFLayer class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
      10                 :  *
      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 25470 2013-01-06 19:52:19Z rouault $");
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                              OGRLayer()                              */
      40                 : /************************************************************************/
      41                 : 
      42           17897 : OGRLayer::OGRLayer()
      43                 : 
      44                 : {
      45           17897 :     m_poStyleTable = NULL;
      46           17897 :     m_poAttrQuery = NULL;
      47           17897 :     m_poAttrIndex = NULL;
      48           17897 :     m_nRefCount = 0;
      49                 : 
      50           17897 :     m_nFeaturesRead = 0;
      51                 : 
      52           17897 :     m_poFilterGeom = NULL;
      53           17897 :     m_bFilterIsEnvelope = FALSE;
      54           17897 :     m_pPreparedFilterGeom = NULL;
      55           17897 : }
      56                 : 
      57                 : /************************************************************************/
      58                 : /*                             ~OGRLayer()                              */
      59                 : /************************************************************************/
      60                 : 
      61           17897 : OGRLayer::~OGRLayer()
      62                 : 
      63                 : {
      64           17897 :     if ( m_poStyleTable )
      65                 :     {
      66               3 :         delete m_poStyleTable;
      67               3 :         m_poStyleTable = NULL;
      68                 :     }
      69                 : 
      70           17897 :     if( m_poAttrIndex != NULL )
      71                 :     {
      72              47 :         delete m_poAttrIndex;
      73              47 :         m_poAttrIndex = NULL;
      74                 :     }
      75                 : 
      76           17897 :     if( m_poAttrQuery != NULL )
      77                 :     {
      78             109 :         delete m_poAttrQuery;
      79             109 :         m_poAttrQuery = NULL;
      80                 :     }
      81                 : 
      82           17897 :     if( m_poFilterGeom )
      83                 :     {
      84              86 :         delete m_poFilterGeom;
      85              86 :         m_poFilterGeom = NULL;
      86                 :     }
      87                 : 
      88           17897 :     if( m_pPreparedFilterGeom != NULL )
      89                 :     {
      90              86 :         OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
      91              86 :         m_pPreparedFilterGeom = NULL;
      92                 :     }
      93           17897 : }
      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              70 : int OGRLayer::GetRefCount() const
     144                 : 
     145                 : {
     146              70 :     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             538 : int OGRLayer::GetFeatureCount( int bForce )
     166                 : 
     167                 : {
     168                 :     OGRFeature     *poFeature;
     169             538 :     int            nFeatureCount = 0;
     170                 : 
     171             538 :     if( !bForce )
     172               0 :         return -1;
     173                 : 
     174             538 :     ResetReading();
     175          214157 :     while( (poFeature = GetNextFeature()) != NULL )
     176                 :     {
     177          213081 :         nFeatureCount++;
     178          213081 :         delete poFeature;
     179                 :     }
     180             538 :     ResetReading();
     181                 : 
     182             538 :     return nFeatureCount;
     183                 : }
     184                 : 
     185                 : /************************************************************************/
     186                 : /*                       OGR_L_GetFeatureCount()                        */
     187                 : /************************************************************************/
     188                 : 
     189             725 : int OGR_L_GetFeatureCount( OGRLayerH hLayer, int bForce )
     190                 : 
     191                 : {
     192             725 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetFeature", 0 );
     193                 : 
     194             725 :     return ((OGRLayer *) hLayer)->GetFeatureCount(bForce);
     195                 : }
     196                 : 
     197                 : /************************************************************************/
     198                 : /*                             GetExtent()                              */
     199                 : /************************************************************************/
     200                 : 
     201             212 : OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce )
     202                 : 
     203                 : {
     204                 :     OGRFeature  *poFeature;
     205             212 :     OGREnvelope oEnv;
     206             212 :     GBool       bExtentSet = FALSE;
     207                 : 
     208             212 :     psExtent->MinX = 0.0;
     209             212 :     psExtent->MaxX = 0.0;
     210             212 :     psExtent->MinY = 0.0;
     211             212 :     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             212 :     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             144 :     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             144 :     ResetReading();
     232           70739 :     while( (poFeature = GetNextFeature()) != NULL )
     233                 :     {
     234           70451 :         OGRGeometry *poGeom = poFeature->GetGeometryRef();
     235           70451 :         if (poGeom == NULL || poGeom->IsEmpty())
     236                 :         {
     237                 :             /* Do nothing */
     238                 :         }
     239           70029 :         else if (!bExtentSet)
     240                 :         {
     241             132 :             poGeom->getEnvelope(psExtent);
     242             132 :             bExtentSet = TRUE;
     243                 :         }
     244                 :         else
     245                 :         {
     246           69897 :             poGeom->getEnvelope(&oEnv);
     247           69897 :             if (oEnv.MinX < psExtent->MinX) 
     248             203 :                 psExtent->MinX = oEnv.MinX;
     249           69897 :             if (oEnv.MinY < psExtent->MinY) 
     250            2063 :                 psExtent->MinY = oEnv.MinY;
     251           69897 :             if (oEnv.MaxX > psExtent->MaxX) 
     252             307 :                 psExtent->MaxX = oEnv.MaxX;
     253           69897 :             if (oEnv.MaxY > psExtent->MaxY) 
     254             177 :                 psExtent->MaxY = oEnv.MaxY;
     255                 :         }
     256           70451 :         delete poFeature;
     257                 :     }
     258             144 :     ResetReading();
     259                 : 
     260             144 :     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            2285 : OGRErr OGRLayer::SetAttributeFilter( const char *pszQuery )
     280                 : 
     281                 : {
     282                 : /* -------------------------------------------------------------------- */
     283                 : /*      Are we just clearing any existing query?                        */
     284                 : /* -------------------------------------------------------------------- */
     285            2285 :     if( pszQuery == NULL || strlen(pszQuery) == 0 )
     286                 :     {
     287            1401 :         if( m_poAttrQuery )
     288                 :         {
     289             382 :             delete m_poAttrQuery;
     290             382 :             m_poAttrQuery = NULL;
     291             382 :             ResetReading();
     292                 :         }
     293            1401 :         return OGRERR_NONE;
     294                 :     }
     295                 : 
     296                 : /* -------------------------------------------------------------------- */
     297                 : /*      Or are we installing a new query?                               */
     298                 : /* -------------------------------------------------------------------- */
     299                 :     OGRErr      eErr;
     300                 : 
     301             884 :     if( !m_poAttrQuery )
     302             491 :         m_poAttrQuery = new OGRFeatureQuery();
     303                 : 
     304             884 :     eErr = m_poAttrQuery->Compile( GetLayerDefn(), pszQuery );
     305             884 :     if( eErr != OGRERR_NONE )
     306                 :     {
     307               0 :         delete m_poAttrQuery;
     308               0 :         m_poAttrQuery = NULL;
     309                 :     }
     310                 : 
     311             884 :     ResetReading();
     312                 : 
     313             884 :     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             241 : OGRErr OGR_L_SetAttributeFilter( OGRLayerH hLayer, const char *pszQuery )
     366                 : 
     367                 : {
     368             241 :     VALIDATE_POINTER1( hLayer, "OGR_L_SetAttributeFilter", OGRERR_INVALID_HANDLE );
     369                 : 
     370             241 :     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           47973 :     while( (poFeature = GetNextFeature()) != NULL )
     384                 :     {
     385           47812 :         if( poFeature->GetFID() == nFID )
     386              13 :             return poFeature;
     387                 :         else
     388           47799 :             delete poFeature;
     389                 :     }
     390                 :     
     391              74 :     return NULL;
     392                 : }
     393                 : 
     394                 : /************************************************************************/
     395                 : /*                          OGR_L_GetFeature()                          */
     396                 : /************************************************************************/
     397                 : 
     398             100 : OGRFeatureH OGR_L_GetFeature( OGRLayerH hLayer, long nFeatureId )
     399                 : 
     400                 : {
     401             100 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetFeature", NULL );
     402                 : 
     403             100 :     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           87546 : OGRFeatureH OGR_L_GetNextFeature( OGRLayerH hLayer )
     448                 : 
     449                 : {
     450           87546 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetNextFeature", NULL );
     451                 : 
     452           87546 :     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           33946 : OGRErr OGR_L_CreateFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
     493                 : 
     494                 : {
     495           33946 :     VALIDATE_POINTER1( hLayer, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE );
     496           33946 :     VALIDATE_POINTER1( hFeat, "OGR_L_CreateFeature", OGRERR_INVALID_HANDLE );
     497                 : 
     498           33946 :     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            4662 : OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField, 
     533                 :                           int bApproxOK )
     534                 : 
     535                 : {
     536            4662 :     VALIDATE_POINTER1( hLayer, "OGR_L_CreateField", OGRERR_INVALID_HANDLE );
     537            4662 :     VALIDATE_POINTER1( hField, "OGR_L_CreateField", OGRERR_INVALID_HANDLE );
     538                 : 
     539                 :     return ((OGRLayer *) hLayer)->CreateField( (OGRFieldDefn *) hField, 
     540            4662 :                                                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             810 : OGRErr OGRLayer::StartTransaction()
     704                 : 
     705                 : {
     706             810 :     return OGRERR_NONE;
     707                 : }
     708                 : 
     709                 : /************************************************************************/
     710                 : /*                       OGR_L_StartTransaction()                       */
     711                 : /************************************************************************/
     712                 : 
     713              70 : OGRErr OGR_L_StartTransaction( OGRLayerH hLayer )
     714                 : 
     715                 : {
     716              70 :     VALIDATE_POINTER1( hLayer, "OGR_L_StartTransaction", OGRERR_INVALID_HANDLE );
     717                 : 
     718              70 :     return ((OGRLayer *)hLayer)->StartTransaction();
     719                 : }
     720                 : 
     721                 : /************************************************************************/
     722                 : /*                         CommitTransaction()                          */
     723                 : /************************************************************************/
     724                 : 
     725             787 : OGRErr OGRLayer::CommitTransaction()
     726                 : 
     727                 : {
     728             787 :     return OGRERR_NONE;
     729                 : }
     730                 : 
     731                 : /************************************************************************/
     732                 : /*                       OGR_L_CommitTransaction()                      */
     733                 : /************************************************************************/
     734                 : 
     735              67 : OGRErr OGR_L_CommitTransaction( OGRLayerH hLayer )
     736                 : 
     737                 : {
     738              67 :     VALIDATE_POINTER1( hLayer, "OGR_L_CommitTransaction", OGRERR_INVALID_HANDLE );
     739                 : 
     740              67 :     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           32867 : OGRFeatureDefnH OGR_L_GetLayerDefn( OGRLayerH hLayer )
     770                 : 
     771                 : {
     772           32867 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetLayerDefn", NULL );
     773                 : 
     774           32867 :     return (OGRFeatureDefnH) ((OGRLayer *)hLayer)->GetLayerDefn();
     775                 : }
     776                 : 
     777                 : /************************************************************************/
     778                 : /*                        OGR_L_GetSpatialRef()                         */
     779                 : /************************************************************************/
     780                 : 
     781             323 : OGRSpatialReferenceH OGR_L_GetSpatialRef( OGRLayerH hLayer )
     782                 : 
     783                 : {
     784             323 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetSpatialRef", NULL );
     785                 : 
     786             323 :     return (OGRSpatialReferenceH) ((OGRLayer *) hLayer)->GetSpatialRef();
     787                 : }
     788                 : 
     789                 : /************************************************************************/
     790                 : /*                        OGR_L_TestCapability()                        */
     791                 : /************************************************************************/
     792                 : 
     793             146 : int OGR_L_TestCapability( OGRLayerH hLayer, const char *pszCap )
     794                 : 
     795                 : {
     796             146 :     VALIDATE_POINTER1( hLayer, "OGR_L_TestCapability", 0 );
     797             146 :     VALIDATE_POINTER1( pszCap, "OGR_L_TestCapability", 0 );
     798                 : 
     799             146 :     return ((OGRLayer *) hLayer)->TestCapability( pszCap );
     800                 : }
     801                 : 
     802                 : /************************************************************************/
     803                 : /*                          GetSpatialFilter()                          */
     804                 : /************************************************************************/
     805                 : 
     806             139 : OGRGeometry *OGRLayer::GetSpatialFilter()
     807                 : 
     808                 : {
     809             139 :     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           19556 : void OGRLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
     829                 : 
     830                 : {
     831           19556 :     if( InstallFilter( poGeomIn ) )
     832           17830 :         ResetReading();
     833           19556 : }
     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           19762 : int OGRLayer::InstallFilter( OGRGeometry * poFilter )
     899                 : 
     900                 : {
     901           19762 :     if( m_poFilterGeom == NULL && poFilter == NULL )
     902            1838 :         return FALSE;
     903                 : 
     904                 : /* -------------------------------------------------------------------- */
     905                 : /*      Replace the existing filter.                                    */
     906                 : /* -------------------------------------------------------------------- */
     907           17924 :     if( m_poFilterGeom != NULL )
     908                 :     {
     909           17716 :         delete m_poFilterGeom;
     910           17716 :         m_poFilterGeom = NULL;
     911                 :     }
     912                 : 
     913           17924 :     if( m_pPreparedFilterGeom != NULL )
     914                 :     {
     915           17716 :         OGRDestroyPreparedGeometry(m_pPreparedFilterGeom);
     916           17716 :         m_pPreparedFilterGeom = NULL;
     917                 :     }
     918                 : 
     919           17924 :     if( poFilter != NULL )
     920           17802 :         m_poFilterGeom = poFilter->clone();
     921                 : 
     922           17924 :     m_bFilterIsEnvelope = FALSE;
     923                 : 
     924           17924 :     if( m_poFilterGeom == NULL )
     925             122 :         return TRUE;
     926                 : 
     927           17802 :     if( m_poFilterGeom != NULL )
     928           17802 :         m_poFilterGeom->getEnvelope( &m_sFilterEnvelope );
     929                 : 
     930                 :     /* Compile geometry filter as a prepared geometry */
     931           17802 :     m_pPreparedFilterGeom = OGRCreatePreparedGeometry(m_poFilterGeom);
     932                 : 
     933                 : /* -------------------------------------------------------------------- */
     934                 : /*      Now try to determine if the filter is really a rectangle.       */
     935                 : /* -------------------------------------------------------------------- */
     936           17802 :     if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
     937              13 :         return TRUE;
     938                 : 
     939           17789 :     OGRPolygon *poPoly = (OGRPolygon *) m_poFilterGeom;
     940                 : 
     941           17789 :     if( poPoly->getNumInteriorRings() != 0 )
     942               0 :         return TRUE;
     943                 : 
     944           17789 :     OGRLinearRing *poRing = poPoly->getExteriorRing();
     945           17789 :     if (poRing == NULL)
     946               0 :         return TRUE;
     947                 : 
     948           17789 :     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           17789 :     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           17789 :     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           17704 :         m_bFilterIsEnvelope = TRUE;
     963                 : 
     964                 :     // Polygon with first segment in "x" direction. 
     965           17789 :     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            1147 :         m_bFilterIsEnvelope = TRUE;
     970                 : 
     971           17789 :     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          178553 : 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          178553 :     if( m_poFilterGeom == NULL )
     991              28 :         return TRUE;
     992                 : 
     993          178525 :     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          178098 :     OGREnvelope sGeomEnv;
    1002                 : 
    1003          178098 :     poGeometry->getEnvelope( &sGeomEnv );
    1004                 : 
    1005          178098 :     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           69500 :     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           56055 :         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           13445 :         if( m_bFilterIsEnvelope )
    1034                 :         {
    1035           13430 :             OGRLineString* poLS = NULL;
    1036                 : 
    1037           13430 :             switch( wkbFlatten(poGeometry->getGeometryType()) )
    1038                 :             {
    1039                 :                 case wkbPolygon:
    1040                 :                 {
    1041            5803 :                     OGRPolygon* poPoly = (OGRPolygon* )poGeometry;
    1042            5803 :                     OGRLinearRing* poRing = poPoly->getExteriorRing();
    1043            5803 :                     if (poRing != NULL && poPoly->getNumInteriorRings() == 0)
    1044                 :                     {
    1045            5480 :                         poLS = poRing;
    1046                 :                     }
    1047            5803 :                     break;
    1048                 :                 }
    1049                 : 
    1050                 :                 case wkbLineString:
    1051            7626 :                     poLS = (OGRLineString* )poGeometry;
    1052                 :                     break;
    1053                 : 
    1054                 :                 default:
    1055                 :                     break;
    1056                 :             }
    1057                 : 
    1058           13430 :             if( poLS != NULL )
    1059                 :             {
    1060           13106 :                 int nNumPoints = poLS->getNumPoints();
    1061          426803 :                 for(int i = 0; i < nNumPoints; i++)
    1062                 :                 {
    1063          424768 :                     double x = poLS->getX(i);
    1064          424768 :                     double y = poLS->getY(i);
    1065          424768 :                     if (x >= m_sFilterEnvelope.MinX &&
    1066                 :                         y >= m_sFilterEnvelope.MinY &&
    1067                 :                         x <= m_sFilterEnvelope.MaxX &&
    1068                 :                         y <= m_sFilterEnvelope.MaxY)
    1069                 :                     {
    1070           11071 :                         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            2374 :         if( OGRGeometryFactory::haveGEOS() )
    1081                 :         {
    1082                 :             //CPLDebug("OGRLayer", "GEOS intersection");
    1083            2374 :             if( m_pPreparedFilterGeom != NULL )
    1084                 :                 return OGRPreparedGeometryIntersects(m_pPreparedFilterGeom,
    1085            2374 :                                                      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           19022 : void OGR_L_ResetReading( OGRLayerH hLayer )
    1099                 : 
    1100                 : {
    1101           19022 :     VALIDATE_POINTER0( hLayer, "OGR_L_ResetReading" );
    1102                 : 
    1103           19022 :     ((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             457 : OGRErr OGRLayer::InitializeIndexSupport( const char *pszFilename )
    1115                 : 
    1116                 : {
    1117                 :     OGRErr eErr;
    1118                 : 
    1119             457 :     if (m_poAttrIndex != NULL)
    1120             410 :         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              73 : OGRErr OGR_L_DeleteFeature( OGRLayerH hDS, long nFID )
    1171                 : 
    1172                 : {
    1173              73 :     VALIDATE_POINTER1( hDS, "OGR_L_DeleteFeature", OGRERR_INVALID_HANDLE );
    1174                 : 
    1175              73 :     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             541 : const char *OGRLayer::GetGeometryColumn()
    1227                 : 
    1228                 : {
    1229             541 :     return "";
    1230                 : }
    1231                 : 
    1232                 : /************************************************************************/
    1233                 : /*                      OGR_L_GetGeometryColumn()                       */
    1234                 : /************************************************************************/
    1235                 : 
    1236              31 : const char *OGR_L_GetGeometryColumn( OGRLayerH hLayer )
    1237                 : 
    1238                 : {
    1239              31 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetGeometryColumn", NULL );
    1240                 : 
    1241              31 :     return ((OGRLayer *) hLayer)->GetGeometryColumn();
    1242                 : }
    1243                 : 
    1244                 : /************************************************************************/
    1245                 : /*                            GetStyleTable()                           */
    1246                 : /************************************************************************/
    1247                 : 
    1248             130 : OGRStyleTable *OGRLayer::GetStyleTable()
    1249                 : {
    1250             130 :     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             130 : void OGRLayer::SetStyleTable(OGRStyleTable *poStyleTable)
    1269                 : {
    1270             130 :     if ( m_poStyleTable )
    1271               0 :         delete m_poStyleTable;
    1272             130 :     if ( poStyleTable )
    1273               0 :         m_poStyleTable = poStyleTable->Clone();
    1274             130 : }
    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         1060630 : const char *OGRLayer::GetName()
    1320                 : 
    1321                 : {
    1322         1060630 :     return GetLayerDefn()->GetName();
    1323                 : }
    1324                 : 
    1325                 : /************************************************************************/
    1326                 : /*                           OGR_L_GetName()                            */
    1327                 : /************************************************************************/
    1328                 : 
    1329            2058 : const char* OGR_L_GetName( OGRLayerH hLayer )
    1330                 : 
    1331                 : {
    1332            2058 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetName", "" );
    1333                 : 
    1334            2058 :     return ((OGRLayer *) hLayer)->GetName();
    1335                 : }
    1336                 : 
    1337                 : /************************************************************************/
    1338                 : /*                            GetGeomType()                             */
    1339                 : /************************************************************************/
    1340                 : 
    1341            1399 : OGRwkbGeometryType OGRLayer::GetGeomType()
    1342                 : {
    1343            1399 :     return GetLayerDefn()->GetGeomType();
    1344                 : }
    1345                 : /************************************************************************/
    1346                 : /*                         OGR_L_GetGeomType()                          */
    1347                 : /************************************************************************/
    1348                 : 
    1349             119 : OGRwkbGeometryType OGR_L_GetGeomType( OGRLayerH hLayer )
    1350                 : 
    1351                 : {
    1352             119 :     VALIDATE_POINTER1( hLayer, "OGR_L_GetGeomType", wkbUnknown );
    1353                 : 
    1354             119 :     return ((OGRLayer *) hLayer)->GetGeomType();
    1355                 : }
    1356                 : 
    1357                 : /************************************************************************/
    1358                 : /*                          SetIgnoredFields()                          */
    1359                 : /************************************************************************/
    1360                 : 
    1361            1692 : OGRErr OGRLayer::SetIgnoredFields( const char **papszFields )
    1362                 : {
    1363            1692 :     OGRFeatureDefn *poDefn = GetLayerDefn();
    1364                 : 
    1365                 :     // first set everything as *not* ignored
    1366            9304 :     for( int iField = 0; iField < poDefn->GetFieldCount(); iField++ )
    1367                 :     {
    1368            7612 :         poDefn->GetFieldDefn(iField)->SetIgnored( FALSE );
    1369                 :     }
    1370            1692 :     poDefn->SetGeometryIgnored( FALSE );
    1371            1692 :     poDefn->SetStyleIgnored( FALSE );
    1372                 :     
    1373            1692 :     if ( papszFields == NULL )
    1374            1457 :         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                 : static
    1417              29 : OGRErr clone_spatial_filter(OGRLayer *pLayer, OGRGeometry **ppGeometry)
    1418                 : {
    1419              29 :     OGRErr ret = OGRERR_NONE;
    1420              29 :     OGRGeometry *g = pLayer->GetSpatialFilter();
    1421              29 :     *ppGeometry = g ? g->clone() : NULL;
    1422              29 :     return ret;
    1423                 : }
    1424                 : 
    1425                 : static
    1426              39 : OGRErr create_field_map(OGRFeatureDefn *poDefn, int **map)
    1427                 : {
    1428              39 :     OGRErr ret = OGRERR_NONE;
    1429              39 :     int n = poDefn->GetFieldCount();
    1430              39 :     if (n > 0) {
    1431               0 :         *map = (int*)VSIMalloc(sizeof(int) * n);
    1432               0 :         if (!(*map)) return OGRERR_NOT_ENOUGH_MEMORY;
    1433                 :     }
    1434              39 :     return ret;
    1435                 : }
    1436                 : 
    1437                 : static
    1438              22 : OGRErr set_result_schema(OGRLayer *pLayerResult,
    1439                 :                          OGRFeatureDefn *poDefnInput, 
    1440                 :                          OGRFeatureDefn *poDefnMethod,
    1441                 :                          int *mapInput,
    1442                 :                          int *mapMethod,
    1443                 :                          int combined,
    1444                 :                          char** papszOptions)
    1445                 : {
    1446              22 :     OGRErr ret = OGRERR_NONE;
    1447              22 :     OGRFeatureDefn *poDefnResult = pLayerResult->GetLayerDefn();
    1448              22 :     const char* pszInputPrefix = CSLFetchNameValue(papszOptions, "INPUT_PREFIX");
    1449              22 :     const char* pszMethodPrefix = CSLFetchNameValue(papszOptions, "METHOD_PREFIX");
    1450              22 :     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
    1451              22 :     if (poDefnResult->GetFieldCount() > 0) {
    1452                 :         // the user has defined the schema of the output layer
    1453               0 :         for( int iField = 0; iField < poDefnInput->GetFieldCount(); iField++ ) {
    1454               0 :             CPLString osName(poDefnInput->GetFieldDefn(iField)->GetNameRef());
    1455               0 :             if( pszInputPrefix != NULL )
    1456               0 :                 osName = pszInputPrefix + osName;
    1457               0 :             mapInput[iField] = poDefnResult->GetFieldIndex(osName);
    1458                 :         }
    1459               0 :         if (!mapMethod) return ret;
    1460               0 :         for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
    1461               0 :             CPLString osName(poDefnInput->GetFieldDefn(iField)->GetNameRef());
    1462               0 :             if( pszMethodPrefix != NULL )
    1463               0 :                 osName = pszMethodPrefix + osName;
    1464               0 :             mapMethod[iField] = poDefnResult->GetFieldIndex(osName);
    1465                 :         }
    1466                 :     } else {
    1467                 :         // use schema from the input layer or from input and method layers
    1468              22 :         int nFieldsInput = poDefnInput->GetFieldCount();
    1469              22 :         for( int iField = 0; iField < nFieldsInput; iField++ ) {
    1470               0 :             OGRFieldDefn oFieldDefn(poDefnInput->GetFieldDefn(iField));
    1471               0 :             if( pszInputPrefix != NULL )
    1472               0 :                 oFieldDefn.SetName(CPLSPrintf("%s%s", pszInputPrefix, oFieldDefn.GetNameRef()));
    1473               0 :             ret = pLayerResult->CreateField(&oFieldDefn);
    1474               0 :             if (!bSkipFailures && ret != OGRERR_NONE) return ret;
    1475               0 :             ret = OGRERR_NONE;
    1476               0 :             mapInput[iField] = iField;
    1477                 :         }
    1478              22 :         if (!combined) return ret;
    1479              13 :         if (!mapMethod) return ret;
    1480               0 :         for( int iField = 0; iField < poDefnMethod->GetFieldCount(); iField++ ) {
    1481               0 :             OGRFieldDefn oFieldDefn(poDefnMethod->GetFieldDefn(iField));
    1482               0 :             if( pszMethodPrefix != NULL )
    1483               0 :                 oFieldDefn.SetName(CPLSPrintf("%s%s", pszMethodPrefix, oFieldDefn.GetNameRef()));
    1484               0 :             ret = pLayerResult->CreateField(&oFieldDefn);
    1485               0 :             if (!bSkipFailures && ret != OGRERR_NONE) return ret;
    1486               0 :             ret = OGRERR_NONE;
    1487               0 :             mapMethod[iField] = nFieldsInput+iField;
    1488                 :         }
    1489                 :     }
    1490               0 :     return ret;
    1491                 : }
    1492                 : 
    1493                 : static
    1494              52 : OGRGeometry *set_filter_from(OGRLayer *pLayer, OGRGeometry *pGeometryExistingFilter, OGRFeature *pFeature)
    1495                 : {
    1496              52 :     OGRGeometry *geom = pFeature->GetGeometryRef();
    1497              52 :     if (!geom) return NULL;
    1498              52 :     if (pGeometryExistingFilter) {
    1499               0 :         if (!geom->Intersects(pGeometryExistingFilter)) return NULL;
    1500               0 :         OGRGeometry *intersection = geom->Intersection(pGeometryExistingFilter);
    1501               0 :         pLayer->SetSpatialFilter(intersection);
    1502               0 :         if (intersection) delete intersection;
    1503                 :     } else {
    1504              52 :         pLayer->SetSpatialFilter(geom);
    1505                 :     }
    1506              52 :     return geom;
    1507                 : }
    1508                 : 
    1509              20 : static OGRGeometry* promote_to_multi(OGRGeometry* poGeom)
    1510                 : {
    1511              20 :     OGRwkbGeometryType eType = wkbFlatten(poGeom->getGeometryType());
    1512              20 :     if( eType == wkbPolygon )
    1513              20 :         return OGRGeometryFactory::forceToMultiPolygon(poGeom);
    1514               0 :     else if( eType == wkbLineString )
    1515               0 :         return OGRGeometryFactory::forceToMultiLineString(poGeom);
    1516                 :     else
    1517               0 :         return poGeom;
    1518                 : }
    1519                 : 
    1520                 : /************************************************************************/
    1521                 : /*                          Intersection()                              */
    1522                 : /************************************************************************/
    1523                 : /**
    1524                 :  * \brief Intersection of two layers.
    1525                 :  *
    1526                 :  * The result layer contains features whose geometries represent areas
    1527                 :  * that are common between features in the input layer and in the
    1528                 :  * method layer. The features in the result layer have attributes from
    1529                 :  * both input and method layers. The schema of the result layer can be
    1530                 :  * set by the user or, if it is empty, is initialized to contain all
    1531                 :  * fields in the input and method layers.
    1532                 :  *
    1533                 :  * \note If the schema of the result is set by user and contains
    1534                 :  * fields that have the same name as a field in input and in method
    1535                 :  * layer, then the attribute in the result feature will get the value
    1536                 :  * from the feature of the method layer.
    1537                 :  *
    1538                 :  * \note For best performance use the minimum amount of features in
    1539                 :  * the method layer and copy it into a memory layer.
    1540                 :  *
    1541                 :  * \note This method relies on GEOS support. Do not use unless the
    1542                 :  * GEOS support is compiled in.
    1543                 :  *
    1544                 :  * The recognized list of options is :
    1545                 :  * <ul>
    1546                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    1547                 :  *     feature could not be inserted.
    1548                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    1549                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    1550                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    1551                 :  *     will be created from the fields of the input layer.
    1552                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    1553                 :  *     will be created from the fields of the method layer.
    1554                 :  * </ul>
    1555                 :  *
    1556                 :  * This method is the same as the C function OGR_L_Intersection().
    1557                 :  *
    1558                 :  * @param pLayerMethod the method layer. Should not be NULL.
    1559                 :  *
    1560                 :  * @param pLayerResult the layer where the features resulting from the
    1561                 :  * operation are inserted. Should not be NULL. See above the note
    1562                 :  * about the schema.
    1563                 :  *
    1564                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    1565                 :  *
    1566                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    1567                 :  * reporting progress or NULL.
    1568                 :  *
    1569                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    1570                 :  *
    1571                 :  * @return an error code if there was an error or the execution was
    1572                 :  * interrupted, OGRERR_NONE otherwise.
    1573                 :  *
    1574                 :  * @since OGR 1.10
    1575                 :  */
    1576                 : 
    1577               3 : OGRErr OGRLayer::Intersection( OGRLayer *pLayerMethod, 
    1578                 :                                OGRLayer *pLayerResult, 
    1579                 :                                char** papszOptions, 
    1580                 :                                GDALProgressFunc pfnProgress, 
    1581                 :                                void * pProgressArg )
    1582                 : {
    1583               3 :     OGRErr ret = OGRERR_NONE;
    1584               3 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    1585               3 :     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
    1586               3 :     OGRFeatureDefn *poDefnResult = NULL;
    1587               3 :     OGRGeometry *pGeometryMethodFilter = NULL;
    1588               3 :     int *mapInput = NULL;
    1589               3 :     int *mapMethod = NULL;
    1590               3 :     OGREnvelope sEnvelopeMethod;
    1591                 :     GBool bEnvelopeSet;
    1592               3 :     double progress_max = GetFeatureCount(0);
    1593               3 :     double progress_counter = 0;
    1594               3 :     double progress_ticker = 0;
    1595               3 :     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
    1596               3 :     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
    1597                 : 
    1598                 :     // check for GEOS
    1599               3 :     if (!OGRGeometryFactory::haveGEOS()) {
    1600               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    1601                 :     }
    1602                 : 
    1603                 :     // get resources
    1604               3 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    1605               3 :     if (ret != OGRERR_NONE) goto done;
    1606               3 :     ret = create_field_map(poDefnInput, &mapInput);
    1607               3 :     if (ret != OGRERR_NONE) goto done;
    1608               3 :     ret = create_field_map(poDefnMethod, &mapMethod);
    1609               3 :     if (ret != OGRERR_NONE) goto done;
    1610               3 :     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
    1611               3 :     if (ret != OGRERR_NONE) goto done;
    1612               3 :     poDefnResult = pLayerResult->GetLayerDefn();
    1613               3 :     bEnvelopeSet = pLayerMethod->GetExtent(&sEnvelopeMethod, 1) == OGRERR_NONE;
    1614                 : 
    1615               3 :     ResetReading();
    1616              15 :     while (OGRFeature *x = GetNextFeature()) {
    1617                 : 
    1618               6 :         if (pfnProgress) {
    1619               0 :             double p = progress_counter/progress_max;
    1620               0 :             if (p > progress_ticker) {
    1621               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    1622               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    1623               0 :                     ret = OGRERR_FAILURE;
    1624               0 :                     delete x;
    1625               0 :                     goto done;
    1626                 :                 }
    1627                 :             }
    1628               0 :             progress_counter += 1.0;
    1629                 :         }
    1630                 : 
    1631                 :         // is it worth to proceed?
    1632               6 :         if (bEnvelopeSet) {
    1633               6 :             OGRGeometry *x_geom = x->GetGeometryRef();
    1634               6 :             if (x_geom) {
    1635               6 :                 OGREnvelope x_env;
    1636               6 :                 x_geom->getEnvelope(&x_env);
    1637               6 :                 if (x_env.MaxX < sEnvelopeMethod.MinX 
    1638                 :                     || x_env.MaxY < sEnvelopeMethod.MinY
    1639                 :                     || sEnvelopeMethod.MaxX < x_env.MinX
    1640                 :                     || sEnvelopeMethod.MaxY < x_env.MinY) {
    1641               0 :                     delete x;
    1642               0 :                     continue;
    1643                 :                 }
    1644                 :             } else {
    1645               0 :                 delete x;
    1646               0 :                 continue;
    1647                 :             }
    1648                 :         }
    1649                 : 
    1650                 :         // set up the filter for method layer
    1651               6 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    1652               6 :         if (!x_geom) {
    1653               0 :             delete x;
    1654               0 :             continue;
    1655                 :         }
    1656                 : 
    1657               6 :         pLayerMethod->ResetReading();
    1658              22 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    1659               8 :             OGRGeometry *y_geom = y->GetGeometryRef();
    1660               8 :             if (!y_geom) {delete y; continue;}
    1661               8 :             OGRGeometry* poIntersection = x_geom->Intersection(y_geom);
    1662              32 :             if( poIntersection == NULL || poIntersection->IsEmpty() ||
    1663               8 :                 (x_geom->getDimension() == 2 &&
    1664               8 :                 y_geom->getDimension() == 2 &&
    1665               8 :                 poIntersection->getDimension() < 2) )
    1666                 :             {
    1667               2 :                 delete poIntersection;
    1668               2 :                 delete y;
    1669                 :             }
    1670                 :             else
    1671                 :             {
    1672               6 :                 OGRFeature *z = new OGRFeature(poDefnResult);
    1673               6 :                 z->SetFieldsFrom(x, mapInput);
    1674               6 :                 z->SetFieldsFrom(y, mapMethod);
    1675               6 :                 if( bPromoteToMulti )
    1676               2 :                     poIntersection = promote_to_multi(poIntersection);
    1677               6 :                 z->SetGeometryDirectly(poIntersection);
    1678               6 :                 delete y;
    1679               6 :                 ret = pLayerResult->CreateFeature(z);
    1680               6 :                 delete z;
    1681               6 :                 if (!bSkipFailures && ret != OGRERR_NONE) {delete x; goto done;}
    1682               6 :                 ret = OGRERR_NONE;
    1683                 :             }
    1684                 :         }
    1685                 : 
    1686              12 :         delete x;
    1687                 :     }
    1688               3 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    1689               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    1690               0 :       ret = OGRERR_FAILURE;
    1691                 :       goto done;
    1692                 :     }
    1693                 : done:
    1694                 :     // release resources
    1695               3 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    1696               3 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    1697               3 :     if (mapInput) VSIFree(mapInput);
    1698               3 :     if (mapMethod) VSIFree(mapMethod);
    1699               3 :     return ret;
    1700                 : }
    1701                 : 
    1702                 : /************************************************************************/
    1703                 : /*                       OGR_L_Intersection()                           */
    1704                 : /************************************************************************/
    1705                 : /**
    1706                 :  * \brief Intersection of two layers.
    1707                 :  *
    1708                 :  * The result layer contains features whose geometries represent areas
    1709                 :  * that are common between features in the input layer and in the
    1710                 :  * method layer. The features in the result layer have attributes from
    1711                 :  * both input and method layers. The schema of the result layer can be
    1712                 :  * set by the user or, if it is empty, is initialized to contain all
    1713                 :  * fields in the input and method layers.
    1714                 :  *
    1715                 :  * \note If the schema of the result is set by user and contains
    1716                 :  * fields that have the same name as a field in input and in method
    1717                 :  * layer, then the attribute in the result feature will get the value
    1718                 :  * from the feature of the method layer.
    1719                 :  *
    1720                 :  * \note For best performance use the minimum amount of features in
    1721                 :  * the method layer and copy it into a memory layer.
    1722                 :  *
    1723                 :  * \note This method relies on GEOS support. Do not use unless the
    1724                 :  * GEOS support is compiled in.
    1725                 :  *
    1726                 :  * The recognized list of options is :
    1727                 :  * <ul>
    1728                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    1729                 :  *     feature could not be inserted.
    1730                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    1731                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    1732                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    1733                 :  *     will be created from the fields of the input layer.
    1734                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    1735                 :  *     will be created from the fields of the method layer.
    1736                 :  * </ul>
    1737                 :  *
    1738                 :  * This function is the same as the C++ method OGRLayer::Intersection().
    1739                 :  * 
    1740                 :  * @param pLayerInput the input layer. Should not be NULL.
    1741                 :  *
    1742                 :  * @param pLayerMethod the method layer. Should not be NULL.
    1743                 :  *
    1744                 :  * @param pLayerResult the layer where the features resulting from the
    1745                 :  * operation are inserted. Should not be NULL. See above the note
    1746                 :  * about the schema.
    1747                 :  *
    1748                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    1749                 :  *
    1750                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    1751                 :  * reporting progress or NULL.
    1752                 :  *
    1753                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    1754                 :  *
    1755                 :  * @return an error code if there was an error or the execution was
    1756                 :  * interrupted, OGRERR_NONE otherwise.
    1757                 :  *
    1758                 :  * @since OGR 1.10
    1759                 :  */
    1760                 : 
    1761               3 : OGRErr OGR_L_Intersection( OGRLayerH pLayerInput, 
    1762                 :                            OGRLayerH pLayerMethod, 
    1763                 :                            OGRLayerH pLayerResult, 
    1764                 :                            char** papszOptions, 
    1765                 :                            GDALProgressFunc pfnProgress, 
    1766                 :                            void * pProgressArg )
    1767                 : 
    1768                 : {
    1769               3 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
    1770               3 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
    1771               3 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Intersection", OGRERR_INVALID_HANDLE );
    1772                 : 
    1773               3 :     return ((OGRLayer *)pLayerInput)->Intersection( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    1774                 : }
    1775                 : 
    1776                 : /************************************************************************/
    1777                 : /*                              Union()                                 */
    1778                 : /************************************************************************/
    1779                 : 
    1780                 : /**
    1781                 :  * \brief Union of two layers.
    1782                 :  *
    1783                 :  * The result layer contains features whose geometries represent areas
    1784                 :  * that are in either in the input layer or in the method layer. The
    1785                 :  * features in the result layer have attributes from both input and
    1786                 :  * method layers. For features which represent areas that are only in
    1787                 :  * the input or in the method layer the respective attributes have
    1788                 :  * undefined values. The schema of the result layer can be set by the
    1789                 :  * user or, if it is empty, is initialized to contain all fields in
    1790                 :  * the input and method layers.
    1791                 :  *
    1792                 :  * \note If the schema of the result is set by user and contains
    1793                 :  * fields that have the same name as a field in input and in method
    1794                 :  * layer, then the attribute in the result feature will get the value
    1795                 :  * from the feature of the method layer (even if it is undefined).
    1796                 :  *
    1797                 :  * \note For best performance use the minimum amount of features in
    1798                 :  * the method layer and copy it into a memory layer.
    1799                 :  *
    1800                 :  * \note This method relies on GEOS support. Do not use unless the
    1801                 :  * GEOS support is compiled in.
    1802                 :  *
    1803                 :  * The recognized list of options is :
    1804                 :  * <ul>
    1805                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    1806                 :  *     feature could not be inserted.
    1807                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    1808                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    1809                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    1810                 :  *     will be created from the fields of the input layer.
    1811                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    1812                 :  *     will be created from the fields of the method layer.
    1813                 :  * </ul>
    1814                 :  *
    1815                 :  * This method is the same as the C function OGR_L_Union().
    1816                 :  * 
    1817                 :  * @param pLayerMethod the method layer. Should not be NULL.
    1818                 :  *
    1819                 :  * @param pLayerResult the layer where the features resulting from the
    1820                 :  * operation are inserted. Should not be NULL. See above the note
    1821                 :  * about the schema.
    1822                 :  *
    1823                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    1824                 :  *
    1825                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    1826                 :  * reporting progress or NULL.
    1827                 :  *
    1828                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    1829                 :  *
    1830                 :  * @return an error code if there was an error or the execution was
    1831                 :  * interrupted, OGRERR_NONE otherwise.
    1832                 :  *
    1833                 :  * @since OGR 1.10
    1834                 :  */
    1835                 : 
    1836               4 : OGRErr OGRLayer::Union( OGRLayer *pLayerMethod, 
    1837                 :                         OGRLayer *pLayerResult, 
    1838                 :                         char** papszOptions, 
    1839                 :                         GDALProgressFunc pfnProgress, 
    1840                 :                         void * pProgressArg )
    1841                 : {
    1842               4 :     OGRErr ret = OGRERR_NONE;
    1843               4 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    1844               4 :     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
    1845               4 :     OGRFeatureDefn *poDefnResult = NULL;
    1846               4 :     OGRGeometry *pGeometryMethodFilter = NULL;
    1847               4 :     OGRGeometry *pGeometryInputFilter = NULL;
    1848               4 :     int *mapInput = NULL;
    1849               4 :     int *mapMethod = NULL;
    1850               4 :     double progress_max = GetFeatureCount(0) + pLayerMethod->GetFeatureCount(0);
    1851               4 :     double progress_counter = 0;
    1852               4 :     double progress_ticker = 0;
    1853               4 :     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
    1854               4 :     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
    1855                 : 
    1856                 :     // check for GEOS
    1857               4 :     if (!OGRGeometryFactory::haveGEOS()) {
    1858               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    1859                 :     }
    1860                 : 
    1861                 :     // get resources
    1862               4 :     ret = clone_spatial_filter(this, &pGeometryInputFilter);
    1863               4 :     if (ret != OGRERR_NONE) goto done;
    1864               4 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    1865               4 :     if (ret != OGRERR_NONE) goto done;
    1866               4 :     ret = create_field_map(poDefnInput, &mapInput);
    1867               4 :     if (ret != OGRERR_NONE) goto done;
    1868               4 :     ret = create_field_map(poDefnMethod, &mapMethod);
    1869               4 :     if (ret != OGRERR_NONE) goto done;
    1870               4 :     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
    1871               4 :     if (ret != OGRERR_NONE) goto done;
    1872               4 :     poDefnResult = pLayerResult->GetLayerDefn();
    1873                 : 
    1874                 :     // add features based on input layer
    1875               4 :     ResetReading();
    1876              18 :     while (OGRFeature *x = GetNextFeature()) {
    1877                 : 
    1878               7 :         if (pfnProgress) {
    1879               0 :             double p = progress_counter/progress_max;
    1880               0 :             if (p > progress_ticker) {
    1881               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    1882               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    1883               0 :                     ret = OGRERR_FAILURE;
    1884               0 :                     delete x;
    1885               0 :                     goto done;
    1886                 :                 }
    1887                 :             }
    1888               0 :             progress_counter += 1.0;
    1889                 :         }
    1890                 : 
    1891                 :         // set up the filter on method layer
    1892               7 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    1893               7 :         if (!x_geom) {
    1894               0 :             delete x; 
    1895               0 :             continue;
    1896                 :         }
    1897                 :         
    1898               7 :         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
    1899               7 :         pLayerMethod->ResetReading();
    1900              25 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    1901               9 :             OGRGeometry *y_geom = y->GetGeometryRef();
    1902               9 :             if (!y_geom) {delete y; continue;}
    1903               9 :             OGRGeometry *poIntersection = x_geom->Intersection(y_geom);
    1904              35 :             if( poIntersection == NULL || poIntersection->IsEmpty() ||
    1905               9 :                 (x_geom->getDimension() == 2 &&
    1906               9 :                 y_geom->getDimension() == 2 &&
    1907               8 :                 poIntersection->getDimension() < 2) )
    1908                 :             {
    1909               2 :                 delete poIntersection;
    1910               2 :                 delete y;
    1911                 :             }
    1912                 :             else
    1913                 :             {
    1914               7 :                 OGRFeature *z = new OGRFeature(poDefnResult);
    1915               7 :                 z->SetFieldsFrom(x, mapInput);
    1916               7 :                 z->SetFieldsFrom(y, mapMethod);
    1917               7 :                 if( bPromoteToMulti )
    1918               2 :                     poIntersection = promote_to_multi(poIntersection);
    1919               7 :                 z->SetGeometryDirectly(poIntersection);
    1920               7 :                 OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
    1921               7 :                 if (x_geom_diff) delete x_geom_diff;
    1922               7 :                 x_geom_diff = x_geom_diff_new;
    1923               7 :                 delete y;
    1924               7 :                 ret = pLayerResult->CreateFeature(z);
    1925               7 :                 delete z;
    1926               7 :                 if (!bSkipFailures && ret != OGRERR_NONE) {delete x; if (x_geom_diff) delete x_geom_diff; goto done;}
    1927               7 :                 ret = OGRERR_NONE;
    1928                 :             }
    1929                 :         }
    1930                 : 
    1931              14 :         if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
    1932                 :         {
    1933               2 :             delete x_geom_diff;
    1934               2 :             delete x;
    1935                 :         }
    1936                 :         else
    1937                 :         {
    1938               5 :             OGRFeature *z = new OGRFeature(poDefnResult);
    1939               5 :             z->SetFieldsFrom(x, mapInput);
    1940               5 :             if( bPromoteToMulti )
    1941               2 :                 x_geom_diff = promote_to_multi(x_geom_diff);
    1942               5 :             z->SetGeometryDirectly(x_geom_diff);
    1943               5 :             delete x;
    1944               5 :             ret = pLayerResult->CreateFeature(z);
    1945               5 :             delete z;
    1946               5 :             if (!bSkipFailures && ret != OGRERR_NONE) goto done;
    1947               5 :             ret = OGRERR_NONE;
    1948                 :         }
    1949                 :     }
    1950                 : 
    1951                 :     // restore filter on method layer and add features based on it
    1952               4 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    1953               4 :     pLayerMethod->ResetReading();
    1954              14 :     while (OGRFeature *x = pLayerMethod->GetNextFeature()) {
    1955                 : 
    1956               5 :         if (pfnProgress) {
    1957               0 :             double p = progress_counter/progress_max;
    1958               0 :             if (p > progress_ticker) {
    1959               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    1960               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    1961               0 :                     ret = OGRERR_FAILURE;
    1962               0 :                     delete x;
    1963               0 :                     goto done;
    1964                 :                 }
    1965                 :             }
    1966               0 :             progress_counter += 1.0;
    1967                 :         }
    1968                 : 
    1969                 :         // set up the filter on input layer
    1970               5 :         OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
    1971               5 :         if (!x_geom) {
    1972               0 :             delete x; 
    1973               0 :             continue;
    1974                 :         }
    1975                 :         
    1976               5 :         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
    1977               5 :         ResetReading();
    1978              23 :         while (OGRFeature *y = GetNextFeature()) {
    1979               9 :             OGRGeometry *y_geom = y->GetGeometryRef();
    1980               9 :             if (!y_geom) {delete y; continue;}
    1981               9 :             OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
    1982               9 :             if (x_geom_diff) delete x_geom_diff;
    1983               9 :             x_geom_diff = x_geom_diff_new;
    1984               9 :             delete y;
    1985                 :         }
    1986                 : 
    1987              10 :         if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
    1988                 :         {
    1989               3 :             delete x_geom_diff;
    1990               3 :             delete x;
    1991                 :         }
    1992                 :         else
    1993                 :         {
    1994               2 :             OGRFeature *z = new OGRFeature(poDefnResult);
    1995               2 :             z->SetFieldsFrom(x, mapMethod);
    1996               2 :             if( bPromoteToMulti )
    1997               1 :                 x_geom_diff = promote_to_multi(x_geom_diff);
    1998               2 :             z->SetGeometryDirectly(x_geom_diff);
    1999               2 :             delete x;
    2000               2 :             ret = pLayerResult->CreateFeature(z);
    2001               2 :             delete z;
    2002               2 :             if (!bSkipFailures && ret != OGRERR_NONE) goto done;
    2003               2 :             ret = OGRERR_NONE;
    2004                 :         }
    2005                 :     }
    2006               4 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    2007               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2008               0 :       ret = OGRERR_FAILURE;
    2009                 :       goto done;
    2010                 :     }
    2011                 : done:
    2012                 :     // release resources
    2013               4 :     SetSpatialFilter(pGeometryInputFilter);
    2014               4 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2015               4 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    2016               4 :     if (pGeometryInputFilter) delete pGeometryInputFilter;
    2017               4 :     if (mapInput) VSIFree(mapInput);
    2018               4 :     if (mapMethod) VSIFree(mapMethod);
    2019               4 :     return ret;
    2020                 : }
    2021                 : 
    2022                 : /************************************************************************/
    2023                 : /*                           OGR_L_Union()                              */
    2024                 : /************************************************************************/
    2025                 : 
    2026                 : /**
    2027                 :  * \brief Union of two layers.
    2028                 :  *
    2029                 :  * The result layer contains features whose geometries represent areas
    2030                 :  * that are in either in the input layer or in the method layer. The
    2031                 :  * features in the result layer have attributes from both input and
    2032                 :  * method layers. For features which represent areas that are only in
    2033                 :  * the input or in the method layer the respective attributes have
    2034                 :  * undefined values. The schema of the result layer can be set by the
    2035                 :  * user or, if it is empty, is initialized to contain all fields in
    2036                 :  * the input and method layers.
    2037                 :  *
    2038                 :  * \note If the schema of the result is set by user and contains
    2039                 :  * fields that have the same name as a field in input and in method
    2040                 :  * layer, then the attribute in the result feature will get the value
    2041                 :  * from the feature of the method layer (even if it is undefined).
    2042                 :  *
    2043                 :  * \note For best performance use the minimum amount of features in
    2044                 :  * the method layer and copy it into a memory layer.
    2045                 :  *
    2046                 :  * \note This method relies on GEOS support. Do not use unless the
    2047                 :  * GEOS support is compiled in.
    2048                 :  *
    2049                 :  * The recognized list of options is :
    2050                 :  * <ul>
    2051                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    2052                 :  *     feature could not be inserted.
    2053                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    2054                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    2055                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    2056                 :  *     will be created from the fields of the input layer.
    2057                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    2058                 :  *     will be created from the fields of the method layer.
    2059                 :  * </ul>
    2060                 :  *
    2061                 :  * This function is the same as the C++ method OGRLayer::Union().
    2062                 :  * 
    2063                 :  * @param pLayerInput the input layer. Should not be NULL.
    2064                 :  *
    2065                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2066                 :  *
    2067                 :  * @param pLayerResult the layer where the features resulting from the
    2068                 :  * operation are inserted. Should not be NULL. See above the note
    2069                 :  * about the schema.
    2070                 :  *
    2071                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2072                 :  *
    2073                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2074                 :  * reporting progress or NULL.
    2075                 :  *
    2076                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2077                 :  *
    2078                 :  * @return an error code if there was an error or the execution was
    2079                 :  * interrupted, OGRERR_NONE otherwise.
    2080                 :  *
    2081                 :  * @since OGR 1.10 
    2082                 :  */
    2083                 : 
    2084               4 : OGRErr OGR_L_Union( OGRLayerH pLayerInput, 
    2085                 :                     OGRLayerH pLayerMethod, 
    2086                 :                     OGRLayerH pLayerResult, 
    2087                 :                     char** papszOptions, 
    2088                 :                     GDALProgressFunc pfnProgress, 
    2089                 :                     void * pProgressArg )
    2090                 : 
    2091                 : {
    2092               4 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Union", OGRERR_INVALID_HANDLE );
    2093               4 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Union", OGRERR_INVALID_HANDLE );
    2094               4 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Union", OGRERR_INVALID_HANDLE );
    2095                 : 
    2096               4 :     return ((OGRLayer *)pLayerInput)->Union( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    2097                 : }
    2098                 : 
    2099                 : /************************************************************************/
    2100                 : /*                          SymDifference()                             */
    2101                 : /************************************************************************/
    2102                 : 
    2103                 : /**
    2104                 :  * \brief Symmetrical difference of two layers.
    2105                 :  *
    2106                 :  * The result layer contains features whose geometries represent areas
    2107                 :  * that are in either in the input layer or in the method layer but
    2108                 :  * not in both. The features in the result layer have attributes from
    2109                 :  * both input and method layers. For features which represent areas
    2110                 :  * that are only in the input or in the method layer the respective
    2111                 :  * attributes have undefined values. The schema of the result layer
    2112                 :  * can be set by the user or, if it is empty, is initialized to
    2113                 :  * contain all fields in the input and method layers.
    2114                 :  *
    2115                 :  * \note If the schema of the result is set by user and contains
    2116                 :  * fields that have the same name as a field in input and in method
    2117                 :  * layer, then the attribute in the result feature will get the value
    2118                 :  * from the feature of the method layer (even if it is undefined).
    2119                 :  *
    2120                 :  * \note For best performance use the minimum amount of features in
    2121                 :  * the method layer and copy it into a memory layer.
    2122                 :  *
    2123                 :  * \note This method relies on GEOS support. Do not use unless the
    2124                 :  * GEOS support is compiled in.
    2125                 :  *
    2126                 :  * The recognized list of options is :
    2127                 :  * <ul>
    2128                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    2129                 :  *     feature could not be inserted.
    2130                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    2131                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    2132                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    2133                 :  *     will be created from the fields of the input layer.
    2134                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    2135                 :  *     will be created from the fields of the method layer.
    2136                 :  * </ul>
    2137                 :  *
    2138                 :  * This method is the same as the C function OGR_L_SymDifference().
    2139                 :  * 
    2140                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2141                 :  *
    2142                 :  * @param pLayerResult the layer where the features resulting from the
    2143                 :  * operation are inserted. Should not be NULL. See above the note
    2144                 :  * about the schema.
    2145                 :  *
    2146                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2147                 :  *
    2148                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2149                 :  * reporting progress or NULL.
    2150                 :  *
    2151                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2152                 :  *
    2153                 :  * @return an error code if there was an error or the execution was
    2154                 :  * interrupted, OGRERR_NONE otherwise.
    2155                 :  *
    2156                 :  * @since OGR 1.10
    2157                 :  */
    2158                 : 
    2159               3 : OGRErr OGRLayer::SymDifference( OGRLayer *pLayerMethod, 
    2160                 :                                 OGRLayer *pLayerResult, 
    2161                 :                                 char** papszOptions, 
    2162                 :                                 GDALProgressFunc pfnProgress, 
    2163                 :                                 void * pProgressArg )
    2164                 : {
    2165               3 :     OGRErr ret = OGRERR_NONE;
    2166               3 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    2167               3 :     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
    2168               3 :     OGRFeatureDefn *poDefnResult = NULL;
    2169               3 :     OGRGeometry *pGeometryMethodFilter = NULL;
    2170               3 :     OGRGeometry *pGeometryInputFilter = NULL;
    2171               3 :     int *mapInput = NULL;
    2172               3 :     int *mapMethod = NULL;
    2173               3 :     double progress_max = GetFeatureCount(0) + pLayerMethod->GetFeatureCount(0);
    2174               3 :     double progress_counter = 0;
    2175               3 :     double progress_ticker = 0;
    2176               3 :     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
    2177               3 :     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
    2178                 : 
    2179                 :     // check for GEOS
    2180               3 :     if (!OGRGeometryFactory::haveGEOS()) {
    2181               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    2182                 :     }
    2183                 : 
    2184                 :     // get resources
    2185               3 :     ret = clone_spatial_filter(this, &pGeometryInputFilter);
    2186               3 :     if (ret != OGRERR_NONE) goto done;
    2187               3 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    2188               3 :     if (ret != OGRERR_NONE) goto done;
    2189               3 :     ret = create_field_map(poDefnInput, &mapInput);
    2190               3 :     if (ret != OGRERR_NONE) goto done;
    2191               3 :     ret = create_field_map(poDefnMethod, &mapMethod);
    2192               3 :     if (ret != OGRERR_NONE) goto done;
    2193               3 :     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
    2194               3 :     if (ret != OGRERR_NONE) goto done;
    2195               3 :     poDefnResult = pLayerResult->GetLayerDefn();
    2196                 : 
    2197                 :     // add features based on input layer
    2198               3 :     ResetReading();
    2199              15 :     while (OGRFeature *x = GetNextFeature()) {
    2200                 : 
    2201               6 :         if (pfnProgress) {
    2202               0 :             double p = progress_counter/progress_max;
    2203               0 :             if (p > progress_ticker) {
    2204               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2205               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2206               0 :                     ret = OGRERR_FAILURE;
    2207               0 :                     delete x;
    2208               0 :                     goto done;
    2209                 :                 }
    2210                 :             }
    2211               0 :             progress_counter += 1.0;
    2212                 :         }
    2213                 : 
    2214                 :         // set up the filter on method layer
    2215               6 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    2216               6 :         if (!x_geom) {
    2217               0 :             delete x; 
    2218               0 :             continue;
    2219                 :         }
    2220                 :         
    2221               6 :         OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
    2222               6 :         pLayerMethod->ResetReading();
    2223              16 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    2224               7 :             OGRGeometry *y_geom = y->GetGeometryRef();
    2225               7 :             if (!y_geom) {delete y; continue;}
    2226               7 :             OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
    2227               7 :             if (geom) delete geom;
    2228               7 :             geom = geom_new;
    2229               7 :             delete y;
    2230               7 :             if (geom && geom->IsEmpty()) break;
    2231                 :         }
    2232                 : 
    2233               6 :         OGRFeature *z = NULL;
    2234               6 :         if (geom && !geom->IsEmpty()) {
    2235               4 :             z = new OGRFeature(poDefnResult);
    2236               4 :             z->SetFieldsFrom(x, mapInput);
    2237               4 :             if( bPromoteToMulti )
    2238               2 :                 geom = promote_to_multi(geom);
    2239               4 :             z->SetGeometryDirectly(geom);
    2240                 :         } else {
    2241               2 :             if (geom) delete geom;
    2242                 :         }
    2243               6 :         delete x;
    2244               6 :         if (z) {
    2245               4 :             ret = pLayerResult->CreateFeature(z);
    2246               4 :             delete z;
    2247               4 :             if (!bSkipFailures && ret != OGRERR_NONE) goto done;
    2248               4 :             ret = OGRERR_NONE;
    2249                 :         }
    2250                 :     }
    2251                 : 
    2252                 :     // restore filter on method layer and add features based on it
    2253               3 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2254               3 :     pLayerMethod->ResetReading();
    2255              11 :     while (OGRFeature *x = pLayerMethod->GetNextFeature()) {
    2256                 : 
    2257               4 :         if (pfnProgress) {
    2258               0 :             double p = progress_counter/progress_max;
    2259               0 :             if (p > progress_ticker) {
    2260               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2261               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2262               0 :                     ret = OGRERR_FAILURE;
    2263               0 :                     delete x;
    2264               0 :                     goto done;
    2265                 :                 }
    2266                 :             }
    2267               0 :             progress_counter += 1.0;
    2268                 :         }
    2269                 : 
    2270                 :         // set up the filter on input layer
    2271               4 :         OGRGeometry *x_geom = set_filter_from(this, pGeometryInputFilter, x);
    2272               4 :         if (!x_geom) {
    2273               0 :             delete x; 
    2274               0 :             continue;
    2275                 :         }
    2276                 :         
    2277               4 :         OGRGeometry *geom = x_geom->clone(); // this will be the geometry of the result feature
    2278               4 :         ResetReading();
    2279              14 :         while (OGRFeature *y = GetNextFeature()) {
    2280               7 :             OGRGeometry *y_geom = y->GetGeometryRef();
    2281               7 :             if (!y_geom) {delete y; continue;}
    2282               7 :             OGRGeometry *geom_new = geom ? geom->Difference(y_geom) : NULL;
    2283               7 :             if (geom) delete geom;
    2284               7 :             geom = geom_new;
    2285               7 :             delete y;
    2286               7 :             if (geom == NULL || geom->IsEmpty()) break;
    2287                 :         }
    2288                 : 
    2289               4 :         OGRFeature *z = NULL;
    2290               4 :         if (geom && !geom->IsEmpty()) {
    2291               2 :             z = new OGRFeature(poDefnResult);
    2292               2 :             z->SetFieldsFrom(x, mapMethod);
    2293               2 :             if( bPromoteToMulti )
    2294               1 :                 geom = promote_to_multi(geom);
    2295               2 :             z->SetGeometryDirectly(geom);
    2296                 :         } else {
    2297               2 :             if (geom) delete geom;
    2298                 :         }
    2299               4 :         delete x;
    2300               4 :         if (z) {
    2301               2 :             ret = pLayerResult->CreateFeature(z);
    2302               2 :             delete z;
    2303               2 :             if (!bSkipFailures && ret != OGRERR_NONE) goto done;
    2304               2 :             ret = OGRERR_NONE;
    2305                 :         }
    2306                 :     }
    2307               3 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    2308               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2309               0 :       ret = OGRERR_FAILURE;
    2310                 :       goto done;
    2311                 :     }
    2312                 : done:
    2313                 :     // release resources
    2314               3 :     SetSpatialFilter(pGeometryInputFilter);
    2315               3 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2316               3 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    2317               3 :     if (pGeometryInputFilter) delete pGeometryInputFilter;
    2318               3 :     if (mapInput) VSIFree(mapInput);
    2319               3 :     if (mapMethod) VSIFree(mapMethod);
    2320               3 :     return ret;
    2321                 : }
    2322                 : 
    2323                 : /************************************************************************/
    2324                 : /*                        OGR_L_SymDifference()                         */
    2325                 : /************************************************************************/
    2326                 : 
    2327                 : /**
    2328                 :  * \brief Symmetrical difference of two layers.
    2329                 :  *
    2330                 :  * The result layer contains features whose geometries represent areas
    2331                 :  * that are in either in the input layer or in the method layer but
    2332                 :  * not in both. The features in the result layer have attributes from
    2333                 :  * both input and method layers. For features which represent areas
    2334                 :  * that are only in the input or in the method layer the respective
    2335                 :  * attributes have undefined values. The schema of the result layer
    2336                 :  * can be set by the user or, if it is empty, is initialized to
    2337                 :  * contain all fields in the input and method layers.
    2338                 :  *
    2339                 :  * \note If the schema of the result is set by user and contains
    2340                 :  * fields that have the same name as a field in input and in method
    2341                 :  * layer, then the attribute in the result feature will get the value
    2342                 :  * from the feature of the method layer (even if it is undefined).
    2343                 :  *
    2344                 :  * \note For best performance use the minimum amount of features in
    2345                 :  * the method layer and copy it into a memory layer.
    2346                 :  *
    2347                 :  * \note This method relies on GEOS support. Do not use unless the
    2348                 :  * GEOS support is compiled in.
    2349                 :  *
    2350                 :  * The recognized list of options is :
    2351                 :  * <ul>
    2352                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    2353                 :  *     feature could not be inserted.
    2354                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    2355                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    2356                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    2357                 :  *     will be created from the fields of the input layer.
    2358                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    2359                 :  *     will be created from the fields of the method layer.
    2360                 :  * </ul>
    2361                 :  *
    2362                 :  * This function is the same as the C++ method OGRLayer::SymDifference().
    2363                 :  *
    2364                 :  * @param pLayerInput the input layer. Should not be NULL.
    2365                 :  *
    2366                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2367                 :  *
    2368                 :  * @param pLayerResult the layer where the features resulting from the
    2369                 :  * operation are inserted. Should not be NULL. See above the note
    2370                 :  * about the schema.
    2371                 :  *
    2372                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2373                 :  *
    2374                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2375                 :  * reporting progress or NULL.
    2376                 :  *
    2377                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2378                 :  *
    2379                 :  * @return an error code if there was an error or the execution was
    2380                 :  * interrupted, OGRERR_NONE otherwise.
    2381                 :  *
    2382                 :  * @since OGR 1.10
    2383                 :  */
    2384                 : 
    2385               3 : OGRErr OGR_L_SymDifference( OGRLayerH pLayerInput, 
    2386                 :                             OGRLayerH pLayerMethod, 
    2387                 :                             OGRLayerH pLayerResult, 
    2388                 :                             char** papszOptions, 
    2389                 :                             GDALProgressFunc pfnProgress, 
    2390                 :                             void * pProgressArg )
    2391                 : 
    2392                 : {
    2393               3 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
    2394               3 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
    2395               3 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_SymDifference", OGRERR_INVALID_HANDLE );
    2396                 : 
    2397               3 :     return ((OGRLayer *)pLayerInput)->SymDifference( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    2398                 : }
    2399                 : 
    2400                 : /************************************************************************/
    2401                 : /*                            Identity()                                */
    2402                 : /************************************************************************/
    2403                 : 
    2404                 : /**
    2405                 :  * \brief Identify the features of this layer with the ones from the
    2406                 :  * identity layer.
    2407                 :  *
    2408                 :  * The result layer contains features whose geometries represent areas
    2409                 :  * that are in the input layer. The features in the result layer have
    2410                 :  * attributes from both input and method layers. The schema of the
    2411                 :  * result layer can be set by the user or, if it is empty, is
    2412                 :  * initialized to contain all fields in input and method layers.
    2413                 :  *
    2414                 :  * \note If the schema of the result is set by user and contains
    2415                 :  * fields that have the same name as a field in input and in method
    2416                 :  * layer, then the attribute in the result feature will get the value
    2417                 :  * from the feature of the method layer (even if it is undefined).
    2418                 :  *
    2419                 :  * \note For best performance use the minimum amount of features in
    2420                 :  * the method layer and copy it into a memory layer.
    2421                 :  *
    2422                 :  * \note This method relies on GEOS support. Do not use unless the
    2423                 :  * GEOS support is compiled in.
    2424                 :  *
    2425                 :  * The recognized list of options is :
    2426                 :  * <ul>
    2427                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    2428                 :  *     feature could not be inserted.
    2429                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    2430                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    2431                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    2432                 :  *     will be created from the fields of the input layer.
    2433                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    2434                 :  *     will be created from the fields of the method layer.
    2435                 :  * </ul>
    2436                 :  *
    2437                 :  * This method is the same as the C function OGR_L_Identity().
    2438                 :  * 
    2439                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2440                 :  *
    2441                 :  * @param pLayerResult the layer where the features resulting from the
    2442                 :  * operation are inserted. Should not be NULL. See above the note
    2443                 :  * about the schema.
    2444                 :  *
    2445                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2446                 :  *
    2447                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2448                 :  * reporting progress or NULL.
    2449                 :  *
    2450                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2451                 :  *
    2452                 :  * @return an error code if there was an error or the execution was
    2453                 :  * interrupted, OGRERR_NONE otherwise.
    2454                 :  *
    2455                 :  * @since OGR 1.10
    2456                 :  */
    2457                 : 
    2458               3 : OGRErr OGRLayer::Identity( OGRLayer *pLayerMethod, 
    2459                 :                            OGRLayer *pLayerResult, 
    2460                 :                            char** papszOptions, 
    2461                 :                            GDALProgressFunc pfnProgress, 
    2462                 :                            void * pProgressArg )
    2463                 : {
    2464               3 :     OGRErr ret = OGRERR_NONE;
    2465               3 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    2466               3 :     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
    2467               3 :     OGRFeatureDefn *poDefnResult = NULL;
    2468               3 :     OGRGeometry *pGeometryMethodFilter = NULL;
    2469               3 :     int *mapInput = NULL;
    2470               3 :     int *mapMethod = NULL;
    2471               3 :     double progress_max = GetFeatureCount(0);
    2472               3 :     double progress_counter = 0;
    2473               3 :     double progress_ticker = 0;
    2474               3 :     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
    2475               3 :     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
    2476                 : 
    2477                 :     // check for GEOS
    2478               3 :     if (!OGRGeometryFactory::haveGEOS()) {
    2479               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    2480                 :     }
    2481                 : 
    2482                 :     // get resources
    2483               3 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    2484               3 :     if (ret != OGRERR_NONE) goto done;
    2485               3 :     ret = create_field_map(poDefnInput, &mapInput);
    2486               3 :     if (ret != OGRERR_NONE) goto done;
    2487               3 :     ret = create_field_map(poDefnMethod, &mapMethod);
    2488               3 :     if (ret != OGRERR_NONE) goto done;
    2489               3 :     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 1, papszOptions);
    2490               3 :     if (ret != OGRERR_NONE) goto done;
    2491               3 :     poDefnResult = pLayerResult->GetLayerDefn();
    2492                 : 
    2493                 :     // split the features in input layer to the result layer
    2494               3 :     ResetReading();
    2495              15 :     while (OGRFeature *x = GetNextFeature()) {
    2496                 : 
    2497               6 :         if (pfnProgress) {
    2498               0 :             double p = progress_counter/progress_max;
    2499               0 :             if (p > progress_ticker) {
    2500               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2501               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2502               0 :                     ret = OGRERR_FAILURE;
    2503               0 :                     delete x;
    2504               0 :                     goto done;
    2505                 :                 }
    2506                 :             }
    2507               0 :             progress_counter += 1.0;
    2508                 :         }
    2509                 : 
    2510                 :         // set up the filter on method layer
    2511               6 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    2512               6 :         if (!x_geom) {
    2513               0 :             delete x; 
    2514               0 :             continue;
    2515                 :         }
    2516                 :         
    2517               6 :         OGRGeometry *x_geom_diff = x_geom->clone(); // this will be the geometry of the result feature
    2518               6 :         pLayerMethod->ResetReading();
    2519              22 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    2520               8 :             OGRGeometry *y_geom = y->GetGeometryRef();
    2521               8 :             if (!y_geom) {delete y; continue;}
    2522               8 :             OGRGeometry* poIntersection = x_geom->Intersection(y_geom);
    2523              32 :             if( poIntersection == NULL || poIntersection->IsEmpty() ||
    2524               8 :                 (x_geom->getDimension() == 2 &&
    2525               8 :                 y_geom->getDimension() == 2 &&
    2526               8 :                 poIntersection->getDimension() < 2) )
    2527                 :             {
    2528               2 :                 delete poIntersection;
    2529               2 :                 delete y;
    2530                 :             }
    2531                 :             else
    2532                 :             {
    2533               6 :                 OGRFeature *z = new OGRFeature(poDefnResult);
    2534               6 :                 z->SetFieldsFrom(x, mapInput);
    2535               6 :                 z->SetFieldsFrom(y, mapMethod);
    2536               6 :                 if( bPromoteToMulti )
    2537               2 :                     poIntersection = promote_to_multi(poIntersection);
    2538               6 :                 z->SetGeometryDirectly(poIntersection);
    2539               6 :                 OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
    2540               6 :                 if (x_geom_diff) delete x_geom_diff;
    2541               6 :                 x_geom_diff = x_geom_diff_new;
    2542               6 :                 delete y;
    2543               6 :                 ret = pLayerResult->CreateFeature(z);
    2544               6 :                 delete z;
    2545               6 :                 if (!bSkipFailures && ret != OGRERR_NONE) {delete x; delete x_geom_diff; goto done;}
    2546               6 :                 ret = OGRERR_NONE;
    2547                 :             }
    2548                 :         }
    2549                 : 
    2550              12 :         if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
    2551                 :         {
    2552               2 :             delete x_geom_diff;
    2553               2 :             delete x;
    2554                 :         }
    2555                 :         else
    2556                 :         {
    2557               4 :             OGRFeature *z = new OGRFeature(poDefnResult);
    2558               4 :             z->SetFieldsFrom(x, mapInput);
    2559               4 :             if( bPromoteToMulti )
    2560               2 :                 x_geom_diff = promote_to_multi(x_geom_diff);
    2561               4 :             z->SetGeometryDirectly(x_geom_diff);
    2562               4 :             delete x;
    2563               4 :             ret = pLayerResult->CreateFeature(z);
    2564               4 :             delete z;
    2565               4 :             if (!bSkipFailures && ret != OGRERR_NONE) goto done;
    2566               4 :             ret = OGRERR_NONE;
    2567                 :         }
    2568                 :     }
    2569               3 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    2570               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2571               0 :       ret = OGRERR_FAILURE;
    2572                 :       goto done;
    2573                 :     }
    2574                 : done:
    2575                 :     // release resources
    2576               3 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2577               3 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    2578               3 :     if (mapInput) VSIFree(mapInput);
    2579               3 :     if (mapMethod) VSIFree(mapMethod);
    2580               3 :     return ret;
    2581                 : }
    2582                 : 
    2583                 : /************************************************************************/
    2584                 : /*                         OGR_L_Identity()                             */
    2585                 : /************************************************************************/
    2586                 : 
    2587                 : /**
    2588                 :  * \brief Identify the features of this layer with the ones from the
    2589                 :  * identity layer.
    2590                 :  *
    2591                 :  * The result layer contains features whose geometries represent areas
    2592                 :  * that are in the input layer. The features in the result layer have
    2593                 :  * attributes from both input and method layers. The schema of the
    2594                 :  * result layer can be set by the user or, if it is empty, is
    2595                 :  * initialized to contain all fields in input and method layers.
    2596                 :  *
    2597                 :  * \note If the schema of the result is set by user and contains
    2598                 :  * fields that have the same name as a field in input and in method
    2599                 :  * layer, then the attribute in the result feature will get the value
    2600                 :  * from the feature of the method layer (even if it is undefined).
    2601                 :  *
    2602                 :  * \note For best performance use the minimum amount of features in
    2603                 :  * the method layer and copy it into a memory layer.
    2604                 :  *
    2605                 :  * \note This method relies on GEOS support. Do not use unless the
    2606                 :  * GEOS support is compiled in.
    2607                 :  *
    2608                 :  * The recognized list of options is :
    2609                 :  * <ul>
    2610                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    2611                 :  *     feature could not be inserted.
    2612                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    2613                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    2614                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    2615                 :  *     will be created from the fields of the input layer.
    2616                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    2617                 :  *     will be created from the fields of the method layer.
    2618                 :  * </ul>
    2619                 :  *
    2620                 :  * This function is the same as the C++ method OGRLayer::Identity().
    2621                 :  * 
    2622                 :  * @param pLayerInput the input layer. Should not be NULL.
    2623                 :  *
    2624                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2625                 :  *
    2626                 :  * @param pLayerResult the layer where the features resulting from the
    2627                 :  * operation are inserted. Should not be NULL. See above the note
    2628                 :  * about the schema.
    2629                 :  *
    2630                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2631                 :  *
    2632                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2633                 :  * reporting progress or NULL.
    2634                 :  *
    2635                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2636                 :  *
    2637                 :  * @return an error code if there was an error or the execution was
    2638                 :  * interrupted, OGRERR_NONE otherwise.
    2639                 :  *
    2640                 :  * @since OGR 1.10
    2641                 :  */
    2642                 : 
    2643               3 : OGRErr OGR_L_Identity( OGRLayerH pLayerInput, 
    2644                 :                        OGRLayerH pLayerMethod, 
    2645                 :                        OGRLayerH pLayerResult, 
    2646                 :                        char** papszOptions, 
    2647                 :                        GDALProgressFunc pfnProgress, 
    2648                 :                        void * pProgressArg )
    2649                 : 
    2650                 : {
    2651               3 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
    2652               3 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
    2653               3 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Identity", OGRERR_INVALID_HANDLE );
    2654                 : 
    2655               3 :     return ((OGRLayer *)pLayerInput)->Identity( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    2656                 : }
    2657                 : 
    2658                 : /************************************************************************/
    2659                 : /*                             Update()                                 */
    2660                 : /************************************************************************/
    2661                 : 
    2662                 : /**
    2663                 :  * \brief Update this layer with features from the update layer.
    2664                 :  *
    2665                 :  * The result layer contains features whose geometries represent areas
    2666                 :  * that are either in the input layer or in the method layer. The
    2667                 :  * features in the result layer have areas of the features of the
    2668                 :  * method layer or those ares of the features of the input layer that
    2669                 :  * are not covered by the method layer. The features of the result
    2670                 :  * layer get their attributes from the input layer. The schema of the
    2671                 :  * result layer can be set by the user or, if it is empty, is
    2672                 :  * initialized to contain all fields in the input layer.
    2673                 :  *
    2674                 :  * \note If the schema of the result is set by user and contains
    2675                 :  * fields that have the same name as a field in the method layer, then
    2676                 :  * the attribute in the result feature the originates from the method
    2677                 :  * layer will get the value from the feature of the method layer.
    2678                 :  *
    2679                 :  * \note For best performance use the minimum amount of features in
    2680                 :  * the method layer and copy it into a memory layer.
    2681                 :  *
    2682                 :  * \note This method relies on GEOS support. Do not use unless the
    2683                 :  * GEOS support is compiled in.
    2684                 :  *
    2685                 :  * The recognized list of options is :
    2686                 :  * <ul>
    2687                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    2688                 :  *     feature could not be inserted.
    2689                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    2690                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    2691                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    2692                 :  *     will be created from the fields of the input layer.
    2693                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    2694                 :  *     will be created from the fields of the method layer.
    2695                 :  * </ul>
    2696                 :  *
    2697                 :  * This method is the same as the C function OGR_L_Update().
    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               4 : OGRErr OGRLayer::Update( OGRLayer *pLayerMethod, 
    2719                 :                          OGRLayer *pLayerResult, 
    2720                 :                          char** papszOptions, 
    2721                 :                          GDALProgressFunc pfnProgress, 
    2722                 :                          void * pProgressArg )
    2723                 : {
    2724               4 :     OGRErr ret = OGRERR_NONE;
    2725               4 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    2726               4 :     OGRFeatureDefn *poDefnMethod = pLayerMethod->GetLayerDefn();
    2727               4 :     OGRFeatureDefn *poDefnResult = NULL;
    2728               4 :     OGRGeometry *pGeometryMethodFilter = NULL;
    2729               4 :     int *mapInput = NULL;
    2730               4 :     int *mapMethod = NULL;
    2731               4 :     double progress_max = GetFeatureCount(0) + pLayerMethod->GetFeatureCount(0);
    2732               4 :     double progress_counter = 0;
    2733               4 :     double progress_ticker = 0;
    2734               4 :     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
    2735               4 :     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
    2736                 : 
    2737                 :     // check for GEOS
    2738               4 :     if (!OGRGeometryFactory::haveGEOS()) {
    2739               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    2740                 :     }
    2741                 : 
    2742                 :     // get resources
    2743               4 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    2744               4 :     if (ret != OGRERR_NONE) goto done;
    2745               4 :     ret = create_field_map(poDefnInput, &mapInput);
    2746               4 :     if (ret != OGRERR_NONE) goto done;
    2747               4 :     ret = create_field_map(poDefnMethod, &mapMethod);
    2748               4 :     if (ret != OGRERR_NONE) goto done;
    2749               4 :     ret = set_result_schema(pLayerResult, poDefnInput, poDefnMethod, mapInput, mapMethod, 0, papszOptions);
    2750               4 :     if (ret != OGRERR_NONE) goto done;
    2751               4 :     poDefnResult = pLayerResult->GetLayerDefn();
    2752                 : 
    2753                 :     // add clipped features from the input layer
    2754               4 :     ResetReading();
    2755              20 :     while (OGRFeature *x = GetNextFeature()) {
    2756                 : 
    2757               8 :         if (pfnProgress) {
    2758               0 :             double p = progress_counter/progress_max;
    2759               0 :             if (p > progress_ticker) {
    2760               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2761               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2762               0 :                     ret = OGRERR_FAILURE;
    2763               0 :                     delete x;
    2764               0 :                     goto done;
    2765                 :                 }
    2766                 :             }
    2767               0 :             progress_counter += 1.0;
    2768                 :         }
    2769                 : 
    2770                 :         // set up the filter on method layer
    2771               8 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    2772               8 :         if (!x_geom) {
    2773               0 :             delete x; 
    2774               0 :             continue;
    2775                 :         }
    2776                 :         
    2777               8 :         OGRGeometry *x_geom_diff = x_geom->clone(); //this will be the geometry of a result feature
    2778               8 :         pLayerMethod->ResetReading();
    2779              32 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    2780              12 :             OGRGeometry *y_geom = y->GetGeometryRef();
    2781              12 :             if (!y_geom) {delete y; continue;}
    2782              12 :             OGRGeometry *x_geom_diff_new = x_geom_diff ? x_geom_diff->Difference(y_geom) : NULL;
    2783              12 :             if (x_geom_diff) delete x_geom_diff;
    2784              12 :             x_geom_diff = x_geom_diff_new;
    2785              12 :             delete y;
    2786                 :         }
    2787                 : 
    2788              16 :         if( x_geom_diff == NULL || x_geom_diff->IsEmpty() )
    2789                 :         {
    2790               4 :             delete x_geom_diff;
    2791               4 :             delete x;
    2792                 :         }
    2793                 :         else
    2794                 :         {
    2795               4 :             OGRFeature *z = new OGRFeature(poDefnResult);
    2796               4 :             z->SetFieldsFrom(x, mapInput);
    2797               4 :             if( bPromoteToMulti )
    2798               2 :                 x_geom_diff = promote_to_multi(x_geom_diff);
    2799               4 :             z->SetGeometryDirectly(x_geom_diff);
    2800               4 :             delete x;
    2801               4 :             ret = pLayerResult->CreateFeature(z);
    2802               4 :             delete z;
    2803               4 :             if (!bSkipFailures && ret != OGRERR_NONE) goto done;
    2804               4 :             ret = OGRERR_NONE;
    2805                 :         }
    2806                 :     }
    2807                 : 
    2808                 :     // restore the original filter and add features from the update layer
    2809               4 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2810               4 :     pLayerMethod->ResetReading();
    2811              16 :     while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    2812                 : 
    2813               6 :         if (pfnProgress) {
    2814               0 :             double p = progress_counter/progress_max;
    2815               0 :             if (p > progress_ticker) {
    2816               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    2817               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2818               0 :                     ret = OGRERR_FAILURE;
    2819               0 :                     delete y;
    2820               0 :                     goto done;
    2821                 :                 }
    2822                 :             }
    2823               0 :             progress_counter += 1.0;
    2824                 :         }
    2825                 : 
    2826               6 :         OGRGeometry *y_geom = y->GetGeometryRef();
    2827               6 :         if (!y_geom) {delete y; continue;}
    2828               6 :         OGRFeature *z = new OGRFeature(poDefnResult);
    2829               6 :         if (mapMethod) z->SetFieldsFrom(y, mapMethod);
    2830               6 :         z->SetGeometry(y_geom);
    2831               6 :         delete y;
    2832               6 :         ret = pLayerResult->CreateFeature(z);
    2833               6 :         delete z;
    2834               6 :         if (!bSkipFailures && ret != OGRERR_NONE) goto done;
    2835               6 :         ret = OGRERR_NONE;
    2836                 :     }
    2837               4 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    2838               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    2839               0 :       ret = OGRERR_FAILURE;
    2840                 :       goto done;
    2841                 :     }
    2842                 : done:
    2843                 :     // release resources
    2844               4 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    2845               4 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    2846               4 :     if (mapInput) VSIFree(mapInput);
    2847               4 :     if (mapMethod) VSIFree(mapMethod);
    2848               4 :     return ret;
    2849                 : }
    2850                 : 
    2851                 : /************************************************************************/
    2852                 : /*                          OGR_L_Update()                              */
    2853                 : /************************************************************************/
    2854                 : 
    2855                 : /**
    2856                 :  * \brief Update this layer with features from the update layer.
    2857                 :  *
    2858                 :  * The result layer contains features whose geometries represent areas
    2859                 :  * that are either in the input layer or in the method layer. The
    2860                 :  * features in the result layer have areas of the features of the
    2861                 :  * method layer or those ares of the features of the input layer that
    2862                 :  * are not covered by the method layer. The features of the result
    2863                 :  * layer get their attributes from the input layer. The schema of the
    2864                 :  * result layer can be set by the user or, if it is empty, is
    2865                 :  * initialized to contain all fields in the input layer.
    2866                 :  *
    2867                 :  * \note If the schema of the result is set by user and contains
    2868                 :  * fields that have the same name as a field in the method layer, then
    2869                 :  * the attribute in the result feature the originates from the method
    2870                 :  * layer will get the value from the feature of the method layer.
    2871                 :  *
    2872                 :  * \note For best performance use the minimum amount of features in
    2873                 :  * the method layer and copy it into a memory layer.
    2874                 :  *
    2875                 :  * \note This method relies on GEOS support. Do not use unless the
    2876                 :  * GEOS support is compiled in.
    2877                 :  *
    2878                 :  * The recognized list of options is :
    2879                 :  * <ul>
    2880                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    2881                 :  *     feature could not be inserted.
    2882                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    2883                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    2884                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    2885                 :  *     will be created from the fields of the input layer.
    2886                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    2887                 :  *     will be created from the fields of the method layer.
    2888                 :  * </ul>
    2889                 :  *
    2890                 :  * This function is the same as the C++ method OGRLayer::Update().
    2891                 :  * 
    2892                 :  * @param pLayerInput the input layer. Should not be NULL.
    2893                 :  *
    2894                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2895                 :  *
    2896                 :  * @param pLayerResult the layer where the features resulting from the
    2897                 :  * operation are inserted. Should not be NULL. See above the note
    2898                 :  * about the schema.
    2899                 :  *
    2900                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2901                 :  *
    2902                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2903                 :  * reporting progress or NULL.
    2904                 :  *
    2905                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2906                 :  *
    2907                 :  * @return an error code if there was an error or the execution was
    2908                 :  * interrupted, OGRERR_NONE otherwise.
    2909                 :  *
    2910                 :  * @since OGR 1.10
    2911                 :  */
    2912                 : 
    2913               4 : OGRErr OGR_L_Update( OGRLayerH pLayerInput, 
    2914                 :                      OGRLayerH pLayerMethod, 
    2915                 :                      OGRLayerH pLayerResult, 
    2916                 :                      char** papszOptions, 
    2917                 :                      GDALProgressFunc pfnProgress, 
    2918                 :                      void * pProgressArg )
    2919                 : 
    2920                 : {
    2921               4 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Update", OGRERR_INVALID_HANDLE );
    2922               4 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Update", OGRERR_INVALID_HANDLE );
    2923               4 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Update", OGRERR_INVALID_HANDLE );
    2924                 : 
    2925               4 :     return ((OGRLayer *)pLayerInput)->Update( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    2926                 : }
    2927                 : 
    2928                 : /************************************************************************/
    2929                 : /*                              Clip()                                  */
    2930                 : /************************************************************************/
    2931                 : 
    2932                 : /**
    2933                 :  * \brief Clip off areas that are not covered by the method layer.
    2934                 :  *
    2935                 :  * The result layer contains features whose geometries represent areas
    2936                 :  * that are in the input layer and in the method layer. The features
    2937                 :  * in the result layer have the (possibly clipped) areas of features
    2938                 :  * in the input layer and the attributes from the same features. The
    2939                 :  * schema of the result layer can be set by the user or, if it is
    2940                 :  * empty, is initialized to contain all fields in the input layer.
    2941                 :  *
    2942                 :  * \note For best performance use the minimum amount of features in
    2943                 :  * the method layer and copy it into a memory layer.
    2944                 :  *
    2945                 :  * \note This method relies on GEOS support. Do not use unless the
    2946                 :  * GEOS support is compiled in.
    2947                 :  *
    2948                 :  * The recognized list of options is :
    2949                 :  * <ul>
    2950                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    2951                 :  *     feature could not be inserted.
    2952                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    2953                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    2954                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    2955                 :  *     will be created from the fields of the input layer.
    2956                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    2957                 :  *     will be created from the fields of the method layer.
    2958                 :  * </ul>
    2959                 :  *
    2960                 :  * This method is the same as the C function OGR_L_Clip().
    2961                 :  * 
    2962                 :  * @param pLayerMethod the method layer. Should not be NULL.
    2963                 :  *
    2964                 :  * @param pLayerResult the layer where the features resulting from the
    2965                 :  * operation are inserted. Should not be NULL. See above the note
    2966                 :  * about the schema.
    2967                 :  *
    2968                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    2969                 :  *
    2970                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    2971                 :  * reporting progress or NULL.
    2972                 :  *
    2973                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    2974                 :  *
    2975                 :  * @return an error code if there was an error or the execution was
    2976                 :  * interrupted, OGRERR_NONE otherwise.
    2977                 :  *
    2978                 :  * @since OGR 1.10
    2979                 :  */
    2980                 : 
    2981               2 : OGRErr OGRLayer::Clip( OGRLayer *pLayerMethod, 
    2982                 :                        OGRLayer *pLayerResult, 
    2983                 :                        char** papszOptions, 
    2984                 :                        GDALProgressFunc pfnProgress, 
    2985                 :                        void * pProgressArg )
    2986                 : {
    2987               2 :     OGRErr ret = OGRERR_NONE;
    2988               2 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    2989               2 :     OGRFeatureDefn *poDefnResult = NULL;
    2990               2 :     OGRGeometry *pGeometryMethodFilter = NULL;
    2991               2 :     int *mapInput = NULL;
    2992               2 :     double progress_max = GetFeatureCount(0);
    2993               2 :     double progress_counter = 0;
    2994               2 :     double progress_ticker = 0;
    2995               2 :     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
    2996               2 :     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
    2997                 : 
    2998                 :     // check for GEOS
    2999               2 :     if (!OGRGeometryFactory::haveGEOS()) {
    3000               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    3001                 :     }
    3002                 : 
    3003               2 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    3004               2 :     if (ret != OGRERR_NONE) goto done;
    3005               2 :     ret = create_field_map(poDefnInput, &mapInput);
    3006               2 :     if (ret != OGRERR_NONE) goto done;
    3007               2 :     ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0, papszOptions);
    3008               2 :     if (ret != OGRERR_NONE) goto done;
    3009                 :     
    3010               2 :     poDefnResult = pLayerResult->GetLayerDefn();
    3011               2 :     ResetReading();
    3012              10 :     while (OGRFeature *x = GetNextFeature()) {
    3013                 : 
    3014               4 :         if (pfnProgress) {
    3015               0 :             double p = progress_counter/progress_max;
    3016               0 :             if (p > progress_ticker) {
    3017               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    3018               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    3019               0 :                     ret = OGRERR_FAILURE;
    3020               0 :                     delete x;
    3021               0 :                     goto done;
    3022                 :                 }
    3023                 :             }
    3024               0 :             progress_counter += 1.0;
    3025                 :         }
    3026                 : 
    3027                 :         // set up the filter on method layer
    3028               4 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    3029               4 :         if (!x_geom) {
    3030               0 :             delete x; 
    3031               0 :             continue;
    3032                 :         }
    3033                 :         
    3034               4 :         OGRGeometry *geom = NULL; // this will be the geometry of the result feature 
    3035               4 :         pLayerMethod->ResetReading();
    3036                 :         // incrementally add area from y to geom
    3037              12 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    3038               4 :             OGRGeometry *y_geom = y->GetGeometryRef();
    3039               4 :             if (!y_geom) {delete y; continue;}
    3040               4 :             if (!geom) {
    3041               4 :                 geom = y_geom->clone();
    3042                 :             } else {
    3043               0 :                 OGRGeometry *geom_new = geom->Union(y_geom);
    3044               0 :                 delete geom;
    3045               0 :                 geom = geom_new;
    3046                 :             }
    3047               4 :             delete y;
    3048                 :         }
    3049                 : 
    3050                 :         // possibly add a new feature with area x intersection sum of y
    3051               4 :         OGRFeature *z = NULL;
    3052               4 :         if (geom) {
    3053               4 :             OGRGeometry* poIntersection = x_geom->Intersection(geom);
    3054               4 :             if( poIntersection != NULL && !poIntersection->IsEmpty() )
    3055                 :             {
    3056               4 :                 z = new OGRFeature(poDefnResult);
    3057               4 :                 z->SetFieldsFrom(x, mapInput);
    3058               4 :                 if( bPromoteToMulti )
    3059               2 :                     poIntersection = promote_to_multi(poIntersection);
    3060               4 :                 z->SetGeometryDirectly(poIntersection);
    3061                 :             }
    3062                 :             else
    3063               0 :                 delete poIntersection;
    3064               4 :             delete geom;
    3065                 :         }
    3066               4 :         delete x;
    3067               4 :         if (z) {
    3068               4 :             if (z->GetGeometryRef() != NULL && !z->GetGeometryRef()->IsEmpty())
    3069               4 :                 ret = pLayerResult->CreateFeature(z);
    3070               4 :             delete z;
    3071               4 :             if (!bSkipFailures && ret != OGRERR_NONE) goto done;
    3072               4 :             ret = OGRERR_NONE;
    3073                 :         }
    3074                 :     }
    3075               2 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    3076               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    3077               0 :       ret = OGRERR_FAILURE;
    3078                 :       goto done;
    3079                 :     }
    3080                 : done:
    3081                 :     // release resources
    3082               2 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    3083               2 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    3084               2 :     if (mapInput) VSIFree(mapInput);
    3085               2 :     return ret;
    3086                 : }
    3087                 : 
    3088                 : /************************************************************************/
    3089                 : /*                           OGR_L_Clip()                               */
    3090                 : /************************************************************************/
    3091                 : 
    3092                 : /**
    3093                 :  * \brief Clip off areas that are not covered by the method layer.
    3094                 :  *
    3095                 :  * The result layer contains features whose geometries represent areas
    3096                 :  * that are in the input layer and in the method layer. The features
    3097                 :  * in the result layer have the (possibly clipped) areas of features
    3098                 :  * in the input layer and the attributes from the same features. The
    3099                 :  * schema of the result layer can be set by the user or, if it is
    3100                 :  * empty, is initialized to contain all fields in the input layer.
    3101                 :  *
    3102                 :  * \note For best performance use the minimum amount of features in
    3103                 :  * the method layer and copy it into a memory layer.
    3104                 :  *
    3105                 :  * \note This method relies on GEOS support. Do not use unless the
    3106                 :  * GEOS support is compiled in.
    3107                 :  *
    3108                 :  * The recognized list of options is :
    3109                 :  * <ul>
    3110                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    3111                 :  *     feature could not be inserted.
    3112                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    3113                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    3114                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    3115                 :  *     will be created from the fields of the input layer.
    3116                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    3117                 :  *     will be created from the fields of the method layer.
    3118                 :  * </ul>
    3119                 :  *
    3120                 :  * This function is the same as the C++ method OGRLayer::Clip().
    3121                 :  * 
    3122                 :  * @param pLayerInput the input layer. Should not be NULL.
    3123                 :  *
    3124                 :  * @param pLayerMethod the method layer. Should not be NULL.
    3125                 :  *
    3126                 :  * @param pLayerResult the layer where the features resulting from the
    3127                 :  * operation are inserted. Should not be NULL. See above the note
    3128                 :  * about the schema.
    3129                 :  *
    3130                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    3131                 :  *
    3132                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    3133                 :  * reporting progress or NULL.
    3134                 :  *
    3135                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    3136                 :  *
    3137                 :  * @return an error code if there was an error or the execution was
    3138                 :  * interrupted, OGRERR_NONE otherwise.
    3139                 :  *
    3140                 :  * @since OGR 1.10
    3141                 :  */
    3142                 : 
    3143               2 : OGRErr OGR_L_Clip( OGRLayerH pLayerInput, 
    3144                 :                    OGRLayerH pLayerMethod, 
    3145                 :                    OGRLayerH pLayerResult, 
    3146                 :                    char** papszOptions, 
    3147                 :                    GDALProgressFunc pfnProgress, 
    3148                 :                    void * pProgressArg )
    3149                 : 
    3150                 : {
    3151               2 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
    3152               2 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
    3153               2 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Clip", OGRERR_INVALID_HANDLE );
    3154                 : 
    3155               2 :     return ((OGRLayer *)pLayerInput)->Clip( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    3156                 : }
    3157                 : 
    3158                 : /************************************************************************/
    3159                 : /*                              Erase()                                 */
    3160                 : /************************************************************************/
    3161                 : 
    3162                 : /**
    3163                 :  * \brief Remove areas that are covered by the method layer.
    3164                 :  *
    3165                 :  * The result layer contains features whose geometries represent areas
    3166                 :  * that are in the input layer but not in the method layer. The
    3167                 :  * features in the result layer have attributes from the input
    3168                 :  * layer. The schema of the result layer can be set by the user or, if
    3169                 :  * it is empty, is initialized to contain all fields in the input
    3170                 :  * layer.
    3171                 :  *
    3172                 :  * \note For best performance use the minimum amount of features in
    3173                 :  * the method layer and copy it into a memory layer.
    3174                 :  *
    3175                 :  * \note This method relies on GEOS support. Do not use unless the
    3176                 :  * GEOS support is compiled in.
    3177                 :  *
    3178                 :  * The recognized list of options is :
    3179                 :  * <ul>
    3180                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    3181                 :  *     feature could not be inserted.
    3182                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    3183                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    3184                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    3185                 :  *     will be created from the fields of the input layer.
    3186                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    3187                 :  *     will be created from the fields of the method layer.
    3188                 :  * </ul>
    3189                 :  *
    3190                 :  * This method is the same as the C function OGR_L_Erase().
    3191                 :  *
    3192                 :  * @param pLayerMethod the method layer. Should not be NULL.
    3193                 :  *
    3194                 :  * @param pLayerResult the layer where the features resulting from the
    3195                 :  * operation are inserted. Should not be NULL. See above the note
    3196                 :  * about the schema.
    3197                 :  *
    3198                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    3199                 :  *
    3200                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    3201                 :  * reporting progress or NULL.
    3202                 :  *
    3203                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    3204                 :  *
    3205                 :  * @return an error code if there was an error or the execution was
    3206                 :  * interrupted, OGRERR_NONE otherwise.
    3207                 :  *
    3208                 :  * @since OGR 1.10
    3209                 :  */
    3210                 : 
    3211               3 : OGRErr OGRLayer::Erase( OGRLayer *pLayerMethod, 
    3212                 :                         OGRLayer *pLayerResult, 
    3213                 :                         char** papszOptions, 
    3214                 :                         GDALProgressFunc pfnProgress, 
    3215                 :                         void * pProgressArg )
    3216                 : {
    3217               3 :     OGRErr ret = OGRERR_NONE;
    3218               3 :     OGRFeatureDefn *poDefnInput = GetLayerDefn();
    3219               3 :     OGRFeatureDefn *poDefnResult = NULL;
    3220               3 :     OGRGeometry *pGeometryMethodFilter = NULL;
    3221               3 :     int *mapInput = NULL;
    3222               3 :     double progress_max = GetFeatureCount(0);
    3223               3 :     double progress_counter = 0;
    3224               3 :     double progress_ticker = 0;
    3225               3 :     int bSkipFailures = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "SKIP_FAILURES", "NO"));
    3226               3 :     int bPromoteToMulti = CSLTestBoolean(CSLFetchNameValueDef(papszOptions, "PROMOTE_TO_MULTI", "NO"));
    3227                 : 
    3228                 :     // check for GEOS
    3229               3 :     if (!OGRGeometryFactory::haveGEOS()) {
    3230               0 :         return OGRERR_UNSUPPORTED_OPERATION;
    3231                 :     }
    3232                 : 
    3233                 :     // get resources
    3234               3 :     ret = clone_spatial_filter(pLayerMethod, &pGeometryMethodFilter);
    3235               3 :     if (ret != OGRERR_NONE) goto done;
    3236               3 :     ret = create_field_map(poDefnInput, &mapInput);
    3237               3 :     if (ret != OGRERR_NONE) goto done;
    3238               3 :     ret = set_result_schema(pLayerResult, poDefnInput, NULL, mapInput, NULL, 0, papszOptions);
    3239               3 :     if (ret != OGRERR_NONE) goto done;
    3240               3 :     poDefnResult = pLayerResult->GetLayerDefn();
    3241                 : 
    3242               3 :     ResetReading();
    3243              15 :     while (OGRFeature *x = GetNextFeature()) {
    3244                 : 
    3245               6 :         if (pfnProgress) {
    3246               0 :             double p = progress_counter/progress_max;
    3247               0 :             if (p > progress_ticker) {
    3248               0 :                 if (!pfnProgress(p, "", pProgressArg)) {
    3249               0 :                     CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    3250               0 :                     ret = OGRERR_FAILURE;
    3251               0 :                     delete x;
    3252               0 :                     goto done;
    3253                 :                 }
    3254                 :             }
    3255               0 :             progress_counter += 1.0;
    3256                 :         }
    3257                 : 
    3258                 :         // set up the filter on the method layer
    3259               6 :         OGRGeometry *x_geom = set_filter_from(pLayerMethod, pGeometryMethodFilter, x);
    3260               6 :         if (!x_geom) {
    3261               0 :             delete x; 
    3262               0 :             continue;
    3263                 :         }
    3264                 : 
    3265               6 :         OGRGeometry *geom = NULL; // this will be the geometry of the result feature
    3266               6 :         pLayerMethod->ResetReading();
    3267                 :         // incrementally add area from y to geom
    3268              22 :         while (OGRFeature *y = pLayerMethod->GetNextFeature()) {
    3269               8 :             OGRGeometry *y_geom = y->GetGeometryRef();
    3270               8 :             if (!y_geom) {delete y; continue;}
    3271               8 :             if (!geom) {
    3272               6 :                 geom = y_geom->clone();
    3273                 :             } else {
    3274               2 :                 OGRGeometry *geom_new = geom->Union(y_geom);
    3275               2 :                 delete geom;
    3276               2 :                 geom = geom_new;
    3277                 :             }
    3278               8 :             delete y;
    3279                 :         }
    3280                 : 
    3281                 :         // possibly add a new feature with area x minus sum of y
    3282               6 :         OGRFeature *z = NULL;
    3283               6 :         if (geom) {
    3284               6 :             OGRGeometry* x_geom_diff = x_geom->Difference(geom);
    3285               6 :             if( x_geom_diff != NULL && !x_geom_diff->IsEmpty() )
    3286                 :             {
    3287               4 :                 z = new OGRFeature(poDefnResult);
    3288               4 :                 z->SetFieldsFrom(x, mapInput);
    3289               4 :                 if( bPromoteToMulti )
    3290               2 :                     x_geom_diff = promote_to_multi(x_geom_diff);
    3291               4 :                 z->SetGeometryDirectly(x_geom_diff);
    3292                 :             }
    3293                 :             else
    3294               2 :                 delete x_geom_diff;
    3295               6 :             delete geom;
    3296                 :         }
    3297               6 :         delete x;
    3298               6 :         if (z) {
    3299               4 :             if (z->GetGeometryRef() != NULL && !z->GetGeometryRef()->IsEmpty())
    3300               4 :                 ret = pLayerResult->CreateFeature(z);
    3301               4 :             delete z;
    3302               4 :             if (!bSkipFailures && ret != OGRERR_NONE) goto done;
    3303               4 :             ret = OGRERR_NONE;
    3304                 :         }
    3305                 :     }
    3306               3 :     if (pfnProgress && !pfnProgress(1.0, "", pProgressArg)) {
    3307               0 :       CPLError(CE_Failure, CPLE_UserInterrupt, "User terminated");
    3308               0 :       ret = OGRERR_FAILURE;
    3309                 :       goto done;
    3310                 :     }
    3311                 : done:
    3312                 :     // release resources
    3313               3 :     pLayerMethod->SetSpatialFilter(pGeometryMethodFilter);
    3314               3 :     if (pGeometryMethodFilter) delete pGeometryMethodFilter;
    3315               3 :     if (mapInput) VSIFree(mapInput);
    3316               3 :     return ret;
    3317                 : }
    3318                 : 
    3319                 : /************************************************************************/
    3320                 : /*                           OGR_L_Erase()                              */
    3321                 : /************************************************************************/
    3322                 : 
    3323                 : /**
    3324                 :  * \brief Remove areas that are covered by the method layer.
    3325                 :  *
    3326                 :  * The result layer contains features whose geometries represent areas
    3327                 :  * that are in the input layer but not in the method layer. The
    3328                 :  * features in the result layer have attributes from the input
    3329                 :  * layer. The schema of the result layer can be set by the user or, if
    3330                 :  * it is empty, is initialized to contain all fields in the input
    3331                 :  * layer.
    3332                 :  *
    3333                 :  * \note For best performance use the minimum amount of features in
    3334                 :  * the method layer and copy it into a memory layer.
    3335                 :  *
    3336                 :  * \note This method relies on GEOS support. Do not use unless the
    3337                 :  * GEOS support is compiled in.
    3338                 :  *
    3339                 :  * The recognized list of options is :
    3340                 :  * <ul>
    3341                 :  * <li>SKIP_FAILURES=YES/NO. Set it to YES to go on, even when a
    3342                 :  *     feature could not be inserted.
    3343                 :  * <li>PROMOTE_TO_MULTI=YES/NO. Set it to YES to convert Polygons
    3344                 :  *     into MultiPolygons, or LineStrings to MultiLineStrings.
    3345                 :  * <li>INPUT_PREFIX=string. Set a prefix for the field names that
    3346                 :  *     will be created from the fields of the input layer.
    3347                 :  * <li>METHOD_PREFIX=string. Set a prefix for the field names that
    3348                 :  *     will be created from the fields of the method layer.
    3349                 :  * </ul>
    3350                 :  *
    3351                 :  * This function is the same as the C++ method OGRLayer::Erase().
    3352                 :  * 
    3353                 :  * @param pLayerInput the input layer. Should not be NULL.
    3354                 :  *
    3355                 :  * @param pLayerMethod the method layer. Should not be NULL.
    3356                 :  *
    3357                 :  * @param pLayerResult the layer where the features resulting from the
    3358                 :  * operation are inserted. Should not be NULL. See above the note
    3359                 :  * about the schema.
    3360                 :  *
    3361                 :  * @param papszOptions NULL terminated list of options (may be NULL).
    3362                 :  *
    3363                 :  * @param pfnProgress a GDALProgressFunc() compatible callback function for
    3364                 :  * reporting progress or NULL.
    3365                 :  *
    3366                 :  * @param pProgressArg argument to be passed to pfnProgress. May be NULL.
    3367                 :  *
    3368                 :  * @return an error code if there was an error or the execution was
    3369                 :  * interrupted, OGRERR_NONE otherwise.
    3370                 :  *
    3371                 :  * @since OGR 1.10
    3372                 :  */
    3373                 : 
    3374               3 : OGRErr OGR_L_Erase( OGRLayerH pLayerInput, 
    3375                 :                     OGRLayerH pLayerMethod, 
    3376                 :                     OGRLayerH pLayerResult, 
    3377                 :                     char** papszOptions, 
    3378                 :                     GDALProgressFunc pfnProgress, 
    3379                 :                     void * pProgressArg )
    3380                 : 
    3381                 : {
    3382               3 :     VALIDATE_POINTER1( pLayerInput, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
    3383               3 :     VALIDATE_POINTER1( pLayerMethod, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
    3384               3 :     VALIDATE_POINTER1( pLayerResult, "OGR_L_Erase", OGRERR_INVALID_HANDLE );
    3385                 : 
    3386               3 :     return ((OGRLayer *)pLayerInput)->Erase( (OGRLayer *)pLayerMethod, (OGRLayer *)pLayerResult, papszOptions, pfnProgress, pProgressArg );
    3387                 : }

Generated by: LCOV version 1.7