LCOV - code coverage report
Current view: directory - ogr/ogrsf_frmts/shape - shape2ogr.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 491 455 92.7 %
Date: 2012-12-26 Functions: 8 8 100.0 %

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

Generated by: LCOV version 1.7