LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/pgeo - ogrpgeolayer.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 273
Code covered: 0.0 % Executed lines: 0

       1                 : /******************************************************************************
       2                 :  * $Id: ogrpgeolayer.cpp 19778 2010-05-27 20:44:52Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements OGRPGeoLayer class, code shared between 
       6                 :  *           the direct table access, and the generic SQL results.
       7                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
      11                 :  *
      12                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      13                 :  * copy of this software and associated documentation files (the "Software"),
      14                 :  * to deal in the Software without restriction, including without limitation
      15                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      16                 :  * and/or sell copies of the Software, and to permit persons to whom the
      17                 :  * Software is furnished to do so, subject to the following conditions:
      18                 :  *
      19                 :  * The above copyright notice and this permission notice shall be included
      20                 :  * in all copies or substantial portions of the Software.
      21                 :  *
      22                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      23                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      24                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      25                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      26                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      27                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      28                 :  * DEALINGS IN THE SOFTWARE.
      29                 :  ****************************************************************************/
      30                 : 
      31                 : #include "cpl_conv.h"
      32                 : #include "ogr_pgeo.h"
      33                 : #include "cpl_string.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ogrpgeolayer.cpp 19778 2010-05-27 20:44:52Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                            OGRPGeoLayer()                            */
      39                 : /************************************************************************/
      40                 : 
      41               0 : OGRPGeoLayer::OGRPGeoLayer()
      42                 : 
      43                 : {
      44               0 :     poDS = NULL;
      45                 : 
      46               0 :     pszGeomColumn = NULL;
      47               0 :     pszFIDColumn = NULL;
      48                 : 
      49               0 :     poStmt = NULL;
      50                 : 
      51               0 :     iNextShapeId = 0;
      52                 : 
      53               0 :     poSRS = NULL;
      54               0 :     nSRSId = -2; // we haven't even queried the database for it yet. 
      55               0 : }
      56                 : 
      57                 : /************************************************************************/
      58                 : /*                            ~OGRPGeoLayer()                             */
      59                 : /************************************************************************/
      60                 : 
      61               0 : OGRPGeoLayer::~OGRPGeoLayer()
      62                 : 
      63                 : {
      64               0 :     if( m_nFeaturesRead > 0 && poFeatureDefn != NULL )
      65                 :     {
      66                 :         CPLDebug( "PGeo", "%d features read on layer '%s'.",
      67                 :                   (int) m_nFeaturesRead, 
      68               0 :                   poFeatureDefn->GetName() );
      69                 :     }
      70                 : 
      71               0 :     if( poStmt != NULL )
      72                 :     {
      73               0 :         delete poStmt;
      74               0 :         poStmt = NULL;
      75                 :     }
      76                 : 
      77               0 :     if( poFeatureDefn != NULL )
      78                 :     {
      79               0 :         poFeatureDefn->Release();
      80               0 :         poFeatureDefn = NULL;
      81                 :     }
      82                 : 
      83               0 :     CPLFree( pszGeomColumn );
      84               0 :     CPLFree( panFieldOrdinals ); 
      85               0 :     CPLFree( pszFIDColumn );
      86                 : 
      87               0 :     if( poSRS != NULL )
      88                 :     {
      89               0 :         poSRS->Release();
      90               0 :         poSRS = NULL;
      91                 :     }
      92               0 : }
      93                 : 
      94                 : /************************************************************************/
      95                 : /*                          BuildFeatureDefn()                          */
      96                 : /*                                                                      */
      97                 : /*      Build feature definition from a set of column definitions       */
      98                 : /*      set on a statement.  Sift out geometry and FID fields.          */
      99                 : /************************************************************************/
     100                 : 
     101                 : CPLErr OGRPGeoLayer::BuildFeatureDefn( const char *pszLayerName, 
     102               0 :                                        CPLODBCStatement *poStmt )
     103                 : 
     104                 : {
     105               0 :     poFeatureDefn = new OGRFeatureDefn( pszLayerName );
     106               0 :     int    nRawColumns = poStmt->GetColCount();
     107                 : 
     108               0 :     poFeatureDefn->Reference();
     109                 : 
     110               0 :     panFieldOrdinals = (int *) CPLMalloc( sizeof(int) * nRawColumns );
     111                 : 
     112               0 :     for( int iCol = 0; iCol < nRawColumns; iCol++ )
     113                 :     {
     114               0 :         OGRFieldDefn    oField( poStmt->GetColName(iCol), OFTString );
     115                 : 
     116               0 :         oField.SetWidth( MAX(0,poStmt->GetColSize( iCol )) );
     117                 : 
     118               0 :         if( pszGeomColumn != NULL 
     119                 :             && EQUAL(poStmt->GetColName(iCol),pszGeomColumn) )
     120               0 :             continue;
     121                 : 
     122               0 :         if( pszFIDColumn == NULL 
     123                 :             && EQUAL(poStmt->GetColName(iCol),"OBJECTID") )
     124                 :         {
     125               0 :             pszFIDColumn = CPLStrdup(poStmt->GetColName(iCol));
     126                 :         }
     127                 : 
     128               0 :         if( pszGeomColumn == NULL 
     129                 :             && EQUAL(poStmt->GetColName(iCol),"Shape") )
     130                 :         {
     131               0 :             pszGeomColumn = CPLStrdup(poStmt->GetColName(iCol));
     132                 :             continue;
     133                 :         }
     134                 :         
     135               0 :         switch( poStmt->GetColType(iCol) )
     136                 :         {
     137                 :           case SQL_INTEGER:
     138                 :           case SQL_SMALLINT:
     139               0 :             oField.SetType( OFTInteger );
     140               0 :             break;
     141                 : 
     142                 :           case SQL_BINARY:
     143                 :           case SQL_VARBINARY:
     144                 :           case SQL_LONGVARBINARY:
     145               0 :             oField.SetType( OFTBinary );
     146               0 :             break;
     147                 : 
     148                 :           case SQL_DECIMAL:
     149               0 :             oField.SetType( OFTReal );
     150               0 :             oField.SetPrecision( poStmt->GetColPrecision(iCol) );
     151               0 :             break;
     152                 : 
     153                 :           case SQL_FLOAT:
     154                 :           case SQL_REAL:
     155                 :           case SQL_DOUBLE:
     156               0 :             oField.SetType( OFTReal );
     157               0 :             oField.SetWidth( 0 );
     158               0 :             break;
     159                 : 
     160                 :           case SQL_C_DATE:
     161               0 :             oField.SetType( OFTDate );
     162               0 :             break;
     163                 : 
     164                 :           case SQL_C_TIME:
     165               0 :             oField.SetType( OFTTime );
     166               0 :             break;
     167                 : 
     168                 :           case SQL_C_TIMESTAMP:
     169               0 :             oField.SetType( OFTDateTime );
     170                 :             break;
     171                 : 
     172                 :           default:
     173                 :             /* leave it as OFTString */;
     174                 :         }
     175                 : 
     176               0 :         poFeatureDefn->AddFieldDefn( &oField );
     177               0 :         panFieldOrdinals[poFeatureDefn->GetFieldCount() - 1] = iCol+1;
     178                 :     }
     179                 : 
     180               0 :     return CE_None;
     181                 : }
     182                 : 
     183                 : 
     184                 : /************************************************************************/
     185                 : /*                            ResetReading()                            */
     186                 : /************************************************************************/
     187                 : 
     188               0 : void OGRPGeoLayer::ResetReading()
     189                 : 
     190                 : {
     191               0 :     iNextShapeId = 0;
     192               0 : }
     193                 : 
     194                 : /************************************************************************/
     195                 : /*                           GetNextFeature()                           */
     196                 : /************************************************************************/
     197                 : 
     198               0 : OGRFeature *OGRPGeoLayer::GetNextFeature()
     199                 : 
     200                 : {
     201               0 :     for( ; TRUE; )
     202                 :     {
     203                 :         OGRFeature      *poFeature;
     204                 : 
     205               0 :         poFeature = GetNextRawFeature();
     206               0 :         if( poFeature == NULL )
     207               0 :             return NULL;
     208                 : 
     209               0 :         if( (m_poFilterGeom == NULL
     210                 :             || FilterGeometry( poFeature->GetGeometryRef() ) )
     211                 :             && (m_poAttrQuery == NULL
     212                 :                 || m_poAttrQuery->Evaluate( poFeature )) )
     213               0 :             return poFeature;
     214                 : 
     215               0 :         delete poFeature;
     216                 :     }
     217                 : }
     218                 : 
     219                 : /************************************************************************/
     220                 : /*                         GetNextRawFeature()                          */
     221                 : /************************************************************************/
     222                 : 
     223               0 : OGRFeature *OGRPGeoLayer::GetNextRawFeature()
     224                 : 
     225                 : {
     226               0 :     OGRErr err = OGRERR_NONE;
     227                 : 
     228               0 :     if( GetStatement() == NULL )
     229               0 :         return NULL;
     230                 : 
     231                 : /* -------------------------------------------------------------------- */
     232                 : /*      If we are marked to restart then do so, and fetch a record.     */
     233                 : /* -------------------------------------------------------------------- */
     234               0 :     if( !poStmt->Fetch() )
     235                 :     {
     236               0 :         delete poStmt;
     237               0 :         poStmt = NULL;
     238               0 :         return NULL;
     239                 :     }
     240                 : 
     241                 : /* -------------------------------------------------------------------- */
     242                 : /*      Create a feature from the current result.                       */
     243                 : /* -------------------------------------------------------------------- */
     244                 :     int         iField;
     245               0 :     OGRFeature *poFeature = new OGRFeature( poFeatureDefn );
     246                 : 
     247               0 :     if( pszFIDColumn != NULL && poStmt->GetColId(pszFIDColumn) > -1 )
     248                 :         poFeature->SetFID( 
     249               0 :             atoi(poStmt->GetColData(poStmt->GetColId(pszFIDColumn))) );
     250                 :     else
     251               0 :         poFeature->SetFID( iNextShapeId );
     252                 : 
     253               0 :     iNextShapeId++;
     254               0 :     m_nFeaturesRead++;
     255                 : 
     256                 : /* -------------------------------------------------------------------- */
     257                 : /*      Set the fields.                                                 */
     258                 : /* -------------------------------------------------------------------- */
     259               0 :     for( iField = 0; iField < poFeatureDefn->GetFieldCount(); iField++ )
     260                 :     {
     261               0 :         int iSrcField = panFieldOrdinals[iField]-1;
     262               0 :         const char *pszValue = poStmt->GetColData( iSrcField );
     263                 : 
     264               0 :         if( pszValue == NULL )
     265                 :             /* no value */;
     266               0 :         else if( poFeature->GetFieldDefnRef(iField)->GetType() == OFTBinary )
     267                 :             poFeature->SetField( iField, 
     268                 :                                  poStmt->GetColDataLength(iSrcField),
     269               0 :                                  (GByte *) pszValue );
     270                 :         else
     271               0 :             poFeature->SetField( iField, pszValue );
     272                 :     }
     273                 : 
     274                 : /* -------------------------------------------------------------------- */
     275                 : /*      Try to extract a geometry.                                      */
     276                 : /* -------------------------------------------------------------------- */
     277               0 :     if( pszGeomColumn != NULL )
     278                 :     {
     279               0 :         int iField = poStmt->GetColId( pszGeomColumn );
     280               0 :         GByte *pabyShape = (GByte *) poStmt->GetColData( iField );
     281               0 :         int nBytes = poStmt->GetColDataLength(iField);
     282               0 :         OGRGeometry *poGeom = NULL;
     283                 : 
     284               0 :         if( pabyShape != NULL )
     285                 :         {
     286               0 :             err = createFromShapeBin( pabyShape, &poGeom, nBytes );
     287               0 :             if( OGRERR_NONE != err )
     288                 :             {
     289                 :                 CPLDebug( "PGeo",
     290                 :                           "Translation shape binary to OGR geometry failed (FID=%ld)",
     291               0 :                            (long)poFeature->GetFID() );
     292                 :             }
     293                 :         }
     294                 : 
     295               0 :         if( poGeom != NULL && OGRERR_NONE == err )
     296                 :         {
     297               0 :             poGeom->assignSpatialReference( poSRS );
     298               0 :             poFeature->SetGeometryDirectly( poGeom );
     299                 :         }
     300                 :     }
     301                 : 
     302               0 :     return poFeature;
     303                 : }
     304                 : 
     305                 : /************************************************************************/
     306                 : /*                             GetFeature()                             */
     307                 : /************************************************************************/
     308                 : 
     309               0 : OGRFeature *OGRPGeoLayer::GetFeature( long nFeatureId )
     310                 : 
     311                 : {
     312                 :     /* This should be implemented directly! */
     313                 : 
     314               0 :     return OGRLayer::GetFeature( nFeatureId );
     315                 : }
     316                 : 
     317                 : /************************************************************************/
     318                 : /*                           TestCapability()                           */
     319                 : /************************************************************************/
     320                 : 
     321               0 : int OGRPGeoLayer::TestCapability( const char * pszCap )
     322                 : 
     323                 : {
     324               0 :     return FALSE;
     325                 : }
     326                 : 
     327                 : /************************************************************************/
     328                 : /*                           GetSpatialRef()                            */
     329                 : /************************************************************************/
     330                 : 
     331               0 : OGRSpatialReference *OGRPGeoLayer::GetSpatialRef()
     332                 : 
     333                 : {
     334               0 :     return poSRS;
     335                 : }
     336                 : 
     337                 : /************************************************************************/
     338                 : /*                           TestCapability()                           */
     339                 : /************************************************************************/
     340                 : 
     341               0 : void OGRPGeoLayer::LookupSRID( int nSRID )
     342                 : 
     343                 : {
     344                 : /* -------------------------------------------------------------------- */
     345                 : /*      Fetch the corresponding WKT from the SpatialRef table.          */
     346                 : /* -------------------------------------------------------------------- */
     347               0 :     CPLODBCStatement oStmt( poDS->GetSession() );
     348                 :         
     349                 :     oStmt.Appendf( "SELECT srtext FROM GDB_SpatialRefs WHERE srid = %d",
     350               0 :                   nSRID );
     351                 : 
     352               0 :     if( !oStmt.ExecuteSQL() )
     353                 :     {
     354                 :         CPLError( CE_Failure, CPLE_AppDefined,
     355                 :                   "'%s' failed.\n%s", 
     356                 :                   oStmt.GetCommand(),
     357               0 :                   poDS->GetSession()->GetLastError() );
     358               0 :         return;
     359                 :     }
     360                 : 
     361               0 :     if( !oStmt.Fetch() )
     362                 :     {
     363                 :         CPLError( CE_Warning, CPLE_AppDefined,
     364                 :                   "SRID %d lookup failed.\n%s", 
     365               0 :                   nSRID, poDS->GetSession()->GetLastError() );
     366                 :         return;
     367                 :     }
     368                 : 
     369                 : /* -------------------------------------------------------------------- */
     370                 : /*      Check that it isn't just a GUID.  We don't know how to          */
     371                 : /*      translate those.                                                */
     372                 : /* -------------------------------------------------------------------- */
     373               0 :     char *pszSRText = (char *) oStmt.GetColData(0);
     374                 : 
     375               0 :     if( pszSRText[0] == '{' )
     376                 :     {
     377               0 :         CPLDebug( "PGEO", "Ignoreing GUID SRTEXT: %s", pszSRText );
     378                 :         return;
     379                 :     }
     380                 : 
     381                 : /* -------------------------------------------------------------------- */
     382                 : /*      Turn it into an OGRSpatialReference.                            */
     383                 : /* -------------------------------------------------------------------- */
     384               0 :     poSRS = new OGRSpatialReference();
     385                 :     
     386               0 :     if( poSRS->importFromWkt( &pszSRText ) != OGRERR_NONE )
     387                 :     {
     388                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     389                 :                   "importFromWKT() failed on SRS '%s'.",
     390               0 :                   pszSRText);
     391               0 :         delete poSRS;
     392               0 :         poSRS = NULL;
     393                 :     }
     394               0 :     else if( poSRS->morphFromESRI() != OGRERR_NONE )
     395                 :     {
     396                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     397               0 :                   "morphFromESRI() failed on SRS." );
     398               0 :         delete poSRS;
     399               0 :         poSRS = NULL;
     400                 :     }
     401                 :     else
     402               0 :         nSRSId = nSRID;
     403                 : }
     404                 : 
     405                 : /************************************************************************/
     406                 : /*                         createFromShapeBin()                         */
     407                 : /*                                                                      */
     408                 : /*      Translate shapefile binary representation to an OGR             */
     409                 : /*      geometry.                                                       */
     410                 : /************************************************************************/
     411                 : 
     412                 : OGRErr OGRPGeoLayer::createFromShapeBin( GByte *pabyShape, 
     413                 :                                          OGRGeometry **ppoGeom,
     414               0 :                                          int nBytes )
     415                 : 
     416                 : {
     417               0 :     *ppoGeom = NULL;
     418                 : 
     419               0 :     if( nBytes < 1 )
     420               0 :         return OGRERR_FAILURE;
     421                 : 
     422               0 :     int nSHPType = pabyShape[0];
     423                 : 
     424                 : 
     425                 : //    CPLDebug( "PGeo", 
     426                 : //              "Shape type read from PGeo data is nSHPType = %d", 
     427                 : //              nSHPType );
     428                 : 
     429                 : /* -------------------------------------------------------------------- */
     430                 : /*      type 50 appears to just be an alias for normal line             */
     431                 : /*      strings. (#1484)                                                */
     432                 : /*      Type 51 appears to just be an alias for normal polygon. (#3100) */
     433                 : /*      TODO: These types include additional attributes including       */
     434                 : /*      non-linear segments and such. They should be handled.           */
     435                 : /* -------------------------------------------------------------------- */
     436               0 :     switch( nSHPType )
     437                 :     {
     438                 :       case 50:
     439               0 :         nSHPType = SHPT_ARC;
     440               0 :         break;
     441                 :       case 51:
     442               0 :         nSHPType = SHPT_POLYGON;
     443               0 :         break;
     444                 :       case 52:
     445               0 :         nSHPType = SHPT_POINT;
     446               0 :         break;
     447                 :       case 53:
     448               0 :         nSHPType = SHPT_MULTIPOINT;
     449               0 :         break;
     450                 :       case 54:
     451               0 :         nSHPType = SHPT_MULTIPATCH;
     452                 :     }
     453                 : 
     454                 : /* ==================================================================== */
     455                 : /*  Extract vertices for a Polygon or Arc.        */
     456                 : /* ==================================================================== */
     457               0 :     if(    nSHPType == SHPT_ARC
     458                 :         || nSHPType == SHPT_ARCZ
     459                 :         || nSHPType == SHPT_ARCM
     460                 :         || nSHPType == SHPT_ARCZM
     461                 :         || nSHPType == SHPT_POLYGON 
     462                 :         || nSHPType == SHPT_POLYGONZ
     463                 :         || nSHPType == SHPT_POLYGONM
     464                 :         || nSHPType == SHPT_POLYGONZM
     465                 :         || nSHPType == SHPT_MULTIPATCH 
     466                 :         || nSHPType == SHPT_MULTIPATCHM)
     467                 :     {
     468                 :         GInt32         nPoints, nParts;
     469                 :         int            i, nOffset;
     470                 :         GInt32         *panPartStart;
     471                 : 
     472               0 :         if (nBytes < 44)
     473                 :         {
     474                 :             CPLError(CE_Failure, CPLE_AppDefined,
     475               0 :                      "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
     476               0 :             return OGRERR_FAILURE;
     477                 :         }
     478                 : 
     479                 : /* -------------------------------------------------------------------- */
     480                 : /*      Extract part/point count, and build vertex and part arrays      */
     481                 : /*      to proper size.                                                 */
     482                 : /* -------------------------------------------------------------------- */
     483               0 :   memcpy( &nPoints, pabyShape + 40, 4 );
     484               0 :   memcpy( &nParts, pabyShape + 36, 4 );
     485                 : 
     486                 :   CPL_LSBPTR32( &nPoints );
     487                 :   CPL_LSBPTR32( &nParts );
     488                 : 
     489               0 :         if (nPoints < 0 || nParts < 0 ||
     490                 :             nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
     491                 :         {
     492                 :             CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d, nParts=%d.",
     493               0 :                      nPoints, nParts);
     494               0 :             return OGRERR_FAILURE;
     495                 :         }
     496                 : 
     497                 :         int bHasZ = (  nSHPType == SHPT_POLYGONZ
     498                 :                     || nSHPType == SHPT_POLYGONZM
     499                 :                     || nSHPType == SHPT_ARCZ
     500                 :                     || nSHPType == SHPT_ARCZM
     501                 :                     || nSHPType == SHPT_MULTIPATCH 
     502               0 :                     || nSHPType == SHPT_MULTIPATCHM );
     503                 : 
     504               0 :         int bIsMultiPatch = ( nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM );
     505                 : 
     506                 :         /* With the previous checks on nPoints and nParts, */
     507                 :         /* we should not overflow here and after */
     508                 :         /* since 50 M * (16 + 8 + 8) = 1 600 MB */
     509               0 :         int nRequiredSize = 44 + 4 * nParts + 16 * nPoints;
     510               0 :         if ( bHasZ )
     511                 :         {
     512               0 :             nRequiredSize += 16 + 8 * nPoints;
     513                 :         }
     514               0 :         if( bIsMultiPatch )
     515                 :         {
     516               0 :             nRequiredSize += 4 * nParts;
     517                 :         }
     518               0 :         if (nRequiredSize > nBytes)
     519                 :         {
     520                 :             CPLError(CE_Failure, CPLE_AppDefined,
     521                 :                      "Corrupted Shape : nPoints=%d, nParts=%d, nBytes=%d, nSHPType=%d",
     522               0 :                      nPoints, nParts, nBytes, nSHPType);
     523               0 :             return OGRERR_FAILURE;
     524                 :         }
     525                 : 
     526               0 :         panPartStart = (GInt32 *) VSICalloc(nParts,sizeof(GInt32));
     527               0 :         if (panPartStart == NULL)
     528                 :         {
     529                 :             CPLError(CE_Failure, CPLE_OutOfMemory,
     530               0 :                      "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
     531               0 :             return OGRERR_FAILURE;
     532                 :         }
     533                 : 
     534                 : /* -------------------------------------------------------------------- */
     535                 : /*      Copy out the part array from the record.                        */
     536                 : /* -------------------------------------------------------------------- */
     537               0 :   memcpy( panPartStart, pabyShape + 44, 4 * nParts );
     538               0 :   for( i = 0; i < nParts; i++ )
     539                 :   {
     540                 :             CPL_LSBPTR32( panPartStart + i );
     541                 : 
     542                 :             /* We check that the offset is inside the vertex array */
     543               0 :             if (panPartStart[i] < 0 ||
     544                 :                 panPartStart[i] >= nPoints)
     545                 :             {
     546                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     547                 :                          "Corrupted Shape : panPartStart[%d] = %d, nPoints = %d",
     548               0 :                          i, panPartStart[i], nPoints); 
     549               0 :                 CPLFree(panPartStart);
     550               0 :                 return OGRERR_FAILURE;
     551                 :             }
     552               0 :             if (i > 0 && panPartStart[i] <= panPartStart[i-1])
     553                 :             {
     554                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     555                 :                          "Corrupted Shape : panPartStart[%d] = %d, panPartStart[%d] = %d",
     556               0 :                          i, panPartStart[i], i - 1, panPartStart[i - 1]); 
     557               0 :                 CPLFree(panPartStart);
     558               0 :                 return OGRERR_FAILURE;
     559                 :             }
     560                 :   }
     561                 : 
     562               0 :   nOffset = 44 + 4*nParts;
     563                 : 
     564                 : /* -------------------------------------------------------------------- */
     565                 : /*      If this is a multipatch, we will also have parts types.  For    */
     566                 : /*      now we ignore and skip past them.                               */
     567                 : /* -------------------------------------------------------------------- */
     568               0 :         if( bIsMultiPatch )
     569               0 :             nOffset += 4*nParts;
     570                 :         
     571                 : /* -------------------------------------------------------------------- */
     572                 : /*      Copy out the vertices from the record.                          */
     573                 : /* -------------------------------------------------------------------- */
     574               0 :         double *padfX = (double *) VSIMalloc(sizeof(double)*nPoints);
     575               0 :         double *padfY = (double *) VSIMalloc(sizeof(double)*nPoints);
     576               0 :         double *padfZ = (double *) VSICalloc(sizeof(double),nPoints);
     577               0 :         if (padfX == NULL || padfY == NULL || padfZ == NULL)
     578                 :         {
     579               0 :             CPLFree( panPartStart );
     580               0 :             CPLFree( padfX );
     581               0 :             CPLFree( padfY );
     582               0 :             CPLFree( padfZ );
     583                 :             CPLError(CE_Failure, CPLE_OutOfMemory,
     584               0 :                      "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
     585               0 :             return OGRERR_FAILURE;
     586                 :         }
     587                 : 
     588               0 :   for( i = 0; i < nPoints; i++ )
     589                 :   {
     590               0 :       memcpy(padfX + i, pabyShape + nOffset + i * 16, 8 );
     591               0 :       memcpy(padfY + i, pabyShape + nOffset + i * 16 + 8, 8 );
     592                 :             CPL_LSBPTR64( padfX + i );
     593                 :             CPL_LSBPTR64( padfY + i );
     594                 :   }
     595                 : 
     596               0 :         nOffset += 16*nPoints;
     597                 :         
     598                 : /* -------------------------------------------------------------------- */
     599                 : /*      If we have a Z coordinate, collect that now.                    */
     600                 : /* -------------------------------------------------------------------- */
     601               0 :         if( bHasZ )
     602                 :         {
     603               0 :             for( i = 0; i < nPoints; i++ )
     604                 :             {
     605               0 :                 memcpy( padfZ + i, pabyShape + nOffset + 16 + i*8, 8 );
     606                 :                 CPL_LSBPTR64( padfZ + i );
     607                 :             }
     608                 : 
     609               0 :             nOffset += 16 + 8*nPoints;
     610                 :         }
     611                 : 
     612                 : /* -------------------------------------------------------------------- */
     613                 : /*      Build corresponding OGR objects.                                */
     614                 : /* -------------------------------------------------------------------- */
     615               0 :         if(    nSHPType == SHPT_ARC 
     616                 :             || nSHPType == SHPT_ARCZ
     617                 :             || nSHPType == SHPT_ARCM
     618                 :             || nSHPType == SHPT_ARCZM )
     619                 :         {
     620                 : /* -------------------------------------------------------------------- */
     621                 : /*      Arc - As LineString                                             */
     622                 : /* -------------------------------------------------------------------- */
     623               0 :             if( nParts == 1 )
     624                 :             {
     625               0 :                 OGRLineString *poLine = new OGRLineString();
     626               0 :                 *ppoGeom = poLine;
     627                 : 
     628               0 :                 poLine->setPoints( nPoints, padfX, padfY, padfZ );
     629                 :             }
     630                 : 
     631                 : /* -------------------------------------------------------------------- */
     632                 : /*      Arc - As MultiLineString                                        */
     633                 : /* -------------------------------------------------------------------- */
     634                 :             else
     635                 :             {
     636               0 :                 OGRMultiLineString *poMulti = new OGRMultiLineString;
     637               0 :                 *ppoGeom = poMulti;
     638                 : 
     639               0 :                 for( i = 0; i < nParts; i++ )
     640                 :                 {
     641               0 :                     OGRLineString *poLine = new OGRLineString;
     642                 :                     int nVerticesInThisPart;
     643                 : 
     644               0 :                     if( i == nParts-1 )
     645               0 :                         nVerticesInThisPart = nPoints - panPartStart[i];
     646                 :                     else
     647                 :                         nVerticesInThisPart = 
     648               0 :                             panPartStart[i+1] - panPartStart[i];
     649                 : 
     650                 :                     poLine->setPoints( nVerticesInThisPart, 
     651                 :                                        padfX + panPartStart[i], 
     652                 :                                        padfY + panPartStart[i], 
     653               0 :                                        padfZ + panPartStart[i] );
     654                 : 
     655               0 :                     poMulti->addGeometryDirectly( poLine );
     656                 :                 }
     657                 :             }
     658                 :         } /* ARC */
     659                 : 
     660                 : /* -------------------------------------------------------------------- */
     661                 : /*      Polygon                                                         */
     662                 : /* -------------------------------------------------------------------- */
     663               0 :         else if(    nSHPType == SHPT_POLYGON
     664                 :                  || nSHPType == SHPT_POLYGONZ
     665                 :                  || nSHPType == SHPT_POLYGONM
     666                 :                  || nSHPType == SHPT_POLYGONZM )
     667                 :         {
     668               0 :             if (nParts != 0)
     669                 :             {
     670               0 :                 if (nParts == 1)
     671                 :                 {
     672               0 :                     OGRPolygon *poOGRPoly = new OGRPolygon;
     673               0 :                     *ppoGeom = poOGRPoly;
     674               0 :                     OGRLinearRing *poRing = new OGRLinearRing;
     675               0 :                     int nVerticesInThisPart = nPoints - panPartStart[0];
     676                 :                     
     677                 :                     poRing->setPoints( nVerticesInThisPart, 
     678                 :                                        padfX + panPartStart[0], 
     679                 :                                        padfY + panPartStart[0], 
     680               0 :                                        padfZ + panPartStart[0] );
     681                 :                     
     682               0 :                     poOGRPoly->addRingDirectly( poRing );
     683                 :                 }
     684                 :                 else 
     685                 :                 {
     686               0 :                     OGRGeometry *poOGR = NULL;
     687               0 :                     OGRPolygon** tabPolygons = new OGRPolygon*[nParts];
     688                 :                
     689               0 :                     for( i = 0; i < nParts; i++ )
     690                 :                     {
     691               0 :                         tabPolygons[i] = new OGRPolygon();
     692               0 :                         OGRLinearRing *poRing = new OGRLinearRing;
     693                 :                         int nVerticesInThisPart;
     694                 :                         
     695               0 :                         if( i == nParts-1 )
     696               0 :                             nVerticesInThisPart = nPoints - panPartStart[i];
     697                 :                         else
     698                 :                             nVerticesInThisPart = 
     699               0 :                                 panPartStart[i+1] - panPartStart[i];
     700                 :                         
     701                 :                         poRing->setPoints( nVerticesInThisPart, 
     702                 :                                            padfX + panPartStart[i], 
     703                 :                                            padfY + panPartStart[i], 
     704               0 :                                            padfZ + panPartStart[i] );
     705               0 :                         tabPolygons[i]->addRingDirectly(poRing);
     706                 :                     }
     707                 : 
     708                 :                     int isValidGeometry;
     709               0 :                     const char* papszOptions[] = { "METHOD=ONLY_CCW", NULL };
     710                 :                     poOGR = OGRGeometryFactory::organizePolygons( 
     711               0 :                         (OGRGeometry**)tabPolygons, nParts, &isValidGeometry, papszOptions );
     712                 : 
     713               0 :                     if (!isValidGeometry)
     714                 :                     {
     715                 :                         CPLError(CE_Warning, CPLE_AppDefined,
     716                 :                                  "Geometry of polygon cannot be translated to Simple Geometry. "
     717               0 :                                  "All polygons will be contained in a multipolygon.\n");
     718                 :                     }
     719                 : 
     720               0 :                     *ppoGeom = poOGR;
     721               0 :                     delete[] tabPolygons;
     722                 :                 }
     723                 :             }
     724                 :         } /* polygon */
     725                 : 
     726                 : /* -------------------------------------------------------------------- */
     727                 : /*      Multipatch                                                      */
     728                 : /* -------------------------------------------------------------------- */
     729                 :         else if( bIsMultiPatch )
     730                 :         {
     731                 :             /* return to this later */
     732                 :         } 
     733                 : 
     734               0 :         CPLFree( panPartStart );
     735               0 :         CPLFree( padfX );
     736               0 :         CPLFree( padfY );
     737               0 :         CPLFree( padfZ );
     738                 : 
     739               0 :         if( !bHasZ )
     740               0 :             (*ppoGeom)->setCoordinateDimension( 2 );
     741                 : 
     742               0 :         return OGRERR_NONE;
     743                 :     }
     744                 : 
     745                 : /* ==================================================================== */
     746                 : /*  Extract vertices for a MultiPoint.          */
     747                 : /* ==================================================================== */
     748               0 :     else if(    nSHPType == SHPT_MULTIPOINT
     749                 :              || nSHPType == SHPT_MULTIPOINTM
     750                 :              || nSHPType == SHPT_MULTIPOINTZ
     751                 :              || nSHPType == SHPT_MULTIPOINTZM )
     752                 :     {
     753                 : #ifdef notdef
     754                 :   int32   nPoints;
     755                 :   int       i, nOffset;
     756                 : 
     757                 :   memcpy( &nPoints, psSHP->pabyRec + 44, 4 );
     758                 :   if( bBigEndian ) SwapWord( 4, &nPoints );
     759                 : 
     760                 :   psShape->nVertices = nPoints;
     761                 :         psShape->padfX = (double *) calloc(nPoints,sizeof(double));
     762                 :         psShape->padfY = (double *) calloc(nPoints,sizeof(double));
     763                 :         psShape->padfZ = (double *) calloc(nPoints,sizeof(double));
     764                 :         psShape->padfM = (double *) calloc(nPoints,sizeof(double));
     765                 : 
     766                 :   for( i = 0; i < nPoints; i++ )
     767                 :   {
     768                 :       memcpy(psShape->padfX+i, psSHP->pabyRec + 48 + 16 * i, 8 );
     769                 :       memcpy(psShape->padfY+i, psSHP->pabyRec + 48 + 16 * i + 8, 8 );
     770                 : 
     771                 :       if( bBigEndian ) SwapWord( 8, psShape->padfX + i );
     772                 :       if( bBigEndian ) SwapWord( 8, psShape->padfY + i );
     773                 :   }
     774                 : 
     775                 :         nOffset = 48 + 16*nPoints;
     776                 :         
     777                 : /* -------------------------------------------------------------------- */
     778                 : /*  Get the X/Y bounds.           */
     779                 : /* -------------------------------------------------------------------- */
     780                 :         memcpy( &(psShape->dfXMin), psSHP->pabyRec + 8 +  4, 8 );
     781                 :         memcpy( &(psShape->dfYMin), psSHP->pabyRec + 8 + 12, 8 );
     782                 :         memcpy( &(psShape->dfXMax), psSHP->pabyRec + 8 + 20, 8 );
     783                 :         memcpy( &(psShape->dfYMax), psSHP->pabyRec + 8 + 28, 8 );
     784                 : 
     785                 :   if( bBigEndian ) SwapWord( 8, &(psShape->dfXMin) );
     786                 :   if( bBigEndian ) SwapWord( 8, &(psShape->dfYMin) );
     787                 :   if( bBigEndian ) SwapWord( 8, &(psShape->dfXMax) );
     788                 :   if( bBigEndian ) SwapWord( 8, &(psShape->dfYMax) );
     789                 : 
     790                 : /* -------------------------------------------------------------------- */
     791                 : /*      If we have a Z coordinate, collect that now.                    */
     792                 : /* -------------------------------------------------------------------- */
     793                 :         if( psShape->nSHPType == SHPT_MULTIPOINTZ || psShape->nSHPType == SHPT_MULTIPOINTZM )
     794                 :         {
     795                 :             memcpy( &(psShape->dfZMin), psSHP->pabyRec + nOffset, 8 );
     796                 :             memcpy( &(psShape->dfZMax), psSHP->pabyRec + nOffset + 8, 8 );
     797                 :             
     798                 :             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMin) );
     799                 :             if( bBigEndian ) SwapWord( 8, &(psShape->dfZMax) );
     800                 :             
     801                 :             for( i = 0; i < nPoints; i++ )
     802                 :             {
     803                 :                 memcpy( psShape->padfZ + i,
     804                 :                         psSHP->pabyRec + nOffset + 16 + i*8, 8 );
     805                 :                 if( bBigEndian ) SwapWord( 8, psShape->padfZ + i );
     806                 :             }
     807                 : 
     808                 :             nOffset += 16 + 8*nPoints;
     809                 :         }
     810                 : 
     811                 : /* -------------------------------------------------------------------- */
     812                 : /*      If we have a M measure value, then read it now.  We assume      */
     813                 : /*      that the measure can be present for any shape if the size is    */
     814                 : /*      big enough, but really it will only occur for the Z shapes      */
     815                 : /*      (options), and the M shapes.                                    */
     816                 : /* -------------------------------------------------------------------- */
     817                 :         if( psSHP->panRecSize[hEntity]+8 >= nOffset + 16 + 8*nPoints )
     818                 :         {
     819                 :             memcpy( &(psShape->dfMMin), psSHP->pabyRec + nOffset, 8 );
     820                 :             memcpy( &(psShape->dfMMax), psSHP->pabyRec + nOffset + 8, 8 );
     821                 :             
     822                 :             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMin) );
     823                 :             if( bBigEndian ) SwapWord( 8, &(psShape->dfMMax) );
     824                 :             
     825                 :             for( i = 0; i < nPoints; i++ )
     826                 :             {
     827                 :                 memcpy( psShape->padfM + i,
     828                 :                         psSHP->pabyRec + nOffset + 16 + i*8, 8 );
     829                 :                 if( bBigEndian ) SwapWord( 8, psShape->padfM + i );
     830                 :             }
     831                 :         }
     832                 : #endif
     833                 :     }
     834                 : 
     835                 : /* ==================================================================== */
     836                 : /*      Extract vertices for a point.                                   */
     837                 : /* ==================================================================== */
     838               0 :     else if(    nSHPType == SHPT_POINT
     839                 :              || nSHPType == SHPT_POINTM
     840                 :              || nSHPType == SHPT_POINTZ
     841                 :              || nSHPType == SHPT_POINTZM )
     842                 :     {
     843                 :         int nOffset;
     844               0 :         double  dfX, dfY, dfZ = 0;
     845                 : 
     846               0 :         int bHasZ = (nSHPType == SHPT_POINTZ || nSHPType == SHPT_POINTZM);
     847                 : 
     848               0 :         if (nBytes < 4 + 8 + 8 + ((nSHPType == SHPT_POINTZ) ? 8 : 0))
     849                 :         {
     850                 :             CPLError(CE_Failure, CPLE_AppDefined,
     851               0 :                      "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
     852               0 :             return OGRERR_FAILURE;
     853                 :         }
     854                 :         
     855               0 :   memcpy( &dfX, pabyShape + 4, 8 );
     856               0 :   memcpy( &dfY, pabyShape + 4 + 8, 8 );
     857                 : 
     858                 :         CPL_LSBPTR64( &dfX );
     859                 :         CPL_LSBPTR64( &dfY );
     860               0 :         nOffset = 20 + 8;
     861                 :         
     862               0 :         if( bHasZ )
     863                 :         {
     864               0 :             memcpy( &dfZ, pabyShape + 4 + 16, 8 );
     865                 :             CPL_LSBPTR64( &dfZ );
     866                 :         }
     867                 : 
     868               0 :         *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
     869                 : 
     870               0 :         if( !bHasZ )
     871               0 :             (*ppoGeom)->setCoordinateDimension( 2 );
     872                 : 
     873               0 :         return OGRERR_NONE;
     874                 :     }
     875                 : 
     876               0 :     char* pszHex = CPLBinaryToHex( nBytes, pabyShape );
     877                 :     CPLDebug( "PGEO", "Unsupported geometry type:%d\nnBytes=%d, hex=%s",
     878               0 :               nSHPType, nBytes, pszHex );
     879               0 :     CPLFree(pszHex);
     880                 : 
     881               0 :     return OGRERR_FAILURE;
     882                 : }
     883                 : 
     884                 : /************************************************************************/
     885                 : /*                            GetFIDColumn()                            */
     886                 : /************************************************************************/
     887                 : 
     888               0 : const char *OGRPGeoLayer::GetFIDColumn() 
     889                 : 
     890                 : {
     891               0 :     if( pszFIDColumn != NULL )
     892               0 :         return pszFIDColumn;
     893                 :     else
     894               0 :         return "";
     895                 : }
     896                 : 
     897                 : /************************************************************************/
     898                 : /*                         GetGeometryColumn()                          */
     899                 : /************************************************************************/
     900                 : 
     901               0 : const char *OGRPGeoLayer::GetGeometryColumn() 
     902                 : 
     903                 : {
     904               0 :     if( pszGeomColumn != NULL )
     905               0 :         return pszGeomColumn;
     906                 :     else
     907               0 :         return "";
     908                 : }

Generated by: LTP GCOV extension version 1.5