LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/shape - shape2ogr.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 367 349 95.1 %
Date: 2010-01-09 Functions: 7 7 100.0 %

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

Generated by: LCOV version 1.7