LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vrt - ogrvrtlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 670 492 73.4 %
Date: 2011-12-18 Functions: 27 23 85.2 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrvrtlayer.cpp 23575 2011-12-14 20:24:08Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRVRTLayer class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 2003, Frank Warmerdam <warmerdam@pobox.com>
      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 "cpl_conv.h"
      31                 : #include "ogr_vrt.h"
      32                 : #include "cpl_string.h"
      33                 : #include <string>
      34                 : 
      35                 : CPL_CVSID("$Id: ogrvrtlayer.cpp 23575 2011-12-14 20:24:08Z rouault $");
      36                 : 
      37                 : typedef struct 
      38                 : {
      39                 :     OGRwkbGeometryType  eType;
      40                 :     const char          *pszName;
      41                 : } OGRGeomTypeName;
      42                 : 
      43                 : static const OGRGeomTypeName asGeomTypeNames[] = { /* 25D versions are implicit */
      44                 :     { wkbUnknown, "wkbUnknown" },
      45                 :     { wkbPoint, "wkbPoint" },
      46                 :     { wkbLineString, "wkbLineString" },
      47                 :     { wkbPolygon, "wkbPolygon" },
      48                 :     { wkbMultiPoint, "wkbMultiPoint" },
      49                 :     { wkbMultiLineString, "wkbMultiLineString" },
      50                 :     { wkbMultiPolygon, "wkbMultiPolygon" },
      51                 :     { wkbGeometryCollection, "wkbGeometryCollection" },
      52                 :     { wkbNone, "wkbNone" },
      53                 :     { wkbLinearRing, "wkbLinearRing" },
      54                 :     { wkbNone, NULL }
      55                 : };
      56                 : 
      57                 : /************************************************************************/
      58                 : /*                            OGRVRTLayer()                             */
      59                 : /************************************************************************/
      60                 : 
      61             216 : OGRVRTLayer::OGRVRTLayer(OGRVRTDataSource* poDSIn)
      62                 : 
      63                 : {
      64             216 :     poDS = poDSIn;
      65                 : 
      66             216 :     bHasFullInitialized = FALSE;
      67             216 :     eGeomType = wkbUnknown;
      68             216 :     psLTree = NULL;
      69                 : 
      70             216 :     poFeatureDefn = NULL;
      71             216 :     poSrcLayer = NULL;
      72             216 :     poSRS = NULL;
      73             216 :     poSrcDS = NULL;
      74                 : 
      75             216 :     bUseSpatialSubquery = FALSE;
      76             216 :     iFIDField = -1;
      77             216 :     iStyleField = -1;
      78                 : 
      79             216 :     eGeometryStyle = VGS_Direct;
      80             216 :     iGeomField = iGeomXField = iGeomYField = iGeomZField = -1;
      81                 : 
      82             216 :     pszAttrFilter = NULL;
      83                 : 
      84             216 :     bNeedReset = TRUE;
      85             216 :     bSrcLayerFromSQL = FALSE;
      86                 : 
      87             216 :     bSrcClip = FALSE;
      88             216 :     poSrcRegion = NULL;
      89             216 :     bUpdate = FALSE;
      90             216 :     bAttrFilterPassThrough = FALSE;
      91             216 : }
      92                 : 
      93                 : /************************************************************************/
      94                 : /*                            ~OGRVRTLayer()                            */
      95                 : /************************************************************************/
      96                 : 
      97             216 : OGRVRTLayer::~OGRVRTLayer()
      98                 : 
      99                 : {
     100             216 :     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
     101                 :     {
     102                 :         CPLDebug( "VRT", "%d features read on layer '%s'.",
     103                 :                   (int) m_nFeaturesRead, 
     104              45 :                   poFeatureDefn->GetName() );
     105                 :     }
     106                 : 
     107             216 :     if( poSRS != NULL )
     108              97 :         poSRS->Release();
     109                 : 
     110             216 :     if( poSrcDS != NULL )
     111                 :     {
     112              90 :         if( bSrcLayerFromSQL && poSrcLayer )
     113               2 :             poSrcDS->ReleaseResultSet( poSrcLayer );
     114                 : 
     115              90 :         if( bSrcDSShared )
     116              18 :             OGRSFDriverRegistrar::GetRegistrar()->ReleaseDataSource( poSrcDS );
     117                 :         else
     118              72 :             delete poSrcDS;
     119                 :     }
     120                 : 
     121             216 :     if( poFeatureDefn )
     122             105 :         poFeatureDefn->Release();
     123                 : 
     124             216 :     CPLFree( pszAttrFilter );
     125                 : 
     126             216 :     if( poSrcRegion != NULL )
     127               3 :         delete poSrcRegion;
     128             216 : }
     129                 : 
     130                 : /************************************************************************/
     131                 : /*                         FastInitialize()                             */
     132                 : /************************************************************************/
     133                 : 
     134             216 : int OGRVRTLayer::FastInitialize( CPLXMLNode *psLTree, const char *pszVRTDirectory,
     135                 :                              int bUpdate)
     136                 : 
     137                 : {
     138             216 :     this->psLTree = psLTree;
     139             216 :     this->bUpdate = bUpdate;
     140             216 :     osVRTDirectory = pszVRTDirectory;
     141                 : 
     142             216 :     if( !EQUAL(psLTree->pszValue,"OGRVRTLayer") )
     143               0 :         return FALSE;
     144                 : 
     145                 : /* -------------------------------------------------------------------- */
     146                 : /*      Get layer name.                                                 */
     147                 : /* -------------------------------------------------------------------- */
     148             216 :     const char *pszLayerName = CPLGetXMLValue( psLTree, "name", NULL );
     149                 : 
     150             216 :     if( pszLayerName == NULL )
     151                 :     {
     152                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     153               0 :                   "Missing name attribute on OGRVRTLayer" );
     154               0 :         return FALSE;
     155                 :     }
     156                 : 
     157             216 :     osName = pszLayerName;
     158                 : 
     159                 : /* -------------------------------------------------------------------- */
     160                 : /*      Do we have a fixed geometry type?  If so use it                 */
     161                 : /* -------------------------------------------------------------------- */
     162             216 :      const char *pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
     163             216 :      if( pszGType != NULL )
     164                 :      {
     165                 :          int iType;
     166                 : 
     167             342 :          for( iType = 0; asGeomTypeNames[iType].pszName != NULL; iType++ )
     168                 :          {
     169             342 :              if( EQUALN(pszGType, asGeomTypeNames[iType].pszName,
     170                 :                         strlen(asGeomTypeNames[iType].pszName)) )
     171                 :              {
     172             168 :                  eGeomType = asGeomTypeNames[iType].eType;
     173                 : 
     174             168 :                  if( strstr(pszGType,"25D") != NULL )
     175               0 :                      eGeomType = (OGRwkbGeometryType) (eGeomType | wkb25DBit);
     176             168 :                  break;
     177                 :              }
     178                 :          }
     179                 : 
     180             168 :          if( asGeomTypeNames[iType].pszName == NULL )
     181                 :          {
     182                 :              CPLError( CE_Failure, CPLE_AppDefined,
     183                 :                        "GeometryType %s not recognised.",
     184               0 :                        pszGType );
     185               0 :              return FALSE;
     186                 :          }
     187                 :      }
     188                 : 
     189                 : /* -------------------------------------------------------------------- */
     190                 : /*      Apply a spatial reference system if provided                    */
     191                 : /* -------------------------------------------------------------------- */
     192             216 :      const char* pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
     193             216 :      if( pszLayerSRS != NULL )
     194                 :      {
     195              96 :          if( EQUAL(pszLayerSRS,"NULL") )
     196               0 :              poSRS = NULL;
     197                 :          else
     198                 :          {
     199              96 :              OGRSpatialReference oSRS;
     200                 : 
     201              96 :              if( oSRS.SetFromUserInput( pszLayerSRS ) != OGRERR_NONE )
     202                 :              {
     203                 :                  CPLError( CE_Failure, CPLE_AppDefined,
     204               0 :                            "Failed to import LayerSRS `%s'.", pszLayerSRS );
     205               0 :                  return FALSE;
     206                 :              }
     207              96 :              poSRS = oSRS.Clone();
     208                 :          }
     209                 :      }
     210                 : 
     211             216 :      return TRUE;
     212                 : }
     213                 : 
     214                 : /************************************************************************/
     215                 : /*                         FullInitialize()                             */
     216                 : /************************************************************************/
     217                 : 
     218             105 : int OGRVRTLayer::FullInitialize()
     219                 : 
     220                 : {
     221             105 :     const char *pszSharedSetting = NULL;
     222             105 :     const char *pszSQL = NULL;
     223             105 :     const char *pszSrcRegion = NULL;
     224             105 :     const char *pszGType = NULL;
     225             105 :     const char *pszLayerSRS = NULL;
     226             105 :     const char *pszEncoding = NULL;
     227             105 :     const char *pszFIDFieldName = NULL;
     228             105 :     const char *pszStyleFieldName = NULL;
     229             105 :     CPLXMLNode *psChild = NULL;
     230                 : 
     231             105 :     if (bHasFullInitialized)
     232               0 :         return TRUE;
     233                 : 
     234             105 :     bHasFullInitialized = TRUE;
     235                 : 
     236             105 :     poFeatureDefn = new OGRFeatureDefn( osName );
     237             105 :     poFeatureDefn->Reference();
     238                 : 
     239                 : /* -------------------------------------------------------------------- */
     240                 : /*      Figure out the data source name.  It may be treated relative    */
     241                 : /*      to vrt filename, but normally it is used directly.              */
     242                 : /* -------------------------------------------------------------------- */
     243             105 :     OGRSFDriverRegistrar *poReg = OGRSFDriverRegistrar::GetRegistrar();
     244             105 :     char *pszSrcDSName = (char *) CPLGetXMLValue(psLTree,"SrcDataSource",NULL);
     245                 : 
     246             105 :     if( pszSrcDSName == NULL )
     247                 :     {
     248                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     249              13 :                   "Missing SrcDataSource for layer %s.", osName.c_str() );
     250              13 :         goto error;
     251                 :     }
     252                 : 
     253              92 :     if( CSLTestBoolean(CPLGetXMLValue( psLTree, "SrcDataSource.relativetoVRT", 
     254                 :                                        "0")) )
     255                 :     {
     256                 :         pszSrcDSName = CPLStrdup(
     257              30 :             CPLProjectRelativeFilename( osVRTDirectory, pszSrcDSName ) );
     258                 :     }
     259                 :     else
     260                 :     {
     261              62 :         pszSrcDSName = CPLStrdup(pszSrcDSName);
     262                 :     }
     263                 : 
     264                 : /* -------------------------------------------------------------------- */
     265                 : /*      Are we accessing this datasource in shared mode?  We default    */
     266                 : /*      to shared for SrcSQL requests, but we also allow the XML to     */
     267                 : /*      control our shared setting with an attribute on the             */
     268                 : /*      datasource element.                                             */
     269                 : /* -------------------------------------------------------------------- */
     270                 :     pszSharedSetting = CPLGetXMLValue( psLTree,
     271                 :                                                    "SrcDataSource.shared",
     272              92 :                                                    NULL );
     273              92 :     if( pszSharedSetting == NULL )
     274                 :     {
     275              75 :         if( CPLGetXMLValue( psLTree, "SrcSQL", NULL ) == NULL )
     276              73 :             pszSharedSetting = "OFF";
     277                 :         else
     278               2 :             pszSharedSetting = "ON";
     279                 :     }
     280                 : 
     281              92 :     bSrcDSShared = CSLTestBoolean( pszSharedSetting );
     282                 : 
     283                 :     // update mode doesn't make sense if we have a SrcSQL element
     284              92 :     if (CPLGetXMLValue( psLTree, "SrcSQL", NULL ) != NULL)
     285               2 :         bUpdate = FALSE;
     286                 : 
     287                 : /* -------------------------------------------------------------------- */
     288                 : /*      Try to access the datasource.                                   */
     289                 : /* -------------------------------------------------------------------- */
     290                 : try_again:
     291              92 :     CPLErrorReset();
     292              92 :     if( EQUAL(pszSrcDSName,"@dummy@") )
     293                 :     {
     294               0 :         OGRSFDriver *poMemDriver = OGRSFDriverRegistrar::GetRegistrar()->GetDriverByName("Memory");
     295               0 :         if (poMemDriver != NULL)
     296                 :         {
     297               0 :             poSrcDS = poMemDriver->CreateDataSource( "@dummy@" );
     298               0 :             poSrcDS->CreateLayer( "@dummy@" );
     299                 :         }
     300                 :     }
     301              92 :     else if( bSrcDSShared )
     302                 :     {
     303              19 :         if (poDS->IsInForbiddenNames(pszSrcDSName))
     304                 :         {
     305               1 :             CPLError(CE_Failure, CPLE_AppDefined, "Cyclic VRT opening detected !");
     306                 :         }
     307                 :         else
     308                 :         {
     309              18 :             poSrcDS = poReg->OpenShared( pszSrcDSName, bUpdate, NULL );
     310                 :             /* Is it a VRT datasource ? */
     311              18 :             if (poSrcDS != NULL && poSrcDS->GetDriver() == poDS->GetDriver())
     312                 :             {
     313               1 :                 OGRVRTDataSource* poVRTSrcDS = (OGRVRTDataSource*)poSrcDS;
     314               1 :                 poVRTSrcDS->AddForbiddenNames(poDS->GetName());
     315                 :             }
     316                 :         }
     317                 :     }
     318                 :     else
     319                 :     {
     320              73 :         if (poDS->GetCallLevel() < 32)
     321                 :         {
     322              72 :             poSrcDS = poReg->Open( pszSrcDSName, bUpdate, NULL );
     323                 :             /* Is it a VRT datasource ? */
     324              72 :             if (poSrcDS != NULL && poSrcDS->GetDriver() == poDS->GetDriver())
     325                 :             {
     326              32 :                 OGRVRTDataSource* poVRTSrcDS = (OGRVRTDataSource*)poSrcDS;
     327              32 :                 poVRTSrcDS->SetCallLevel(poDS->GetCallLevel() + 1);
     328                 :             }
     329                 :         }
     330                 :         else
     331                 :         {
     332                 :             CPLError(CE_Failure, CPLE_AppDefined,
     333               1 :                      "Trying to open a VRT from a VRT from a VRT from ... [32 times] a VRT !");
     334                 :         }
     335                 :     }
     336                 : 
     337              92 :     if( poSrcDS == NULL ) 
     338                 :     {
     339               2 :         if (bUpdate)
     340                 :         {
     341                 :             CPLError( CE_Warning, CPLE_AppDefined,
     342                 :                       "Cannot open datasource `%s' in update mode. Trying again in read-only mode",
     343               0 :                        pszSrcDSName );
     344               0 :             bUpdate = FALSE;
     345               0 :             goto try_again;
     346                 :         }
     347               2 :         if( strlen(CPLGetLastErrorMsg()) == 0 )
     348                 :             CPLError( CE_Failure, CPLE_AppDefined, 
     349                 :                       "Failed to open datasource `%s'.", 
     350               0 :                       pszSrcDSName );
     351               2 :         CPLFree( pszSrcDSName );
     352               2 :         goto error;
     353                 :     }
     354                 : 
     355              90 :     this->bUpdate = bUpdate;
     356                 : 
     357                 : /* -------------------------------------------------------------------- */
     358                 : /*      Is this layer derived from an SQL query result?                 */
     359                 : /* -------------------------------------------------------------------- */
     360              90 :     pszSQL = CPLGetXMLValue( psLTree, "SrcSQL", NULL );
     361                 : 
     362              90 :     if( pszSQL != NULL )
     363                 :     {
     364               2 :         poSrcLayer = poSrcDS->ExecuteSQL( pszSQL, NULL, NULL );
     365               2 :         if( poSrcLayer == NULL )
     366                 :         {
     367                 :             CPLError( CE_Failure, CPLE_AppDefined,
     368                 :                       "SQL statement failed, or returned no layer result:\n%s",
     369               0 :                       pszSQL );
     370               0 :             goto error;
     371                 :         }
     372               2 :         bSrcLayerFromSQL = TRUE;
     373                 :     }
     374                 : 
     375                 : /* -------------------------------------------------------------------- */
     376                 : /*      Fetch the layer if it is a regular layer.                       */
     377                 : /* -------------------------------------------------------------------- */
     378              90 :     if( poSrcLayer == NULL )
     379                 :     {
     380                 :         const char *pszSrcLayerName = CPLGetXMLValue( psLTree, "SrcLayer", 
     381              88 :                                                       osName );
     382                 :         
     383              88 :         poSrcLayer = poSrcDS->GetLayerByName( pszSrcLayerName );
     384              88 :         if( poSrcLayer == NULL )
     385                 :         {
     386                 :             CPLError( CE_Failure, CPLE_AppDefined,
     387                 :                   "Failed to find layer '%s' on datasource '%s'.", 
     388               0 :                       pszSrcLayerName, pszSrcDSName );
     389               0 :             CPLFree( pszSrcDSName );
     390               0 :             goto error;
     391                 :         }
     392                 :     }
     393                 :         
     394              90 :     CPLFree( pszSrcDSName );
     395                 : 
     396                 : /* -------------------------------------------------------------------- */
     397                 : /*      Do we have a fixed geometry type?  If not derive from the       */
     398                 : /*      source layer.                                                   */
     399                 : /* -------------------------------------------------------------------- */
     400              90 :      pszGType = CPLGetXMLValue( psLTree, "GeometryType", NULL );
     401              90 :      if( pszGType == NULL )
     402                 :      {
     403              46 :          eGeomType = poSrcLayer->GetLayerDefn()->GetGeomType();
     404                 :      }
     405              90 :      poFeatureDefn->SetGeomType(eGeomType);
     406                 : 
     407                 : /* -------------------------------------------------------------------- */
     408                 : /*      Copy spatial reference system from source if not provided       */
     409                 : /* -------------------------------------------------------------------- */
     410              90 :      pszLayerSRS = CPLGetXMLValue( psLTree, "LayerSRS", NULL );
     411              90 :      if( pszLayerSRS == NULL )
     412                 :      {
     413              50 :          CPLAssert(poSRS == NULL);
     414              50 :          if( poSrcLayer->GetSpatialRef() != NULL )
     415               1 :              poSRS = poSrcLayer->GetSpatialRef()->Clone();
     416                 :          else
     417              49 :              poSRS = NULL;
     418                 :      }
     419                 : 
     420                 : /* -------------------------------------------------------------------- */
     421                 : /*      Handle GeometryField.                                           */
     422                 : /* -------------------------------------------------------------------- */
     423                 : 
     424              90 :      pszEncoding = CPLGetXMLValue( psLTree,"GeometryField.encoding", "direct");
     425                 : 
     426              90 :      if( EQUAL(pszEncoding,"Direct") )
     427              40 :          eGeometryStyle = VGS_Direct;
     428              50 :      else if( EQUAL(pszEncoding,"None") )
     429               0 :          eGeometryStyle = VGS_None;
     430              50 :      else if( EQUAL(pszEncoding,"WKT") )
     431              20 :          eGeometryStyle = VGS_WKT;
     432              30 :      else if( EQUAL(pszEncoding,"WKB") )
     433               1 :          eGeometryStyle = VGS_WKB;
     434              29 :      else if( EQUAL(pszEncoding,"Shape") )
     435               0 :          eGeometryStyle = VGS_Shape;
     436              29 :      else if( EQUAL(pszEncoding,"PointFromColumns") )
     437                 :      {
     438              29 :          eGeometryStyle = VGS_PointFromColumns;
     439                 :          bUseSpatialSubquery = 
     440                 :              CSLTestBoolean(
     441                 :                  CPLGetXMLValue(psLTree, 
     442                 :                                 "GeometryField.useSpatialSubquery",
     443              29 :                                 "TRUE"));
     444                 : 
     445              29 :          iGeomXField = poSrcLayer->GetLayerDefn()->GetFieldIndex(
     446              58 :              CPLGetXMLValue( psLTree, "GeometryField.x", "missing" ) );
     447              29 :          iGeomYField = poSrcLayer->GetLayerDefn()->GetFieldIndex(
     448              58 :              CPLGetXMLValue( psLTree, "GeometryField.y", "missing" ) );
     449              29 :          iGeomZField = poSrcLayer->GetLayerDefn()->GetFieldIndex(
     450              58 :              CPLGetXMLValue( psLTree, "GeometryField.z", "missing" ) );
     451                 : 
     452              29 :          if( iGeomXField == -1 || iGeomYField == -1 )
     453                 :          {
     454                 :              CPLError( CE_Failure, CPLE_AppDefined, 
     455               0 :                        "Unable to identify source X or Y field for PointFromColumns encoding." );
     456               0 :              goto error;
     457                 :          }
     458                 :      }
     459                 :      else
     460                 :      {
     461                 :          CPLError( CE_Failure, CPLE_AppDefined, 
     462               0 :                    "encoding=\"%s\" not recognised.", pszEncoding );
     463               0 :          goto error;
     464                 :      }
     465                 : 
     466              90 :      if( eGeometryStyle == VGS_WKT
     467                 :          || eGeometryStyle == VGS_WKB
     468                 :          || eGeometryStyle == VGS_Shape )
     469                 :      {
     470                 :          const char *pszFieldName = 
     471              21 :              CPLGetXMLValue( psLTree, "GeometryField.field", "missing" );
     472                 : 
     473              21 :          iGeomField = poSrcLayer->GetLayerDefn()->GetFieldIndex(pszFieldName);
     474                 : 
     475              21 :          if( iGeomField == -1 )
     476                 :          {
     477                 :              CPLError( CE_Failure, CPLE_AppDefined, 
     478                 :                        "Unable to identify source field '%s' for geometry.",
     479               0 :                        pszFieldName );
     480               0 :              goto error;
     481                 :          }
     482                 :      }
     483                 : 
     484                 : /* -------------------------------------------------------------------- */
     485                 : /*      Figure out what should be used as an FID.                       */
     486                 : /* -------------------------------------------------------------------- */
     487              90 :      pszFIDFieldName = CPLGetXMLValue( psLTree, "FID", NULL );
     488                 : 
     489              90 :      if( pszFIDFieldName != NULL )
     490                 :      {
     491                 :          iFIDField = 
     492              16 :              poSrcLayer->GetLayerDefn()->GetFieldIndex( pszFIDFieldName );
     493              16 :          if( iFIDField == -1 )
     494                 :          {
     495                 :              CPLError( CE_Failure, CPLE_AppDefined, 
     496                 :                        "Unable to identify FID field '%s'.",
     497               0 :                        pszFIDFieldName );
     498               0 :              goto error;
     499                 :          }
     500                 :      }
     501                 : 
     502                 : /* -------------------------------------------------------------------- */
     503                 : /*      Figure out what should be used as a Style                       */
     504                 : /* -------------------------------------------------------------------- */
     505              90 :      pszStyleFieldName = CPLGetXMLValue( psLTree, "Style", NULL );
     506                 : 
     507              90 :      if( pszStyleFieldName != NULL )
     508                 :      {
     509                 :          iStyleField = 
     510               0 :              poSrcLayer->GetLayerDefn()->GetFieldIndex( pszStyleFieldName );
     511               0 :          if( iStyleField == -1 )
     512                 :          {
     513                 :              CPLError( CE_Failure, CPLE_AppDefined, 
     514                 :                        "Unable to identify Style field '%s'.",
     515               0 :                        pszStyleFieldName );
     516               0 :              goto error;
     517                 :          }
     518                 :      }
     519                 : 
     520                 : /* ==================================================================== */
     521                 : /*      Search for schema definitions in the VRT.                       */
     522                 : /* ==================================================================== */
     523             518 :      for( psChild = psLTree->psChild; psChild != NULL; psChild=psChild->psNext )
     524                 :      {
     525             428 :          if( psChild->eType == CXT_Element && EQUAL(psChild->pszValue,"Field") )
     526                 :          {
     527                 : /* -------------------------------------------------------------------- */
     528                 : /*      Field name.                                                     */
     529                 : /* -------------------------------------------------------------------- */
     530               6 :              const char *pszName = CPLGetXMLValue( psChild, "name", NULL );
     531               6 :              if( pszName == NULL )
     532                 :              {
     533                 :                  CPLError( CE_Failure, CPLE_AppDefined, 
     534               0 :                            "Unable to identify Field name." );
     535               0 :                  goto error;
     536                 :              }
     537                 : 
     538               6 :              OGRFieldDefn oFieldDefn( pszName, OFTString );
     539                 :              
     540                 : /* -------------------------------------------------------------------- */
     541                 : /*      Type                                                            */
     542                 : /* -------------------------------------------------------------------- */
     543               6 :              const char *pszArg = CPLGetXMLValue( psChild, "type", NULL );
     544                 : 
     545               6 :              if( pszArg != NULL )
     546                 :              {
     547                 :                  int iType;
     548                 : 
     549               8 :                  for( iType = 0; iType <= (int) OFTMaxType; iType++ )
     550                 :                  {
     551               8 :                      if( EQUAL(pszArg,OGRFieldDefn::GetFieldTypeName(
     552                 :                                    (OGRFieldType)iType)) )
     553                 :                      {
     554               4 :                          oFieldDefn.SetType( (OGRFieldType) iType );
     555               4 :                          break;
     556                 :                      }
     557                 :                  }
     558                 : 
     559               4 :                  if( iType > (int) OFTMaxType )
     560                 :                  {
     561                 :                      CPLError( CE_Failure, CPLE_AppDefined, 
     562                 :                                "Unable to identify Field type '%s'.",
     563               0 :                                pszArg );
     564                 :                      goto error;
     565                 :                  }
     566                 :              }
     567                 : 
     568                 : /* -------------------------------------------------------------------- */
     569                 : /*      Width and precision.                                            */
     570                 : /* -------------------------------------------------------------------- */
     571                 :              oFieldDefn.SetWidth( 
     572               6 :                  atoi(CPLGetXMLValue( psChild, "width", "0" )) );
     573                 :              oFieldDefn.SetPrecision( 
     574               6 :                  atoi(CPLGetXMLValue( psChild, "precision", "0" )) );
     575                 : 
     576                 : /* -------------------------------------------------------------------- */
     577                 : /*      Create the field.                                               */
     578                 : /* -------------------------------------------------------------------- */
     579               6 :              poFeatureDefn->AddFieldDefn( &oFieldDefn );
     580                 : 
     581               6 :              abDirectCopy.push_back( FALSE );
     582                 : 
     583                 : /* -------------------------------------------------------------------- */
     584                 : /*      Source field.                                                   */
     585                 : /* -------------------------------------------------------------------- */
     586                 :              int iSrcField = 
     587               6 :                  poSrcLayer->GetLayerDefn()->GetFieldIndex( pszName );
     588                 : 
     589               6 :              pszArg = CPLGetXMLValue( psChild, "src", NULL );
     590                 : 
     591               6 :              if( pszArg != NULL )
     592                 :              {
     593                 :                  iSrcField = 
     594               2 :                      poSrcLayer->GetLayerDefn()->GetFieldIndex( pszArg );
     595               2 :                  if( iSrcField == -1 )
     596                 :                  {
     597                 :                      CPLError( CE_Failure, CPLE_AppDefined,
     598                 :                                "Unable to find source field '%s'.",
     599               0 :                                pszArg );
     600                 :                      goto error;
     601                 :                  }
     602                 :              }
     603                 :              
     604               6 :              anSrcField.push_back( iSrcField );
     605                 :          }
     606                 :      }
     607                 : 
     608              90 :      CPLAssert( poFeatureDefn->GetFieldCount() == (int) anSrcField.size() );
     609                 : 
     610                 : /* -------------------------------------------------------------------- */
     611                 : /*      Create the schema, if it was not explicitly in the VRT.         */
     612                 : /* -------------------------------------------------------------------- */
     613              90 :      if( poFeatureDefn->GetFieldCount() == 0 )
     614                 :      {
     615                 :          int bReportSrcColumn =
     616              88 :              CSLTestBoolean(CPLGetXMLValue( psLTree, "GeometryField.reportSrcColumn", "YES" ));
     617                 : 
     618                 :          int iSrcField;
     619                 :          int iDstField;
     620              88 :          OGRFeatureDefn *poSrcDefn = poSrcLayer->GetLayerDefn();
     621              88 :          int nSrcFieldCount = poSrcDefn->GetFieldCount();
     622              88 :          int nDstFieldCount = nSrcFieldCount;
     623              88 :          if (bReportSrcColumn == FALSE)
     624                 :          {
     625               2 :              if (iGeomXField != -1) nDstFieldCount --;
     626               2 :              if (iGeomYField != -1) nDstFieldCount --;
     627               2 :              if (iGeomZField != -1) nDstFieldCount --;
     628               2 :              if (iGeomField != -1) nDstFieldCount --;
     629                 :          }
     630                 :          
     631             297 :          for( iSrcField = 0, iDstField = 0; iSrcField < nSrcFieldCount; iSrcField++ )
     632                 :          {
     633             209 :              if (bReportSrcColumn == FALSE &&
     634                 :                  (iSrcField == iGeomXField || iSrcField == iGeomYField ||
     635                 :                   iSrcField == iGeomZField || iSrcField == iGeomField))
     636               4 :                  continue;
     637                 :              
     638             205 :              poFeatureDefn->AddFieldDefn( poSrcDefn->GetFieldDefn( iSrcField ) );
     639             205 :              anSrcField.push_back( iSrcField );
     640             205 :              abDirectCopy.push_back( TRUE );
     641             205 :              iDstField++;
     642                 :          }
     643              88 :          bAttrFilterPassThrough = TRUE;
     644                 :      }
     645                 : 
     646                 : /* -------------------------------------------------------------------- */
     647                 : /*      Allow vrt to override whether attribute filters should be       */
     648                 : /*      passed through.                                                 */
     649                 : /* -------------------------------------------------------------------- */
     650              90 :      if( CPLGetXMLValue( psLTree, "attrFilterPassThrough", NULL ) != NULL )
     651                 :          bAttrFilterPassThrough = 
     652                 :              CSLTestBoolean(
     653                 :                  CPLGetXMLValue(psLTree, "attrFilterPassThrough",
     654               0 :                                 "TRUE") );
     655                 : 
     656                 : /* -------------------------------------------------------------------- */
     657                 : /*      Do we have a SrcRegion?                                         */
     658                 : /* -------------------------------------------------------------------- */
     659              90 :      pszSrcRegion = CPLGetXMLValue( psLTree, "SrcRegion", NULL );
     660              90 :      if( pszSrcRegion != NULL )
     661                 :      {
     662               3 :         OGRGeometryFactory::createFromWkt( (char**) &pszSrcRegion, NULL, &poSrcRegion );
     663               3 :         if( poSrcRegion == NULL || wkbFlatten(poSrcRegion->getGeometryType()) != wkbPolygon)
     664                 :         {
     665                 :             CPLError(CE_Warning, CPLE_AppDefined,
     666               0 :                         "Ignoring SrcRegion. It must be a valid WKT polygon");
     667               0 :             delete poSrcRegion;
     668               0 :             poSrcRegion = NULL;
     669                 :         }
     670                 : 
     671               3 :         bSrcClip = CSLTestBoolean(CPLGetXMLValue( psLTree, "SrcRegion.clip", "FALSE" ));
     672                 :      }
     673                 : 
     674              90 :      return TRUE;
     675                 : 
     676                 : error:
     677              15 :     if( poFeatureDefn )
     678              15 :         poFeatureDefn->Release();
     679              15 :     poFeatureDefn = new OGRFeatureDefn( osName );
     680              15 :     poFeatureDefn->Reference();
     681              15 :     return FALSE;
     682                 : }
     683                 : 
     684                 : /************************************************************************/
     685                 : /*                            ResetReading()                            */
     686                 : /************************************************************************/
     687                 : 
     688             122 : void OGRVRTLayer::ResetReading()
     689                 : 
     690                 : {
     691             122 :     bNeedReset = TRUE;
     692             122 : }
     693                 : 
     694                 : /************************************************************************/
     695                 : /*                         ResetSourceReading()                         */
     696                 : /************************************************************************/
     697                 : 
     698              87 : int OGRVRTLayer::ResetSourceReading()
     699                 : 
     700                 : {
     701              87 :     int bSuccess = TRUE;
     702                 : 
     703                 : /* -------------------------------------------------------------------- */
     704                 : /*      Do we want to let source layer do spatial restriction?          */
     705                 : /* -------------------------------------------------------------------- */
     706              87 :     char *pszFilter = NULL;
     707              87 :     if( (m_poFilterGeom || poSrcRegion) && bUseSpatialSubquery &&
     708                 :          eGeometryStyle == VGS_PointFromColumns )
     709                 :     {
     710                 :         const char *pszXField, *pszYField;
     711                 : 
     712               7 :         pszXField = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomXField)->GetNameRef();
     713               7 :         pszYField = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomYField)->GetNameRef();
     714               7 :         if (bUseSpatialSubquery)
     715                 :         {
     716               7 :             OGRFieldType xType = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomXField)->GetType();
     717               7 :             OGRFieldType yType = poSrcLayer->GetLayerDefn()->GetFieldDefn(iGeomYField)->GetType();
     718               7 :             if (!((xType == OFTReal || xType == OFTInteger) && (yType == OFTReal || yType == OFTInteger)))
     719                 :             {
     720                 :                 CPLError(CE_Warning, CPLE_AppDefined,
     721                 :                         "The '%s' and/or '%s' fields of the source layer are not declared as numeric fields,\n"
     722                 :                         "so the spatial filter cannot be turned into an attribute filter on them",
     723               1 :                          pszXField, pszYField);
     724               1 :                 bUseSpatialSubquery = FALSE;
     725                 :             }
     726                 :         }
     727               7 :         if (bUseSpatialSubquery)
     728                 :         {
     729               6 :             OGREnvelope sEnvelope;
     730                 : 
     731                 :             pszFilter = (char *) 
     732               6 :                 CPLMalloc(2*strlen(pszXField)+2*strlen(pszYField) + 100);
     733                 : 
     734               6 :             if (poSrcRegion != NULL)
     735                 :             {
     736               5 :                 if (m_poFilterGeom == NULL)
     737               3 :                     poSrcRegion->getEnvelope( &sEnvelope );
     738                 :                 else
     739                 :                 {
     740               2 :                     OGRGeometry* poIntersection = poSrcRegion->Intersection(m_poFilterGeom);
     741               2 :                     if (poIntersection)
     742                 :                     {
     743               2 :                         poIntersection->getEnvelope( &sEnvelope );
     744               2 :                         delete poIntersection;
     745                 :                     }
     746                 :                     else
     747                 :                     {
     748               0 :                         sEnvelope.MinX = 0;
     749               0 :                         sEnvelope.MaxX = 0;
     750               0 :                         sEnvelope.MinY = 0;
     751               0 :                         sEnvelope.MaxY = 0;
     752                 :                     }
     753                 :                 }
     754                 :             }
     755                 :             else
     756               1 :                 m_poFilterGeom->getEnvelope( &sEnvelope );
     757                 : 
     758                 :             sprintf( pszFilter, 
     759                 :                     "%s > %.15g AND %s < %.15g AND %s > %.15g AND %s < %.15g", 
     760                 :                     pszXField, sEnvelope.MinX,
     761                 :                     pszXField, sEnvelope.MaxX,
     762                 :                     pszYField, sEnvelope.MinY,
     763               6 :                     pszYField, sEnvelope.MaxY );
     764                 :             char* pszComma;
     765              12 :             while((pszComma = strchr(pszFilter, ',')) != NULL)
     766               0 :                 *pszComma = '.';
     767                 :         }
     768                 :     }
     769                 : 
     770                 : /* -------------------------------------------------------------------- */
     771                 : /*      Install spatial + attr filter query on source layer.            */
     772                 : /* -------------------------------------------------------------------- */
     773             163 :     if( pszFilter == NULL && pszAttrFilter == NULL )
     774              76 :         bSuccess = (poSrcLayer->SetAttributeFilter( NULL ) == CE_None);
     775                 : 
     776              17 :     else if( pszFilter != NULL && pszAttrFilter == NULL )
     777               6 :         bSuccess = (poSrcLayer->SetAttributeFilter( pszFilter ) == CE_None);
     778                 : 
     779              10 :     else if( pszFilter == NULL && pszAttrFilter != NULL )
     780               5 :         bSuccess = (poSrcLayer->SetAttributeFilter( pszAttrFilter ) == CE_None);
     781                 : 
     782                 :     else
     783                 :     {
     784               0 :         CPLString osMerged = pszFilter;
     785                 : 
     786               0 :         osMerged += " AND ";
     787               0 :         osMerged += pszAttrFilter;
     788                 : 
     789               0 :         bSuccess = (poSrcLayer->SetAttributeFilter(osMerged) == CE_None);
     790                 :     }
     791                 : 
     792              87 :     CPLFree( pszFilter );
     793                 : 
     794                 : /* -------------------------------------------------------------------- */
     795                 : /*      Clear spatial filter (to be safe) for non direct geometries     */
     796                 : /*      and reset reading.            */
     797                 : /* -------------------------------------------------------------------- */
     798              87 :     if (eGeometryStyle == VGS_Direct)
     799                 :     {
     800              30 :         if (poSrcRegion == NULL)
     801              25 :             poSrcLayer->SetSpatialFilter( m_poFilterGeom );
     802               5 :         else if (m_poFilterGeom == NULL)
     803               3 :             poSrcLayer->SetSpatialFilter( poSrcRegion );
     804                 :         else
     805                 :         {
     806               2 :             if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
     807                 :             {
     808                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     809               0 :                          "Spatial filter should be polygon when a SrcRegion is defined. Ignoring it");
     810               0 :                 poSrcLayer->SetSpatialFilter( poSrcRegion );
     811                 :             }
     812                 :             else
     813                 :             {
     814               2 :                 OGRGeometry* poIntersection = m_poFilterGeom->Intersection(poSrcRegion);
     815               2 :                 poSrcLayer->SetSpatialFilter( poIntersection );
     816               2 :                 delete poIntersection;
     817                 :             }
     818                 :         }
     819                 :     }
     820                 :     else
     821              57 :         poSrcLayer->SetSpatialFilter( NULL );
     822              87 :     poSrcLayer->ResetReading();
     823              87 :     bNeedReset = FALSE;
     824                 : 
     825              87 :     return bSuccess;
     826                 : }
     827                 : 
     828                 : /************************************************************************/
     829                 : /*                           GetNextFeature()                           */
     830                 : /************************************************************************/
     831                 : 
     832            9366 : OGRFeature *OGRVRTLayer::GetNextFeature()
     833                 : 
     834                 : {
     835            9366 :     if (!bHasFullInitialized) FullInitialize();
     836            9366 :     if (!poSrcLayer) return NULL;
     837                 : 
     838            9365 :     if( bNeedReset )
     839                 :     {
     840              72 :         if( !ResetSourceReading() )
     841               0 :             return NULL;
     842                 :     }
     843                 : 
     844               7 :     for( ; TRUE; )
     845                 :     {
     846                 :         OGRFeature      *poSrcFeature, *poFeature;
     847                 : 
     848            9372 :         poSrcFeature = poSrcLayer->GetNextFeature();
     849            9372 :         if( poSrcFeature == NULL )
     850              48 :             return NULL;
     851                 : 
     852            9324 :         poFeature = TranslateFeature( poSrcFeature, TRUE );
     853            9324 :         delete poSrcFeature;
     854                 : 
     855            9324 :         if( poFeature == NULL )
     856               4 :             return NULL;
     857                 : 
     858            9320 :         if( (eGeometryStyle == VGS_Direct || m_poFilterGeom == NULL
     859                 :             || FilterGeometry( poFeature->GetGeometryRef() ) )
     860                 :             && (m_poAttrQuery == NULL
     861                 :                 || m_poAttrQuery->Evaluate( poFeature )) )
     862            9313 :             return poFeature;
     863                 : 
     864               7 :         delete poFeature;
     865                 :     }
     866                 : }
     867                 : 
     868                 : /************************************************************************/
     869                 : /*                          TranslateFeature()                          */
     870                 : /*                                                                      */
     871                 : /*      Translate a source feature into a feature for this layer.       */
     872                 : /************************************************************************/
     873                 : 
     874            9341 : OGRFeature *OGRVRTLayer::TranslateFeature( OGRFeature*& poSrcFeat, int bUseSrcRegion )
     875                 : 
     876                 : {
     877                 : retry:
     878            9341 :     OGRFeature *poDstFeat = new OGRFeature( poFeatureDefn );
     879                 : 
     880            9341 :     m_nFeaturesRead++;
     881                 : 
     882                 : /* -------------------------------------------------------------------- */
     883                 : /*      Handle FID.                                                     */
     884                 : /* -------------------------------------------------------------------- */
     885            9341 :     if( iFIDField == -1 )
     886            9317 :         poDstFeat->SetFID( poSrcFeat->GetFID() );
     887                 :     else
     888              24 :         poDstFeat->SetFID( poSrcFeat->GetFieldAsInteger( iFIDField ) );
     889                 :     
     890                 : /* -------------------------------------------------------------------- */
     891                 : /*      Handle style string.                                            */
     892                 : /* -------------------------------------------------------------------- */
     893            9341 :     if( iStyleField != -1 )
     894                 :     {
     895               0 :         if( poSrcFeat->IsFieldSet(iStyleField) )
     896                 :             poDstFeat->SetStyleString( 
     897               0 :                 poSrcFeat->GetFieldAsString(iStyleField) );
     898                 :     }
     899                 :     else
     900                 :     {
     901            9341 :         if( poSrcFeat->GetStyleString() != NULL )
     902               0 :             poDstFeat->SetStyleString(poSrcFeat->GetStyleString());
     903                 :     }
     904                 :     
     905                 : /* -------------------------------------------------------------------- */
     906                 : /*      Handle the geometry.  Eventually there will be several more     */
     907                 : /*      supported options.                                              */
     908                 : /* -------------------------------------------------------------------- */
     909            9341 :     if( eGeometryStyle == VGS_None )
     910                 :     {
     911                 :         /* do nothing */
     912                 :     }
     913            9341 :     else if( eGeometryStyle == VGS_WKT )
     914                 :     {
     915              43 :         char *pszWKT = (char *) poSrcFeat->GetFieldAsString( iGeomField );
     916                 :         
     917              43 :         if( pszWKT != NULL )
     918                 :         {
     919              43 :             OGRGeometry *poGeom = NULL;
     920                 : 
     921              43 :             OGRGeometryFactory::createFromWkt( &pszWKT, NULL, &poGeom );
     922              43 :             if( poGeom == NULL )
     923                 :                 CPLDebug( "OGR_VRT", "Did not get geometry from %s",
     924               0 :                           pszWKT );
     925                 : 
     926              43 :             poDstFeat->SetGeometryDirectly( poGeom );
     927                 :         }
     928                 :     }
     929            9298 :     else if( eGeometryStyle == VGS_WKB )
     930                 :     {
     931                 :         int nBytes;
     932                 :         GByte *pabyWKB;
     933               1 :         int bNeedFree = FALSE;
     934                 : 
     935               1 :         if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
     936                 :         {
     937               0 :             pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
     938                 :         }
     939                 :         else
     940                 :         {
     941               1 :             const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
     942                 : 
     943               1 :             pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
     944               1 :             bNeedFree = TRUE;
     945                 :         }
     946                 :         
     947               1 :         if( pabyWKB != NULL )
     948                 :         {
     949               1 :             OGRGeometry *poGeom = NULL;
     950                 : 
     951               1 :             if( OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeom,
     952                 :                                                    nBytes ) == OGRERR_NONE )
     953               1 :                 poDstFeat->SetGeometryDirectly( poGeom );
     954                 :         }
     955                 : 
     956               1 :         if( bNeedFree )
     957               1 :             CPLFree( pabyWKB );
     958                 :     }
     959            9297 :     else if( eGeometryStyle == VGS_Shape )
     960                 :     {
     961                 :         int nBytes;
     962                 :         GByte *pabyWKB;
     963               0 :         int bNeedFree = FALSE;
     964                 : 
     965               0 :         if( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
     966                 :         {
     967               0 :             pabyWKB = poSrcFeat->GetFieldAsBinary( iGeomField, &nBytes );
     968                 :         }
     969                 :         else
     970                 :         {
     971               0 :             const char *pszWKT = poSrcFeat->GetFieldAsString( iGeomField );
     972                 : 
     973               0 :             pabyWKB = CPLHexToBinary( pszWKT, &nBytes );
     974               0 :             bNeedFree = TRUE;
     975                 :         }
     976                 :         
     977               0 :         if( pabyWKB != NULL )
     978                 :         {
     979               0 :             OGRGeometry *poGeom = NULL;
     980                 : 
     981               0 :             if( createFromShapeBin( pabyWKB, &poGeom, nBytes ) == OGRERR_NONE )
     982               0 :                 poDstFeat->SetGeometryDirectly( poGeom );
     983                 :         }
     984                 : 
     985               0 :         if( bNeedFree )
     986               0 :             CPLFree( pabyWKB );
     987                 :     }
     988            9297 :     else if( eGeometryStyle == VGS_Direct )
     989                 :     {
     990              69 :         poDstFeat->SetGeometry( poSrcFeat->GetGeometryRef() );
     991                 :     }
     992            9228 :     else if( eGeometryStyle == VGS_PointFromColumns )
     993                 :     {
     994            9228 :         if( iGeomZField != -1 )
     995                 :             poDstFeat->SetGeometryDirectly( 
     996                 :                 new OGRPoint( poSrcFeat->GetFieldAsDouble( iGeomXField ),
     997                 :                               poSrcFeat->GetFieldAsDouble( iGeomYField ),
     998            9210 :                               poSrcFeat->GetFieldAsDouble( iGeomZField ) ) );
     999                 :         else
    1000                 :             poDstFeat->SetGeometryDirectly( 
    1001                 :                 new OGRPoint( poSrcFeat->GetFieldAsDouble( iGeomXField ),
    1002              18 :                               poSrcFeat->GetFieldAsDouble( iGeomYField ) ) );
    1003                 :     }
    1004                 :     else
    1005                 :         /* add other options here. */;
    1006                 : 
    1007                 :     /* In the non direct case, we need to check that the geometry intersects the source */
    1008                 :     /* region before an optionnal clipping */
    1009            9341 :     if( bUseSrcRegion && eGeometryStyle != VGS_Direct && poSrcRegion != NULL )
    1010                 :     {
    1011              23 :         OGRGeometry* poGeom = poDstFeat->GetGeometryRef();
    1012              23 :         if (poGeom != NULL && !poGeom->Intersects(poSrcRegion))
    1013                 :         {
    1014              14 :             delete poSrcFeat;
    1015              14 :             delete poDstFeat;
    1016                 : 
    1017                 :             /* Fetch next source feature and retry translating it */
    1018              14 :             poSrcFeat = poSrcLayer->GetNextFeature();
    1019              14 :             if (poSrcFeat == NULL)
    1020               4 :                 return NULL;
    1021                 : 
    1022              10 :             goto retry;
    1023                 :         }
    1024                 :     }
    1025                 : 
    1026                 :     /* Clip the geometry to the SrcRegion if asked */
    1027            9327 :     if (poSrcRegion != NULL && bSrcClip && poDstFeat->GetGeometryRef() != NULL)
    1028                 :     {
    1029               0 :         OGRGeometry* poClippedGeom = poDstFeat->GetGeometryRef()->Intersection(poSrcRegion);
    1030               0 :         poDstFeat->SetGeometryDirectly(poClippedGeom);
    1031                 :     }
    1032                 : 
    1033            9327 :     if (poDstFeat->GetGeometryRef() != NULL && poSRS != NULL)
    1034            9279 :         poDstFeat->GetGeometryRef()->assignSpatialReference(poSRS);
    1035                 : 
    1036                 : /* -------------------------------------------------------------------- */
    1037                 : /*      Copy fields.                                                    */
    1038                 : /* -------------------------------------------------------------------- */
    1039                 :     int iVRTField;
    1040                 : 
    1041           37389 :     for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
    1042                 :     {
    1043           28062 :         if( anSrcField[iVRTField] == -1 )
    1044               5 :             continue;
    1045                 : 
    1046           28057 :         OGRFieldDefn *poDstDefn = poFeatureDefn->GetFieldDefn( iVRTField );
    1047           28057 :         OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
    1048                 : 
    1049           28057 :         if( !poSrcFeat->IsFieldSet( anSrcField[iVRTField] ) )
    1050               0 :             continue;
    1051                 : 
    1052           28057 :         if( abDirectCopy[iVRTField] 
    1053                 :             && poDstDefn->GetType() == poSrcDefn->GetType() )
    1054                 :         {
    1055                 :             poDstFeat->SetField( iVRTField,
    1056           28047 :                                  poSrcFeat->GetRawFieldRef( anSrcField[iVRTField] ) );
    1057                 :         }
    1058                 :         else
    1059                 :         {
    1060                 :             /* Eventually we need to offer some more sophisticated translation
    1061                 :                options here for more esoteric types. */
    1062              10 :             if (poDstDefn->GetType() == OFTReal)
    1063                 :                 poDstFeat->SetField( iVRTField, 
    1064               0 :                                  poSrcFeat->GetFieldAsDouble(anSrcField[iVRTField]));
    1065                 :             else
    1066                 :                 poDstFeat->SetField( iVRTField, 
    1067              10 :                                  poSrcFeat->GetFieldAsString(anSrcField[iVRTField]));
    1068                 :         }
    1069                 :     }
    1070                 : 
    1071            9327 :     return poDstFeat;
    1072                 : }
    1073                 : 
    1074                 : 
    1075                 : /************************************************************************/
    1076                 : /*                             GetFeature()                             */
    1077                 : /************************************************************************/
    1078                 : 
    1079               8 : OGRFeature *OGRVRTLayer::GetFeature( long nFeatureId )
    1080                 : 
    1081                 : {
    1082               8 :     if (!bHasFullInitialized) FullInitialize();
    1083               8 :     if (!poSrcLayer) return NULL;
    1084                 : 
    1085               7 :     bNeedReset = TRUE;
    1086                 : 
    1087                 : /* -------------------------------------------------------------------- */
    1088                 : /*      If the FID is directly mapped, we can do a simple               */
    1089                 : /*      GetFeature() to get our target feature.  Otherwise we need      */
    1090                 : /*      to setup an appropriate query to get it.                        */
    1091                 : /* -------------------------------------------------------------------- */
    1092                 :     OGRFeature      *poSrcFeature, *poFeature;
    1093                 :     
    1094               7 :     if( iFIDField == -1 )
    1095                 :     {
    1096               5 :         poSrcFeature = poSrcLayer->GetFeature( nFeatureId );
    1097                 :     }
    1098                 :     else 
    1099                 :     {
    1100               2 :         const char* pszFID = poSrcLayer->GetLayerDefn()->GetFieldDefn(iFIDField)->GetNameRef();
    1101               2 :         char* pszFIDQuery = (char*)CPLMalloc(strlen(pszFID) + 64);
    1102                 : 
    1103               2 :         poSrcLayer->ResetReading();
    1104               2 :         sprintf( pszFIDQuery, "%s = %ld", pszFID, nFeatureId );
    1105               2 :         poSrcLayer->SetSpatialFilter( NULL );
    1106               2 :         poSrcLayer->SetAttributeFilter( pszFIDQuery );
    1107               2 :         CPLFree(pszFIDQuery);
    1108                 :         
    1109               2 :         poSrcFeature = poSrcLayer->GetNextFeature();
    1110                 :     }
    1111                 : 
    1112               7 :     if( poSrcFeature == NULL )
    1113               0 :         return NULL;
    1114                 :     
    1115                 : /* -------------------------------------------------------------------- */
    1116                 : /*      Translate feature and return it.                                */
    1117                 : /* -------------------------------------------------------------------- */
    1118               7 :     poFeature = TranslateFeature( poSrcFeature, FALSE );
    1119               7 :     delete poSrcFeature;
    1120                 : 
    1121               7 :     return poFeature;
    1122                 : }
    1123                 : 
    1124                 : /************************************************************************/
    1125                 : /*                          SetNextByIndex()                            */
    1126                 : /************************************************************************/
    1127                 : 
    1128               4 : OGRErr OGRVRTLayer::SetNextByIndex( long nIndex )
    1129                 : {
    1130               4 :     if (!bHasFullInitialized) FullInitialize();
    1131               4 :     if (!poSrcLayer) return OGRERR_FAILURE;
    1132                 : 
    1133               3 :     if (TestCapability(OLCFastSetNextByIndex))
    1134               3 :         return poSrcLayer->SetNextByIndex(nIndex);
    1135                 : 
    1136               0 :     return OGRLayer::SetNextByIndex(nIndex);
    1137                 : }
    1138                 : 
    1139                 : /************************************************************************/
    1140                 : /*               TranslateVRTFeatureToSrcFeature()                      */
    1141                 : /*                                                                      */
    1142                 : /*      Translate a VRT feature into a feature for the source layer     */
    1143                 : /************************************************************************/
    1144                 : 
    1145               3 : OGRFeature* OGRVRTLayer::TranslateVRTFeatureToSrcFeature( OGRFeature* poVRTFeature)
    1146                 : {
    1147               3 :     OGRFeature *poSrcFeat = new OGRFeature( poSrcLayer->GetLayerDefn() );
    1148                 : 
    1149               3 :     poSrcFeat->SetFID( poVRTFeature->GetFID() );
    1150                 : 
    1151                 : /* -------------------------------------------------------------------- */
    1152                 : /*      Handle style string.                                            */
    1153                 : /* -------------------------------------------------------------------- */
    1154               3 :     if( iStyleField != -1 )
    1155                 :     {
    1156               0 :         if( poVRTFeature->GetStyleString() != NULL )
    1157               0 :             poSrcFeat->SetField( iStyleField, poVRTFeature->GetStyleString() );
    1158                 :     }
    1159                 :     else
    1160                 :     {
    1161               3 :         if( poVRTFeature->GetStyleString() != NULL )
    1162               0 :             poSrcFeat->SetStyleString(poVRTFeature->GetStyleString());
    1163                 :     }
    1164                 :     
    1165                 : /* -------------------------------------------------------------------- */
    1166                 : /*      Handle the geometry.  Eventually there will be several more     */
    1167                 : /*      supported options.                                              */
    1168                 : /* -------------------------------------------------------------------- */
    1169               3 :     if( eGeometryStyle == VGS_None )
    1170                 :     {
    1171                 :         /* do nothing */
    1172                 :     }
    1173               3 :     else if( eGeometryStyle == VGS_WKT )
    1174                 :     {
    1175               1 :         OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
    1176               1 :         if (poGeom != NULL)
    1177                 :         {
    1178               1 :             char* pszWKT = NULL;
    1179               1 :             if (poGeom->exportToWkt(&pszWKT) == OGRERR_NONE)
    1180                 :             {
    1181               1 :                 poSrcFeat->SetField(iGeomField, pszWKT);
    1182                 :             }
    1183               1 :             CPLFree(pszWKT);
    1184                 :         }
    1185                 :     }
    1186               2 :     else if( eGeometryStyle == VGS_WKB )
    1187                 :     {
    1188               1 :         OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
    1189               1 :         if (poGeom != NULL)
    1190                 :         {
    1191               1 :             int nSize = poGeom->WkbSize();
    1192               1 :             GByte* pabyData = (GByte*)CPLMalloc(nSize);
    1193               1 :             if (poGeom->exportToWkb(wkbNDR, pabyData) == OGRERR_NONE)
    1194                 :             {
    1195               1 :                 if ( poSrcFeat->GetFieldDefnRef(iGeomField)->GetType() == OFTBinary )
    1196                 :                 {
    1197               0 :                     poSrcFeat->SetField(iGeomField, nSize, pabyData);
    1198                 :                 }
    1199                 :                 else
    1200                 :                 {
    1201               1 :                     char* pszHexWKB = CPLBinaryToHex(nSize, pabyData);
    1202               1 :                     poSrcFeat->SetField(iGeomField, pszHexWKB);
    1203               1 :                     CPLFree(pszHexWKB);
    1204                 :                 }
    1205                 :             }
    1206               1 :             CPLFree(pabyData);
    1207                 :         }
    1208                 :     }
    1209               1 :     else if( eGeometryStyle == VGS_Shape )
    1210                 :     {
    1211               0 :         CPLDebug("OGR_VRT", "Update of VGS_Shape geometries not supported");
    1212                 :     }
    1213               1 :     else if( eGeometryStyle == VGS_Direct )
    1214                 :     {
    1215               0 :         poSrcFeat->SetGeometry( poVRTFeature->GetGeometryRef() );
    1216                 :     }
    1217               1 :     else if( eGeometryStyle == VGS_PointFromColumns )
    1218                 :     {
    1219               1 :         OGRGeometry* poGeom = poVRTFeature->GetGeometryRef();
    1220               1 :         if (poGeom != NULL)
    1221                 :         {
    1222               1 :             if (wkbFlatten(poGeom->getGeometryType()) != wkbPoint)
    1223                 :             {
    1224                 :                 CPLError(CE_Warning, CPLE_NotSupported,
    1225               0 :                          "Cannot set a non ponctual geometry for PointFromColumns geometry");
    1226                 :             }
    1227                 :             else
    1228                 :             {
    1229               1 :                 poSrcFeat->SetField( iGeomXField, ((OGRPoint*)poGeom)->getX() );
    1230               1 :                 poSrcFeat->SetField( iGeomYField, ((OGRPoint*)poGeom)->getY() );
    1231               1 :                 if( iGeomZField != -1 )
    1232                 :                 {
    1233               0 :                     poSrcFeat->SetField( iGeomZField, ((OGRPoint*)poGeom)->getZ() );
    1234                 :                 }
    1235                 :             }
    1236                 :         }
    1237                 :     }
    1238                 :     else
    1239                 :         /* add other options here. */;
    1240                 : 
    1241               3 :     if (poSrcFeat->GetGeometryRef() != NULL && poSRS != NULL)
    1242               0 :         poSrcFeat->GetGeometryRef()->assignSpatialReference(poSRS);
    1243                 : 
    1244                 : /* -------------------------------------------------------------------- */
    1245                 : /*      Copy fields.                                                    */
    1246                 : /* -------------------------------------------------------------------- */
    1247                 : 
    1248                 :     int iVRTField;
    1249                 : 
    1250              11 :     for( iVRTField = 0; iVRTField < poFeatureDefn->GetFieldCount(); iVRTField++ )
    1251                 :     {
    1252                 :         /* Do not set source geometry columns. Have been set just above */
    1253               8 :         if (anSrcField[iVRTField] == iGeomField || anSrcField[iVRTField] == iGeomXField ||
    1254                 :             anSrcField[iVRTField] == iGeomYField || anSrcField[iVRTField] == iGeomZField)
    1255               2 :             continue;
    1256                 : 
    1257               6 :         OGRFieldDefn *poVRTDefn = poFeatureDefn->GetFieldDefn( iVRTField );
    1258               6 :         OGRFieldDefn *poSrcDefn = poSrcLayer->GetLayerDefn()->GetFieldDefn( anSrcField[iVRTField] );
    1259                 : 
    1260               6 :         if( abDirectCopy[iVRTField] 
    1261                 :             && poVRTDefn->GetType() == poSrcDefn->GetType() )
    1262                 :         {
    1263                 :             poSrcFeat->SetField( anSrcField[iVRTField],
    1264               6 :                                  poVRTFeature->GetRawFieldRef( iVRTField ) );
    1265                 :         }
    1266                 :         else
    1267                 :         {
    1268                 :             /* Eventually we need to offer some more sophisticated translation
    1269                 :                options here for more esoteric types. */
    1270                 :             poSrcFeat->SetField( anSrcField[iVRTField], 
    1271               0 :                                  poVRTFeature->GetFieldAsString(iVRTField));
    1272                 :         }
    1273                 :     }
    1274                 : 
    1275               3 :     return poSrcFeat;
    1276                 : }
    1277                 : 
    1278                 : /************************************************************************/
    1279                 : /*                           CreateFeature()                            */
    1280                 : /************************************************************************/
    1281                 : 
    1282               5 : OGRErr OGRVRTLayer::CreateFeature( OGRFeature* poVRTFeature )
    1283                 : {
    1284               5 :     if (!bHasFullInitialized) FullInitialize();
    1285               5 :     if (!poSrcLayer) return OGRERR_FAILURE;
    1286                 : 
    1287               4 :     if(!bUpdate)
    1288                 :     {
    1289                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1290               1 :             "The CreateFeature() operation is not permitted on a read-only VRT." );
    1291               1 :         return OGRERR_FAILURE;
    1292                 :     }
    1293                 : 
    1294               3 :     if( iFIDField != -1 )
    1295                 :     {
    1296                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1297               0 :             "The CreateFeature() operation is not supported if the FID option is specified." );
    1298               0 :         return OGRERR_FAILURE;
    1299                 :     }
    1300                 : 
    1301               3 :     OGRFeature* poSrcFeature = TranslateVRTFeatureToSrcFeature(poVRTFeature);
    1302               3 :     poSrcFeature->SetFID(OGRNullFID);
    1303               3 :     OGRErr eErr = poSrcLayer->CreateFeature(poSrcFeature);
    1304               3 :     if (eErr == OGRERR_NONE)
    1305                 :     {
    1306               3 :         poVRTFeature->SetFID(poSrcFeature->GetFID());
    1307                 :     }
    1308               3 :     delete poSrcFeature;
    1309               3 :     return eErr;
    1310                 : }
    1311                 : 
    1312                 : /************************************************************************/
    1313                 : /*                             SetFeature()                             */
    1314                 : /************************************************************************/
    1315                 : 
    1316               2 : OGRErr OGRVRTLayer::SetFeature( OGRFeature* poVRTFeature )
    1317                 : {
    1318               2 :     if (!bHasFullInitialized) FullInitialize();
    1319               2 :     if (!poSrcLayer) return OGRERR_FAILURE;
    1320                 : 
    1321               1 :     if(!bUpdate)
    1322                 :     {
    1323                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1324               1 :             "The SetFeature() operation is not permitted on a read-only VRT." );
    1325               1 :         return OGRERR_FAILURE;
    1326                 :     }
    1327                 : 
    1328               0 :     if( iFIDField != -1 )
    1329                 :     {
    1330                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1331               0 :             "The SetFeature() operation is not supported if the FID option is specified." );
    1332               0 :         return OGRERR_FAILURE;
    1333                 :     }
    1334                 : 
    1335               0 :     OGRFeature* poSrcFeature = TranslateVRTFeatureToSrcFeature(poVRTFeature);
    1336               0 :     OGRErr eErr = poSrcLayer->SetFeature(poSrcFeature);
    1337               0 :     delete poSrcFeature;
    1338               0 :     return eErr;
    1339                 : }
    1340                 : 
    1341                 : /************************************************************************/
    1342                 : /*                           DeleteFeature()                            */
    1343                 : /************************************************************************/
    1344                 : 
    1345               2 : OGRErr OGRVRTLayer::DeleteFeature( long nFID )
    1346                 : 
    1347                 : {
    1348               2 :     if (!bHasFullInitialized) FullInitialize();
    1349               2 :     if (!poSrcLayer) return OGRERR_FAILURE;
    1350                 : 
    1351               1 :     if(!bUpdate )
    1352                 :     {
    1353                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1354               1 :             "The DeleteFeature() operation is not permitted on a read-only VRT." );
    1355               1 :         return OGRERR_FAILURE;
    1356                 :     }
    1357                 : 
    1358               0 :     if( iFIDField != -1 )
    1359                 :     {
    1360                 :         CPLError( CE_Failure, CPLE_AppDefined, 
    1361               0 :             "The DeleteFeature() operation is not supported if the FID option is specified." );
    1362               0 :         return OGRERR_FAILURE;
    1363                 :     }
    1364                 : 
    1365               0 :     return poSrcLayer->DeleteFeature(nFID);
    1366                 : }
    1367                 : 
    1368                 : /************************************************************************/
    1369                 : /*                         SetAttributeFilter()                         */
    1370                 : /************************************************************************/
    1371                 : 
    1372              18 : OGRErr OGRVRTLayer::SetAttributeFilter( const char *pszNewQuery )
    1373                 : 
    1374                 : {
    1375              18 :     if (!bHasFullInitialized) FullInitialize();
    1376              18 :     if (!poSrcLayer) return OGRERR_FAILURE;
    1377                 : 
    1378              17 :     if( bAttrFilterPassThrough )
    1379                 :     {
    1380              16 :         CPLFree( pszAttrFilter );
    1381              28 :         if( pszNewQuery == NULL || strlen(pszNewQuery) == 0 )
    1382              12 :             pszAttrFilter = NULL;
    1383                 :         else
    1384               4 :             pszAttrFilter = CPLStrdup( pszNewQuery );
    1385                 : 
    1386              16 :         ResetReading();
    1387              16 :         return OGRERR_NONE;
    1388                 :     }
    1389                 :     else
    1390                 :     {
    1391                 :         /* setup m_poAttrQuery */
    1392               1 :         return OGRLayer::SetAttributeFilter( pszNewQuery );
    1393                 :     }
    1394                 : }
    1395                 : 
    1396                 : /************************************************************************/
    1397                 : /*                           TestCapability()                           */
    1398                 : /************************************************************************/
    1399                 : 
    1400              20 : int OGRVRTLayer::TestCapability( const char * pszCap )
    1401                 : 
    1402                 : {
    1403              20 :     if (!bHasFullInitialized) FullInitialize();
    1404              20 :     if (!poSrcLayer) return FALSE;
    1405                 : 
    1406              19 :     if ( EQUAL(pszCap,OLCFastFeatureCount) ||
    1407                 :          EQUAL(pszCap,OLCFastSetNextByIndex) )
    1408                 :         return (eGeometryStyle == VGS_Direct ||
    1409                 :                (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
    1410                 :                m_poAttrQuery == NULL &&
    1411               8 :                poSrcLayer->TestCapability(pszCap);
    1412                 : 
    1413              11 :     else if( EQUAL(pszCap,OLCFastSpatialFilter) )
    1414                 :         return eGeometryStyle == VGS_Direct && m_poAttrQuery == NULL &&
    1415               4 :                poSrcLayer->TestCapability(pszCap);
    1416                 : 
    1417               7 :     else if ( EQUAL(pszCap,OLCFastGetExtent) )
    1418                 :         return eGeometryStyle == VGS_Direct &&
    1419                 :                m_poAttrQuery == NULL &&
    1420                 :                poSrcRegion == NULL &&
    1421               3 :                poSrcLayer->TestCapability(pszCap);
    1422                 : 
    1423               4 :     else if( EQUAL(pszCap,OLCRandomRead) )
    1424               2 :         return iFIDField == -1 && poSrcLayer->TestCapability(pszCap);
    1425                 : 
    1426               2 :     else if( EQUAL(pszCap,OLCSequentialWrite) 
    1427                 :              || EQUAL(pszCap,OLCRandomWrite)
    1428                 :              || EQUAL(pszCap,OLCDeleteFeature) )
    1429               1 :         return bUpdate && iFIDField == -1 && poSrcLayer->TestCapability(pszCap);
    1430                 : 
    1431               1 :     else if( EQUAL(pszCap,OLCStringsAsUTF8) )
    1432               1 :         return poSrcLayer->TestCapability(pszCap);
    1433                 : 
    1434               0 :     return FALSE;
    1435                 : }
    1436                 : 
    1437                 : /************************************************************************/
    1438                 : /*                           GetSpatialRef()                            */
    1439                 : /************************************************************************/
    1440                 : 
    1441              64 : OGRSpatialReference *OGRVRTLayer::GetSpatialRef()
    1442                 : 
    1443                 : {
    1444              64 :     if (CPLGetXMLValue( psLTree, "LayerSRS", NULL ) != NULL)
    1445              28 :         return poSRS;
    1446                 : 
    1447              36 :     if (!bHasFullInitialized) FullInitialize();
    1448              36 :     if (!poSrcLayer) return NULL;
    1449                 : 
    1450              34 :     return poSRS;
    1451                 : }
    1452                 : 
    1453                 : /************************************************************************/
    1454                 : /*                              GetExtent()                             */
    1455                 : /************************************************************************/
    1456                 : 
    1457               8 : OGRErr OGRVRTLayer::GetExtent( OGREnvelope *psExtent, int bForce )
    1458                 : {
    1459               8 :     if (!bHasFullInitialized) FullInitialize();
    1460               8 :     if (!poSrcLayer) return OGRERR_FAILURE;
    1461                 : 
    1462               7 :     if ( eGeometryStyle == VGS_Direct &&
    1463                 :          m_poAttrQuery == NULL &&
    1464                 :          poSrcRegion == NULL )
    1465                 :     {
    1466               3 :         if( bNeedReset )
    1467               2 :             ResetSourceReading();
    1468                 : 
    1469               3 :         return poSrcLayer->GetExtent(psExtent, bForce);
    1470                 :     }
    1471                 : 
    1472               4 :     return OGRLayer::GetExtent(psExtent, bForce);
    1473                 : }
    1474                 : 
    1475                 : /************************************************************************/
    1476                 : /*                          GetFeatureCount()                           */
    1477                 : /************************************************************************/
    1478                 : 
    1479              30 : int OGRVRTLayer::GetFeatureCount( int bForce )
    1480                 : 
    1481                 : {
    1482              30 :     if (!bHasFullInitialized) FullInitialize();
    1483              30 :     if (!poSrcLayer) return 0;
    1484                 : 
    1485              29 :     if ((eGeometryStyle == VGS_Direct ||
    1486                 :          (poSrcRegion == NULL && m_poFilterGeom == NULL)) &&
    1487                 :          m_poAttrQuery == NULL )
    1488                 :     {
    1489              19 :         if( bNeedReset )
    1490              13 :             ResetSourceReading();
    1491                 : 
    1492              19 :         return poSrcLayer->GetFeatureCount( bForce );
    1493                 :     }
    1494                 :     else
    1495              10 :         return OGRLayer::GetFeatureCount( bForce );
    1496                 : }
    1497                 : 
    1498                 : 
    1499                 : /************************************************************************/
    1500                 : /*                          SetSpatialFilter()                          */
    1501                 : /************************************************************************/
    1502                 : 
    1503              31 : void OGRVRTLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
    1504                 : {
    1505              31 :     if (!bHasFullInitialized) FullInitialize();
    1506              31 :     if (!poSrcLayer) return;
    1507                 : 
    1508              30 :     if (eGeometryStyle == VGS_Direct)
    1509              19 :         bNeedReset = TRUE;
    1510              30 :     OGRLayer::SetSpatialFilter(poGeomIn);
    1511                 : }
    1512                 : 
    1513                 : /************************************************************************/
    1514                 : /*                             SyncToDisk()                             */
    1515                 : /************************************************************************/
    1516                 : 
    1517               2 : OGRErr OGRVRTLayer::SyncToDisk()
    1518                 : {
    1519               2 :     if (!bHasFullInitialized) FullInitialize();
    1520               2 :     if (!poSrcLayer) return OGRERR_FAILURE;
    1521                 : 
    1522               1 :     return poSrcLayer->SyncToDisk();
    1523                 : }
    1524                 : 
    1525                 : /************************************************************************/
    1526                 : /*                         createFromShapeBin()                         */
    1527                 : /*                                                                      */
    1528                 : /*      Translate shapefile binary representation to an OGR             */
    1529                 : /*      geometry.                                                       */
    1530                 : /************************************************************************/
    1531                 : 
    1532                 : #define SHPT_NULL 0
    1533                 : #define SHPT_POINT  1
    1534                 : #define SHPT_ARC  3
    1535                 : #define SHPT_POLYGON  5
    1536                 : #define SHPT_MULTIPOINT 8
    1537                 : #define SHPT_POINTZ 11
    1538                 : #define SHPT_ARCZ 13
    1539                 : #define SHPT_POLYGONZ 15
    1540                 : #define SHPT_MULTIPOINTZ 18
    1541                 : #define SHPT_POINTM 21
    1542                 : #define SHPT_ARCM 23
    1543                 : #define SHPT_POLYGONM 25
    1544                 : #define SHPT_MULTIPOINTM 28
    1545                 : #define SHPT_MULTIPATCH 31
    1546                 : 
    1547               0 : OGRErr OGRVRTLayer::createFromShapeBin( GByte *pabyShape, OGRGeometry **ppoGeom,
    1548                 :                                         int nBytes )
    1549                 : 
    1550                 : {
    1551               0 :     *ppoGeom = NULL;
    1552                 : 
    1553               0 :     if( nBytes < 1 )
    1554               0 :         return OGRERR_FAILURE;
    1555                 : 
    1556                 : //    printf( "%s\n", CPLBinaryToHex( nBytes, pabyShape ) );
    1557                 : 
    1558               0 :     int nSHPType = pabyShape[0];
    1559                 : 
    1560                 : /* ==================================================================== */
    1561                 : /*  Extract vertices for a Polygon or Arc.        */
    1562                 : /* ==================================================================== */
    1563               0 :     if( nSHPType == SHPT_POLYGON 
    1564                 :         || nSHPType == SHPT_ARC
    1565                 :         || nSHPType == SHPT_POLYGONZ
    1566                 :         || nSHPType == SHPT_POLYGONM
    1567                 :         || nSHPType == SHPT_ARCZ
    1568                 :         || nSHPType == SHPT_ARCM
    1569                 :         || nSHPType == SHPT_MULTIPATCH )
    1570                 :     {
    1571                 :   GInt32    nPoints, nParts;
    1572                 :   int       i, nOffset;
    1573                 :         GInt32         *panPartStart;
    1574                 : 
    1575                 : /* -------------------------------------------------------------------- */
    1576                 : /*      Extract part/point count, and build vertex and part arrays      */
    1577                 : /*      to proper size.                                                 */
    1578                 : /* -------------------------------------------------------------------- */
    1579               0 :   memcpy( &nPoints, pabyShape + 40, 4 );
    1580               0 :   memcpy( &nParts, pabyShape + 36, 4 );
    1581                 : 
    1582                 :   CPL_LSBPTR32( &nPoints );
    1583                 :   CPL_LSBPTR32( &nParts );
    1584                 : 
    1585               0 :         panPartStart = (GInt32 *) CPLCalloc(nParts,sizeof(GInt32));
    1586                 : 
    1587                 : /* -------------------------------------------------------------------- */
    1588                 : /*      Copy out the part array from the record.                        */
    1589                 : /* -------------------------------------------------------------------- */
    1590               0 :   memcpy( panPartStart, pabyShape + 44, 4 * nParts );
    1591               0 :   for( i = 0; i < nParts; i++ )
    1592                 :   {
    1593                 :             CPL_LSBPTR32( panPartStart + i );
    1594                 :   }
    1595                 : 
    1596               0 :   nOffset = 44 + 4*nParts;
    1597                 : 
    1598                 : /* -------------------------------------------------------------------- */
    1599                 : /*      If this is a multipatch, we will also have parts types.  For    */
    1600                 : /*      now we ignore and skip past them.                               */
    1601                 : /* -------------------------------------------------------------------- */
    1602               0 :         if( nSHPType == SHPT_MULTIPATCH )
    1603               0 :             nOffset += 4*nParts;
    1604                 :         
    1605                 : /* -------------------------------------------------------------------- */
    1606                 : /*      Copy out the vertices from the record.                          */
    1607                 : /* -------------------------------------------------------------------- */
    1608               0 :         double *padfX = (double *) CPLMalloc(sizeof(double)*nPoints);
    1609               0 :         double *padfY = (double *) CPLMalloc(sizeof(double)*nPoints);
    1610               0 :         double *padfZ = (double *) CPLCalloc(sizeof(double),nPoints);
    1611                 : 
    1612               0 :   for( i = 0; i < nPoints; i++ )
    1613                 :   {
    1614               0 :       memcpy(padfX + i, pabyShape + nOffset + i * 16, 8 );
    1615               0 :       memcpy(padfY + i, pabyShape + nOffset + i * 16 + 8, 8 );
    1616                 :             CPL_LSBPTR64( padfX + i );
    1617                 :             CPL_LSBPTR64( padfY + i );
    1618                 :   }
    1619                 : 
    1620               0 :         nOffset += 16*nPoints;
    1621                 :         
    1622                 : /* -------------------------------------------------------------------- */
    1623                 : /*      If we have a Z coordinate, collect that now.                    */
    1624                 : /* -------------------------------------------------------------------- */
    1625               0 :         if( nSHPType == SHPT_POLYGONZ
    1626                 :             || nSHPType == SHPT_ARCZ
    1627                 :             || nSHPType == SHPT_MULTIPATCH )
    1628                 :         {
    1629               0 :             for( i = 0; i < nPoints; i++ )
    1630                 :             {
    1631               0 :                 memcpy( padfZ + i, pabyShape + nOffset + 16 + i*8, 8 );
    1632                 :                 CPL_LSBPTR64( padfZ + i );
    1633                 :             }
    1634                 : 
    1635               0 :             nOffset += 16 + 8*nPoints;
    1636                 :         }
    1637                 : 
    1638                 : /* -------------------------------------------------------------------- */
    1639                 : /*      Build corresponding OGR objects.                                */
    1640                 : /* -------------------------------------------------------------------- */
    1641               0 :         if( nSHPType == SHPT_ARC 
    1642                 :             || nSHPType == SHPT_ARCZ
    1643                 :             || nSHPType == SHPT_ARCM )
    1644                 :         {
    1645                 : /* -------------------------------------------------------------------- */
    1646                 : /*      Arc - As LineString                                             */
    1647                 : /* -------------------------------------------------------------------- */
    1648               0 :             if( nParts == 1 )
    1649                 :             {
    1650               0 :                 OGRLineString *poLine = new OGRLineString();
    1651               0 :                 *ppoGeom = poLine;
    1652                 : 
    1653               0 :                 poLine->setPoints( nPoints, padfX, padfY, padfX );
    1654                 :             }
    1655                 : 
    1656                 : /* -------------------------------------------------------------------- */
    1657                 : /*      Arc - As MultiLineString                                        */
    1658                 : /* -------------------------------------------------------------------- */
    1659                 :             else
    1660                 :             {
    1661               0 :                 OGRMultiLineString *poMulti = new OGRMultiLineString;
    1662               0 :                 *ppoGeom = poMulti;
    1663                 : 
    1664               0 :                 for( i = 0; i < nParts; i++ )
    1665                 :                 {
    1666               0 :                     OGRLineString *poLine = new OGRLineString;
    1667                 :                     int nVerticesInThisPart;
    1668                 : 
    1669               0 :                     if( i == nParts-1 )
    1670               0 :                         nVerticesInThisPart = nPoints - panPartStart[i];
    1671                 :                     else
    1672                 :                         nVerticesInThisPart = 
    1673               0 :                             panPartStart[i+1] - panPartStart[i];
    1674                 : 
    1675                 :                     poLine->setPoints( nVerticesInThisPart, 
    1676               0 :                                        padfX + panPartStart[i], 
    1677               0 :                                        padfY + panPartStart[i], 
    1678               0 :                                        padfZ + panPartStart[i] );
    1679                 : 
    1680               0 :                     poMulti->addGeometryDirectly( poLine );
    1681                 :                 }
    1682                 :             }
    1683                 :         } /* ARC */
    1684                 : 
    1685                 : /* -------------------------------------------------------------------- */
    1686                 : /*      Polygon                                                         */
    1687                 : /* -------------------------------------------------------------------- */
    1688               0 :         else if( nSHPType == SHPT_POLYGON
    1689                 :                  || nSHPType == SHPT_POLYGONZ
    1690                 :                  || nSHPType == SHPT_POLYGONM )
    1691                 :         {
    1692               0 :             OGRPolygon *poMulti = new OGRPolygon;
    1693               0 :             *ppoGeom = poMulti;
    1694                 : 
    1695               0 :             for( i = 0; i < nParts; i++ )
    1696                 :             {
    1697               0 :                 OGRLinearRing *poRing = new OGRLinearRing;
    1698                 :                 int nVerticesInThisPart;
    1699                 : 
    1700               0 :                 if( i == nParts-1 )
    1701               0 :                     nVerticesInThisPart = nPoints - panPartStart[i];
    1702                 :                 else
    1703                 :                     nVerticesInThisPart = 
    1704               0 :                         panPartStart[i+1] - panPartStart[i];
    1705                 : 
    1706                 :                 poRing->setPoints( nVerticesInThisPart, 
    1707               0 :                                    padfX + panPartStart[i], 
    1708               0 :                                    padfY + panPartStart[i], 
    1709               0 :                                    padfZ + panPartStart[i] );
    1710                 : 
    1711               0 :                 poMulti->addRingDirectly( poRing );
    1712                 :             }
    1713                 :         } /* polygon */
    1714                 : 
    1715                 : /* -------------------------------------------------------------------- */
    1716                 : /*      Multipatch                                                      */
    1717                 : /* -------------------------------------------------------------------- */
    1718                 :         else if( nSHPType == SHPT_MULTIPATCH )
    1719                 :         {
    1720                 :             /* return to this later */
    1721                 :         } 
    1722                 : 
    1723               0 :         CPLFree( panPartStart );
    1724               0 :         CPLFree( padfX );
    1725               0 :         CPLFree( padfY );
    1726               0 :         CPLFree( padfZ );
    1727                 : 
    1728               0 :         if( nSHPType == SHPT_ARC
    1729                 :             || nSHPType == SHPT_POLYGON )
    1730               0 :             (*ppoGeom)->setCoordinateDimension( 2 );
    1731                 : 
    1732               0 :         return OGRERR_NONE;
    1733                 :     }
    1734                 : 
    1735                 : /* ==================================================================== */
    1736                 : /*  Extract vertices for a MultiPoint.          */
    1737                 : /* ==================================================================== */
    1738               0 :     else if( nSHPType == SHPT_MULTIPOINT
    1739                 :              || nSHPType == SHPT_MULTIPOINTM
    1740                 :              || nSHPType == SHPT_MULTIPOINTZ )
    1741                 :     {
    1742                 : #ifdef notdef
    1743                 :   int32   nPoints;
    1744                 :   int       i, nOffset;
    1745                 : 
    1746                 :   memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
    1747                 :   if( bBigEndian ) SwapWord( 4, &nPoints );
    1748                 : 
    1749                 :   psShape->nVertices = nPoints;
    1750                 :         psShape->padfX = (double *) calloc(nPoints,sizeof(double));
    1751                 :         psShape->padfY = (double *) calloc(nPoints,sizeof(double));
    1752                 :         psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
    1753                 :         psShape->padfM = (double *) calloc(nPoints,sizeof(double));
    1754                 : 
    1755                 :   for( i = 0; i < nPoints; i++ )
    1756                 :   {
    1757                 :       memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
    1758                 :       memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
    1759                 : 
    1760                 :       if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
    1761                 :       if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
    1762                 :   }
    1763                 : 
    1764                 :         nOffset = 48 + 16*nPoints;
    1765                 :         
    1766                 : /* -------------------------------------------------------------------- */
    1767                 : /*  Get the X/Y bounds.           */
    1768                 : /* -------------------------------------------------------------------- */
    1769                 :         memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 +  4, 8 );
    1770                 :         memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
    1771                 :         memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
    1772                 :         memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
    1773                 : 
    1774                 :   if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
    1775                 :   if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
    1776                 :   if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
    1777                 :   if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
    1778                 : 
    1779                 : /* -------------------------------------------------------------------- */
    1780                 : /*      If we have a Z coordinate, collect that now.                    */
    1781                 : /* -------------------------------------------------------------------- */
    1782                 :         if( psShape->nSHPType == SHPT_MULTIPOINTZ )
    1783                 :         {
    1784                 :             memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
    1785                 :             memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
    1786                 :             
    1787                 :             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
    1788                 :             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
    1789                 :             
    1790                 :             for( i = 0; i < nPoints; i++ )
    1791                 :             {
    1792                 :                 memcpy( psShape->padfZ + i,
    1793                 :                         psSHP->pabyRec + nOffset + 16 + i*8, 8 );
    1794                 :                 if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
    1795                 :             }
    1796                 : 
    1797                 :             nOffset += 16 + 8*nPoints;
    1798                 :         }
    1799                 : 
    1800                 : /* -------------------------------------------------------------------- */
    1801                 : /*      If we have a M measure value, then read it now.  We assume      */
    1802                 : /*      that the measure can be present for any shape if the size is    */
    1803                 : /*      big enough, but really it will only occur for the Z shapes      */
    1804                 : /*      (options), and the M shapes.                                    */
    1805                 : /* -------------------------------------------------------------------- */
    1806                 :         if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
    1807                 :         {
    1808                 :             memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
    1809                 :             memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
    1810                 :             
    1811                 :             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
    1812                 :             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
    1813                 :             
    1814                 :             for( i = 0; i < nPoints; i++ )
    1815                 :             {
    1816                 :                 memcpy( psShape->padfM + i,
    1817                 :                         psSHP->pabyRec + nOffset + 16 + i*8, 8 );
    1818                 :                 if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
    1819                 :             }
    1820                 :         }
    1821                 : #endif
    1822                 :     }
    1823                 : 
    1824                 : /* ==================================================================== */
    1825                 : /*      Extract vertices for a point.                                   */
    1826                 : /* ==================================================================== */
    1827               0 :     else if( nSHPType == SHPT_POINT
    1828                 :              || nSHPType == SHPT_POINTM
    1829                 :              || nSHPType == SHPT_POINTZ )
    1830                 :     {
    1831                 :         int nOffset;
    1832               0 :         double  dfX, dfY, dfZ = 0;
    1833                 :         
    1834               0 :   memcpy( &dfX, pabyShape + 4, 8 );
    1835               0 :   memcpy( &dfY, pabyShape + 4 + 8, 8 );
    1836                 : 
    1837                 :         CPL_LSBPTR64( &dfX );
    1838                 :         CPL_LSBPTR64( &dfY );
    1839               0 :         nOffset = 20 + 8;
    1840                 :         
    1841               0 :         if( nSHPType == SHPT_POINTZ )
    1842                 :         {
    1843               0 :             memcpy( &dfZ, pabyShape + 4 + 16, 8 );
    1844                 :             CPL_LSBPTR64( &dfY );
    1845                 :         }
    1846                 : 
    1847               0 :         *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
    1848                 : 
    1849               0 :         if( nSHPType != SHPT_POINTZ )
    1850               0 :             (*ppoGeom)->setCoordinateDimension( 2 );
    1851                 : 
    1852               0 :         return OGRERR_NONE;
    1853                 :     }
    1854                 : 
    1855               0 :     return OGRERR_FAILURE;
    1856                 : }
    1857                 : 
    1858                 : /************************************************************************/
    1859                 : /*                            GetLayerDefn()                            */
    1860                 : /************************************************************************/
    1861                 : 
    1862             146 : OGRFeatureDefn *OGRVRTLayer::GetLayerDefn()
    1863                 : {
    1864             146 :     if (!bHasFullInitialized) FullInitialize();
    1865                 : 
    1866             146 :     return poFeatureDefn;
    1867                 : }
    1868                 : 
    1869                 : /************************************************************************/
    1870                 : /*                             GetGeomType()                            */
    1871                 : /************************************************************************/
    1872                 : 
    1873               3 : OGRwkbGeometryType OGRVRTLayer::GetGeomType()
    1874                 : {
    1875               3 :     if (CPLGetXMLValue( psLTree, "GeometryType", NULL ) != NULL)
    1876               3 :         return eGeomType;
    1877                 : 
    1878               0 :     return GetLayerDefn()->GetGeomType();
    1879                 : }

Generated by: LCOV version 1.7