LTP GCOV extension - code coverage report
Current view: directory - ogr/ogrsf_frmts/shape - shape2ogr.cpp
Test: gdal_filtered.info
Date: 2010-07-12 Instrumented lines: 414
Code covered: 93.2 % Executed lines: 386

       1                 : /******************************************************************************
       2                 :  * $Id: shape2ogr.cpp 19964 2010-07-04 16:27:05Z warmerdam $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  Implements translation of Shapefile shapes into OGR
       6                 :  *           representation.
       7                 :  * Author:   Frank Warmerdam, warmerda@home.com
       8                 :  *
       9                 :  ******************************************************************************
      10                 :  * Copyright (c) 1999,  Les Technologies SoftMap Inc.
      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 "ogrshape.h"
      32                 : #include "cpl_conv.h"
      33                 : 
      34                 : CPL_CVSID("$Id: shape2ogr.cpp 19964 2010-07-04 16:27:05Z warmerdam $");
      35                 : 
      36                 : static const double EPSILON = 1E-5;
      37                 : 
      38                 : /************************************************************************/
      39                 : /*                            epsilonEqual()                            */
      40                 : /************************************************************************/
      41                 : 
      42                 : static inline bool epsilonEqual(double a, double b, double eps) 
      43                 : {
      44                 :     return (::fabs(a - b) < eps);
      45                 : }
      46                 : 
      47                 : /************************************************************************/
      48                 : /*                        RingStartEnd                                  */
      49                 : /*        set first and last vertex for given ring                      */
      50                 : /************************************************************************/
      51            1248 : void RingStartEnd ( SHPObject *psShape, int ring, int *start, int *end )
      52                 : {
      53            1248 :     if( psShape->panPartStart == NULL )
      54                 :     {
      55               0 :       *start = 0;
      56               0 :         *end = psShape->nVertices - 1;
      57                 :     }
      58                 :     else
      59                 :     {
      60            1248 :         if( ring == psShape->nParts - 1 )
      61            1200 :             *end = psShape->nVertices - 1;
      62                 :         else
      63              48 :             *end = psShape->panPartStart[ring+1] - 1;
      64                 : 
      65            1248 :         *start = psShape->panPartStart[ring];
      66                 :     }
      67            1248 : }
      68                 :     
      69                 : /************************************************************************/
      70                 : /*                        CreateLinearRing                              */
      71                 : /*                                                                      */
      72                 : /************************************************************************/
      73            1248 : OGRLinearRing * CreateLinearRing ( SHPObject *psShape, int ring )
      74                 : {
      75                 :     OGRLinearRing *poRing;
      76                 :     int nRingStart, nRingEnd, nRingPoints;
      77                 : 
      78            1248 :     poRing = new OGRLinearRing();
      79                 : 
      80            1248 :     RingStartEnd ( psShape, ring, &nRingStart, &nRingEnd );
      81                 : 
      82            1248 :     nRingPoints = nRingEnd - nRingStart + 1;
      83                 : 
      84                 :     poRing->setPoints( nRingPoints, psShape->padfX + nRingStart, 
      85            1248 :          psShape->padfY + nRingStart, psShape->padfZ + nRingStart );
      86                 : 
      87            1248 :     return ( poRing );
      88                 : }
      89                 : 
      90                 : 
      91                 : /************************************************************************/
      92                 : /*                          SHPReadOGRObject()                          */
      93                 : /*                                                                      */
      94                 : /*      Read an item in a shapefile, and translate to OGR geometry      */
      95                 : /*      representation.                                                 */
      96                 : /************************************************************************/
      97                 : 
      98           17322 : OGRGeometry *SHPReadOGRObject( SHPHandle hSHP, int iShape, SHPObject *psShape )
      99                 : {
     100                 :     // CPLDebug( "Shape", "SHPReadOGRObject( iShape=%d )\n", iShape );
     101                 : 
     102           17322 :     OGRGeometry *poOGR = NULL;
     103                 : 
     104           17322 :     if( psShape == NULL )
     105           17256 :         psShape = SHPReadObject( hSHP, iShape );
     106                 : 
     107           17322 :     if( psShape == NULL )
     108                 :     {
     109              10 :         return NULL;
     110                 :     }
     111                 : 
     112                 : /* -------------------------------------------------------------------- */
     113                 : /*      Point.                                                          */
     114                 : /* -------------------------------------------------------------------- */
     115           31989 :     else if( psShape->nSHPType == SHPT_POINT
     116                 :              || psShape->nSHPType == SHPT_POINTM
     117                 :              || psShape->nSHPType == SHPT_POINTZ )
     118                 :     {
     119                 :         poOGR = new OGRPoint( psShape->padfX[0], psShape->padfY[0],
     120           14677 :                               psShape->padfZ[0] );
     121                 : 
     122           14677 :         if( psShape->nSHPType == SHPT_POINT )
     123                 :         {
     124              34 :             poOGR->setCoordinateDimension( 2 );
     125                 :         }
     126                 :     }
     127                 : 
     128                 : /* -------------------------------------------------------------------- */
     129                 : /*      Multipoint.                                                     */
     130                 : /* -------------------------------------------------------------------- */
     131            2643 :     else if( psShape->nSHPType == SHPT_MULTIPOINT
     132                 :              || psShape->nSHPType == SHPT_MULTIPOINTM
     133                 :              || psShape->nSHPType == SHPT_MULTIPOINTZ )
     134                 :     {
     135               8 :         if (psShape->nVertices == 0)
     136                 :         {
     137               1 :             poOGR = NULL;
     138                 :         }
     139                 :         else
     140                 :         {
     141               7 :             OGRMultiPoint *poOGRMPoint = new OGRMultiPoint();
     142                 :             int             i;
     143                 : 
     144              20 :             for( i = 0; i < psShape->nVertices; i++ )
     145                 :             {
     146                 :                 OGRPoint    *poPoint;
     147                 : 
     148                 :                 poPoint = new OGRPoint( psShape->padfX[i], psShape->padfY[i],
     149              13 :                                         psShape->padfZ[i] );
     150                 : 
     151              13 :                 poOGRMPoint->addGeometry( poPoint );
     152                 : 
     153              26 :                 delete poPoint;
     154                 :             }
     155                 : 
     156               7 :             poOGR = poOGRMPoint;
     157                 : 
     158               7 :             if( psShape->nSHPType == SHPT_MULTIPOINT )
     159               5 :                 poOGR->setCoordinateDimension( 2 );
     160                 :         }
     161                 :     }
     162                 : 
     163                 : /* -------------------------------------------------------------------- */
     164                 : /*      Arc (LineString)                                                */
     165                 : /*                                                                      */
     166                 : /*      I am ignoring parts though they can apply to arcs as well.      */
     167                 : /* -------------------------------------------------------------------- */
     168            4031 :     else if( psShape->nSHPType == SHPT_ARC
     169                 :              || psShape->nSHPType == SHPT_ARCM
     170                 :              || psShape->nSHPType == SHPT_ARCZ )
     171                 :     {
     172            1404 :         if( psShape->nParts == 0 )
     173                 :         {
     174               1 :             poOGR = NULL;
     175                 :         }
     176            1403 :         else if( psShape->nParts == 1 )
     177                 :         {
     178            1395 :             OGRLineString *poOGRLine = new OGRLineString();
     179                 : 
     180                 :             poOGRLine->setPoints( psShape->nVertices,
     181            1395 :                                   psShape->padfX, psShape->padfY, psShape->padfZ );
     182                 : 
     183            1395 :             poOGR = poOGRLine;
     184                 :         }
     185                 :         else
     186                 :         {
     187                 :             int iRing;
     188                 :             OGRMultiLineString *poOGRMulti;
     189                 :         
     190               8 :             poOGR = poOGRMulti = new OGRMultiLineString();
     191                 :             
     192              25 :             for( iRing = 0; iRing < psShape->nParts; iRing++ )
     193                 :             {
     194                 :                 OGRLineString   *poLine;
     195                 :                 int     nRingPoints;
     196                 :                 int     nRingStart;
     197                 : 
     198              17 :                 poLine = new OGRLineString();
     199                 : 
     200              17 :                 if( psShape->panPartStart == NULL )
     201                 :                 {
     202               0 :                     nRingPoints = psShape->nVertices;
     203               0 :                     nRingStart = 0;
     204                 :                 }
     205                 :                 else
     206                 :                 {
     207                 : 
     208              17 :                     if( iRing == psShape->nParts - 1 )
     209                 :                         nRingPoints =
     210               8 :                             psShape->nVertices - psShape->panPartStart[iRing];
     211                 :                     else
     212                 :                         nRingPoints = psShape->panPartStart[iRing+1]
     213               9 :                             - psShape->panPartStart[iRing];
     214              17 :                     nRingStart = psShape->panPartStart[iRing];
     215                 :                 }
     216                 :             
     217                 :                 poLine->setPoints( nRingPoints, 
     218                 :                                    psShape->padfX + nRingStart,
     219                 :                                    psShape->padfY + nRingStart,
     220              17 :                                    psShape->padfZ + nRingStart );
     221                 : 
     222              17 :                 poOGRMulti->addGeometryDirectly( poLine );
     223                 :             }
     224                 :         }
     225                 : 
     226            1404 :         if( poOGR != NULL && psShape->nSHPType == SHPT_ARC )
     227             147 :             poOGR->setCoordinateDimension( 2 );
     228                 :     }
     229                 : 
     230                 : /* -------------------------------------------------------------------- */
     231                 : /*      Polygon                                                         */
     232                 : /*                                                                      */
     233                 : /* As for now Z coordinate is not handled correctly                     */
     234                 : /* -------------------------------------------------------------------- */
     235            2423 :     else if( psShape->nSHPType == SHPT_POLYGON
     236                 :              || psShape->nSHPType == SHPT_POLYGONM
     237                 :              || psShape->nSHPType == SHPT_POLYGONZ )
     238                 :     {
     239                 :         int iRing;
     240                 :         
     241                 :         //CPLDebug( "Shape", "Shape type: polygon with nParts=%d \n", psShape->nParts );
     242                 : 
     243            1200 :         if ( psShape->nParts == 0 )
     244                 :         {
     245               1 :             poOGR = NULL;
     246                 :         }
     247            1199 :         else if ( psShape->nParts == 1 )
     248                 :         {
     249                 :             /* Surely outer ring */
     250            1175 :             OGRPolygon *poOGRPoly = NULL;
     251            1175 :             OGRLinearRing *poRing = NULL;
     252                 : 
     253            1175 :             poOGR = poOGRPoly = new OGRPolygon();
     254            1175 :             poRing = CreateLinearRing ( psShape, 0 );
     255            1175 :             poOGRPoly->addRingDirectly( poRing );
     256                 :         }
     257                 : 
     258                 :         else
     259                 :         {
     260              24 :             OGRPolygon** tabPolygons = new OGRPolygon*[psShape->nParts];
     261             188 :             for( iRing = 0; iRing < psShape->nParts; iRing++ )
     262                 :             {
     263              70 :                 tabPolygons[iRing] = new OGRPolygon();
     264              70 :                 tabPolygons[iRing]->addRingDirectly(CreateLinearRing ( psShape, iRing ));
     265                 :             }
     266                 : 
     267                 :             int isValidGeometry;
     268              24 :             const char* papszOptions[] = { "METHOD=ONLY_CCW", NULL };
     269                 :             poOGR = OGRGeometryFactory::organizePolygons( 
     270              24 :                 (OGRGeometry**)tabPolygons, psShape->nParts, &isValidGeometry, papszOptions );
     271                 : 
     272              24 :             if (!isValidGeometry)
     273                 :             {
     274                 :                 CPLError(CE_Warning, CPLE_AppDefined, 
     275                 :                         "Geometry of polygon of fid %d cannot be translated to Simple Geometry. "
     276                 :                         "All polygons will be contained in a multipolygon.\n",
     277               0 :                         iShape);
     278                 :             }
     279                 : 
     280              24 :             delete[] tabPolygons;
     281                 :         }
     282                 : 
     283            1200 :         if( poOGR != NULL && psShape->nSHPType == SHPT_POLYGON )
     284                 :         {
     285            1195 :             poOGR->setCoordinateDimension( 2 );
     286                 :         }
     287                 :     }
     288                 : 
     289                 : /* -------------------------------------------------------------------- */
     290                 : /*      MultiPatch                                                      */
     291                 : /* -------------------------------------------------------------------- */
     292              23 :     else if( psShape->nSHPType == SHPT_MULTIPATCH )
     293                 :     {
     294               1 :         OGRMultiPolygon *poMP = new OGRMultiPolygon();
     295                 :         int iPart;
     296               1 :         OGRPolygon *poLastPoly = NULL;
     297                 : 
     298               6 :         for( iPart = 0; iPart < psShape->nParts; iPart++ )
     299                 :         {
     300                 :             int nPartPoints, nPartStart;
     301                 : 
     302                 :             // Figure out details about this part's vertex list.
     303               5 :             if( psShape->panPartStart == NULL )
     304                 :             {
     305               0 :                 nPartPoints = psShape->nVertices;
     306               0 :                 nPartStart = 0;
     307                 :             }
     308                 :             else
     309                 :             {
     310                 :                 
     311               5 :                 if( iPart == psShape->nParts - 1 )
     312                 :                     nPartPoints =
     313               1 :                         psShape->nVertices - psShape->panPartStart[iPart];
     314                 :                 else
     315                 :                     nPartPoints = psShape->panPartStart[iPart+1]
     316               4 :                         - psShape->panPartStart[iPart];
     317               5 :                 nPartStart = psShape->panPartStart[iPart];
     318                 :             }
     319                 : 
     320               5 :             if( psShape->panPartType[iPart] == SHPP_TRISTRIP )
     321                 :             {
     322                 :                 int iBaseVert;
     323                 : 
     324               1 :                 if( poLastPoly != NULL )
     325                 :                 {
     326               0 :                     poMP->addGeometryDirectly( poLastPoly );
     327               0 :                     poLastPoly = NULL;
     328                 :                 }
     329                 : 
     330              14 :                 for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
     331                 :                 {
     332               6 :                     OGRPolygon *poPoly = new OGRPolygon();
     333              12 :                     OGRLinearRing *poRing = new OGRLinearRing();
     334               6 :                     int iSrcVert = iBaseVert + nPartStart;
     335                 : 
     336                 :                     poRing->setPoint( 0, 
     337                 :                                       psShape->padfX[iSrcVert], 
     338                 :                                       psShape->padfY[iSrcVert], 
     339               6 :                                       psShape->padfZ[iSrcVert] );
     340                 :                     poRing->setPoint( 1, 
     341                 :                                       psShape->padfX[iSrcVert+1], 
     342                 :                                       psShape->padfY[iSrcVert+1], 
     343               6 :                                       psShape->padfZ[iSrcVert+1] );
     344                 : 
     345                 :                     poRing->setPoint( 2, 
     346                 :                                       psShape->padfX[iSrcVert+2], 
     347                 :                                       psShape->padfY[iSrcVert+2], 
     348               6 :                                       psShape->padfZ[iSrcVert+2] );
     349                 :                     poRing->setPoint( 3, 
     350                 :                                       psShape->padfX[iSrcVert], 
     351                 :                                       psShape->padfY[iSrcVert], 
     352               6 :                                       psShape->padfZ[iSrcVert] );
     353                 :                         
     354               6 :                     poPoly->addRingDirectly( poRing );
     355               6 :                     poMP->addGeometryDirectly( poPoly );
     356                 :                 }
     357                 :             }
     358               4 :             else if( psShape->panPartType[iPart] == SHPP_TRIFAN )
     359                 :             {
     360                 :                 int iBaseVert;
     361                 : 
     362               1 :                 if( poLastPoly != NULL )
     363                 :                 {
     364               0 :                     poMP->addGeometryDirectly( poLastPoly );
     365               0 :                     poLastPoly = NULL;
     366                 :                 }
     367                 : 
     368              10 :                 for( iBaseVert = 0; iBaseVert < nPartPoints-2; iBaseVert++ )
     369                 :                 {
     370               4 :                     OGRPolygon *poPoly = new OGRPolygon();
     371               8 :                     OGRLinearRing *poRing = new OGRLinearRing();
     372               4 :                     int iSrcVert = iBaseVert + nPartStart;
     373                 : 
     374                 :                     poRing->setPoint( 0, 
     375                 :                                       psShape->padfX[0], 
     376                 :                                       psShape->padfY[0], 
     377               4 :                                       psShape->padfZ[0] );
     378                 :                     poRing->setPoint( 1, 
     379                 :                                       psShape->padfX[iSrcVert+1], 
     380                 :                                       psShape->padfY[iSrcVert+1], 
     381               4 :                                       psShape->padfZ[iSrcVert+1] );
     382                 : 
     383                 :                     poRing->setPoint( 2, 
     384                 :                                       psShape->padfX[iSrcVert+2], 
     385                 :                                       psShape->padfY[iSrcVert+2], 
     386               4 :                                       psShape->padfZ[iSrcVert+2] );
     387                 :                     poRing->setPoint( 3, 
     388                 :                                       psShape->padfX[0], 
     389                 :                                       psShape->padfY[0], 
     390               4 :                                       psShape->padfZ[0] );
     391                 :                         
     392               4 :                     poPoly->addRingDirectly( poRing );
     393               4 :                     poMP->addGeometryDirectly( poPoly );
     394                 :                 }
     395                 :             }
     396               6 :             else if( psShape->panPartType[iPart] == SHPP_OUTERRING
     397                 :                      || psShape->panPartType[iPart] == SHPP_INNERRING
     398                 :                      || psShape->panPartType[iPart] == SHPP_FIRSTRING
     399                 :                      || psShape->panPartType[iPart] == SHPP_RING )
     400                 :             {
     401               3 :                 if( poLastPoly != NULL 
     402                 :                     && (psShape->panPartType[iPart] == SHPP_OUTERRING
     403                 :                         || psShape->panPartType[iPart] == SHPP_FIRSTRING) )
     404                 :                 {
     405               0 :                     poMP->addGeometryDirectly( poLastPoly );
     406               0 :                     poLastPoly = NULL;
     407                 :                 }
     408                 : 
     409               3 :                 if( poLastPoly == NULL )
     410               1 :                     poLastPoly = new OGRPolygon();
     411                 : 
     412                 :                 poLastPoly->addRingDirectly( 
     413               3 :                     CreateLinearRing( psShape, iPart ) );
     414                 :             }
     415                 :             else
     416                 :                 CPLDebug( "OGR", "Unrecognised parttype %d, ignored.", 
     417               0 :                           psShape->panPartType[iPart] );
     418                 :         }
     419                 : 
     420               1 :         if( poLastPoly != NULL )
     421                 :         {
     422               1 :             poMP->addGeometryDirectly( poLastPoly );
     423               1 :             poLastPoly = NULL;
     424                 :         }
     425                 : 
     426               1 :         poOGR = poMP;
     427                 :     }
     428                 : 
     429                 : /* -------------------------------------------------------------------- */
     430                 : /*      Otherwise for now we just ignore the object.                    */
     431                 : /* -------------------------------------------------------------------- */
     432                 :     else
     433                 :     {
     434              22 :         if( psShape->nSHPType != SHPT_NULL )
     435                 :         {
     436               0 :             CPLDebug( "OGR", "Unsupported shape type in SHPReadOGRObject()" );
     437                 :         }
     438                 : 
     439                 :         /* nothing returned */
     440                 :     }
     441                 :     
     442                 : /* -------------------------------------------------------------------- */
     443                 : /*      Cleanup shape, and set feature id.                              */
     444                 : /* -------------------------------------------------------------------- */
     445           17312 :     SHPDestroyObject( psShape );
     446                 : 
     447           17312 :     return poOGR;
     448                 : }
     449                 : 
     450                 : /************************************************************************/
     451                 : /*                         SHPWriteOGRObject()                          */
     452                 : /************************************************************************/
     453                 : 
     454           15899 : OGRErr SHPWriteOGRObject( SHPHandle hSHP, int iShape, OGRGeometry *poGeom )
     455                 : 
     456                 : {
     457                 :     int nReturnedShapeID;
     458                 : /* ==================================================================== */
     459                 : /*      Write "shape" with no geometry or with empty geometry           */
     460                 : /* ==================================================================== */
     461           15899 :     if( poGeom == NULL || poGeom->IsEmpty() )
     462                 :     {
     463                 :         SHPObject       *psShape;
     464                 : 
     465              15 :         psShape = SHPCreateSimpleObject( SHPT_NULL, 0, NULL, NULL, NULL );
     466              15 :         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
     467              15 :         SHPDestroyObject( psShape );
     468              15 :         if( nReturnedShapeID == -1 )
     469                 :         {
     470                 :             //Assuming error is reported by SHPWriteObject()
     471               0 :             return OGRERR_FAILURE;
     472                 :         }
     473                 :     }
     474                 : 
     475                 : /* ==================================================================== */
     476                 : /*      Write point geometry.                                           */
     477                 : /* ==================================================================== */
     478           30555 :     else if( hSHP->nShapeType == SHPT_POINT
     479                 :              || hSHP->nShapeType == SHPT_POINTM
     480                 :              || hSHP->nShapeType == SHPT_POINTZ )
     481                 :     {
     482                 :         SHPObject       *psShape;
     483           14677 :         OGRPoint        *poPoint = (OGRPoint *) poGeom;
     484           14677 :         double          dfX, dfY, dfZ = 0;
     485                 : 
     486           14677 :         if( poGeom->getGeometryType() != wkbPoint
     487                 :             && poGeom->getGeometryType() != wkbPoint25D )        
     488                 :         {
     489                 :             CPLError( CE_Failure, CPLE_AppDefined,
     490                 :                       "Attempt to write non-point (%s) geometry to"
     491                 :                       " point shapefile.",
     492               6 :                       poGeom->getGeometryName() );
     493                 : 
     494               6 :             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     495                 :         }
     496                 : 
     497           14671 :         dfX = poPoint->getX();
     498           14671 :         dfY = poPoint->getY();
     499           14671 :         dfZ = poPoint->getZ();
     500                 :         
     501                 :         psShape = SHPCreateSimpleObject( hSHP->nShapeType, 1,
     502           14671 :                                          &dfX, &dfY, &dfZ );
     503           14671 :         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
     504           14671 :         SHPDestroyObject( psShape );
     505           14671 :         if( nReturnedShapeID == -1 )
     506               0 :             return OGRERR_FAILURE;
     507                 :     }
     508                 : /* ==================================================================== */
     509                 : /*      MultiPoint.                                                     */
     510                 : /* ==================================================================== */
     511            1212 :     else if( hSHP->nShapeType == SHPT_MULTIPOINT
     512                 :              || hSHP->nShapeType == SHPT_MULTIPOINTM
     513                 :              || hSHP->nShapeType == SHPT_MULTIPOINTZ )
     514                 :     {
     515              11 :         OGRMultiPoint   *poMP = (OGRMultiPoint *) poGeom;
     516                 :         double          *padfX, *padfY, *padfZ;
     517                 :         int             iPoint;
     518                 :         SHPObject       *psShape;
     519                 : 
     520              11 :         if( wkbFlatten(poGeom->getGeometryType()) != wkbMultiPoint )
     521                 :         {
     522                 :             CPLError( CE_Failure, CPLE_AppDefined,
     523                 :                       "Attempt to write non-multipoint (%s) geometry to "
     524                 :                       "multipoint shapefile.",
     525               6 :                       poGeom->getGeometryName() );
     526                 : 
     527               6 :             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     528                 :         }
     529                 : 
     530               5 :         padfX = (double *) CPLMalloc(sizeof(double)*poMP->getNumGeometries());
     531               5 :         padfY = (double *) CPLMalloc(sizeof(double)*poMP->getNumGeometries());
     532               5 :         padfZ = (double *) CPLCalloc(sizeof(double),poMP->getNumGeometries());
     533                 : 
     534               5 :         int iDstPoints = 0;
     535              15 :         for( iPoint = 0; iPoint < poMP->getNumGeometries(); iPoint++ )
     536                 :         {
     537              10 :             OGRPoint    *poPoint = (OGRPoint *) poMP->getGeometryRef(iPoint);
     538                 : 
     539                 :             /* Ignore POINT EMPTY */
     540              10 :             if (poPoint->IsEmpty() == FALSE)
     541                 :             {
     542               9 :                 padfX[iDstPoints] = poPoint->getX();
     543               9 :                 padfY[iDstPoints] = poPoint->getY();
     544               9 :                 padfZ[iDstPoints] = poPoint->getZ();
     545               9 :                 iDstPoints ++;
     546                 :             }
     547                 :             else
     548                 :                 CPLDebug( "OGR", 
     549               1 :                               "Ignore POINT EMPTY inside MULTIPOINT in shapefile writer." );
     550                 :         }
     551                 : 
     552                 :         psShape = SHPCreateSimpleObject( hSHP->nShapeType,
     553                 :                                          iDstPoints,
     554               5 :                                          padfX, padfY, padfZ );
     555               5 :         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
     556               5 :         SHPDestroyObject( psShape );
     557                 :         
     558               5 :         CPLFree( padfX );
     559               5 :         CPLFree( padfY );
     560               5 :         CPLFree( padfZ );
     561               5 :         if( nReturnedShapeID == -1 )
     562               0 :             return OGRERR_FAILURE;
     563                 :     }
     564                 : 
     565                 : /* ==================================================================== */
     566                 : /*      Arcs from simple line strings.                                  */
     567                 : /* ==================================================================== */
     568            1196 :     else if( (hSHP->nShapeType == SHPT_ARC
     569                 :               || hSHP->nShapeType == SHPT_ARCM
     570                 :               || hSHP->nShapeType == SHPT_ARCZ)
     571                 :              && wkbFlatten(poGeom->getGeometryType()) == wkbLineString )
     572                 :     {
     573             762 :         OGRLineString   *poArc = (OGRLineString *) poGeom;
     574                 :         double          *padfX, *padfY, *padfZ;
     575                 :         int             iPoint;
     576                 :         SHPObject       *psShape;
     577                 : 
     578             762 :         padfX = (double *) CPLMalloc(sizeof(double)*poArc->getNumPoints());
     579             762 :         padfY = (double *) CPLMalloc(sizeof(double)*poArc->getNumPoints());
     580             762 :         padfZ = (double *) CPLCalloc(sizeof(double),poArc->getNumPoints());
     581                 : 
     582           22304 :         for( iPoint = 0; iPoint < poArc->getNumPoints(); iPoint++ )
     583                 :         {
     584           21542 :             padfX[iPoint] = poArc->getX( iPoint );
     585           21542 :             padfY[iPoint] = poArc->getY( iPoint );
     586           21542 :             padfZ[iPoint] = poArc->getZ( iPoint );
     587                 :         }
     588                 : 
     589                 :         psShape = SHPCreateSimpleObject( hSHP->nShapeType,
     590                 :                                          poArc->getNumPoints(),
     591             762 :                                          padfX, padfY, padfZ );
     592             762 :         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
     593             762 :         SHPDestroyObject( psShape );
     594                 :         
     595             762 :         CPLFree( padfX );
     596             762 :         CPLFree( padfY );
     597             762 :         CPLFree( padfZ );
     598             762 :         if( nReturnedShapeID == -1 )
     599               0 :             return OGRERR_FAILURE;
     600                 :     }
     601                 : /* ==================================================================== */
     602                 : /*      Arcs - Try to treat as MultiLineString.                         */
     603                 : /* ==================================================================== */
     604             440 :     else if( hSHP->nShapeType == SHPT_ARC
     605                 :              || hSHP->nShapeType == SHPT_ARCM
     606                 :              || hSHP->nShapeType == SHPT_ARCZ )
     607                 :     {
     608                 :         OGRMultiLineString *poML;
     609              18 :         double          *padfX=NULL, *padfY=NULL, *padfZ=NULL;
     610              18 :         int             iGeom, iPoint, nPointCount = 0;
     611                 :         SHPObject       *psShape;
     612                 :         int             *panRingStart;
     613              18 :         int             nParts = 0;
     614                 : 
     615                 :         poML = (OGRMultiLineString *) 
     616              18 :             OGRGeometryFactory::forceToMultiLineString( poGeom->clone() );
     617                 : 
     618              18 :         if( wkbFlatten(poML->getGeometryType()) != wkbMultiLineString )
     619                 :         {
     620              12 :             delete poML;
     621                 :             CPLError( CE_Failure, CPLE_AppDefined,
     622                 :                       "Attempt to write non-linestring (%s) geometry to "
     623                 :                       "ARC type shapefile.",
     624              12 :                       poGeom->getGeometryName() );
     625                 : 
     626              12 :             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     627                 :         }
     628                 : 
     629                 :         panRingStart = (int *) 
     630               6 :             CPLMalloc(sizeof(int) * poML->getNumGeometries());
     631                 : 
     632              20 :         for( iGeom = 0; iGeom < poML->getNumGeometries(); iGeom++ )
     633                 :         {
     634                 :             OGRLineString *poArc = (OGRLineString *)
     635              14 :                 poML->getGeometryRef(iGeom);
     636              14 :             int nNewPoints = poArc->getNumPoints();
     637                 : 
     638                 :             /* Ignore LINESTRING EMPTY */
     639              14 :             if (nNewPoints == 0)
     640                 :             {
     641                 :                 CPLDebug( "OGR", 
     642               1 :                           "Ignore LINESTRING EMPTY inside MULTILINESTRING in shapefile writer." );
     643               1 :                 continue;
     644                 :             }
     645                 : 
     646              13 :             panRingStart[nParts ++] = nPointCount;
     647                 : 
     648                 :             padfX = (double *) 
     649              13 :                 CPLRealloc( padfX, sizeof(double)*(nNewPoints+nPointCount) );
     650                 :             padfY = (double *) 
     651              13 :                 CPLRealloc( padfY, sizeof(double)*(nNewPoints+nPointCount) );
     652                 :             padfZ = (double *) 
     653              13 :                 CPLRealloc( padfZ, sizeof(double)*(nNewPoints+nPointCount) );
     654                 : 
     655              68 :             for( iPoint = 0; iPoint < nNewPoints; iPoint++ )
     656                 :             {
     657              55 :                 padfX[nPointCount] = poArc->getX( iPoint );
     658              55 :                 padfY[nPointCount] = poArc->getY( iPoint );
     659              55 :                 padfZ[nPointCount] = poArc->getZ( iPoint );
     660              55 :                 nPointCount++;
     661                 :             }
     662                 :         }
     663                 : 
     664               6 :         CPLAssert(nParts != 0);
     665                 : 
     666                 :         psShape = SHPCreateObject( hSHP->nShapeType, iShape, 
     667                 :                                     nParts, 
     668                 :                                     panRingStart, NULL,
     669               6 :                                     nPointCount, padfX, padfY, padfZ, NULL);
     670               6 :         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
     671               6 :         SHPDestroyObject( psShape );
     672                 : 
     673               6 :         CPLFree( panRingStart );
     674               6 :         CPLFree( padfX );
     675               6 :         CPLFree( padfY );
     676               6 :         CPLFree( padfZ );
     677                 : 
     678               6 :         delete poML;
     679               6 :         if( nReturnedShapeID == -1 )
     680               0 :             return OGRERR_FAILURE;
     681                 :     }
     682                 : 
     683                 : /* ==================================================================== */
     684                 : /*      Polygons/MultiPolygons                                          */
     685                 : /* ==================================================================== */
     686             818 :     else if( hSHP->nShapeType == SHPT_POLYGON
     687                 :              || hSHP->nShapeType == SHPT_POLYGONM
     688                 :              || hSHP->nShapeType == SHPT_POLYGONZ )
     689                 :     {
     690                 :         OGRPolygon      *poPoly;
     691             416 :         OGRLinearRing   *poRing, **papoRings=NULL;
     692             416 :         double          *padfX=NULL, *padfY=NULL, *padfZ=NULL;
     693             416 :         int             iPoint, iRing, nRings, nVertex=0, *panRingStart;
     694                 :         SHPObject       *psShape;
     695                 : 
     696                 :         /* Collect list of rings */
     697                 : 
     698             416 :         if( wkbFlatten(poGeom->getGeometryType()) == wkbPolygon )
     699                 :         {
     700             382 :             poPoly =  (OGRPolygon *) poGeom;
     701                 : 
     702             382 :             if( poPoly->getExteriorRing() == NULL ||
     703                 :                 poPoly->getExteriorRing()->IsEmpty() )
     704                 :             {
     705                 :                 CPLDebug( "OGR", 
     706               1 :                           "Ignore POLYGON EMPTY in shapefile writer." );
     707               1 :                 nRings = 0;
     708                 :             }
     709                 :             else
     710                 :             {
     711             381 :                 int nSrcRings = poPoly->getNumInteriorRings()+1;
     712             381 :                 nRings = 0;
     713             381 :                 papoRings = (OGRLinearRing **) CPLMalloc(sizeof(void*)*nSrcRings);
     714             769 :                 for( iRing = 0; iRing < nSrcRings; iRing++ )
     715                 :                 {
     716             388 :                     if( iRing == 0 )
     717             381 :                         papoRings[nRings] = poPoly->getExteriorRing();
     718                 :                     else
     719               7 :                         papoRings[nRings] = poPoly->getInteriorRing( iRing-1 );
     720                 : 
     721                 :                     /* Ignore LINEARRING EMPTY */
     722             388 :                     if (papoRings[nRings]->getNumPoints() != 0)
     723             387 :                         nRings ++;
     724                 :                     else
     725                 :                         CPLDebug( "OGR", 
     726               1 :                                 "Ignore LINEARRING EMPTY inside POLYGON in shapefile writer." );
     727                 :                 }
     728                 :             }
     729                 :         }
     730              34 :         else if( wkbFlatten(poGeom->getGeometryType()) == wkbMultiPolygon
     731                 :                  || wkbFlatten(poGeom->getGeometryType()) 
     732                 :                                                 == wkbGeometryCollection )
     733                 :         {
     734              22 :             OGRGeometryCollection *poGC = (OGRGeometryCollection *) poGeom;
     735                 :             int         iGeom;
     736                 : 
     737              22 :             nRings = 0;
     738              60 :             for( iGeom=0; iGeom < poGC->getNumGeometries(); iGeom++ )
     739                 :             {
     740              39 :                 poPoly =  (OGRPolygon *) poGC->getGeometryRef( iGeom );
     741                 : 
     742              39 :                 if( wkbFlatten(poPoly->getGeometryType()) != wkbPolygon )
     743                 :                 {
     744               1 :                     CPLFree( papoRings );
     745                 :                     CPLError( CE_Failure, CPLE_AppDefined,
     746                 :                               "Attempt to write non-polygon (%s) geometry to "
     747                 :                               "POLYGON type shapefile.",
     748               1 :                               poGeom->getGeometryName());
     749                 : 
     750               1 :                     return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     751                 :                 }
     752                 : 
     753                 :                 /* Ignore POLYGON EMPTY */
     754              38 :                 if( poPoly->getExteriorRing() == NULL ||
     755                 :                     poPoly->getExteriorRing()->IsEmpty() )
     756                 :                 {
     757                 :                     CPLDebug( "OGR", 
     758               1 :                               "Ignore POLYGON EMPTY inside MULTIPOLYGON in shapefile writer." );
     759               1 :                     continue;
     760                 :                 }
     761                 : 
     762                 :                 papoRings = (OGRLinearRing **) CPLRealloc(papoRings, 
     763              37 :                      sizeof(void*) * (nRings+poPoly->getNumInteriorRings()+1));
     764              86 :                 for( iRing = 0; 
     765                 :                      iRing < poPoly->getNumInteriorRings()+1; 
     766                 :                      iRing++ )
     767                 :                 {
     768              49 :                     if( iRing == 0 )
     769              37 :                         papoRings[nRings] = poPoly->getExteriorRing();
     770                 :                     else
     771                 :                         papoRings[nRings] = 
     772              12 :                             poPoly->getInteriorRing( iRing-1 );
     773                 : 
     774                 :                     /* Ignore LINEARRING EMPTY */
     775              49 :                     if (papoRings[nRings]->getNumPoints() != 0)
     776              48 :                         nRings ++;
     777                 :                     else
     778                 :                         CPLDebug( "OGR", 
     779               1 :                               "Ignore LINEARRING EMPTY inside POLYGON in shapefile writer." );
     780                 :                 }
     781                 :             }
     782                 :         }
     783                 :         else 
     784                 :         {
     785                 :             CPLError( CE_Failure, CPLE_AppDefined,
     786                 :                       "Attempt to write non-polygon (%s) geometry to "
     787                 :                       "POLYGON type shapefile.",
     788              12 :                       poGeom->getGeometryName() );
     789                 : 
     790              12 :             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     791                 :         }
     792                 : 
     793                 : /* -------------------------------------------------------------------- */
     794                 : /*      If we only had emptypolygons or unacceptable geometries         */
     795                 : /*      write NULL geometry object.                                     */
     796                 : /* -------------------------------------------------------------------- */
     797             403 :         if( nRings == 0 )
     798                 :         {
     799                 :             SHPObject       *psShape;
     800                 :             
     801               1 :             psShape = SHPCreateSimpleObject( SHPT_NULL, 0, NULL, NULL, NULL );
     802               1 :             nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
     803               1 :             SHPDestroyObject( psShape );
     804                 : 
     805               1 :             if( nReturnedShapeID == -1 )
     806               0 :                 return OGRERR_FAILURE;
     807                 : 
     808               1 :             return OGRERR_NONE;
     809                 :         }
     810                 :         
     811                 :         /* count vertices */
     812             402 :         nVertex = 0;
     813             837 :         for( iRing = 0; iRing < nRings; iRing++ )
     814             435 :             nVertex += papoRings[iRing]->getNumPoints();
     815                 : 
     816             402 :         panRingStart = (int *) CPLMalloc(sizeof(int) * nRings);
     817             402 :         padfX = (double *) CPLMalloc(sizeof(double)*nVertex);
     818             402 :         padfY = (double *) CPLMalloc(sizeof(double)*nVertex);
     819             402 :         padfZ = (double *) CPLMalloc(sizeof(double)*nVertex);
     820                 : 
     821                 :         /* collect vertices */
     822             402 :         nVertex = 0;
     823             837 :         for( iRing = 0; iRing < nRings; iRing++ )
     824                 :         {
     825             435 :             poRing = papoRings[iRing];
     826             435 :             panRingStart[iRing] = nVertex;
     827                 : 
     828            8572 :             for( iPoint = 0; iPoint < poRing->getNumPoints(); iPoint++ )
     829                 :             {
     830            8137 :                 padfX[nVertex] = poRing->getX( iPoint );
     831            8137 :                 padfY[nVertex] = poRing->getY( iPoint );
     832            8137 :                 padfZ[nVertex] = poRing->getZ( iPoint );
     833            8137 :                 nVertex++;
     834                 :             }
     835                 :         }
     836                 : 
     837                 :         psShape = SHPCreateObject( hSHP->nShapeType, iShape, nRings,
     838                 :                                    panRingStart, NULL,
     839             402 :                                    nVertex, padfX, padfY, padfZ, NULL );
     840             402 :         SHPRewindObject( hSHP, psShape );
     841             402 :         nReturnedShapeID = SHPWriteObject( hSHP, iShape, psShape );
     842             402 :         SHPDestroyObject( psShape );
     843                 :         
     844             402 :         CPLFree( papoRings );
     845             402 :         CPLFree( panRingStart );
     846             402 :         CPLFree( padfX );
     847             402 :         CPLFree( padfY );
     848             402 :         CPLFree( padfZ );
     849             402 :         if( nReturnedShapeID == -1 )
     850               0 :             return OGRERR_FAILURE;
     851                 :     }
     852                 :     else
     853                 :     {
     854                 :         /* do nothing for multipatch */
     855               0 :         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     856                 :     }
     857                 : 
     858           15861 :     return OGRERR_NONE;
     859                 : }
     860                 : 
     861                 : /************************************************************************/
     862                 : /*                       SHPReadOGRFeatureDefn()                        */
     863                 : /************************************************************************/
     864                 : 
     865                 : OGRFeatureDefn *SHPReadOGRFeatureDefn( const char * pszName,
     866            1023 :                                        SHPHandle hSHP, DBFHandle hDBF )
     867                 : 
     868                 : {
     869            1023 :     OGRFeatureDefn      *poDefn = new OGRFeatureDefn( pszName );
     870                 :     int                 iField;
     871                 : 
     872            1023 :     poDefn->Reference();
     873                 : 
     874            2482 :     for( iField = 0; 
     875                 :          hDBF != NULL && iField < DBFGetFieldCount( hDBF ); 
     876                 :          iField++ )
     877                 :     {
     878                 :         char            szFieldName[20];
     879                 :         int             nWidth, nPrecision;
     880                 :         DBFFieldType    eDBFType;
     881            1459 :         OGRFieldDefn    oField("", OFTInteger);
     882                 :         char            chNativeType;
     883                 : 
     884            1459 :         chNativeType = DBFGetNativeFieldType( hDBF, iField );
     885                 :         eDBFType = DBFGetFieldInfo( hDBF, iField, szFieldName,
     886            1459 :                                     &nWidth, &nPrecision );
     887                 : 
     888            1459 :         oField.SetName( szFieldName );
     889            1459 :         oField.SetWidth( nWidth );
     890            1459 :         oField.SetPrecision( nPrecision );
     891                 : 
     892            1459 :         if( chNativeType == 'D' )
     893                 :         {
     894                 :             /* XXX - mloskot:
     895                 :              * Shapefile date has following 8-chars long format: 20060101.
     896                 :              * OGR splits it as YYYY/MM/DD, so 2 additional characters are required.
     897                 :              * Is this correct assumtion? What about time part of date?
     898                 :              * Shouldn't this format look as datetime: YYYY/MM/DD HH:MM:SS
     899                 :              * with 4 additional characters?
     900                 :              */
     901              22 :             oField.SetWidth( nWidth + 2 );
     902              22 :             oField.SetType( OFTDate );
     903                 :         }
     904            1437 :         else if( eDBFType == FTDouble )
     905            1042 :             oField.SetType( OFTReal );
     906             395 :         else if( eDBFType == FTInteger )
     907              54 :             oField.SetType( OFTInteger );
     908                 :         else
     909             341 :             oField.SetType( OFTString );
     910                 : 
     911            1459 :         poDefn->AddFieldDefn( &oField );
     912                 :     }
     913                 : 
     914            1023 :     if( hSHP == NULL )
     915              23 :         poDefn->SetGeomType( wkbNone );
     916                 :     else
     917                 :     {
     918            1000 :         switch( hSHP->nShapeType )
     919                 :         {
     920                 :           case SHPT_POINT:
     921                 :           case SHPT_POINTM:
     922              97 :             poDefn->SetGeomType( wkbPoint );
     923              97 :             break;
     924                 : 
     925                 :           case SHPT_POINTZ:
     926              46 :             poDefn->SetGeomType( wkbPoint25D );
     927              46 :             break;
     928                 : 
     929                 :           case SHPT_ARC:
     930                 :           case SHPT_ARCM:
     931             213 :             poDefn->SetGeomType( wkbLineString );
     932             213 :             break;
     933                 : 
     934                 :           case SHPT_ARCZ:
     935              76 :             poDefn->SetGeomType( wkbLineString25D );
     936              76 :             break;
     937                 : 
     938                 :           case SHPT_MULTIPOINT:
     939                 :           case SHPT_MULTIPOINTM:
     940              83 :             poDefn->SetGeomType( wkbMultiPoint );
     941              83 :             break;
     942                 : 
     943                 :           case SHPT_MULTIPOINTZ:
     944              41 :             poDefn->SetGeomType( wkbMultiPoint25D );
     945              41 :             break;
     946                 : 
     947                 :           case SHPT_POLYGON:
     948                 :           case SHPT_POLYGONM:
     949             379 :             poDefn->SetGeomType( wkbPolygon );
     950             379 :             break;
     951                 : 
     952                 :           case SHPT_POLYGONZ:
     953              62 :             poDefn->SetGeomType( wkbPolygon25D );
     954                 :             break;
     955                 :             
     956                 :         }
     957                 :     }
     958                 : 
     959            1023 :     return poDefn;
     960                 : }
     961                 : 
     962                 : /************************************************************************/
     963                 : /*                         SHPReadOGRFeature()                          */
     964                 : /************************************************************************/
     965                 : 
     966                 : OGRFeature *SHPReadOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
     967                 :                                OGRFeatureDefn * poDefn, int iShape,
     968           17809 :                                SHPObject *psShape )
     969                 : 
     970                 : {
     971           17809 :     if( iShape < 0 
     972                 :         || (hSHP != NULL && iShape >= hSHP->nRecords)
     973                 :         || (hDBF != NULL && iShape >= hDBF->nRecords) )
     974                 :     {
     975                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     976                 :                   "Attempt to read shape with feature id (%d) out of available"
     977               0 :                   " range.", iShape );
     978               0 :         return NULL;
     979                 :     }
     980                 : 
     981           17809 :     if( hDBF && DBFIsRecordDeleted( hDBF, iShape ) )
     982                 :     {
     983                 :         CPLError( CE_Failure, CPLE_AppDefined, 
     984                 :                   "Attempt to read shape with feature id (%d), but it is marked deleted.",
     985               0 :                   iShape );
     986               0 :         return NULL;
     987                 :     }
     988                 : 
     989           17809 :     OGRFeature  *poFeature = new OGRFeature( poDefn );
     990                 : 
     991                 : /* -------------------------------------------------------------------- */
     992                 : /*      Fetch geometry from Shapefile to OGRFeature.                    */
     993                 : /* -------------------------------------------------------------------- */
     994           17809 :     if( hSHP != NULL )
     995                 :     {
     996           17322 :         OGRGeometry* poGeometry = NULL;
     997           17322 :         poGeometry = SHPReadOGRObject( hSHP, iShape, psShape );
     998                 : 
     999                 :         /*
    1000                 :          * NOTE - mloskot:
    1001                 :          * Two possibilities are expected here (bot hare tested by GDAL Autotests):
    1002                 :          * 1. Read valid geometry and assign it directly.
    1003                 :          * 2. Read and assign null geometry if it can not be read correctly from a shapefile
    1004                 :          *
    1005                 :          * It's NOT required here to test poGeometry == NULL.
    1006                 :          */
    1007                 : 
    1008           17322 :         poFeature->SetGeometryDirectly( poGeometry );
    1009                 :     }
    1010                 : 
    1011                 : /* -------------------------------------------------------------------- */
    1012                 : /*      Fetch feature attributes to OGRFeature fields.                  */
    1013                 : /* -------------------------------------------------------------------- */
    1014                 : 
    1015           39113 :     for( int iField = 0; iField < poDefn->GetFieldCount(); iField++ )
    1016                 :     {
    1017                 :         // Skip null fields.
    1018           21304 :         if( DBFIsAttributeNULL( hDBF, iShape, iField ) )
    1019             510 :             continue;
    1020                 : 
    1021           20794 :         switch( poDefn->GetFieldDefn(iField)->GetType() )
    1022                 :         {
    1023                 :           case OFTString:
    1024                 :             poFeature->SetField( iField,
    1025                 :                                  DBFReadStringAttribute( hDBF, iShape,
    1026            1790 :                                                          iField ) );
    1027            1790 :             break;
    1028                 : 
    1029                 :           case OFTInteger:
    1030                 :             poFeature->SetField( iField,
    1031                 :                                  DBFReadIntegerAttribute( hDBF, iShape,
    1032            1684 :                                                           iField ) );
    1033            1684 :             break;
    1034                 : 
    1035                 :           case OFTReal:
    1036                 :             poFeature->SetField( iField,
    1037                 :                                  DBFReadDoubleAttribute( hDBF, iShape,
    1038           17318 :                                                          iField ) );
    1039           17318 :             break;
    1040                 : 
    1041                 :           case OFTDate:
    1042                 :           {
    1043                 :               OGRField sFld;
    1044                 :               const char* pszDateValue = 
    1045               2 :                   DBFReadStringAttribute(hDBF,iShape,iField); 
    1046                 : 
    1047               2 :               memset( &sFld, 0, sizeof(sFld) );
    1048                 : 
    1049               3 :               if( pszDateValue[2] == '/' && pszDateValue[5] == '/' 
    1050                 :                   && strlen(pszDateValue) >= 10 )
    1051                 :               {
    1052               1 :                   sFld.Date.Month = (GByte)atoi(pszDateValue+0);
    1053               1 :                   sFld.Date.Day   = (GByte)atoi(pszDateValue+3);
    1054               1 :                   sFld.Date.Year  = (GInt16)atoi(pszDateValue+6);
    1055                 :               }
    1056                 :               else
    1057                 :               {
    1058               1 :                   int nFullDate = atoi(pszDateValue);
    1059               1 :                   sFld.Date.Year = (GInt16)(nFullDate / 10000);
    1060               1 :                   sFld.Date.Month = (GByte)((nFullDate / 100) % 100);
    1061               1 :                   sFld.Date.Day = (GByte)(nFullDate % 100);
    1062                 :               }
    1063                 :               
    1064               2 :               poFeature->SetField( iField, &sFld );
    1065                 :           }
    1066               2 :           break;
    1067                 : 
    1068                 :           default:
    1069               0 :             CPLAssert( FALSE );
    1070                 :         }
    1071                 :     }
    1072                 : 
    1073           17809 :     if( poFeature != NULL )
    1074           17809 :         poFeature->SetFID( iShape );
    1075                 : 
    1076           17809 :     return( poFeature );
    1077                 : }
    1078                 : 
    1079                 : /************************************************************************/
    1080                 : /*                         SHPWriteOGRFeature()                         */
    1081                 : /*                                                                      */
    1082                 : /*      Write to an existing feature in a shapefile, or create a new    */
    1083                 : /*      feature.                                                        */
    1084                 : /************************************************************************/
    1085                 : 
    1086                 : OGRErr SHPWriteOGRFeature( SHPHandle hSHP, DBFHandle hDBF,
    1087                 :                            OGRFeatureDefn * poDefn, 
    1088           15921 :                            OGRFeature * poFeature )
    1089                 : 
    1090                 : {
    1091                 : #ifdef notdef
    1092                 : /* -------------------------------------------------------------------- */
    1093                 : /*      Don't write objects with missing geometry.                      */
    1094                 : /* -------------------------------------------------------------------- */
    1095                 :     if( poFeature->GetGeometryRef() == NULL && hSHP != NULL )
    1096                 :     {
    1097                 :         CPLError( CE_Failure, CPLE_AppDefined,
    1098                 :                   "Attempt to write feature without geometry not supported"
    1099                 :                   " for shapefile driver." );
    1100                 :         
    1101                 :         return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
    1102                 :     }
    1103                 : #endif
    1104                 : 
    1105                 : /* -------------------------------------------------------------------- */
    1106                 : /*      Write the geometry.                                             */
    1107                 : /* -------------------------------------------------------------------- */
    1108                 :     OGRErr      eErr;
    1109                 : 
    1110           15921 :     if( hSHP != NULL )
    1111                 :     {
    1112                 :         eErr = SHPWriteOGRObject( hSHP, poFeature->GetFID(),
    1113           15899 :                                   poFeature->GetGeometryRef() );
    1114           15899 :         if( eErr != OGRERR_NONE )
    1115              37 :             return eErr;
    1116                 :     }
    1117                 :     
    1118                 : /* -------------------------------------------------------------------- */
    1119                 : /*      If there is no DBF, the job is done now.                        */
    1120                 : /* -------------------------------------------------------------------- */
    1121           15884 :     if( hDBF == NULL )
    1122                 :     {
    1123                 : /* -------------------------------------------------------------------- */
    1124                 : /*      If this is a new feature, establish it's feature id.            */
    1125                 : /* -------------------------------------------------------------------- */
    1126              14 :         if( hSHP != NULL && poFeature->GetFID() == OGRNullFID )
    1127               1 :             poFeature->SetFID( hSHP->nRecords - 1 );
    1128                 : 
    1129              14 :         return OGRERR_NONE;
    1130                 :     }
    1131                 : 
    1132                 : /* -------------------------------------------------------------------- */
    1133                 : /*      If this is a new feature, establish it's feature id.            */
    1134                 : /* -------------------------------------------------------------------- */
    1135           15870 :     if( poFeature->GetFID() == OGRNullFID )
    1136           15867 :         poFeature->SetFID( DBFGetRecordCount( hDBF ) );
    1137                 : 
    1138                 : /* -------------------------------------------------------------------- */
    1139                 : /*      If this is the first feature to be written, verify that we      */
    1140                 : /*      have at least one attribute in the DBF file.  If not, create    */
    1141                 : /*      a dummy FID attribute to satisfy the requirement that there     */
    1142                 : /*      be at least one attribute.                                      */
    1143                 : /* -------------------------------------------------------------------- */
    1144           15870 :     if( DBFGetRecordCount( hDBF ) == 0 && DBFGetFieldCount( hDBF ) == 0 )
    1145                 :     {
    1146                 :         CPLDebug( "OGR", 
    1147              62 :                "Created dummy FID field for shapefile since schema is empty.");
    1148              62 :         DBFAddField( hDBF, "FID", FTInteger, 11, 0 );
    1149                 :     }
    1150                 : 
    1151                 : /* -------------------------------------------------------------------- */
    1152                 : /*      Write out dummy field value if it exists.                       */
    1153                 : /* -------------------------------------------------------------------- */
    1154           15870 :     if( DBFGetFieldCount( hDBF ) == 1 && poDefn->GetFieldCount() == 0 )
    1155                 :     {
    1156                 :         DBFWriteIntegerAttribute( hDBF, poFeature->GetFID(), 0, 
    1157           14705 :                                   poFeature->GetFID() );
    1158                 :     }
    1159                 : 
    1160                 : /* -------------------------------------------------------------------- */
    1161                 : /*      Write all the fields.                                           */
    1162                 : /* -------------------------------------------------------------------- */
    1163           17841 :     for( int iField = 0; iField < poDefn->GetFieldCount(); iField++ )
    1164                 :     {
    1165            1971 :         if( !poFeature->IsFieldSet( iField ) )
    1166                 :         {
    1167               2 :             DBFWriteNULLAttribute( hDBF, poFeature->GetFID(), iField );
    1168               2 :             continue;
    1169                 :         }
    1170                 : 
    1171            1969 :         switch( poDefn->GetFieldDefn(iField)->GetType() )
    1172                 :         {
    1173                 :           case OFTString:
    1174                 :             DBFWriteStringAttribute( hDBF, poFeature->GetFID(), iField, 
    1175             368 :                                      poFeature->GetFieldAsString( iField ));
    1176             368 :             break;
    1177                 : 
    1178                 :           case OFTInteger:
    1179                 :             DBFWriteIntegerAttribute( hDBF, poFeature->GetFID(), iField, 
    1180             805 :                                       poFeature->GetFieldAsInteger(iField) );
    1181             805 :             break;
    1182                 : 
    1183                 :           case OFTReal:
    1184                 :             DBFWriteDoubleAttribute( hDBF, poFeature->GetFID(), iField, 
    1185             795 :                                      poFeature->GetFieldAsDouble(iField) );
    1186             795 :             break;
    1187                 : 
    1188                 :           case OFTDate:
    1189                 :           {
    1190                 :               int  nYear, nMonth, nDay;
    1191                 : 
    1192               1 :               if( poFeature->GetFieldAsDateTime( iField, &nYear, &nMonth, &nDay,
    1193                 :                                                  NULL, NULL, NULL, NULL ) )
    1194                 :               {
    1195                 :                   DBFWriteIntegerAttribute( hDBF, poFeature->GetFID(), iField, 
    1196               1 :                                             nYear*10000 + nMonth*100 + nDay );
    1197                 :               }
    1198                 :           }
    1199                 :           break;
    1200                 : 
    1201                 :           default:
    1202                 :           {
    1203                 :               /* Ignore fields of other types */
    1204                 :               break;
    1205                 :           }
    1206                 :         }
    1207                 :     }
    1208                 : 
    1209           15870 :     return OGRERR_NONE;
    1210                 : }
    1211                 : 

Generated by: LTP GCOV extension version 1.5