LCOV - code coverage report
Current view: directory - ogr - ogrpgeogeometry.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 520 323 62.1 %
Date: 2013-03-30 Functions: 3 2 66.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrpgeogeometry.cpp 25499 2013-01-13 22:07:12Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements decoder of shapebin geometry for PGeo
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *           Paul Ramsey, pramsey at cleverelephant.ca
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 2005, Frank Warmerdam <warmerdam@pobox.com>
      11                 :  * Copyright (c) 2011, Paul Ramsey <pramsey at cleverelephant.ca>
      12                 :  *
      13                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      14                 :  * copy of this software and associated documentation files (the "Software"),
      15                 :  * to deal in the Software without restriction, including without limitation
      16                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      17                 :  * and/or sell copies of the Software, and to permit persons to whom the
      18                 :  * Software is furnished to do so, subject to the following conditions:
      19                 :  *
      20                 :  * The above copyright notice and this permission notice shall be included
      21                 :  * in all copies or substantial portions of the Software.
      22                 :  *
      23                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      24                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      25                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      26                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      27                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      28                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      29                 :  * DEALINGS IN THE SOFTWARE.
      30                 :  ****************************************************************************/
      31                 : 
      32                 : #include "ogrpgeogeometry.h"
      33                 : #include "ogr_p.h"
      34                 : #include "cpl_string.h"
      35                 : 
      36                 : CPL_CVSID("$Id: ogrpgeogeometry.cpp 25499 2013-01-13 22:07:12Z rouault $");
      37                 : 
      38                 : #define SHPP_TRISTRIP   0
      39                 : #define SHPP_TRIFAN     1
      40                 : #define SHPP_OUTERRING  2
      41                 : #define SHPP_INNERRING  3
      42                 : #define SHPP_FIRSTRING  4
      43                 : #define SHPP_RING       5
      44                 : #define SHPP_TRIANGLES  6 /* Multipatch 9.0 specific */
      45                 : 
      46                 : 
      47                 : /************************************************************************/
      48                 : /*                     OGRCreateFromMultiPatch()                        */
      49                 : /*                                                                      */
      50                 : /*      Translate a multipatch representation to an OGR geometry        */
      51                 : /*      Mostly copied from shape2ogr.cpp                                */
      52                 : /************************************************************************/
      53                 : 
      54               0 : static OGRGeometry* OGRCreateFromMultiPatch(int nParts,
      55                 :                                             GInt32* panPartStart,
      56                 :                                             GInt32* panPartType,
      57                 :                                             int nPoints,
      58                 :                                             double* padfX,
      59                 :                                             double* padfY,
      60                 :                                             double* padfZ)
      61                 : {
      62               0 :     OGRMultiPolygon *poMP = new OGRMultiPolygon();
      63                 :     int iPart;
      64               0 :     OGRPolygon *poLastPoly = NULL;
      65                 : 
      66               0 :     for( iPart = 0; iPart < nParts; iPart++ )
      67                 :     {
      68                 :         int nPartPoints, nPartStart;
      69                 : 
      70                 :         // Figure out details about this part's vertex list.
      71               0 :         if( panPartStart == NULL )
      72                 :         {
      73               0 :             nPartPoints = nPoints;
      74               0 :             nPartStart = 0;
      75                 :         }
      76                 :         else
      77                 :         {
      78                 : 
      79               0 :             if( iPart == nParts - 1 )
      80                 :                 nPartPoints =
      81               0 :                     nPoints - panPartStart[iPart];
      82                 :             else
      83               0 :                 nPartPoints = panPartStart[iPart+1]
      84               0 :                     - panPartStart[iPart];
      85               0 :             nPartStart = panPartStart[iPart];
      86                 :         }
      87                 : 
      88               0 :         panPartType[iPart] &= 0xf;
      89                 : 
      90               0 :         if( panPartType[iPart] == SHPP_TRISTRIP )
      91                 :         {
      92                 :             int iBaseVert;
      93                 : 
      94               0 :             if( poLastPoly != NULL )
      95                 :             {
      96               0 :                 poMP->addGeometryDirectly( poLastPoly );
      97               0 :                 poLastPoly = NULL;
      98                 :             }
      99                 : 
     100               0 :             for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
     101                 :             {
     102               0 :                 OGRPolygon *poPoly = new OGRPolygon();
     103               0 :                 OGRLinearRing *poRing = new OGRLinearRing();
     104               0 :                 int iSrcVert = iBaseVert + nPartStart;
     105                 : 
     106                 :                 poRing->setPoint( 0,
     107                 :                                 padfX[iSrcVert],
     108                 :                                 padfY[iSrcVert],
     109               0 :                                 padfZ[iSrcVert] );
     110                 :                 poRing->setPoint( 1,
     111                 :                                 padfX[iSrcVert+1],
     112                 :                                 padfY[iSrcVert+1],
     113               0 :                                 padfZ[iSrcVert+1] );
     114                 : 
     115                 :                 poRing->setPoint( 2,
     116                 :                                 padfX[iSrcVert+2],
     117                 :                                 padfY[iSrcVert+2],
     118               0 :                                 padfZ[iSrcVert+2] );
     119                 :                 poRing->setPoint( 3,
     120                 :                                 padfX[iSrcVert],
     121                 :                                 padfY[iSrcVert],
     122               0 :                                 padfZ[iSrcVert] );
     123                 : 
     124               0 :                 poPoly->addRingDirectly( poRing );
     125               0 :                 poMP->addGeometryDirectly( poPoly );
     126                 :             }
     127                 :         }
     128               0 :         else if( panPartType[iPart] == SHPP_TRIFAN )
     129                 :         {
     130                 :             int iBaseVert;
     131                 : 
     132               0 :             if( poLastPoly != NULL )
     133                 :             {
     134               0 :                 poMP->addGeometryDirectly( poLastPoly );
     135               0 :                 poLastPoly = NULL;
     136                 :             }
     137                 : 
     138               0 :             for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
     139                 :             {
     140               0 :                 OGRPolygon *poPoly = new OGRPolygon();
     141               0 :                 OGRLinearRing *poRing = new OGRLinearRing();
     142               0 :                 int iSrcVert = iBaseVert + nPartStart;
     143                 : 
     144                 :                 poRing->setPoint( 0,
     145                 :                                 padfX[nPartStart],
     146                 :                                 padfY[nPartStart],
     147               0 :                                 padfZ[nPartStart] );
     148                 :                 poRing->setPoint( 1,
     149                 :                                 padfX[iSrcVert+1],
     150                 :                                 padfY[iSrcVert+1],
     151               0 :                                 padfZ[iSrcVert+1] );
     152                 : 
     153                 :                 poRing->setPoint( 2,
     154                 :                                 padfX[iSrcVert+2],
     155                 :                                 padfY[iSrcVert+2],
     156               0 :                                 padfZ[iSrcVert+2] );
     157                 :                 poRing->setPoint( 3,
     158                 :                                 padfX[nPartStart],
     159                 :                                 padfY[nPartStart],
     160               0 :                                 padfZ[nPartStart] );
     161                 : 
     162               0 :                 poPoly->addRingDirectly( poRing );
     163               0 :                 poMP->addGeometryDirectly( poPoly );
     164                 :             }
     165                 :         }
     166               0 :         else if( panPartType[iPart] == SHPP_OUTERRING
     167               0 :                 || panPartType[iPart] == SHPP_INNERRING
     168               0 :                 || panPartType[iPart] == SHPP_FIRSTRING
     169               0 :                 || panPartType[iPart] == SHPP_RING )
     170                 :         {
     171               0 :             if( poLastPoly != NULL
     172               0 :                 && (panPartType[iPart] == SHPP_OUTERRING
     173               0 :                     || panPartType[iPart] == SHPP_FIRSTRING) )
     174                 :             {
     175               0 :                 poMP->addGeometryDirectly( poLastPoly );
     176               0 :                 poLastPoly = NULL;
     177                 :             }
     178                 : 
     179               0 :             if( poLastPoly == NULL )
     180               0 :                 poLastPoly = new OGRPolygon();
     181                 : 
     182               0 :             OGRLinearRing *poRing = new OGRLinearRing;
     183                 : 
     184                 :             poRing->setPoints( nPartPoints,
     185                 :                                 padfX + nPartStart,
     186                 :                                 padfY + nPartStart,
     187               0 :                                 padfZ + nPartStart );
     188                 : 
     189               0 :             poRing->closeRings();
     190                 : 
     191               0 :             poLastPoly->addRingDirectly( poRing );
     192                 :         }
     193               0 :         else if ( panPartType[iPart] == SHPP_TRIANGLES )
     194                 :         {
     195                 :             int iBaseVert;
     196                 : 
     197               0 :             if( poLastPoly != NULL )
     198                 :             {
     199               0 :                 poMP->addGeometryDirectly( poLastPoly );
     200               0 :                 poLastPoly = NULL;
     201                 :             }
     202                 : 
     203               0 :             for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert+=3 )
     204                 :             {
     205               0 :                 OGRPolygon *poPoly = new OGRPolygon();
     206               0 :                 OGRLinearRing *poRing = new OGRLinearRing();
     207               0 :                 int iSrcVert = iBaseVert + nPartStart;
     208                 : 
     209                 :                 poRing->setPoint( 0,
     210                 :                                 padfX[iSrcVert],
     211                 :                                 padfY[iSrcVert],
     212               0 :                                 padfZ[iSrcVert] );
     213                 :                 poRing->setPoint( 1,
     214                 :                                 padfX[iSrcVert+1],
     215                 :                                 padfY[iSrcVert+1],
     216               0 :                                 padfZ[iSrcVert+1] );
     217                 : 
     218                 :                 poRing->setPoint( 2,
     219                 :                                 padfX[iSrcVert+2],
     220                 :                                 padfY[iSrcVert+2],
     221               0 :                                 padfZ[iSrcVert+2] );
     222                 :                 poRing->setPoint( 3,
     223                 :                                 padfX[iSrcVert],
     224                 :                                 padfY[iSrcVert],
     225               0 :                                 padfZ[iSrcVert] );
     226                 : 
     227               0 :                 poPoly->addRingDirectly( poRing );
     228               0 :                 poMP->addGeometryDirectly( poPoly );
     229                 :             }
     230                 :         }
     231                 :         else
     232                 :             CPLDebug( "OGR", "Unrecognised parttype %d, ignored.",
     233               0 :                     panPartType[iPart] );
     234                 :     }
     235                 : 
     236               0 :     if( poLastPoly != NULL )
     237                 :     {
     238               0 :         poMP->addGeometryDirectly( poLastPoly );
     239               0 :         poLastPoly = NULL;
     240                 :     }
     241                 : 
     242               0 :     return poMP;
     243                 : }
     244                 : 
     245                 : 
     246                 : /************************************************************************/
     247                 : /*                      OGRWriteToShapeBin()                            */
     248                 : /*                                                                      */
     249                 : /*      Translate OGR geometry to a shapefile binary representation     */
     250                 : /************************************************************************/
     251                 : 
     252            1135 : OGRErr OGRWriteToShapeBin( OGRGeometry *poGeom, 
     253                 :                            GByte **ppabyShape,
     254                 :                            int *pnBytes )
     255                 : {
     256            1135 :     GUInt32 nGType = SHPT_NULL;
     257            1135 :     int nShpSize = 4; /* All types start with integer type number */
     258            1135 :     int nShpZSize = 0; /* Z gets tacked onto the end */
     259            1135 :     GUInt32 nPoints = 0;
     260            1135 :     GUInt32 nParts = 0;
     261                 : 
     262                 : /* -------------------------------------------------------------------- */
     263                 : /*      Null or Empty input maps to SHPT_NULL.                          */
     264                 : /* -------------------------------------------------------------------- */
     265            1135 :     if ( ! poGeom || poGeom->IsEmpty() )
     266                 :     {
     267               0 :         *ppabyShape = (GByte*)VSIMalloc(nShpSize);
     268               0 :         GUInt32 zero = SHPT_NULL;
     269               0 :         memcpy(*ppabyShape, &zero, nShpSize);
     270               0 :         *pnBytes = nShpSize;
     271               0 :         return OGRERR_NONE;
     272                 :     }
     273                 : 
     274            1135 :     OGRwkbGeometryType nOGRType = wkbFlatten(poGeom->getGeometryType());
     275            1135 :     int b3d = (poGeom->getGeometryType() & wkb25DBit);
     276            1135 :     int nCoordDims = b3d ? 3 : 2;
     277                 : 
     278                 : /* -------------------------------------------------------------------- */
     279                 : /*      Calculate the shape buffer size                                 */
     280                 : /* -------------------------------------------------------------------- */
     281            1135 :     if ( nOGRType == wkbPoint )
     282                 :     {
     283            1020 :         nShpSize += 8 * nCoordDims;
     284                 :     }
     285             115 :     else if ( nOGRType == wkbLineString )
     286                 :     {
     287              10 :         OGRLineString *poLine = (OGRLineString*)poGeom;
     288              10 :         nPoints = poLine->getNumPoints();
     289              10 :         nParts = 1;
     290              10 :         nShpSize += 16 * nCoordDims; /* xy(z) box */ 
     291              10 :         nShpSize += 4; /* nparts */
     292              10 :         nShpSize += 4; /* npoints */
     293              10 :         nShpSize += 4; /* parts[1] */
     294              10 :         nShpSize += 8 * nCoordDims * nPoints; /* points */
     295              10 :         nShpZSize = 16 + 8 * nPoints;
     296                 :     }
     297             105 :     else if ( nOGRType == wkbPolygon )
     298                 :     {
     299              10 :         poGeom->closeRings();
     300              10 :         OGRPolygon *poPoly = (OGRPolygon*)poGeom;
     301              10 :         nParts = poPoly->getNumInteriorRings() + 1;
     302              20 :         for ( GUInt32 i = 0; i < nParts; i++ )
     303                 :         {
     304                 :             OGRLinearRing *poRing;
     305              10 :             if ( i == 0 )
     306              10 :                 poRing = poPoly->getExteriorRing();
     307                 :             else
     308               0 :                 poRing = poPoly->getInteriorRing(i-1);
     309              10 :             nPoints += poRing->getNumPoints();
     310                 :         }
     311              10 :         nShpSize += 16 * nCoordDims; /* xy(z) box */ 
     312              10 :         nShpSize += 4; /* nparts */
     313              10 :         nShpSize += 4; /* npoints */
     314              10 :         nShpSize += 4 * nParts; /* parts[nparts] */
     315              10 :         nShpSize += 8 * nCoordDims * nPoints; /* points */    
     316              10 :         nShpZSize = 16 + 8 * nPoints;
     317                 :     }
     318              95 :     else if ( nOGRType == wkbMultiPoint )
     319                 :     {
     320              20 :         OGRMultiPoint *poMPoint = (OGRMultiPoint*)poGeom;
     321              60 :         for ( int i = 0; i < poMPoint->getNumGeometries(); i++ )
     322                 :         {
     323              40 :             OGRPoint *poPoint = (OGRPoint*)(poMPoint->getGeometryRef(i));
     324              40 :             if ( poPoint->IsEmpty() ) 
     325               0 :                 continue;
     326              40 :             nPoints++;
     327                 :         }
     328              20 :         nShpSize += 16 * nCoordDims; /* xy(z) box */ 
     329              20 :         nShpSize += 4; /* npoints */
     330              20 :         nShpSize += 8 * nCoordDims * nPoints; /* points */    
     331              20 :         nShpZSize = 16 + 8 * nPoints;
     332                 :     }
     333              75 :     else if ( nOGRType == wkbMultiLineString )
     334                 :     {
     335              30 :         OGRMultiLineString *poMLine = (OGRMultiLineString*)poGeom;
     336              60 :         for ( int i = 0; i < poMLine->getNumGeometries(); i++ )
     337                 :         {
     338              30 :             OGRLineString *poLine = (OGRLineString*)(poMLine->getGeometryRef(i));
     339                 :             /* Skip empties */
     340              30 :             if ( poLine->IsEmpty() ) 
     341               0 :                 continue;
     342              30 :             nParts++;
     343              30 :             nPoints += poLine->getNumPoints();
     344                 :         }
     345              30 :         nShpSize += 16 * nCoordDims; /* xy(z) box */ 
     346              30 :         nShpSize += 4; /* nparts */
     347              30 :         nShpSize += 4; /* npoints */
     348              30 :         nShpSize += 4 * nParts; /* parts[nparts] */
     349              30 :         nShpSize += 8 * nCoordDims * nPoints ; /* points */    
     350              30 :         nShpZSize = 16 + 8 * nPoints;
     351                 :     }
     352              45 :     else if ( nOGRType == wkbMultiPolygon )
     353                 :     {
     354              45 :         poGeom->closeRings();
     355              45 :         OGRMultiPolygon *poMPoly = (OGRMultiPolygon*)poGeom;
     356              90 :         for( int j = 0; j < poMPoly->getNumGeometries(); j++ )
     357                 :         {
     358              45 :             OGRPolygon *poPoly = (OGRPolygon*)(poMPoly->getGeometryRef(j));
     359              45 :             int nRings = poPoly->getNumInteriorRings() + 1;
     360                 : 
     361                 :             /* Skip empties */
     362              45 :             if ( poPoly->IsEmpty() ) 
     363               0 :                 continue;
     364                 : 
     365              45 :             nParts += nRings;
     366              90 :             for ( int i = 0; i < nRings; i++ )
     367                 :             {
     368                 :                 OGRLinearRing *poRing;
     369              45 :                 if ( i == 0 )
     370              45 :                     poRing = poPoly->getExteriorRing();
     371                 :                 else
     372               0 :                     poRing = poPoly->getInteriorRing(i-1);
     373              45 :                 nPoints += poRing->getNumPoints();
     374                 :             }
     375                 :         }
     376              45 :         nShpSize += 16 * nCoordDims; /* xy(z) box */ 
     377              45 :         nShpSize += 4; /* nparts */
     378              45 :         nShpSize += 4; /* npoints */
     379              45 :         nShpSize += 4 * nParts; /* parts[nparts] */
     380              45 :         nShpSize += 8 * nCoordDims * nPoints ; /* points */  
     381              45 :         nShpZSize = 16 + 8 * nPoints;
     382                 :     }
     383                 :     else
     384                 :     {
     385               0 :         return OGRERR_UNSUPPORTED_OPERATION;
     386                 :     }
     387                 : 
     388                 :     /* Allocate our shape buffer */
     389            1135 :     *ppabyShape = (GByte*)VSIMalloc(nShpSize);
     390            1135 :     if ( ! *ppabyShape )
     391               0 :         return OGRERR_FAILURE;
     392                 : 
     393                 :     /* Fill in the output size. */
     394            1135 :     *pnBytes = nShpSize;
     395                 : 
     396                 :     /* Set up write pointers */
     397            1135 :     unsigned char *pabyPtr = *ppabyShape;
     398            1135 :     unsigned char *pabyPtrZ = NULL;
     399            1135 :     if ( b3d )
     400              60 :         pabyPtrZ = pabyPtr + nShpSize - nShpZSize;
     401                 : 
     402                 : /* -------------------------------------------------------------------- */
     403                 : /*      Write in the Shape type number now                              */
     404                 : /* -------------------------------------------------------------------- */
     405            1135 :     switch(nOGRType)
     406                 :     {
     407                 :         case wkbPoint:
     408                 :         {
     409            1020 :             nGType = b3d ? SHPT_POINTZ : SHPT_POINT;
     410            1020 :             break;
     411                 :         }
     412                 :         case wkbMultiPoint:
     413                 :         {
     414              20 :             nGType = b3d ? SHPT_MULTIPOINTZ : SHPT_MULTIPOINT;
     415              20 :             break;
     416                 :         }
     417                 :         case wkbLineString:
     418                 :         case wkbMultiLineString:
     419                 :         {
     420              40 :             nGType = b3d ? SHPT_ARCZ : SHPT_ARC;
     421              40 :             break;
     422                 :         }
     423                 :         case wkbPolygon:
     424                 :         case wkbMultiPolygon:
     425                 :         {
     426              55 :             nGType = b3d ? SHPT_POLYGONZ : SHPT_POLYGON;
     427              55 :             break;
     428                 :         }
     429                 :         default:
     430                 :         {
     431               0 :             return OGRERR_UNSUPPORTED_OPERATION;
     432                 :         }
     433                 :     }
     434                 :     /* Write in the type number and advance the pointer */
     435            1135 :     nGType = CPL_LSBWORD32( nGType );
     436            1135 :     memcpy( pabyPtr, &nGType, 4 );
     437            1135 :     pabyPtr += 4;
     438                 : 
     439                 : 
     440                 : /* -------------------------------------------------------------------- */
     441                 : /*      POINT and POINTZ                                                */
     442                 : /* -------------------------------------------------------------------- */
     443            1135 :     if ( nOGRType == wkbPoint )
     444                 :     {
     445            1020 :         OGRPoint *poPoint = (OGRPoint*)poGeom;
     446            1020 :         double x = poPoint->getX();
     447            1020 :         double y = poPoint->getY();
     448                 : 
     449                 :         /* Copy in the raw data. */
     450            1020 :         memcpy( pabyPtr, &x, 8 );
     451            1020 :         memcpy( pabyPtr+8, &y, 8 );
     452            1020 :         if( b3d )
     453                 :         {
     454              10 :             double z = poPoint->getZ();
     455              10 :             memcpy( pabyPtr+8+8, &z, 8 );
     456                 :         }
     457                 : 
     458                 :         /* Swap if needed. Shape doubles always LSB */
     459                 :         if( OGR_SWAP( wkbNDR ) )
     460                 :         {
     461                 :             CPL_SWAPDOUBLE( pabyPtr );
     462                 :             CPL_SWAPDOUBLE( pabyPtr+8 );
     463                 :             if( b3d )
     464                 :                 CPL_SWAPDOUBLE( pabyPtr+8+8 );
     465                 :         }
     466                 : 
     467            1020 :         return OGRERR_NONE;    
     468                 :     }
     469                 : 
     470                 : /* -------------------------------------------------------------------- */
     471                 : /*      All the non-POINT types require an envelope next                */
     472                 : /* -------------------------------------------------------------------- */
     473             115 :     OGREnvelope3D envelope;
     474             115 :     poGeom->getEnvelope(&envelope);
     475             115 :     memcpy( pabyPtr, &(envelope.MinX), 8 );
     476             115 :     memcpy( pabyPtr+8, &(envelope.MinY), 8 );
     477             115 :     memcpy( pabyPtr+8+8, &(envelope.MaxX), 8 );
     478             115 :     memcpy( pabyPtr+8+8+8, &(envelope.MaxY), 8 );
     479                 : 
     480                 :     /* Swap box if needed. Shape doubles are always LSB */
     481                 :     if( OGR_SWAP( wkbNDR ) )
     482                 :     {
     483                 :         for ( int i = 0; i < 4; i++ )
     484                 :             CPL_SWAPDOUBLE( pabyPtr + 8*i );
     485                 :     }
     486             115 :     pabyPtr += 32;
     487                 : 
     488                 :     /* Write in the Z bounds at the end of the XY buffer */
     489             115 :     if ( b3d )
     490                 :     {
     491              50 :         memcpy( pabyPtrZ, &(envelope.MinZ), 8 );
     492              50 :         memcpy( pabyPtrZ+8, &(envelope.MaxZ), 8 );
     493                 : 
     494                 :         /* Swap Z bounds if necessary */
     495                 :         if( OGR_SWAP( wkbNDR ) )
     496                 :         {
     497                 :             for ( int i = 0; i < 2; i++ )
     498                 :                 CPL_SWAPDOUBLE( pabyPtrZ + 8*i );
     499                 :         } 
     500              50 :         pabyPtrZ += 16;
     501                 :     }
     502                 : 
     503                 : /* -------------------------------------------------------------------- */
     504                 : /*      LINESTRING and LINESTRINGZ                                      */
     505                 : /* -------------------------------------------------------------------- */
     506             115 :     if ( nOGRType == wkbLineString )
     507                 :     {
     508              10 :         const OGRLineString *poLine = (OGRLineString*)poGeom;
     509                 : 
     510                 :         /* Write in the nparts (1) */
     511              10 :         GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
     512              10 :         memcpy( pabyPtr, &nPartsLsb, 4 );
     513              10 :         pabyPtr += 4;
     514                 : 
     515                 :         /* Write in the npoints */
     516              10 :         GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
     517              10 :         memcpy( pabyPtr, &nPointsLsb, 4 );
     518              10 :         pabyPtr += 4;
     519                 : 
     520                 :         /* Write in the part index (0) */
     521              10 :         GUInt32 nPartIndex = 0;
     522              10 :         memcpy( pabyPtr, &nPartIndex, 4 );
     523              10 :         pabyPtr += 4;
     524                 : 
     525                 :         /* Write in the point data */
     526              10 :         poLine->getPoints((OGRRawPoint*)pabyPtr, (double*)pabyPtrZ);
     527                 : 
     528                 :         /* Swap if necessary */
     529                 :         if( OGR_SWAP( wkbNDR ) )
     530                 :         {
     531                 :             for( GUInt32 k = 0; k < nPoints; k++ )
     532                 :             {
     533                 :                 CPL_SWAPDOUBLE( pabyPtr + 16*k );
     534                 :                 CPL_SWAPDOUBLE( pabyPtr + 16*k + 8 );
     535                 :                 if( b3d )
     536                 :                     CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
     537                 :             }
     538                 :         }
     539              10 :         return OGRERR_NONE;    
     540                 : 
     541                 :     }
     542                 : /* -------------------------------------------------------------------- */
     543                 : /*      POLYGON and POLYGONZ                                            */
     544                 : /* -------------------------------------------------------------------- */
     545             105 :     else if ( nOGRType == wkbPolygon )
     546                 :     {
     547              10 :         OGRPolygon *poPoly = (OGRPolygon*)poGeom;
     548                 : 
     549                 :         /* Write in the part count */
     550              10 :         GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
     551              10 :         memcpy( pabyPtr, &nPartsLsb, 4 );
     552              10 :         pabyPtr += 4;
     553                 : 
     554                 :         /* Write in the total point count */
     555              10 :         GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
     556              10 :         memcpy( pabyPtr, &nPointsLsb, 4 );
     557              10 :         pabyPtr += 4;
     558                 : 
     559                 : /* -------------------------------------------------------------------- */
     560                 : /*      Now we have to visit each ring and write an index number into   */
     561                 : /*      the parts list, and the coordinates into the points list.       */
     562                 : /*      to do it in one pass, we will use three write pointers.         */
     563                 : /*      pabyPtr writes the part indexes                                 */
     564                 : /*      pabyPoints writes the xy coordinates                            */
     565                 : /*      pabyPtrZ writes the z coordinates                               */
     566                 : /* -------------------------------------------------------------------- */
     567                 : 
     568                 :         /* Just past the partindex[nparts] array */
     569              10 :         unsigned char* pabyPoints = pabyPtr + 4*nParts; 
     570                 : 
     571              10 :         int nPointIndexCount = 0;
     572                 : 
     573              20 :         for( GUInt32 i = 0; i < nParts; i++ )
     574                 :         {
     575                 :             /* Check our Ring and condition it */
     576                 :             OGRLinearRing *poRing;
     577              10 :             if ( i == 0 ) 
     578                 :             {
     579              10 :                 poRing = poPoly->getExteriorRing();
     580                 :                 /* Outer ring must be clockwise */
     581              10 :                 if ( ! poRing->isClockwise() )
     582               0 :                     poRing->reverseWindingOrder();
     583                 :             }
     584                 :             else
     585                 :             {
     586               0 :                 poRing = poPoly->getInteriorRing(i-1);
     587                 :                 /* Inner rings should be anti-clockwise */
     588               0 :                 if ( poRing->isClockwise() )
     589               0 :                     poRing->reverseWindingOrder();
     590                 :             }
     591                 : 
     592              10 :             int nRingNumPoints = poRing->getNumPoints();
     593                 : 
     594                 :             /* Cannot write un-closed rings to shape */
     595              10 :             if( nRingNumPoints <= 2 || ! poRing->get_IsClosed() )
     596               0 :                 return OGRERR_FAILURE;
     597                 : 
     598                 :             /* Write in the part index */
     599              10 :             GUInt32 nPartIndex = CPL_LSBWORD32( nPointIndexCount );
     600              10 :             memcpy( pabyPtr, &nPartIndex, 4 );
     601                 : 
     602                 :             /* Write in the point data */
     603              10 :             poRing->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
     604                 : 
     605                 :             /* Swap if necessary */
     606                 :             if( OGR_SWAP( wkbNDR ) )
     607                 :             {
     608                 :                 for( int k = 0; k < nRingNumPoints; k++ )
     609                 :                 {
     610                 :                     CPL_SWAPDOUBLE( pabyPoints + 16*k );
     611                 :                     CPL_SWAPDOUBLE( pabyPoints + 16*k + 8 );
     612                 :                     if( b3d )
     613                 :                         CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
     614                 :                 }
     615                 :             }
     616                 : 
     617              10 :             nPointIndexCount += nRingNumPoints;
     618                 :             /* Advance the write pointers */
     619              10 :             pabyPtr += 4;
     620              10 :             pabyPoints += 16 * nRingNumPoints;
     621              10 :             if ( b3d )
     622               5 :                 pabyPtrZ += 8 * nRingNumPoints; 
     623                 :         }
     624                 : 
     625              10 :         return OGRERR_NONE;
     626                 : 
     627                 :     }
     628                 : /* -------------------------------------------------------------------- */
     629                 : /*      MULTIPOINT and MULTIPOINTZ                                      */
     630                 : /* -------------------------------------------------------------------- */
     631              95 :     else if ( nOGRType == wkbMultiPoint )
     632                 :     {
     633              20 :         OGRMultiPoint *poMPoint = (OGRMultiPoint*)poGeom;
     634                 : 
     635                 :         /* Write in the total point count */
     636              20 :         GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
     637              20 :         memcpy( pabyPtr, &nPointsLsb, 4 );
     638              20 :         pabyPtr += 4;
     639                 : 
     640                 : /* -------------------------------------------------------------------- */
     641                 : /*      Now we have to visit each point write it into the points list   */
     642                 : /*      We will use two write pointers.                                 */
     643                 : /*      pabyPtr writes the xy coordinates                               */
     644                 : /*      pabyPtrZ writes the z coordinates                               */
     645                 : /* -------------------------------------------------------------------- */
     646                 : 
     647              60 :         for( GUInt32 i = 0; i < nPoints; i++ )
     648                 :         {
     649              40 :             const OGRPoint *poPt = (OGRPoint*)(poMPoint->getGeometryRef(i));
     650                 : 
     651                 :             /* Skip empties */
     652              40 :             if ( poPt->IsEmpty() ) 
     653               0 :                 continue;
     654                 : 
     655                 :             /* Write the coordinates */
     656              40 :             double x = poPt->getX();
     657              40 :             double y = poPt->getY();
     658              40 :             memcpy(pabyPtr, &x, 8);
     659              40 :             memcpy(pabyPtr+8, &y, 8);
     660              40 :             if ( b3d )
     661                 :             {
     662              20 :                 double z = poPt->getZ();
     663              20 :                 memcpy(pabyPtrZ, &z, 8);
     664                 :             }
     665                 : 
     666                 :             /* Swap if necessary */
     667                 :             if( OGR_SWAP( wkbNDR ) )
     668                 :             {
     669                 :                 CPL_SWAPDOUBLE( pabyPtr );
     670                 :                 CPL_SWAPDOUBLE( pabyPtr + 8 );
     671                 :                 if( b3d )
     672                 :                     CPL_SWAPDOUBLE( pabyPtrZ );
     673                 :             }
     674                 : 
     675                 :             /* Advance the write pointers */
     676              40 :             pabyPtr += 16;
     677              40 :             if ( b3d )
     678              20 :                 pabyPtrZ += 8; 
     679                 :         }    
     680                 : 
     681              20 :         return OGRERR_NONE;
     682                 :     }
     683                 : 
     684                 : /* -------------------------------------------------------------------- */
     685                 : /*      MULTILINESTRING and MULTILINESTRINGZ                            */
     686                 : /* -------------------------------------------------------------------- */
     687              75 :     else if ( nOGRType == wkbMultiLineString )
     688                 :     {
     689              30 :         OGRMultiLineString *poMLine = (OGRMultiLineString*)poGeom;
     690                 : 
     691                 :         /* Write in the part count */
     692              30 :         GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
     693              30 :         memcpy( pabyPtr, &nPartsLsb, 4 );
     694              30 :         pabyPtr += 4;
     695                 : 
     696                 :         /* Write in the total point count */
     697              30 :         GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
     698              30 :         memcpy( pabyPtr, &nPointsLsb, 4 );
     699              30 :         pabyPtr += 4;
     700                 : 
     701                 :         /* Just past the partindex[nparts] array */
     702              30 :         unsigned char* pabyPoints = pabyPtr + 4*nParts; 
     703                 : 
     704              30 :         int nPointIndexCount = 0;
     705                 : 
     706              60 :         for( GUInt32 i = 0; i < nParts; i++ )
     707                 :         {
     708              30 :             const OGRLineString *poLine = (OGRLineString*)(poMLine->getGeometryRef(i));
     709                 : 
     710                 :             /* Skip empties */
     711              30 :             if ( poLine->IsEmpty() ) 
     712               0 :                 continue;
     713                 : 
     714              30 :             int nLineNumPoints = poLine->getNumPoints();
     715                 : 
     716                 :             /* Write in the part index */
     717              30 :             GUInt32 nPartIndex = CPL_LSBWORD32( nPointIndexCount );
     718              30 :             memcpy( pabyPtr, &nPartIndex, 4 );
     719                 : 
     720                 :             /* Write in the point data */
     721              30 :             poLine->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
     722                 : 
     723                 :             /* Swap if necessary */
     724                 :             if( OGR_SWAP( wkbNDR ) )
     725                 :             {
     726                 :                 for( int k = 0; k < nLineNumPoints; k++ )
     727                 :                 {
     728                 :                     CPL_SWAPDOUBLE( pabyPoints + 16*k );
     729                 :                     CPL_SWAPDOUBLE( pabyPoints + 16*k + 8 );
     730                 :                     if( b3d )
     731                 :                         CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
     732                 :                 }
     733                 :             }
     734                 : 
     735              30 :             nPointIndexCount += nLineNumPoints;
     736                 : 
     737                 :             /* Advance the write pointers */
     738              30 :             pabyPtr += 4;
     739              30 :             pabyPoints += 16 * nLineNumPoints;
     740              30 :             if ( b3d )
     741              15 :                 pabyPtrZ += 8 * nLineNumPoints; 
     742                 :         }
     743                 : 
     744              30 :         return OGRERR_NONE;      
     745                 : 
     746                 :     }
     747                 : /* -------------------------------------------------------------------- */
     748                 : /*      MULTIPOLYGON and MULTIPOLYGONZ                                  */
     749                 : /* -------------------------------------------------------------------- */
     750              45 :     else if ( nOGRType == wkbMultiPolygon )
     751                 :     {
     752              45 :         OGRMultiPolygon *poMPoly = (OGRMultiPolygon*)poGeom;
     753                 : 
     754                 :         /* Write in the part count */
     755              45 :         GUInt32 nPartsLsb = CPL_LSBWORD32( nParts );
     756              45 :         memcpy( pabyPtr, &nPartsLsb, 4 );
     757              45 :         pabyPtr += 4;
     758                 : 
     759                 :         /* Write in the total point count */
     760              45 :         GUInt32 nPointsLsb = CPL_LSBWORD32( nPoints );
     761              45 :         memcpy( pabyPtr, &nPointsLsb, 4 );
     762              45 :         pabyPtr += 4;
     763                 : 
     764                 : /* -------------------------------------------------------------------- */
     765                 : /*      Now we have to visit each ring and write an index number into   */
     766                 : /*      the parts list, and the coordinates into the points list.       */
     767                 : /*      to do it in one pass, we will use three write pointers.         */
     768                 : /*      pabyPtr writes the part indexes                                 */
     769                 : /*      pabyPoints writes the xy coordinates                            */
     770                 : /*      pabyPtrZ writes the z coordinates                               */
     771                 : /* -------------------------------------------------------------------- */
     772                 : 
     773                 :         /* Just past the partindex[nparts] array */
     774              45 :         unsigned char* pabyPoints = pabyPtr + 4*nParts; 
     775                 : 
     776              45 :         int nPointIndexCount = 0;
     777                 : 
     778              90 :         for( int i = 0; i < poMPoly->getNumGeometries(); i++ )
     779                 :         {
     780              45 :             OGRPolygon *poPoly = (OGRPolygon*)(poMPoly->getGeometryRef(i));
     781                 : 
     782                 :             /* Skip empties */
     783              45 :             if ( poPoly->IsEmpty() ) 
     784               0 :                 continue;
     785                 : 
     786              45 :             int nRings = 1 + poPoly->getNumInteriorRings();
     787                 : 
     788              90 :             for( int j = 0; j < nRings; j++ )
     789                 :             {
     790                 :                 /* Check our Ring and condition it */
     791                 :                 OGRLinearRing *poRing;
     792              45 :                 if ( j == 0 )
     793                 :                 {
     794              45 :                     poRing = poPoly->getExteriorRing();
     795                 :                     /* Outer ring must be clockwise */
     796              45 :                     if ( ! poRing->isClockwise() )
     797               0 :                         poRing->reverseWindingOrder();
     798                 :                 }
     799                 :                 else
     800                 :                 {
     801               0 :                     poRing = poPoly->getInteriorRing(j-1);
     802                 :                     /* Inner rings should be anti-clockwise */
     803               0 :                     if ( poRing->isClockwise() )
     804               0 :                         poRing->reverseWindingOrder();
     805                 :                 }
     806                 : 
     807              45 :                 int nRingNumPoints = poRing->getNumPoints();
     808                 : 
     809                 :                 /* Cannot write closed rings to shape */
     810              45 :                 if( nRingNumPoints <= 2 || ! poRing->get_IsClosed() )
     811               0 :                     return OGRERR_FAILURE;
     812                 : 
     813                 :                 /* Write in the part index */
     814              45 :                 GUInt32 nPartIndex = CPL_LSBWORD32( nPointIndexCount );
     815              45 :                 memcpy( pabyPtr, &nPartIndex, 4 );
     816                 : 
     817                 :                 /* Write in the point data */
     818              45 :                 poRing->getPoints((OGRRawPoint*)pabyPoints, (double*)pabyPtrZ);
     819                 : 
     820                 :                 /* Swap if necessary */
     821                 :                 if( OGR_SWAP( wkbNDR ) )
     822                 :                 {
     823                 :                     for( int k = 0; k < nRingNumPoints; k++ )
     824                 :                     {
     825                 :                         CPL_SWAPDOUBLE( pabyPoints + 16*k );
     826                 :                         CPL_SWAPDOUBLE( pabyPoints + 16*k + 8 );
     827                 :                         if( b3d )
     828                 :                             CPL_SWAPDOUBLE( pabyPtrZ + 8*k );
     829                 :                     }
     830                 :                 }
     831                 : 
     832              45 :                 nPointIndexCount += nRingNumPoints;
     833                 :                 /* Advance the write pointers */
     834              45 :                 pabyPtr += 4;
     835              45 :                 pabyPoints += 16 * nRingNumPoints;
     836              45 :                 if ( b3d )
     837              15 :                     pabyPtrZ += 8 * nRingNumPoints; 
     838                 :             }
     839                 :         }
     840                 : 
     841              45 :         return OGRERR_NONE;
     842                 : 
     843                 :     }
     844                 :     else
     845                 :     {
     846               0 :         return OGRERR_UNSUPPORTED_OPERATION;
     847                 :     }
     848                 : 
     849                 : }  
     850                 : 
     851                 : 
     852                 : /************************************************************************/
     853                 : /*                      OGRCreateFromShapeBin()                         */
     854                 : /*                                                                      */
     855                 : /*      Translate shapefile binary representation to an OGR             */
     856                 : /*      geometry.                                                       */
     857                 : /************************************************************************/
     858                 : 
     859          274338 : OGRErr OGRCreateFromShapeBin( GByte *pabyShape,
     860                 :                               OGRGeometry **ppoGeom,
     861                 :                               int nBytes )
     862                 : 
     863                 : {
     864          274338 :     *ppoGeom = NULL;
     865                 : 
     866          274338 :     if( nBytes < 4 )
     867                 :     {    
     868                 :         CPLError(CE_Failure, CPLE_AppDefined,
     869                 :                  "Shape buffer size (%d) too small",
     870               0 :                  nBytes);
     871               0 :         return OGRERR_FAILURE;
     872                 :     }
     873                 : 
     874                 : /* -------------------------------------------------------------------- */
     875                 : /*  Detect zlib compressed shapes and uncompress buffer if necessary    */
     876                 : /*  NOTE: this seems to be an undocumented feature, even in the         */
     877                 : /*  extended_shapefile_format.pdf found in the FileGDB API documentation*/
     878                 : /* -------------------------------------------------------------------- */
     879          548676 :     if( nBytes >= 14 &&
     880          274338 :         pabyShape[12] == 0x78 && pabyShape[13] == 0xDA /* zlib marker */)
     881                 :     {
     882                 :         GInt32 nUncompressedSize, nCompressedSize;
     883               0 :         memcpy( &nUncompressedSize, pabyShape + 4, 4 );
     884               0 :         memcpy( &nCompressedSize, pabyShape + 8, 4 );
     885                 :         CPL_LSBPTR32( &nUncompressedSize );
     886                 :         CPL_LSBPTR32( &nCompressedSize );
     887               0 :         if (nCompressedSize + 12 == nBytes &&
     888                 :             nUncompressedSize > 0)
     889                 :         {
     890               0 :             GByte* pabyUncompressedBuffer = (GByte*)VSIMalloc(nUncompressedSize);
     891               0 :             if (pabyUncompressedBuffer == NULL)
     892                 :             {
     893                 :                 CPLError(CE_Failure, CPLE_OutOfMemory,
     894                 :                          "Cannot allocate %d bytes to uncompress zlib buffer",
     895               0 :                          nUncompressedSize);
     896               0 :                 return OGRERR_FAILURE;
     897                 :             }
     898                 : 
     899               0 :             size_t nRealUncompressedSize = 0;
     900               0 :             if( CPLZLibInflate( pabyShape + 12, nCompressedSize,
     901                 :                                 pabyUncompressedBuffer, nUncompressedSize,
     902                 :                                 &nRealUncompressedSize ) == NULL )
     903                 :             {
     904                 :                 CPLError(CE_Failure, CPLE_AppDefined,
     905               0 :                          "CPLZLibInflate() failed");
     906               0 :                 VSIFree(pabyUncompressedBuffer);
     907               0 :                 return OGRERR_FAILURE;
     908                 :             }
     909                 : 
     910                 :             OGRErr eErr = OGRCreateFromShapeBin(pabyUncompressedBuffer,
     911                 :                                                 ppoGeom,
     912               0 :                                                 nRealUncompressedSize);
     913                 : 
     914               0 :             VSIFree(pabyUncompressedBuffer);
     915                 : 
     916               0 :             return eErr;
     917                 :         }
     918                 :     }
     919                 : 
     920          274338 :     int nSHPType = pabyShape[0];
     921                 : 
     922                 : /* -------------------------------------------------------------------- */
     923                 : /*      Return a NULL geometry when SHPT_NULL is encountered.           */
     924                 : /*      Watch out, null return does not mean "bad data" it means        */
     925                 : /*      "no geometry here". Watch the OGRErr for the error status       */
     926                 : /* -------------------------------------------------------------------- */
     927          274338 :     if ( nSHPType == SHPT_NULL )
     928                 :     {
     929               0 :       *ppoGeom = NULL;
     930               0 :       return OGRERR_NONE;
     931                 :     }
     932                 : 
     933                 : //    CPLDebug( "PGeo",
     934                 : //              "Shape type read from PGeo data is nSHPType = %d",
     935                 : //              nSHPType );
     936                 : 
     937                 : /* -------------------------------------------------------------------- */
     938                 : /*      TODO: These types include additional attributes including       */
     939                 : /*      non-linear segments and such. They should be handled.           */
     940                 : /*      This is documented in the extended_shapefile_format.pdf         */
     941                 : /*      from the FileGDB API                                            */
     942                 : /* -------------------------------------------------------------------- */
     943          274338 :     switch( nSHPType )
     944                 :     {
     945                 :       case SHPT_GENERALPOLYLINE:
     946               0 :         nSHPType = SHPT_ARC;
     947               0 :         break;
     948                 :       case SHPT_GENERALPOLYGON:
     949               0 :         nSHPType = SHPT_POLYGON;
     950               0 :         break;
     951                 :       case SHPT_GENERALPOINT:
     952               0 :         nSHPType = SHPT_POINT;
     953               0 :         break;
     954                 :       case SHPT_GENERALMULTIPOINT:
     955               0 :         nSHPType = SHPT_MULTIPOINT;
     956               0 :         break;
     957                 :       case SHPT_GENERALMULTIPATCH:
     958               0 :         nSHPType = SHPT_MULTIPATCH;
     959                 :     }
     960                 : 
     961                 : /* ==================================================================== */
     962                 : /*  Extract vertices for a Polygon or Arc.              */
     963                 : /* ==================================================================== */
     964          274338 :     if(    nSHPType == SHPT_ARC
     965                 :         || nSHPType == SHPT_ARCZ
     966                 :         || nSHPType == SHPT_ARCM
     967                 :         || nSHPType == SHPT_ARCZM
     968                 :         || nSHPType == SHPT_POLYGON
     969                 :         || nSHPType == SHPT_POLYGONZ
     970                 :         || nSHPType == SHPT_POLYGONM
     971                 :         || nSHPType == SHPT_POLYGONZM
     972                 :         || nSHPType == SHPT_MULTIPATCH
     973                 :         || nSHPType == SHPT_MULTIPATCHM)
     974                 :     {
     975                 :         GInt32         nPoints, nParts;
     976                 :         int            i, nOffset;
     977                 :         GInt32         *panPartStart;
     978          273813 :         GInt32         *panPartType = NULL;
     979                 : 
     980          273813 :         if (nBytes < 44)
     981                 :         {
     982                 :             CPLError(CE_Failure, CPLE_AppDefined,
     983               0 :                      "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
     984               0 :             return OGRERR_FAILURE;
     985                 :         }
     986                 : 
     987                 : /* -------------------------------------------------------------------- */
     988                 : /*      Extract part/point count, and build vertex and part arrays      */
     989                 : /*      to proper size.                                                 */
     990                 : /* -------------------------------------------------------------------- */
     991          273813 :         memcpy( &nPoints, pabyShape + 40, 4 );
     992          273813 :         memcpy( &nParts, pabyShape + 36, 4 );
     993                 : 
     994                 :         CPL_LSBPTR32( &nPoints );
     995                 :         CPL_LSBPTR32( &nParts );
     996                 : 
     997          273813 :         if (nPoints < 0 || nParts < 0 ||
     998                 :             nPoints > 50 * 1000 * 1000 || nParts > 10 * 1000 * 1000)
     999                 :         {
    1000                 :             CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d, nParts=%d.",
    1001               0 :                      nPoints, nParts);
    1002               0 :             return OGRERR_FAILURE;
    1003                 :         }
    1004                 : 
    1005                 :         int bHasZ = (  nSHPType == SHPT_POLYGONZ
    1006                 :                     || nSHPType == SHPT_POLYGONZM
    1007                 :                     || nSHPType == SHPT_ARCZ
    1008                 :                     || nSHPType == SHPT_ARCZM
    1009                 :                     || nSHPType == SHPT_MULTIPATCH
    1010          273813 :                     || nSHPType == SHPT_MULTIPATCHM );
    1011                 : 
    1012          273813 :         int bIsMultiPatch = ( nSHPType == SHPT_MULTIPATCH || nSHPType == SHPT_MULTIPATCHM );
    1013                 : 
    1014                 :         /* With the previous checks on nPoints and nParts, */
    1015                 :         /* we should not overflow here and after */
    1016                 :         /* since 50 M * (16 + 8 + 8) = 1 600 MB */
    1017          273813 :         int nRequiredSize = 44 + 4 * nParts + 16 * nPoints;
    1018          273813 :         if ( bHasZ )
    1019                 :         {
    1020          273469 :             nRequiredSize += 16 + 8 * nPoints;
    1021                 :         }
    1022          273813 :         if( bIsMultiPatch )
    1023                 :         {
    1024               0 :             nRequiredSize += 4 * nParts;
    1025                 :         }
    1026          273813 :         if (nRequiredSize > nBytes)
    1027                 :         {
    1028                 :             CPLError(CE_Failure, CPLE_AppDefined,
    1029                 :                      "Corrupted Shape : nPoints=%d, nParts=%d, nBytes=%d, nSHPType=%d",
    1030               0 :                      nPoints, nParts, nBytes, nSHPType);
    1031               0 :             return OGRERR_FAILURE;
    1032                 :         }
    1033                 : 
    1034          273813 :         panPartStart = (GInt32 *) VSICalloc(nParts,sizeof(GInt32));
    1035          273813 :         if (panPartStart == NULL)
    1036                 :         {
    1037                 :             CPLError(CE_Failure, CPLE_OutOfMemory,
    1038               0 :                      "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
    1039               0 :             return OGRERR_FAILURE;
    1040                 :         }
    1041                 : 
    1042                 : /* -------------------------------------------------------------------- */
    1043                 : /*      Copy out the part array from the record.                        */
    1044                 : /* -------------------------------------------------------------------- */
    1045          273813 :         memcpy( panPartStart, pabyShape + 44, 4 * nParts );
    1046          547626 :         for( i = 0; i < nParts; i++ )
    1047                 :         {
    1048                 :             CPL_LSBPTR32( panPartStart + i );
    1049                 : 
    1050                 :             /* We check that the offset is inside the vertex array */
    1051          547626 :             if (panPartStart[i] < 0 ||
    1052          273813 :                 panPartStart[i] >= nPoints)
    1053                 :             {
    1054                 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1055                 :                         "Corrupted Shape : panPartStart[%d] = %d, nPoints = %d",
    1056               0 :                         i, panPartStart[i], nPoints);
    1057               0 :                 CPLFree(panPartStart);
    1058               0 :                 return OGRERR_FAILURE;
    1059                 :             }
    1060          273813 :             if (i > 0 && panPartStart[i] <= panPartStart[i-1])
    1061                 :             {
    1062                 :                 CPLError(CE_Failure, CPLE_AppDefined,
    1063                 :                         "Corrupted Shape : panPartStart[%d] = %d, panPartStart[%d] = %d",
    1064               0 :                         i, panPartStart[i], i - 1, panPartStart[i - 1]);
    1065               0 :                 CPLFree(panPartStart);
    1066               0 :                 return OGRERR_FAILURE;
    1067                 :             }
    1068                 :         }
    1069                 : 
    1070          273813 :         nOffset = 44 + 4*nParts;
    1071                 : 
    1072                 : /* -------------------------------------------------------------------- */
    1073                 : /*      If this is a multipatch, we will also have parts types.         */
    1074                 : /* -------------------------------------------------------------------- */
    1075          273813 :         if( bIsMultiPatch )
    1076                 :         {
    1077               0 :             panPartType = (GInt32 *) VSICalloc(nParts,sizeof(GInt32));
    1078               0 :             if (panPartType == NULL)
    1079                 :             {
    1080                 :                 CPLError(CE_Failure, CPLE_OutOfMemory,
    1081               0 :                         "Not enough memory for panPartType for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
    1082               0 :                 CPLFree(panPartStart);
    1083               0 :                 return OGRERR_FAILURE;
    1084                 :             }
    1085                 : 
    1086               0 :             memcpy( panPartType, pabyShape + nOffset, 4*nParts );
    1087               0 :             for( i = 0; i < nParts; i++ )
    1088                 :             {
    1089                 :                 CPL_LSBPTR32( panPartType + i );
    1090                 :             }
    1091               0 :             nOffset += 4*nParts;
    1092                 :         }
    1093                 : 
    1094                 : /* -------------------------------------------------------------------- */
    1095                 : /*      Copy out the vertices from the record.                          */
    1096                 : /* -------------------------------------------------------------------- */
    1097          273813 :         double *padfX = (double *) VSIMalloc(sizeof(double)*nPoints);
    1098          273813 :         double *padfY = (double *) VSIMalloc(sizeof(double)*nPoints);
    1099          273813 :         double *padfZ = (double *) VSICalloc(sizeof(double),nPoints);
    1100          273813 :         if (padfX == NULL || padfY == NULL || padfZ == NULL)
    1101                 :         {
    1102               0 :             CPLFree( panPartStart );
    1103               0 :             CPLFree( panPartType );
    1104               0 :             CPLFree( padfX );
    1105               0 :             CPLFree( padfY );
    1106               0 :             CPLFree( padfZ );
    1107                 :             CPLError(CE_Failure, CPLE_OutOfMemory,
    1108               0 :                      "Not enough memory for shape (nPoints=%d, nParts=%d)", nPoints, nParts);
    1109               0 :             return OGRERR_FAILURE;
    1110                 :         }
    1111                 : 
    1112         1325218 :         for( i = 0; i < nPoints; i++ )
    1113                 :         {
    1114         1051405 :             memcpy(padfX + i, pabyShape + nOffset + i * 16, 8 );
    1115         1051405 :             memcpy(padfY + i, pabyShape + nOffset + i * 16 + 8, 8 );
    1116                 :             CPL_LSBPTR64( padfX + i );
    1117                 :             CPL_LSBPTR64( padfY + i );
    1118                 :         }
    1119                 : 
    1120          273813 :         nOffset += 16*nPoints;
    1121                 : 
    1122                 : /* -------------------------------------------------------------------- */
    1123                 : /*      If we have a Z coordinate, collect that now.                    */
    1124                 : /* -------------------------------------------------------------------- */
    1125          273813 :         if( bHasZ )
    1126                 :         {
    1127         1321553 :             for( i = 0; i < nPoints; i++ )
    1128                 :             {
    1129         1048084 :                 memcpy( padfZ + i, pabyShape + nOffset + 16 + i*8, 8 );
    1130                 :                 CPL_LSBPTR64( padfZ + i );
    1131                 :             }
    1132                 : 
    1133          273469 :             nOffset += 16 + 8*nPoints;
    1134                 :         }
    1135                 : 
    1136                 : /* -------------------------------------------------------------------- */
    1137                 : /*      Build corresponding OGR objects.                                */
    1138                 : /* -------------------------------------------------------------------- */
    1139          547195 :         if(    nSHPType == SHPT_ARC
    1140                 :             || nSHPType == SHPT_ARCZ
    1141                 :             || nSHPType == SHPT_ARCM
    1142                 :             || nSHPType == SHPT_ARCZM )
    1143                 :         {
    1144                 : /* -------------------------------------------------------------------- */
    1145                 : /*      Arc - As LineString                                             */
    1146                 : /* -------------------------------------------------------------------- */
    1147          273382 :             if( nParts == 1 )
    1148                 :             {
    1149          273382 :                 OGRLineString *poLine = new OGRLineString();
    1150          273382 :                 *ppoGeom = poLine;
    1151                 : 
    1152          273382 :                 poLine->setPoints( nPoints, padfX, padfY, padfZ );
    1153                 :             }
    1154                 : 
    1155                 : /* -------------------------------------------------------------------- */
    1156                 : /*      Arc - As MultiLineString                                        */
    1157                 : /* -------------------------------------------------------------------- */
    1158                 :             else
    1159                 :             {
    1160               0 :                 OGRMultiLineString *poMulti = new OGRMultiLineString;
    1161               0 :                 *ppoGeom = poMulti;
    1162                 : 
    1163               0 :                 for( i = 0; i < nParts; i++ )
    1164                 :                 {
    1165               0 :                     OGRLineString *poLine = new OGRLineString;
    1166                 :                     int nVerticesInThisPart;
    1167                 : 
    1168               0 :                     if( i == nParts-1 )
    1169               0 :                         nVerticesInThisPart = nPoints - panPartStart[i];
    1170                 :                     else
    1171                 :                         nVerticesInThisPart =
    1172               0 :                             panPartStart[i+1] - panPartStart[i];
    1173                 : 
    1174                 :                     poLine->setPoints( nVerticesInThisPart,
    1175               0 :                                        padfX + panPartStart[i],
    1176               0 :                                        padfY + panPartStart[i],
    1177               0 :                                        padfZ + panPartStart[i] );
    1178                 : 
    1179               0 :                     poMulti->addGeometryDirectly( poLine );
    1180                 :                 }
    1181                 :             }
    1182                 :         } /* ARC */
    1183                 : 
    1184                 : /* -------------------------------------------------------------------- */
    1185                 : /*      Polygon                                                         */
    1186                 : /* -------------------------------------------------------------------- */
    1187             862 :         else if(    nSHPType == SHPT_POLYGON
    1188                 :                  || nSHPType == SHPT_POLYGONZ
    1189                 :                  || nSHPType == SHPT_POLYGONM
    1190                 :                  || nSHPType == SHPT_POLYGONZM )
    1191                 :         {
    1192             431 :             if (nParts != 0)
    1193                 :             {
    1194             431 :                 if (nParts == 1)
    1195                 :                 {
    1196             431 :                     OGRPolygon *poOGRPoly = new OGRPolygon;
    1197             431 :                     *ppoGeom = poOGRPoly;
    1198             862 :                     OGRLinearRing *poRing = new OGRLinearRing;
    1199             431 :                     int nVerticesInThisPart = nPoints - panPartStart[0];
    1200                 : 
    1201                 :                     poRing->setPoints( nVerticesInThisPart,
    1202             431 :                                        padfX + panPartStart[0],
    1203             431 :                                        padfY + panPartStart[0],
    1204            1293 :                                        padfZ + panPartStart[0] );
    1205                 : 
    1206             431 :                     poOGRPoly->addRingDirectly( poRing );
    1207                 :                 }
    1208                 :                 else
    1209                 :                 {
    1210               0 :                     OGRGeometry *poOGR = NULL;
    1211               0 :                     OGRPolygon** tabPolygons = new OGRPolygon*[nParts];
    1212                 : 
    1213               0 :                     for( i = 0; i < nParts; i++ )
    1214                 :                     {
    1215               0 :                         tabPolygons[i] = new OGRPolygon();
    1216               0 :                         OGRLinearRing *poRing = new OGRLinearRing;
    1217                 :                         int nVerticesInThisPart;
    1218                 : 
    1219               0 :                         if( i == nParts-1 )
    1220               0 :                             nVerticesInThisPart = nPoints - panPartStart[i];
    1221                 :                         else
    1222                 :                             nVerticesInThisPart =
    1223               0 :                                 panPartStart[i+1] - panPartStart[i];
    1224                 : 
    1225                 :                         poRing->setPoints( nVerticesInThisPart,
    1226               0 :                                            padfX + panPartStart[i],
    1227               0 :                                            padfY + panPartStart[i],
    1228               0 :                                            padfZ + panPartStart[i] );
    1229               0 :                         tabPolygons[i]->addRingDirectly(poRing);
    1230                 :                     }
    1231                 : 
    1232                 :                     int isValidGeometry;
    1233               0 :                     const char* papszOptions[] = { "METHOD=ONLY_CCW", NULL };
    1234                 :                     poOGR = OGRGeometryFactory::organizePolygons(
    1235               0 :                         (OGRGeometry**)tabPolygons, nParts, &isValidGeometry, papszOptions );
    1236                 : 
    1237               0 :                     if (!isValidGeometry)
    1238                 :                     {
    1239                 :                         CPLError(CE_Warning, CPLE_AppDefined,
    1240                 :                                  "Geometry of polygon cannot be translated to Simple Geometry. "
    1241               0 :                                  "All polygons will be contained in a multipolygon.\n");
    1242                 :                     }
    1243                 : 
    1244               0 :                     *ppoGeom = poOGR;
    1245               0 :                     delete[] tabPolygons;
    1246                 :                 }
    1247                 :             }
    1248                 :         } /* polygon */
    1249                 : 
    1250                 : /* -------------------------------------------------------------------- */
    1251                 : /*      Multipatch                                                      */
    1252                 : /* -------------------------------------------------------------------- */
    1253               0 :         else if( bIsMultiPatch )
    1254                 :         {
    1255                 :             *ppoGeom = OGRCreateFromMultiPatch( nParts,
    1256                 :                                                 panPartStart,
    1257                 :                                                 panPartType,
    1258                 :                                                 nPoints,
    1259                 :                                                 padfX,
    1260                 :                                                 padfY,
    1261               0 :                                                 padfZ );
    1262                 :         }
    1263                 : 
    1264          273813 :         CPLFree( panPartStart );
    1265          273813 :         CPLFree( panPartType );
    1266          273813 :         CPLFree( padfX );
    1267          273813 :         CPLFree( padfY );
    1268          273813 :         CPLFree( padfZ );
    1269                 : 
    1270          273813 :         if (*ppoGeom != NULL)
    1271          273813 :             (*ppoGeom)->setCoordinateDimension( bHasZ ? 3 : 2 );
    1272                 : 
    1273          273813 :         return OGRERR_NONE;
    1274                 :     }
    1275                 : 
    1276                 : /* ==================================================================== */
    1277                 : /*  Extract vertices for a MultiPoint.                  */
    1278                 : /* ==================================================================== */
    1279             525 :     else if(    nSHPType == SHPT_MULTIPOINT
    1280                 :              || nSHPType == SHPT_MULTIPOINTM
    1281                 :              || nSHPType == SHPT_MULTIPOINTZ
    1282                 :              || nSHPType == SHPT_MULTIPOINTZM )
    1283                 :     {
    1284                 :       GInt32 nPoints;
    1285                 :       GInt32 nOffsetZ;
    1286                 :       int i;
    1287                 : 
    1288                 :       int bHasZ = (  nSHPType == SHPT_MULTIPOINTZ
    1289             120 :                   || nSHPType == SHPT_MULTIPOINTZM );
    1290                 : 
    1291                 :                 
    1292             120 :       memcpy( &nPoints, pabyShape + 36, 4 );
    1293                 :       CPL_LSBPTR32( &nPoints );
    1294                 : 
    1295             120 :       if (nPoints < 0 || nPoints > 50 * 1000 * 1000 )
    1296                 :       {
    1297                 :           CPLError(CE_Failure, CPLE_AppDefined, "Corrupted Shape : nPoints=%d.",
    1298               0 :                    nPoints);
    1299               0 :           return OGRERR_FAILURE;
    1300                 :       }
    1301                 : 
    1302             120 :       nOffsetZ = 40 + 2*8*nPoints + 2*8;
    1303                 :     
    1304             120 :       OGRMultiPoint *poMultiPt = new OGRMultiPoint;
    1305             120 :       *ppoGeom = poMultiPt;
    1306                 : 
    1307             360 :       for( i = 0; i < nPoints; i++ )
    1308                 :       {
    1309                 :           double x, y, z;
    1310             240 :           OGRPoint *poPt = new OGRPoint;
    1311                 :         
    1312                 :           /* Copy X */
    1313             240 :           memcpy(&x, pabyShape + 40 + i*16, 8);
    1314                 :           CPL_LSBPTR64(&x);
    1315             240 :           poPt->setX(x);
    1316                 :         
    1317                 :           /* Copy Y */
    1318             240 :           memcpy(&y, pabyShape + 40 + i*16 + 8, 8);
    1319                 :           CPL_LSBPTR64(&y);
    1320             240 :           poPt->setY(y);
    1321                 :         
    1322                 :           /* Copy Z */
    1323             240 :           if ( bHasZ )
    1324                 :           {
    1325             120 :             memcpy(&z, pabyShape + nOffsetZ + i*8, 8);
    1326                 :             CPL_LSBPTR64(&z);
    1327             120 :             poPt->setZ(z);
    1328                 :           }
    1329                 :         
    1330             240 :           poMultiPt->addGeometryDirectly( poPt );
    1331                 :       }
    1332                 :       
    1333             120 :       poMultiPt->setCoordinateDimension( bHasZ ? 3 : 2 );
    1334                 :       
    1335             120 :       return OGRERR_NONE;
    1336                 :     }
    1337                 : 
    1338                 : /* ==================================================================== */
    1339                 : /*      Extract vertices for a point.                                   */
    1340                 : /* ==================================================================== */
    1341             405 :     else if(    nSHPType == SHPT_POINT
    1342                 :              || nSHPType == SHPT_POINTM
    1343                 :              || nSHPType == SHPT_POINTZ
    1344                 :              || nSHPType == SHPT_POINTZM )
    1345                 :     {
    1346                 :         int nOffset;
    1347             405 :         double  dfX, dfY, dfZ = 0;
    1348                 : 
    1349             405 :         int bHasZ = (nSHPType == SHPT_POINTZ || nSHPType == SHPT_POINTZM);
    1350                 : 
    1351             405 :         if (nBytes < 4 + 8 + 8 + ((bHasZ) ? 8 : 0))
    1352                 :         {
    1353                 :             CPLError(CE_Failure, CPLE_AppDefined,
    1354               0 :                      "Corrupted Shape : nBytes=%d, nSHPType=%d", nBytes, nSHPType);
    1355               0 :             return OGRERR_FAILURE;
    1356                 :         }
    1357                 : 
    1358             405 :         memcpy( &dfX, pabyShape + 4, 8 );
    1359             405 :         memcpy( &dfY, pabyShape + 4 + 8, 8 );
    1360                 : 
    1361                 :         CPL_LSBPTR64( &dfX );
    1362                 :         CPL_LSBPTR64( &dfY );
    1363             405 :         nOffset = 20 + 8;
    1364                 : 
    1365             405 :         if( bHasZ )
    1366                 :         {
    1367             339 :             memcpy( &dfZ, pabyShape + 4 + 16, 8 );
    1368                 :             CPL_LSBPTR64( &dfZ );
    1369                 :         }
    1370                 : 
    1371             405 :         *ppoGeom = new OGRPoint( dfX, dfY, dfZ );
    1372             744 :         (*ppoGeom)->setCoordinateDimension( bHasZ ? 3 : 2 );
    1373                 : 
    1374             405 :         return OGRERR_NONE;
    1375                 :     }
    1376                 : 
    1377                 :     CPLError(CE_Failure, CPLE_AppDefined,
    1378                 :              "Unsupported geometry type: %d", 
    1379               0 :               nSHPType );
    1380                 : 
    1381               0 :     return OGRERR_FAILURE;
    1382                 : }

Generated by: LCOV version 1.7