LCOV - code coverage report
Current view: directory - ogr - ogrgeometrycollection.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 366 320 87.4 %
Date: 2012-04-28 Functions: 35 33 94.3 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrgeometrycollection.cpp 23952 2012-02-12 01:11:40Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  The OGRGeometryCollection class.
       6                 :  * Author:   Frank Warmerdam, warmerdam@pobox.com
       7                 :  *
       8                 :  ******************************************************************************
       9                 :  * Copyright (c) 1999, Frank Warmerdam
      10                 :  *
      11                 :  * Permission is hereby granted, free of charge, to any person obtaining a
      12                 :  * copy of this software and associated documentation files (the "Software"),
      13                 :  * to deal in the Software without restriction, including without limitation
      14                 :  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      15                 :  * and/or sell copies of the Software, and to permit persons to whom the
      16                 :  * Software is furnished to do so, subject to the following conditions:
      17                 :  *
      18                 :  * The above copyright notice and this permission notice shall be included
      19                 :  * in all copies or substantial portions of the Software.
      20                 :  *
      21                 :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
      22                 :  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
      24                 :  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
      26                 :  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
      27                 :  * DEALINGS IN THE SOFTWARE.
      28                 :  ****************************************************************************/
      29                 : 
      30                 : #include "ogr_geometry.h"
      31                 : #include "ogr_p.h"
      32                 : 
      33                 : CPL_CVSID("$Id: ogrgeometrycollection.cpp 23952 2012-02-12 01:11:40Z rouault $");
      34                 : 
      35                 : /************************************************************************/
      36                 : /*                       OGRGeometryCollection()                        */
      37                 : /************************************************************************/
      38                 : 
      39                 : /**
      40                 :  * \brief Create an empty geometry collection.
      41                 :  */
      42                 : 
      43            6161 : OGRGeometryCollection::OGRGeometryCollection()
      44                 : 
      45                 : {
      46            6161 :     nGeomCount = 0;
      47            6161 :     papoGeoms = NULL;
      48            6161 : }
      49                 : 
      50                 : /************************************************************************/
      51                 : /*                       ~OGRGeometryCollection()                       */
      52                 : /************************************************************************/
      53                 : 
      54            6097 : OGRGeometryCollection::~OGRGeometryCollection()
      55                 : 
      56                 : {
      57            6097 :     empty();
      58            6097 : }
      59                 : 
      60                 : /************************************************************************/
      61                 : /*                               empty()                                */
      62                 : /************************************************************************/
      63                 : 
      64            8292 : void OGRGeometryCollection::empty()
      65                 : 
      66                 : {
      67            8292 :     if( papoGeoms != NULL )
      68                 :     {
      69           15257 :         for( int i = 0; i < nGeomCount; i++ )
      70                 :         {
      71            9910 :             delete papoGeoms[i];
      72                 :         }
      73            5347 :         OGRFree( papoGeoms );
      74                 :     }
      75                 : 
      76            8292 :     nGeomCount = 0;
      77            8292 :     papoGeoms = NULL;
      78            8292 :     nCoordDimension = 2;
      79            8292 : }
      80                 : 
      81                 : 
      82                 : /************************************************************************/
      83                 : /*                               clone()                                */
      84                 : /************************************************************************/
      85                 : 
      86             230 : OGRGeometry *OGRGeometryCollection::clone() const
      87                 : 
      88                 : {
      89                 :     OGRGeometryCollection       *poNewGC;
      90                 : 
      91             230 :     poNewGC = new OGRGeometryCollection;
      92             230 :     poNewGC->assignSpatialReference( getSpatialReference() );
      93                 : 
      94             608 :     for( int i = 0; i < nGeomCount; i++ )
      95                 :     {
      96             378 :         poNewGC->addGeometry( papoGeoms[i] );
      97                 :     }
      98                 : 
      99             230 :     return poNewGC;
     100                 : }
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                          getGeometryType()                           */
     104                 : /************************************************************************/
     105                 : 
     106            1422 : OGRwkbGeometryType OGRGeometryCollection::getGeometryType() const
     107                 : 
     108                 : {
     109            1422 :     if( getCoordinateDimension() == 3 )
     110             418 :         return wkbGeometryCollection25D;
     111                 :     else
     112            1004 :         return wkbGeometryCollection;
     113                 : }
     114                 : 
     115                 : /************************************************************************/
     116                 : /*                            getDimension()                            */
     117                 : /************************************************************************/
     118                 : 
     119               0 : int OGRGeometryCollection::getDimension() const
     120                 : 
     121                 : {
     122               0 :     return 2; // This isn't strictly correct.  It should be based on members.
     123                 : }
     124                 : 
     125                 : /************************************************************************/
     126                 : /*                            flattenTo2D()                             */
     127                 : /************************************************************************/
     128                 : 
     129               6 : void OGRGeometryCollection::flattenTo2D()
     130                 : 
     131                 : {
     132              24 :     for( int i = 0; i < nGeomCount; i++ )
     133              18 :         papoGeoms[i]->flattenTo2D();
     134                 : 
     135               6 :     nCoordDimension = 2;
     136               6 : }
     137                 : 
     138                 : /************************************************************************/
     139                 : /*                          getGeometryName()                           */
     140                 : /************************************************************************/
     141                 : 
     142             604 : const char * OGRGeometryCollection::getGeometryName() const
     143                 : 
     144                 : {
     145             604 :     return "GEOMETRYCOLLECTION";
     146                 : }
     147                 : 
     148                 : /************************************************************************/
     149                 : /*                          getNumGeometries()                          */
     150                 : /************************************************************************/
     151                 : 
     152                 : /**
     153                 :  * \brief Fetch number of geometries in container.
     154                 :  *
     155                 :  * This method relates to the SFCOM IGeometryCollect::get_NumGeometries()
     156                 :  * method.
     157                 :  *
     158                 :  * @return count of children geometries.  May be zero.
     159                 :  */
     160                 : 
     161            8538 : int OGRGeometryCollection::getNumGeometries() const
     162                 : 
     163                 : {
     164            8538 :     return nGeomCount;
     165                 : }
     166                 : 
     167                 : /************************************************************************/
     168                 : /*                           getGeometryRef()                           */
     169                 : /************************************************************************/
     170                 : 
     171                 : /**
     172                 :  * \brief Fetch geometry from container.
     173                 :  *
     174                 :  * This method returns a pointer to an geometry within the container.  The
     175                 :  * returned geometry remains owned by the container, and should not be
     176                 :  * modified.  The pointer is only valid untill the next change to the
     177                 :  * geometry container.  Use IGeometry::clone() to make a copy.
     178                 :  *
     179                 :  * This method relates to the SFCOM IGeometryCollection::get_Geometry() method.
     180                 :  *
     181                 :  * @param i the index of the geometry to fetch, between 0 and
     182                 :  *          getNumGeometries() - 1.
     183                 :  * @return pointer to requested geometry.
     184                 :  */
     185                 : 
     186            4492 : OGRGeometry * OGRGeometryCollection::getGeometryRef( int i ) 
     187                 : 
     188                 : {
     189            4492 :     if( i < 0 || i >= nGeomCount )
     190               0 :         return NULL;
     191                 :     else
     192            4492 :         return papoGeoms[i];
     193                 : }
     194                 : 
     195            2362 : const OGRGeometry * OGRGeometryCollection::getGeometryRef( int i ) const
     196                 : 
     197                 : {
     198            2362 :     if( i < 0 || i >= nGeomCount )
     199               0 :         return NULL;
     200                 :     else
     201            2362 :         return papoGeoms[i];
     202                 : }
     203                 : 
     204                 : /************************************************************************/
     205                 : /*                            addGeometry()                             */
     206                 : /*                                                                      */
     207                 : /*      Add a new geometry to a collection.  Subclasses should          */
     208                 : /*      override this to verify the type of the new geometry, and       */
     209                 : /*      then call this method to actually add it.                       */
     210                 : /************************************************************************/
     211                 : 
     212                 : /**
     213                 :  * \brief Add a geometry to the container.
     214                 :  *
     215                 :  * Some subclasses of OGRGeometryCollection restrict the types of geometry
     216                 :  * that can be added, and may return an error.  The passed geometry is cloned
     217                 :  * to make an internal copy.
     218                 :  *
     219                 :  * There is no SFCOM analog to this method.
     220                 :  *
     221                 :  * This method is the same as the C function OGR_G_AddGeometry().
     222                 :  *
     223                 :  * @param poNewGeom geometry to add to the container.
     224                 :  *
     225                 :  * @return OGRERR_NONE if successful, or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if
     226                 :  * the geometry type is illegal for the type of geometry container.
     227                 :  */
     228                 : 
     229            2416 : OGRErr OGRGeometryCollection::addGeometry( const OGRGeometry * poNewGeom )
     230                 : 
     231                 : {
     232            2416 :     OGRGeometry *poClone = poNewGeom->clone();
     233                 :     OGRErr      eErr;
     234                 : 
     235            2416 :     eErr = addGeometryDirectly( poClone );
     236            2416 :     if( eErr != OGRERR_NONE )
     237               0 :         delete poClone;
     238                 : 
     239            2416 :     return eErr;
     240                 : }
     241                 : 
     242                 : /************************************************************************/
     243                 : /*                        addGeometryDirectly()                         */
     244                 : /*                                                                      */
     245                 : /*      Add a new geometry to a collection.  Subclasses should          */
     246                 : /*      override this to verify the type of the new geometry, and       */
     247                 : /*      then call this method to actually add it.                       */
     248                 : /************************************************************************/
     249                 : 
     250                 : /**
     251                 :  * \brief Add a geometry directly to the container.
     252                 :  *
     253                 :  * Some subclasses of OGRGeometryCollection restrict the types of geometry
     254                 :  * that can be added, and may return an error.  Ownership of the passed
     255                 :  * geometry is taken by the container rather than cloning as addGeometry()
     256                 :  * does.
     257                 :  *
     258                 :  * This method is the same as the C function OGR_G_AddGeometryDirectly().
     259                 :  *
     260                 :  * There is no SFCOM analog to this method.
     261                 :  *
     262                 :  * @param poNewGeom geometry to add to the container.
     263                 :  *
     264                 :  * @return OGRERR_NONE if successful, or OGRERR_UNSUPPORTED_GEOMETRY_TYPE if
     265                 :  * the geometry type is illegal for the type of geometry container.
     266                 :  */
     267                 : 
     268            8372 : OGRErr OGRGeometryCollection::addGeometryDirectly( OGRGeometry * poNewGeom )
     269                 : 
     270                 : {
     271                 :     papoGeoms = (OGRGeometry **) OGRRealloc( papoGeoms,
     272            8372 :                                              sizeof(void*) * (nGeomCount+1) );
     273                 : 
     274            8372 :     papoGeoms[nGeomCount] = poNewGeom;
     275                 : 
     276            8372 :     nGeomCount++;
     277                 : 
     278            8372 :     if( poNewGeom->getCoordinateDimension() == 3 )
     279            1656 :         nCoordDimension = 3;
     280                 : 
     281            8372 :     return OGRERR_NONE;
     282                 : }
     283                 : 
     284                 : /************************************************************************/
     285                 : /*                           removeGeometry()                           */
     286                 : /************************************************************************/
     287                 : 
     288                 : /**
     289                 :  * \brief Remove a geometry from the container.
     290                 :  *
     291                 :  * Removing a geometry will cause the geometry count to drop by one, and all
     292                 :  * "higher" geometries will shuffle down one in index.
     293                 :  *
     294                 :  * There is no SFCOM analog to this method.
     295                 :  *
     296                 :  * This method is the same as the C function OGR_G_RemoveGeometry().
     297                 :  *
     298                 :  * @param iGeom the index of the geometry to delete.  A value of -1 is a
     299                 :  * special flag meaning that all geometries should be removed.
     300                 :  *
     301                 :  * @param bDelete if TRUE the geometry will be deallocated, otherwise it will
     302                 :  * not.  The default is TRUE as the container is considered to own the
     303                 :  * geometries in it. 
     304                 :  *
     305                 :  * @return OGRERR_NONE if successful, or OGRERR_FAILURE if the index is
     306                 :  * out of range.
     307                 :  */
     308                 : 
     309              30 : OGRErr OGRGeometryCollection::removeGeometry( int iGeom, int bDelete )
     310                 : 
     311                 : {
     312              30 :     if( iGeom < -1 || iGeom >= nGeomCount )
     313               0 :         return OGRERR_FAILURE;
     314                 : 
     315                 :     // Special case.
     316              30 :     if( iGeom == -1 )
     317                 :     {
     318               0 :         while( nGeomCount > 0 )
     319               0 :             removeGeometry( nGeomCount-1, bDelete );
     320               0 :         return OGRERR_NONE;
     321                 :     }
     322                 : 
     323              30 :     if( bDelete )
     324               0 :         delete papoGeoms[iGeom];
     325                 : 
     326                 :     memmove( papoGeoms + iGeom, papoGeoms + iGeom + 1, 
     327              30 :              sizeof(void*) * (nGeomCount-iGeom-1) );
     328                 : 
     329              30 :     nGeomCount--;
     330                 : 
     331              30 :     return OGRERR_NONE;
     332                 : }
     333                 : 
     334                 : /************************************************************************/
     335                 : /*                              WkbSize()                               */
     336                 : /*                                                                      */
     337                 : /*      Return the size of this object in well known binary             */
     338                 : /*      representation including the byte order, and type information.  */
     339                 : /************************************************************************/
     340                 : 
     341            1246 : int OGRGeometryCollection::WkbSize() const
     342                 : 
     343                 : {
     344            1246 :     int         nSize = 9;
     345                 : 
     346            2584 :     for( int i = 0; i < nGeomCount; i++ )
     347                 :     {
     348            1338 :         nSize += papoGeoms[i]->WkbSize();
     349                 :     }
     350                 : 
     351            1246 :     return nSize;
     352                 : }
     353                 : 
     354                 : /************************************************************************/
     355                 : /*                       importFromWkbInternal()                        */
     356                 : /************************************************************************/
     357                 : 
     358             821 : OGRErr OGRGeometryCollection::importFromWkbInternal( unsigned char * pabyData,
     359                 :                                                      int nSize, int nRecLevel )
     360                 : 
     361                 : {
     362                 :     OGRwkbByteOrder     eByteOrder;
     363                 :     int                 nDataOffset;
     364                 : 
     365                 :     /* Arbitrary value, but certainly large enough for reasonable usages ! */
     366             821 :     if( nRecLevel == 32 )
     367                 :     {
     368                 :         CPLError( CE_Failure, CPLE_AppDefined,
     369                 :                     "Too many recursiong level (%d) while parsing WKB geometry.",
     370               2 :                     nRecLevel );
     371               2 :         return OGRERR_CORRUPT_DATA;
     372                 :     }
     373                 :     
     374             819 :     if( nSize < 9 && nSize != -1 )
     375               0 :         return OGRERR_NOT_ENOUGH_DATA;
     376                 : 
     377                 : /* -------------------------------------------------------------------- */
     378                 : /*      Get the byte order byte.                                        */
     379                 : /* -------------------------------------------------------------------- */
     380             819 :     eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
     381             819 :     if (!( eByteOrder == wkbXDR || eByteOrder == wkbNDR ))
     382               0 :         return OGRERR_CORRUPT_DATA;
     383                 : 
     384                 : /* -------------------------------------------------------------------- */
     385                 : /*      Get the geometry feature type.  For now we assume that          */
     386                 : /*      geometry type is between 0 and 255 so we only have to fetch     */
     387                 : /*      one byte.                                                       */
     388                 : /* -------------------------------------------------------------------- */
     389                 :     OGRwkbGeometryType eGeometryType;
     390                 : 
     391             819 :     if( eByteOrder == wkbNDR )
     392                 :     {
     393             633 :         eGeometryType = (OGRwkbGeometryType) pabyData[1];
     394                 :     }
     395                 :     else
     396                 :     {
     397             186 :         eGeometryType = (OGRwkbGeometryType) pabyData[4];
     398                 :     }
     399                 : 
     400             819 :     if ( eGeometryType != wkbFlatten(getGeometryType()) )
     401               0 :         return OGRERR_CORRUPT_DATA;
     402                 : 
     403                 : /* -------------------------------------------------------------------- */
     404                 : /*      Clear existing Geoms.                                           */
     405                 : /* -------------------------------------------------------------------- */
     406             819 :     empty();
     407                 :     
     408                 : /* -------------------------------------------------------------------- */
     409                 : /*      Get the geometry count.                                         */
     410                 : /* -------------------------------------------------------------------- */
     411             819 :     memcpy( &nGeomCount, pabyData + 5, 4 );
     412                 :     
     413             819 :     if( OGR_SWAP( eByteOrder ) )
     414             186 :         nGeomCount = CPL_SWAP32(nGeomCount);
     415                 : 
     416             819 :     if (nGeomCount < 0 || nGeomCount > INT_MAX / 9)
     417                 :     {
     418               0 :         nGeomCount = 0;
     419               0 :         return OGRERR_CORRUPT_DATA;
     420                 :     }
     421                 : 
     422                 :     /* Each geometry has a minimum of 9 bytes */
     423             819 :     if (nSize != -1 && nSize - 9 < nGeomCount * 9)
     424                 :     {
     425                 :         CPLError( CE_Failure, CPLE_AppDefined,
     426               0 :                   "Length of input WKB is too small" );
     427               0 :         nGeomCount = 0;
     428               0 :         return OGRERR_NOT_ENOUGH_DATA;
     429                 :     }
     430                 : 
     431             819 :     papoGeoms = (OGRGeometry **) VSIMalloc2(sizeof(void*), nGeomCount);
     432             819 :     if (nGeomCount != 0 && papoGeoms == NULL)
     433                 :     {
     434               0 :         nGeomCount = 0;
     435               0 :         return OGRERR_NOT_ENOUGH_MEMORY;
     436                 :     }
     437                 : 
     438             819 :     nDataOffset = 9;
     439             819 :     if( nSize != -1 )
     440             819 :         nSize -= nDataOffset;
     441                 : 
     442                 : /* -------------------------------------------------------------------- */
     443                 : /*      Get the Geoms.                                                  */
     444                 : /* -------------------------------------------------------------------- */
     445            2387 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     446                 :     {
     447                 :         OGRErr  eErr;
     448            1634 :         OGRGeometry* poSubGeom = NULL;
     449                 : 
     450                 :         /* Parses sub-geometry */
     451            1634 :         unsigned char* pabySubData = pabyData + nDataOffset;
     452            1634 :         if( nSize < 9 && nSize != -1 )
     453               0 :             return OGRERR_NOT_ENOUGH_DATA;
     454                 :         OGRwkbByteOrder eSubGeomByteOrder =
     455            1634 :             DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabySubData);
     456                 : 
     457            1634 :         if( eSubGeomByteOrder != wkbXDR && eSubGeomByteOrder != wkbNDR )
     458               0 :             return OGRERR_CORRUPT_DATA;
     459                 : 
     460                 :         OGRwkbGeometryType eSubGeomType;
     461            1634 :         if( eSubGeomByteOrder == wkbNDR )
     462            1428 :             eSubGeomType = (OGRwkbGeometryType) pabySubData[1];
     463                 :         else
     464             206 :             eSubGeomType = (OGRwkbGeometryType) pabySubData[4];
     465                 : 
     466            3134 :         if( eSubGeomType == wkbPoint ||
     467                 :             eSubGeomType == wkbLineString ||
     468                 :             eSubGeomType == wkbPolygon)
     469                 :         {
     470                 :             eErr = OGRGeometryFactory::
     471                 :                 createFromWkb( pabySubData, NULL,
     472            1500 :                                &poSubGeom, nSize );
     473                 :         }
     474             268 :         else if (eSubGeomType == wkbGeometryCollection ||
     475                 :                  eSubGeomType == wkbMultiPolygon ||
     476                 :                  eSubGeomType == wkbMultiPoint ||
     477                 :                  eSubGeomType == wkbMultiLineString)
     478                 :         {
     479             134 :             poSubGeom = OGRGeometryFactory::createGeometry( eSubGeomType );
     480                 :             eErr = ((OGRGeometryCollection*)poSubGeom)->
     481             134 :                         importFromWkbInternal( pabySubData, nSize, nRecLevel + 1 );
     482                 :         }
     483                 :         else
     484               0 :             return OGRERR_UNSUPPORTED_GEOMETRY_TYPE;
     485                 : 
     486            1634 :         if( eErr != OGRERR_NONE )
     487                 :         {
     488              64 :             nGeomCount = iGeom;
     489              64 :             delete poSubGeom;
     490              64 :             return eErr;
     491                 :         }
     492                 : 
     493            1570 :         if( (eGeometryType == wkbMultiPoint && eSubGeomType != wkbPoint) ||
     494                 :             (eGeometryType == wkbMultiLineString && eSubGeomType != wkbLineString) ||
     495                 :             (eGeometryType == wkbMultiPolygon && eSubGeomType != wkbPolygon) )
     496                 :         {
     497               2 :             nGeomCount = iGeom;
     498                 :             CPLDebug("OGR", "Cannot add geometry of type (%d) to geometry of type (%d)",
     499               2 :                      eSubGeomType, eGeometryType);
     500               2 :             delete poSubGeom;
     501               2 :             return OGRERR_CORRUPT_DATA;
     502                 :         }
     503                 : 
     504            1568 :         papoGeoms[iGeom] = poSubGeom;
     505                 : 
     506            1568 :         if (papoGeoms[iGeom]->getCoordinateDimension() == 3)
     507             558 :             nCoordDimension = 3;
     508                 : 
     509            1568 :         int nSubGeomWkbSize = papoGeoms[iGeom]->WkbSize();
     510            1568 :         if( nSize != -1 )
     511            1568 :             nSize -= nSubGeomWkbSize;
     512                 : 
     513            1568 :         nDataOffset += nSubGeomWkbSize;
     514                 :     }
     515                 :     
     516             753 :     return OGRERR_NONE;
     517                 : }
     518                 : 
     519                 : /************************************************************************/
     520                 : /*                           importFromWkb()                            */
     521                 : /*                                                                      */
     522                 : /*      Initialize from serialized stream in well known binary          */
     523                 : /*      format.                                                         */
     524                 : /************************************************************************/
     525                 : 
     526             687 : OGRErr OGRGeometryCollection::importFromWkb( unsigned char * pabyData,
     527                 :                                              int nSize )
     528                 : 
     529                 : {
     530             687 :     return importFromWkbInternal(pabyData, nSize, 0);
     531                 : }
     532                 : 
     533                 : /************************************************************************/
     534                 : /*                            exportToWkb()                             */
     535                 : /*                                                                      */
     536                 : /*      Build a well known binary representation of this object.        */
     537                 : /************************************************************************/
     538                 : 
     539             238 : OGRErr  OGRGeometryCollection::exportToWkb( OGRwkbByteOrder eByteOrder,
     540                 :                                             unsigned char * pabyData ) const
     541                 : 
     542                 : {
     543                 :     int         nOffset;
     544                 :     
     545                 : /* -------------------------------------------------------------------- */
     546                 : /*      Set the byte order.                                             */
     547                 : /* -------------------------------------------------------------------- */
     548             238 :     pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
     549                 : 
     550                 : /* -------------------------------------------------------------------- */
     551                 : /*      Set the geometry feature type, ensuring that 3D flag is         */
     552                 : /*      preserved.                                                      */
     553                 : /* -------------------------------------------------------------------- */
     554             238 :     GUInt32 nGType = getGeometryType();
     555                 :     
     556             238 :     if( eByteOrder == wkbNDR )
     557             184 :         nGType = CPL_LSBWORD32( nGType );
     558                 :     else
     559              54 :         nGType = CPL_MSBWORD32( nGType );
     560                 : 
     561             238 :     memcpy( pabyData + 1, &nGType, 4 );
     562                 :     
     563                 : /* -------------------------------------------------------------------- */
     564                 : /*      Copy in the raw data.                                           */
     565                 : /* -------------------------------------------------------------------- */
     566             238 :     if( OGR_SWAP( eByteOrder ) )
     567                 :     {
     568                 :         int     nCount;
     569                 : 
     570              54 :         nCount = CPL_SWAP32( nGeomCount );
     571              54 :         memcpy( pabyData+5, &nCount, 4 );
     572                 :     }
     573                 :     else
     574                 :     {
     575             184 :         memcpy( pabyData+5, &nGeomCount, 4 );
     576                 :     }
     577                 :     
     578             238 :     nOffset = 9;
     579                 :     
     580                 : /* ==================================================================== */
     581                 : /*      Serialize each of the Geoms.                                    */
     582                 : /* ==================================================================== */
     583             630 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     584                 :     {
     585             392 :         papoGeoms[iGeom]->exportToWkb( eByteOrder, pabyData + nOffset );
     586                 : 
     587             392 :         nOffset += papoGeoms[iGeom]->WkbSize();
     588                 :     }
     589                 :     
     590             238 :     return OGRERR_NONE;
     591                 : }
     592                 : 
     593                 : /************************************************************************/
     594                 : /*                       importFromWktInternal()                        */
     595                 : /************************************************************************/
     596                 : 
     597             378 : OGRErr OGRGeometryCollection::importFromWktInternal( char ** ppszInput, int nRecLevel )
     598                 : 
     599                 : {
     600                 : 
     601                 :     char        szToken[OGR_WKT_TOKEN_MAX];
     602             378 :     const char  *pszInput = *ppszInput;
     603                 : 
     604                 : 
     605                 :     /* Arbitrary value, but certainly large enough for reasonable usages ! */
     606             378 :     if( nRecLevel == 32 )
     607                 :     {
     608                 :         CPLError( CE_Failure, CPLE_AppDefined,
     609                 :                     "Too many recursiong level (%d) while parsing WKT geometry.",
     610               2 :                     nRecLevel );
     611               2 :         return OGRERR_CORRUPT_DATA;
     612                 :     }
     613                 : 
     614                 : /* -------------------------------------------------------------------- */
     615                 : /*      Clear existing Geoms.                                           */
     616                 : /* -------------------------------------------------------------------- */
     617             376 :     empty();
     618                 : 
     619                 : /* -------------------------------------------------------------------- */
     620                 : /*      Read and verify the type keyword, and ensure it matches the     */
     621                 : /*      actual type of this container.                                  */
     622                 : /* -------------------------------------------------------------------- */
     623             376 :     pszInput = OGRWktReadToken( pszInput, szToken );
     624                 : 
     625             376 :     if( !EQUAL(szToken,getGeometryName()) )
     626               0 :         return OGRERR_CORRUPT_DATA;
     627                 : 
     628                 : /* -------------------------------------------------------------------- */
     629                 : /*      Check for EMPTY ...                                             */
     630                 : /* -------------------------------------------------------------------- */
     631                 :     const char *pszPreScan;
     632             376 :     int bHasZ = FALSE, bHasM = FALSE;
     633                 : 
     634             376 :     pszPreScan = OGRWktReadToken( pszInput, szToken );
     635             376 :     if( EQUAL(szToken,"EMPTY") )
     636                 :     {
     637              26 :         *ppszInput = (char *) pszPreScan;
     638              26 :         empty();
     639              26 :         return OGRERR_NONE;
     640                 :     }
     641                 : 
     642                 : /* -------------------------------------------------------------------- */
     643                 : /*      Check for Z, M or ZM. Will ignore the Measure                   */
     644                 : /* -------------------------------------------------------------------- */
     645             350 :     else if( EQUAL(szToken,"Z") )
     646                 :     {
     647              16 :         bHasZ = TRUE;
     648                 :     }
     649             334 :     else if( EQUAL(szToken,"M") )
     650                 :     {
     651               4 :         bHasM = TRUE;
     652                 :     }
     653             330 :     else if( EQUAL(szToken,"ZM") )
     654                 :     {
     655               4 :         bHasZ = TRUE;
     656               4 :         bHasM = TRUE;
     657                 :     }
     658                 : 
     659             350 :     if (bHasZ || bHasM)
     660                 :     {
     661              24 :         pszInput = pszPreScan;
     662              24 :         pszPreScan = OGRWktReadToken( pszInput, szToken );
     663              24 :         if( EQUAL(szToken,"EMPTY") )
     664                 :         {
     665               8 :             *ppszInput = (char *) pszPreScan;
     666               8 :             empty();
     667                 :             /* FIXME?: In theory we should store the dimension and M presence */
     668                 :             /* if we want to allow round-trip with ExportToWKT v1.2 */
     669               8 :             return OGRERR_NONE;
     670                 :         }
     671                 :     }
     672                 : 
     673             342 :     if( !EQUAL(szToken,"(") )
     674               6 :         return OGRERR_CORRUPT_DATA;
     675                 : 
     676             336 :     if ( !bHasZ && !bHasM )
     677                 :     {
     678                 :         /* Test for old-style GEOMETRYCOLLECTION(EMPTY) */
     679             322 :         pszPreScan = OGRWktReadToken( pszPreScan, szToken );
     680             322 :         if( EQUAL(szToken,"EMPTY") )
     681                 :         {
     682               8 :             pszInput = OGRWktReadToken( pszPreScan, szToken );
     683                 : 
     684               8 :             if( !EQUAL(szToken,")") )
     685               4 :                 return OGRERR_CORRUPT_DATA;
     686                 :             else
     687                 :             {
     688               4 :                 *ppszInput = (char *) pszInput;
     689               4 :                 empty();
     690               4 :                 return OGRERR_NONE;
     691                 :             }
     692                 :         }
     693                 :     }
     694                 : 
     695                 :     /* Skip first '(' */
     696             328 :     pszInput = OGRWktReadToken( pszInput, szToken );
     697                 : 
     698                 : /* ==================================================================== */
     699                 : /*      Read each subgeometry in turn.                                  */
     700                 : /* ==================================================================== */
     701             468 :     do
     702                 :     {
     703             554 :         OGRGeometry *poGeom = NULL;
     704                 :         OGRErr      eErr;
     705                 : 
     706                 :     /* -------------------------------------------------------------------- */
     707                 :     /*      Get the first token, which should be the geometry type.         */
     708                 :     /* -------------------------------------------------------------------- */
     709             554 :         if( OGRWktReadToken( pszInput, szToken ) == NULL )
     710               0 :             return OGRERR_CORRUPT_DATA;
     711                 : 
     712                 :     /* -------------------------------------------------------------------- */
     713                 :     /*      Do the import.                                                  */
     714                 :     /* -------------------------------------------------------------------- */
     715             554 :         if (EQUAL(szToken,"GEOMETRYCOLLECTION"))
     716                 :         {
     717             140 :             poGeom = new OGRGeometryCollection();
     718                 :             eErr = ((OGRGeometryCollection*)poGeom)->
     719             140 :                         importFromWktInternal( (char **) &pszInput, nRecLevel + 1 );
     720                 :         }
     721                 :         else
     722                 :             eErr = OGRGeometryFactory::createFromWkt( (char **) &pszInput,
     723             414 :                                                        NULL, &poGeom );
     724                 : 
     725             554 :         if( eErr != OGRERR_NONE )
     726              86 :             return eErr;
     727                 : 
     728             468 :         addGeometryDirectly( poGeom );
     729                 : 
     730                 : /* -------------------------------------------------------------------- */
     731                 : /*      Read the delimeter following the ring.                          */
     732                 : /* -------------------------------------------------------------------- */
     733                 :         
     734             468 :         pszInput = OGRWktReadToken( pszInput, szToken );
     735                 :         
     736             468 :     } while( szToken[0] == ',' );
     737                 : 
     738                 : /* -------------------------------------------------------------------- */
     739                 : /*      freak if we don't get a closing bracket.                        */
     740                 : /* -------------------------------------------------------------------- */
     741             242 :     if( szToken[0] != ')' )
     742               4 :         return OGRERR_CORRUPT_DATA;
     743                 :     
     744             238 :     *ppszInput = (char *) pszInput;
     745                 :     
     746             238 :     return OGRERR_NONE;
     747                 : }
     748                 : 
     749                 : /************************************************************************/
     750                 : /*                           importFromWkt()                            */
     751                 : /************************************************************************/
     752                 : 
     753             238 : OGRErr OGRGeometryCollection::importFromWkt( char ** ppszInput )
     754                 : 
     755                 : {
     756             238 :     return importFromWktInternal(ppszInput, 0);
     757                 : }
     758                 : 
     759                 : /************************************************************************/
     760                 : /*                            exportToWkt()                             */
     761                 : /*                                                                      */
     762                 : /*      Translate this structure into it's well known text format       */
     763                 : /*      equivelent.  This could be made alot more CPU efficient!        */
     764                 : /************************************************************************/
     765                 : 
     766             192 : OGRErr OGRGeometryCollection::exportToWkt( char ** ppszDstText ) const
     767                 : 
     768                 : {
     769                 :     char        **papszGeoms;
     770             192 :     int         iGeom, nCumulativeLength = 0;
     771                 :     OGRErr      eErr;
     772                 : 
     773             192 :     if( getNumGeometries() == 0 )
     774                 :     {
     775              34 :         *ppszDstText = CPLStrdup("GEOMETRYCOLLECTION EMPTY");
     776              34 :         return OGRERR_NONE;
     777                 :     }
     778                 : 
     779                 : /* -------------------------------------------------------------------- */
     780                 : /*      Build a list of strings containing the stuff for each Geom.     */
     781                 : /* -------------------------------------------------------------------- */
     782             158 :     papszGeoms = (char **) CPLCalloc(sizeof(char *),nGeomCount);
     783                 : 
     784             458 :     for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
     785                 :     {
     786             300 :         eErr = papoGeoms[iGeom]->exportToWkt( &(papszGeoms[iGeom]) );
     787             300 :         if( eErr != OGRERR_NONE )
     788               0 :             goto error;
     789                 : 
     790             300 :         nCumulativeLength += strlen(papszGeoms[iGeom]);
     791                 :     }
     792                 :     
     793                 : /* -------------------------------------------------------------------- */
     794                 : /*      Allocate the right amount of space for the aggregated string    */
     795                 : /* -------------------------------------------------------------------- */
     796             158 :     *ppszDstText = (char *) VSIMalloc(nCumulativeLength + nGeomCount + 23);
     797                 : 
     798             158 :     if( *ppszDstText == NULL )
     799                 :     {
     800               0 :         eErr = OGRERR_NOT_ENOUGH_MEMORY;
     801               0 :         goto error;
     802                 :     }
     803                 : 
     804                 : /* -------------------------------------------------------------------- */
     805                 : /*      Build up the string, freeing temporary strings as we go.        */
     806                 : /* -------------------------------------------------------------------- */
     807             158 :     strcpy( *ppszDstText, getGeometryName() );
     808             158 :     strcat( *ppszDstText, " (" );
     809             158 :     nCumulativeLength = strlen(*ppszDstText);
     810                 : 
     811             458 :     for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
     812                 :     {                                                           
     813             300 :         if( iGeom > 0 )
     814             142 :             (*ppszDstText)[nCumulativeLength++] = ',';
     815                 :         
     816             300 :         int nGeomLength = strlen(papszGeoms[iGeom]);
     817             300 :         memcpy( *ppszDstText + nCumulativeLength, papszGeoms[iGeom], nGeomLength );
     818             300 :         nCumulativeLength += nGeomLength;
     819             300 :         VSIFree( papszGeoms[iGeom] );
     820                 :     }
     821                 : 
     822             158 :     (*ppszDstText)[nCumulativeLength++] = ')';
     823             158 :     (*ppszDstText)[nCumulativeLength] = '\0';
     824                 : 
     825             158 :     CPLFree( papszGeoms );
     826                 : 
     827             158 :     return OGRERR_NONE;
     828                 : 
     829                 : error:
     830               0 :     for( iGeom = 0; iGeom < nGeomCount; iGeom++ )
     831               0 :         CPLFree( papszGeoms[iGeom] );
     832               0 :     CPLFree( papszGeoms );
     833               0 :     return eErr;
     834                 : }
     835                 : 
     836                 : /************************************************************************/
     837                 : /*                            getEnvelope()                             */
     838                 : /************************************************************************/
     839                 : 
     840             900 : void OGRGeometryCollection::getEnvelope( OGREnvelope * psEnvelope ) const
     841                 : 
     842                 : {
     843             900 :     OGREnvelope         oGeomEnv;
     844             900 :     int                 bExtentSet = FALSE;
     845                 : 
     846            2308 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     847                 :     {
     848            1408 :         if (!papoGeoms[iGeom]->IsEmpty())
     849                 :         {
     850            1408 :             if (!bExtentSet)
     851                 :             {
     852             876 :                 papoGeoms[iGeom]->getEnvelope( psEnvelope );
     853             876 :                 bExtentSet = TRUE;
     854                 :             }
     855                 :             else
     856                 :             {
     857             532 :                 papoGeoms[iGeom]->getEnvelope( &oGeomEnv );
     858                 : 
     859             532 :                 if( psEnvelope->MinX > oGeomEnv.MinX )
     860             258 :                     psEnvelope->MinX = oGeomEnv.MinX;
     861             532 :                 if( psEnvelope->MinY > oGeomEnv.MinY )
     862             216 :                     psEnvelope->MinY = oGeomEnv.MinY;
     863             532 :                 if( psEnvelope->MaxX < oGeomEnv.MaxX )
     864             222 :                     psEnvelope->MaxX = oGeomEnv.MaxX;
     865             532 :                 if( psEnvelope->MaxY < oGeomEnv.MaxY )
     866             186 :                     psEnvelope->MaxY = oGeomEnv.MaxY;
     867                 :             }
     868                 :         }
     869                 :     }
     870                 : 
     871             900 :     if (!bExtentSet)
     872                 :     {
     873              24 :         psEnvelope->MinX = psEnvelope->MinY = 0;
     874              24 :         psEnvelope->MaxX = psEnvelope->MaxY = 0;
     875                 :     }
     876             900 : }
     877                 : 
     878                 : /************************************************************************/
     879                 : /*                            getEnvelope()                             */
     880                 : /************************************************************************/
     881                 : 
     882             194 : void OGRGeometryCollection::getEnvelope( OGREnvelope3D * psEnvelope ) const
     883                 : 
     884                 : {
     885             194 :     OGREnvelope3D       oGeomEnv;
     886             194 :     int                 bExtentSet = FALSE;
     887                 : 
     888             428 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     889                 :     {
     890             234 :         if (!papoGeoms[iGeom]->IsEmpty())
     891                 :         {
     892             234 :             if (!bExtentSet)
     893                 :             {
     894             192 :                 papoGeoms[iGeom]->getEnvelope( psEnvelope );
     895             192 :                 bExtentSet = TRUE;
     896                 :             }
     897                 :             else
     898                 :             {
     899              42 :                 papoGeoms[iGeom]->getEnvelope( &oGeomEnv );
     900                 : 
     901              42 :                 if( psEnvelope->MinX > oGeomEnv.MinX )
     902               2 :                     psEnvelope->MinX = oGeomEnv.MinX;
     903              42 :                 if( psEnvelope->MinY > oGeomEnv.MinY )
     904               2 :                     psEnvelope->MinY = oGeomEnv.MinY;
     905              42 :                 if( psEnvelope->MaxX < oGeomEnv.MaxX )
     906              42 :                     psEnvelope->MaxX = oGeomEnv.MaxX;
     907              42 :                 if( psEnvelope->MaxY < oGeomEnv.MaxY )
     908              42 :                     psEnvelope->MaxY = oGeomEnv.MaxY;
     909                 : 
     910              42 :                 if( psEnvelope->MinZ > oGeomEnv.MinZ )
     911              22 :                     psEnvelope->MinZ = oGeomEnv.MinZ;
     912              42 :                 if( psEnvelope->MaxZ < oGeomEnv.MaxZ )
     913               0 :                     psEnvelope->MaxZ = oGeomEnv.MaxZ;
     914                 :             }
     915                 :         }
     916                 :     }
     917                 : 
     918             194 :     if (!bExtentSet)
     919                 :     {
     920               2 :         psEnvelope->MinX = psEnvelope->MinY = psEnvelope->MinZ = 0;
     921               2 :         psEnvelope->MaxX = psEnvelope->MaxY = psEnvelope->MaxZ = 0;
     922                 :     }
     923             194 : }
     924                 : 
     925                 : /************************************************************************/
     926                 : /*                               Equals()                               */
     927                 : /************************************************************************/
     928                 : 
     929             112 : OGRBoolean OGRGeometryCollection::Equals( OGRGeometry * poOther ) const
     930                 : 
     931                 : {
     932             112 :     OGRGeometryCollection *poOGC = (OGRGeometryCollection *) poOther;
     933                 : 
     934             112 :     if( poOGC == this )
     935               0 :         return TRUE;
     936                 :     
     937             112 :     if( poOther->getGeometryType() != getGeometryType() )
     938               0 :         return FALSE;
     939                 : 
     940             112 :     if( getNumGeometries() != poOGC->getNumGeometries() )
     941               0 :         return FALSE;
     942                 :     
     943                 :     // we should eventually test the SRS.
     944                 : 
     945             246 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     946                 :     {
     947             134 :         if( !getGeometryRef(iGeom)->Equals(poOGC->getGeometryRef(iGeom)) )
     948               0 :             return FALSE;
     949                 :     }
     950                 : 
     951             112 :     return TRUE;
     952                 : }
     953                 : 
     954                 : /************************************************************************/
     955                 : /*                             transform()                              */
     956                 : /************************************************************************/
     957                 : 
     958              18 : OGRErr OGRGeometryCollection::transform( OGRCoordinateTransformation *poCT )
     959                 : 
     960                 : {
     961                 : #ifdef DISABLE_OGRGEOM_TRANSFORM
     962                 :     return OGRERR_FAILURE;
     963                 : #else
     964              72 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     965                 :     {
     966                 :         OGRErr  eErr;
     967                 : 
     968              54 :         eErr = papoGeoms[iGeom]->transform( poCT );
     969              54 :         if( eErr != OGRERR_NONE )
     970                 :         {
     971               0 :             if( iGeom != 0 )
     972                 :             {
     973                 :                 CPLDebug("OGR", 
     974                 :                          "OGRGeometryCollection::transform() failed for a geometry other\n"
     975                 :                          "than the first, meaning some geometries are transformed\n"
     976               0 :                          "and some are not!\n" );
     977                 : 
     978               0 :                 return OGRERR_FAILURE;
     979                 :             }
     980                 : 
     981               0 :             return eErr;
     982                 :         }
     983                 :     }
     984                 : 
     985              18 :     assignSpatialReference( poCT->GetTargetCS() );
     986                 : 
     987              18 :     return OGRERR_NONE;
     988                 : #endif
     989                 : }
     990                 : 
     991                 : /************************************************************************/
     992                 : /*                             closeRings()                             */
     993                 : /************************************************************************/
     994                 : 
     995             106 : void OGRGeometryCollection::closeRings()
     996                 : 
     997                 : {
     998             244 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
     999                 :     {
    1000             138 :         if( wkbFlatten(papoGeoms[iGeom]->getGeometryType()) == wkbPolygon )
    1001             104 :             ((OGRPolygon *) papoGeoms[iGeom])->closeRings();
    1002                 :     }
    1003             106 : }
    1004                 : 
    1005                 : /************************************************************************/
    1006                 : /*                       setCoordinateDimension()                       */
    1007                 : /************************************************************************/
    1008                 : 
    1009             256 : void OGRGeometryCollection::setCoordinateDimension( int nNewDimension )
    1010                 : 
    1011                 : {
    1012             710 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
    1013                 :     {
    1014             454 :         papoGeoms[iGeom]->setCoordinateDimension( nNewDimension );
    1015                 :     }
    1016                 : 
    1017             256 :     OGRGeometry::setCoordinateDimension( nNewDimension );
    1018             256 : }
    1019                 : 
    1020                 : 
    1021                 : /************************************************************************/
    1022                 : /*                              get_Length()                            */
    1023                 : /************************************************************************/
    1024                 : 
    1025                 : /**
    1026                 :  * \brief Compute the length of a multicurve.
    1027                 :  *
    1028                 :  * The length is computed as the sum of the length of all members
    1029                 :  * in this collection.
    1030                 :  *
    1031                 :  * @note No warning will be issued if a member of the collection does not
    1032                 :  *       support the get_Length method.
    1033                 :  *
    1034                 :  * @return computed area.
    1035                 :  */
    1036                 : 
    1037               6 : double OGRGeometryCollection::get_Length() const
    1038                 : {
    1039               6 :     double dfLength = 0.0;
    1040              22 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
    1041                 :     {
    1042              16 :         OGRGeometry* geom = papoGeoms[iGeom];
    1043              16 :         switch( wkbFlatten(geom->getGeometryType()) )
    1044                 :         {
    1045                 :             case wkbLinearRing:
    1046                 :             case wkbLineString:
    1047               8 :                 dfLength += ((OGRCurve *) geom)->get_Length();
    1048               8 :                 break;
    1049                 : 
    1050                 :             case wkbGeometryCollection:
    1051               2 :                 dfLength +=((OGRGeometryCollection *) geom)->get_Length();
    1052                 :                 break;
    1053                 : 
    1054                 :             default:
    1055                 :                 break;
    1056                 :         }
    1057                 :     }
    1058                 : 
    1059               6 :     return dfLength;
    1060                 : }
    1061                 : 
    1062                 : /************************************************************************/
    1063                 : /*                              get_Area()                              */
    1064                 : /************************************************************************/
    1065                 : 
    1066                 : /**
    1067                 :  * \brief Compute area of geometry collection.
    1068                 :  *
    1069                 :  * The area is computed as the sum of the areas of all members
    1070                 :  * in this collection.
    1071                 :  *
    1072                 :  * @note No warning will be issued if a member of the collection does not
    1073                 :  *       support the get_Area method.
    1074                 :  *
    1075                 :  * @return computed area.
    1076                 :  */
    1077                 : 
    1078               4 : double OGRGeometryCollection::get_Area() const
    1079                 : {
    1080               4 :     double dfArea = 0.0;
    1081              14 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
    1082                 :     {
    1083              10 :         OGRGeometry* geom = papoGeoms[iGeom];
    1084              10 :         switch( wkbFlatten(geom->getGeometryType()) )
    1085                 :         {
    1086                 :             case wkbPolygon:
    1087               2 :                 dfArea += ((OGRPolygon *) geom)->get_Area();
    1088               2 :                 break;
    1089                 : 
    1090                 :             case wkbMultiPolygon:
    1091               2 :                 dfArea += ((OGRMultiPolygon *) geom)->get_Area();
    1092               2 :                 break;
    1093                 : 
    1094                 :             case wkbLinearRing:
    1095                 :             case wkbLineString:
    1096                 :                 /* This test below is required to filter out wkbLineString geometries
    1097                 :                 * not being of type of wkbLinearRing.
    1098                 :                 */
    1099               2 :                 if( EQUAL( ((OGRGeometry*) geom)->getGeometryName(), "LINEARRING" ) )
    1100                 :                 {
    1101               0 :                     dfArea += ((OGRLinearRing *) geom)->get_Area();
    1102                 :                 }
    1103               2 :                 break;
    1104                 : 
    1105                 :             case wkbGeometryCollection:
    1106               2 :                 dfArea +=((OGRGeometryCollection *) geom)->get_Area();
    1107                 :                 break;
    1108                 : 
    1109                 :             default:
    1110                 :                 break;
    1111                 :         }
    1112                 :     }
    1113                 : 
    1114               4 :     return dfArea;
    1115                 : }
    1116                 : 
    1117                 : /************************************************************************/
    1118                 : /*                               IsEmpty()                              */
    1119                 : /************************************************************************/
    1120                 : 
    1121            1170 : OGRBoolean OGRGeometryCollection::IsEmpty(  ) const
    1122                 : {
    1123            1178 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
    1124            1016 :         if (papoGeoms[iGeom]->IsEmpty() == FALSE)
    1125            1008 :             return FALSE;
    1126             162 :     return TRUE;
    1127                 : }
    1128                 : 
    1129                 : /************************************************************************/
    1130                 : /*              OGRGeometryCollection::segmentize()                     */
    1131                 : /************************************************************************/
    1132                 : 
    1133               0 : void OGRGeometryCollection::segmentize( double dfMaxLength )
    1134                 : {
    1135               0 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
    1136               0 :         papoGeoms[iGeom]->segmentize(dfMaxLength);
    1137               0 : }
    1138                 : 
    1139                 : /************************************************************************/
    1140                 : /*                               swapXY()                               */
    1141                 : /************************************************************************/
    1142                 : 
    1143              30 : void OGRGeometryCollection::swapXY()
    1144                 : {
    1145              60 :     for( int iGeom = 0; iGeom < nGeomCount; iGeom++ )
    1146              30 :         papoGeoms[iGeom]->swapXY();
    1147              30 : }

Generated by: LCOV version 1.7