LCOV - code coverage report
Current view: directory - ogr - ogrgeometrycollection.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 373 322 86.3 %
Date: 2013-03-30 Functions: 35 33 94.3 %

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

Generated by: LCOV version 1.7