LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/vrt - ogrvrtlayer.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 585 384 65.6 %
Date: 2010-01-09 Functions: 21 16 76.2 %

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

Generated by: LCOV version 1.7