LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/shape - shape2ogr.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 453 424 93.6 %
Date: 2011-12-18 Functions: 7 7 100.0 %

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

Generated by: LCOV version 1.7