LCOV - code coverage report
Current view: directory - ogr - ogrpolygon.cpp (source / functions) Found Hit Coverage
Test: gdal_filtered.info Lines: 386 325 84.2 %
Date: 2012-12-26 Functions: 35 30 85.7 %

       1                 : /******************************************************************************
       2                 :  * $Id: ogrpolygon.cpp 24895 2012-09-02 18:12:08Z rouault $
       3                 :  *
       4                 :  * Project:  OpenGIS Simple Features Reference Implementation
       5                 :  * Purpose:  The OGRPolygon geometry 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                 : #include "ogr_geos.h"
      33                 : #include "ogr_api.h"
      34                 : 
      35                 : CPL_CVSID("$Id: ogrpolygon.cpp 24895 2012-09-02 18:12:08Z rouault $");
      36                 : 
      37                 : /************************************************************************/
      38                 : /*                             OGRPolygon()                             */
      39                 : /************************************************************************/
      40                 : 
      41                 : /**
      42                 :  * \brief Create an empty polygon.
      43                 :  */
      44                 : 
      45          144368 : OGRPolygon::OGRPolygon()
      46                 : 
      47                 : {
      48          144368 :     nRingCount = 0;
      49          144368 :     papoRings = NULL;
      50          144368 : }
      51                 : 
      52                 : /************************************************************************/
      53                 : /*                            ~OGRPolygon()                             */
      54                 : /************************************************************************/
      55                 : 
      56          144368 : OGRPolygon::~OGRPolygon()
      57                 : 
      58                 : {
      59          144368 :     empty();
      60          144368 : }
      61                 : 
      62                 : /************************************************************************/
      63                 : /*                               clone()                                */
      64                 : /************************************************************************/
      65                 : 
      66           63494 : OGRGeometry *OGRPolygon::clone() const
      67                 : 
      68                 : {
      69                 :     OGRPolygon  *poNewPolygon;
      70                 : 
      71           63494 :     poNewPolygon = new OGRPolygon;
      72           63494 :     poNewPolygon->assignSpatialReference( getSpatialReference() );
      73                 : 
      74          127285 :     for( int i = 0; i < nRingCount; i++ )
      75                 :     {
      76           63791 :         poNewPolygon->addRing( papoRings[i] );
      77                 :     }
      78                 : 
      79           63494 :     return poNewPolygon;
      80                 : }
      81                 : 
      82                 : /************************************************************************/
      83                 : /*                               empty()                                */
      84                 : /************************************************************************/
      85                 : 
      86          157086 : void OGRPolygon::empty()
      87                 : 
      88                 : {
      89          157086 :     if( papoRings != NULL )
      90                 :     {
      91          290510 :         for( int i = 0; i < nRingCount; i++ )
      92                 :         {
      93          146420 :             delete papoRings[i];
      94                 :         }
      95          144090 :         OGRFree( papoRings );
      96                 :     }
      97                 : 
      98          157086 :     papoRings = NULL;
      99          157086 :     nRingCount = 0;
     100          157086 : }
     101                 : 
     102                 : /************************************************************************/
     103                 : /*                          getGeometryType()                           */
     104                 : /************************************************************************/
     105                 : 
     106          163899 : OGRwkbGeometryType OGRPolygon::getGeometryType() const
     107                 : 
     108                 : {
     109          163899 :     if( getCoordinateDimension() == 3 )
     110            1604 :         return wkbPolygon25D;
     111                 :     else
     112          162295 :         return wkbPolygon;
     113                 : }
     114                 : 
     115                 : /************************************************************************/
     116                 : /*                            getDimension()                            */
     117                 : /************************************************************************/
     118                 : 
     119               0 : int OGRPolygon::getDimension() const
     120                 : 
     121                 : {
     122               0 :     return 2;
     123                 : }
     124                 : 
     125                 : /************************************************************************/
     126                 : /*                            flattenTo2D()                             */
     127                 : /************************************************************************/
     128                 : 
     129              13 : void OGRPolygon::flattenTo2D()
     130                 : 
     131                 : {
     132              26 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
     133              13 :         papoRings[iRing]->flattenTo2D();
     134                 : 
     135              13 :     nCoordDimension = 2;
     136              13 : }
     137                 : 
     138                 : /************************************************************************/
     139                 : /*                          getGeometryName()                           */
     140                 : /************************************************************************/
     141                 : 
     142            1633 : const char * OGRPolygon::getGeometryName() const
     143                 : 
     144                 : {
     145            1633 :     return "POLYGON";
     146                 : }
     147                 : 
     148                 : /************************************************************************/
     149                 : /*                          getExteriorRing()                           */
     150                 : /************************************************************************/
     151                 : 
     152                 : /**
     153                 :  * \brief Fetch reference to external polygon ring.
     154                 :  *
     155                 :  * Note that the returned ring pointer is to an internal data object of
     156                 :  * the OGRPolygon.  It should not be modified or deleted by the application,
     157                 :  * and the pointer is only valid till the polygon is next modified.  Use
     158                 :  * the OGRGeometry::clone() method to make a separate copy within the
     159                 :  * application.
     160                 :  *
     161                 :  * Relates to the SFCOM IPolygon::get_ExteriorRing() method.
     162                 :  *
     163                 :  * @return pointer to external ring.  May be NULL if the OGRPolygon is empty.
     164                 :  */
     165                 : 
     166          144372 : OGRLinearRing *OGRPolygon::getExteriorRing()
     167                 : 
     168                 : {
     169          144372 :     if( nRingCount > 0 )
     170          144348 :         return papoRings[0];
     171                 :     else
     172              24 :         return NULL;
     173                 : }
     174                 : 
     175          114086 : const OGRLinearRing *OGRPolygon::getExteriorRing() const
     176                 : 
     177                 : {
     178          114086 :     if( nRingCount > 0 )
     179          114051 :         return papoRings[0];
     180                 :     else
     181              35 :         return NULL;
     182                 : }
     183                 : 
     184                 : /************************************************************************/
     185                 : /*                        getNumInteriorRings()                         */
     186                 : /************************************************************************/
     187                 : 
     188                 : /**
     189                 :  * \brief Fetch the number of internal rings.
     190                 :  *
     191                 :  * Relates to the SFCOM IPolygon::get_NumInteriorRings() method.
     192                 :  *
     193                 :  * @return count of internal rings, zero or more.
     194                 :  */
     195                 : 
     196                 : 
     197          132584 : int OGRPolygon::getNumInteriorRings() const
     198                 : 
     199                 : {
     200          132584 :     if( nRingCount > 0 )
     201          132582 :         return nRingCount-1;
     202                 :     else
     203               2 :         return 0;
     204                 : }
     205                 : 
     206                 : /************************************************************************/
     207                 : /*                          getInteriorRing()                           */
     208                 : /************************************************************************/
     209                 : 
     210                 : /**
     211                 :  * \brief Fetch reference to indicated internal ring.
     212                 :  *
     213                 :  * Note that the returned ring pointer is to an internal data object of
     214                 :  * the OGRPolygon.  It should not be modified or deleted by the application,
     215                 :  * and the pointer is only valid till the polygon is next modified.  Use
     216                 :  * the OGRGeometry::clone() method to make a separate copy within the
     217                 :  * application.
     218                 :  *
     219                 :  * Relates to the SFCOM IPolygon::get_InternalRing() method.
     220                 :  *
     221                 :  * @param iRing internal ring index from 0 to getNumInternalRings() - 1.
     222                 :  *
     223                 :  * @return pointer to external ring.  May be NULL if the OGRPolygon is empty.
     224                 :  */
     225                 : 
     226             358 : OGRLinearRing *OGRPolygon::getInteriorRing( int iRing )
     227                 : 
     228                 : {
     229             358 :     if( iRing < 0 || iRing >= nRingCount-1 )
     230               0 :         return NULL;
     231                 :     else
     232             358 :         return papoRings[iRing+1];
     233                 : }
     234                 : 
     235              99 : const OGRLinearRing *OGRPolygon::getInteriorRing( int iRing ) const
     236                 : 
     237                 : {
     238              99 :     if( iRing < 0 || iRing >= nRingCount-1 )
     239               0 :         return NULL;
     240                 :     else
     241              99 :         return papoRings[iRing+1];
     242                 : }
     243                 : 
     244                 : /************************************************************************/
     245                 : /*                              addRing()                               */
     246                 : /************************************************************************/
     247                 : 
     248                 : /**
     249                 :  * \brief Add a ring to a polygon.
     250                 :  *
     251                 :  * If the polygon has no external ring (it is empty) this will be used as
     252                 :  * the external ring, otherwise it is used as an internal ring.  The passed
     253                 :  * OGRLinearRing remains the responsibility of the caller (an internal copy
     254                 :  * is made).
     255                 :  *
     256                 :  * This method has no SFCOM analog.
     257                 :  *
     258                 :  * @param poNewRing ring to be added to the polygon.
     259                 :  */
     260                 : 
     261           82666 : void OGRPolygon::addRing( OGRLinearRing * poNewRing )
     262                 : 
     263                 : {
     264                 :     papoRings = (OGRLinearRing **) OGRRealloc( papoRings,
     265           82666 :                                                sizeof(void*) * (nRingCount+1));
     266                 : 
     267           82666 :     papoRings[nRingCount] = new OGRLinearRing( poNewRing );
     268                 : 
     269           82666 :     nRingCount++;
     270                 : 
     271           82666 :     if( poNewRing->getCoordinateDimension() == 3 )
     272             194 :         nCoordDimension = 3;
     273           82666 : }
     274                 : 
     275                 : /************************************************************************/
     276                 : /*                          addRingDirectly()                           */
     277                 : /************************************************************************/
     278                 : 
     279                 : /**
     280                 :  * \brief Add a ring to a polygon.
     281                 :  *
     282                 :  * If the polygon has no external ring (it is empty) this will be used as
     283                 :  * the external ring, otherwise it is used as an internal ring.  Ownership
     284                 :  * of the passed ring is assumed by the OGRPolygon, but otherwise this
     285                 :  * method operates the same as OGRPolygon::AddRing().
     286                 :  *
     287                 :  * This method has no SFCOM analog.
     288                 :  *
     289                 :  * @param poNewRing ring to be added to the polygon.
     290                 :  */
     291                 : 
     292           49377 : void OGRPolygon::addRingDirectly( OGRLinearRing * poNewRing )
     293                 : 
     294                 : {
     295                 :     papoRings = (OGRLinearRing **) OGRRealloc( papoRings,
     296           49377 :                                                sizeof(void*) * (nRingCount+1));
     297                 : 
     298           49377 :     papoRings[nRingCount] = poNewRing;
     299                 : 
     300           49377 :     nRingCount++;
     301                 : 
     302                 : 
     303           49377 :     if( poNewRing->getCoordinateDimension() == 3 )
     304            6487 :         nCoordDimension = 3;
     305           49377 : }
     306                 : 
     307                 : /************************************************************************/
     308                 : /*                              WkbSize()                               */
     309                 : /*                                                                      */
     310                 : /*      Return the size of this object in well known binary             */
     311                 : /*      representation including the byte order, and type information.  */
     312                 : /************************************************************************/
     313                 : 
     314           20628 : int OGRPolygon::WkbSize() const
     315                 : 
     316                 : {
     317           20628 :     int         nSize = 9;
     318           20628 :     int         b3D = getCoordinateDimension() == 3;
     319                 : 
     320           42010 :     for( int i = 0; i < nRingCount; i++ )
     321                 :     {
     322           21382 :         nSize += papoRings[i]->_WkbSize( b3D );
     323                 :     }
     324                 : 
     325           20628 :     return nSize;
     326                 : }
     327                 : 
     328                 : /************************************************************************/
     329                 : /*                           importFromWkb()                            */
     330                 : /*                                                                      */
     331                 : /*      Initialize from serialized stream in well known binary          */
     332                 : /*      format.                                                         */
     333                 : /************************************************************************/
     334                 : 
     335            1656 : OGRErr OGRPolygon::importFromWkb( unsigned char * pabyData,
     336                 :                                   int nSize )
     337                 : 
     338                 : {
     339                 :     OGRwkbByteOrder     eByteOrder;
     340                 :     int                 nDataOffset, b3D;
     341                 :     
     342            1656 :     if( nSize < 9 && nSize != -1 )
     343               0 :         return OGRERR_NOT_ENOUGH_DATA;
     344                 : 
     345                 : /* -------------------------------------------------------------------- */
     346                 : /*      Get the byte order byte.                                        */
     347                 : /* -------------------------------------------------------------------- */
     348            1656 :     eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
     349            1656 :     if (!( eByteOrder == wkbXDR || eByteOrder == wkbNDR ))
     350               0 :         return OGRERR_CORRUPT_DATA;
     351                 : 
     352                 : /* -------------------------------------------------------------------- */
     353                 : /*      Get the geometry feature type.  For now we assume that          */
     354                 : /*      geometry type is between 0 and 255 so we only have to fetch     */
     355                 : /*      one byte.                                                       */
     356                 : /* -------------------------------------------------------------------- */
     357                 : #ifdef DEBUG
     358                 :     OGRwkbGeometryType eGeometryType;
     359                 :     
     360            1656 :     if( eByteOrder == wkbNDR )
     361            1639 :         eGeometryType = (OGRwkbGeometryType) pabyData[1];
     362                 :     else
     363              17 :         eGeometryType = (OGRwkbGeometryType) pabyData[4];
     364                 : 
     365            1656 :     if( eGeometryType != wkbPolygon )
     366               0 :         return OGRERR_CORRUPT_DATA;
     367                 : #endif    
     368                 : 
     369            1656 :     if( eByteOrder == wkbNDR )
     370            1639 :         b3D = pabyData[4] & 0x80 || pabyData[2] & 0x80;
     371                 :     else
     372              17 :         b3D = pabyData[1] & 0x80 || pabyData[3] & 0x80;
     373                 : 
     374            1656 :     if( b3D )
     375             294 :         nCoordDimension = 3;
     376                 :     else
     377            1362 :         nCoordDimension = 2;
     378                 : 
     379                 : /* -------------------------------------------------------------------- */
     380                 : /*      Do we already have some rings?                                  */
     381                 : /* -------------------------------------------------------------------- */
     382            1656 :     if( nRingCount != 0 )
     383                 :     {
     384               0 :         for( int iRing = 0; iRing < nRingCount; iRing++ )
     385               0 :             delete papoRings[iRing];
     386                 : 
     387               0 :         OGRFree( papoRings );
     388               0 :         papoRings = NULL;
     389                 :     }
     390                 :     
     391                 : /* -------------------------------------------------------------------- */
     392                 : /*      Get the ring count.                                             */
     393                 : /* -------------------------------------------------------------------- */
     394            1656 :     memcpy( &nRingCount, pabyData + 5, 4 );
     395                 :     
     396            1656 :     if( OGR_SWAP( eByteOrder ) )
     397              17 :         nRingCount = CPL_SWAP32(nRingCount);
     398                 : 
     399            1656 :     if (nRingCount < 0 || nRingCount > INT_MAX / 4)
     400                 :     {
     401               0 :         nRingCount = 0;
     402               0 :         return OGRERR_CORRUPT_DATA;
     403                 :     }
     404                 : 
     405                 :     /* Each ring has a minimum of 4 bytes (point count) */
     406            1656 :     if (nSize != -1 && nSize - 9 < nRingCount * 4)
     407                 :     {
     408                 :         CPLError( CE_Failure, CPLE_AppDefined,
     409               0 :                   "Length of input WKB is too small" );
     410               0 :         nRingCount = 0;
     411               0 :         return OGRERR_NOT_ENOUGH_DATA;
     412                 :     }
     413                 : 
     414            1656 :     papoRings = (OGRLinearRing **) VSIMalloc2(sizeof(void*), nRingCount);
     415            1656 :     if (nRingCount != 0 && papoRings == NULL)
     416                 :     {
     417               0 :         nRingCount = 0;
     418               0 :         return OGRERR_NOT_ENOUGH_MEMORY;
     419                 :     }
     420                 : 
     421            1656 :     nDataOffset = 9;
     422            1656 :     if( nSize != -1 )
     423            1656 :         nSize -= nDataOffset;
     424                 : 
     425                 : /* -------------------------------------------------------------------- */
     426                 : /*      Get the rings.                                                  */
     427                 : /* -------------------------------------------------------------------- */
     428            3337 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
     429                 :     {
     430                 :         OGRErr  eErr;
     431                 :         
     432            1681 :         papoRings[iRing] = new OGRLinearRing();
     433            5043 :         eErr = papoRings[iRing]->_importFromWkb( eByteOrder, b3D,
     434                 :                                                  pabyData + nDataOffset,
     435            6724 :                                                  nSize );
     436            1681 :         if( eErr != OGRERR_NONE )
     437                 :         {
     438               0 :             delete papoRings[iRing];
     439               0 :             nRingCount = iRing;
     440               0 :             return eErr;
     441                 :         }
     442                 : 
     443            1681 :         if( nSize != -1 )
     444            1681 :             nSize -= papoRings[iRing]->_WkbSize( b3D );
     445                 : 
     446            1681 :         nDataOffset += papoRings[iRing]->_WkbSize( b3D );
     447                 :     }
     448                 :     
     449            1656 :     return OGRERR_NONE;
     450                 : }
     451                 : 
     452                 : /************************************************************************/
     453                 : /*                            exportToWkb()                             */
     454                 : /*                                                                      */
     455                 : /*      Build a well known binary representation of this object.        */
     456                 : /************************************************************************/
     457                 : 
     458           20249 : OGRErr  OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
     459                 :                                  unsigned char * pabyData ) const
     460                 : 
     461                 : {
     462                 :     int         nOffset;
     463           20249 :     int         b3D = getCoordinateDimension() == 3;
     464                 :     
     465                 : /* -------------------------------------------------------------------- */
     466                 : /*      Set the byte order.                                             */
     467                 : /* -------------------------------------------------------------------- */
     468           20249 :     pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
     469                 : 
     470                 : /* -------------------------------------------------------------------- */
     471                 : /*      Set the geometry feature type.                                  */
     472                 : /* -------------------------------------------------------------------- */
     473           20249 :     GUInt32 nGType = getGeometryType();
     474                 :     
     475           20249 :     if( eByteOrder == wkbNDR )
     476           20234 :         nGType = CPL_LSBWORD32( nGType );
     477                 :     else
     478              15 :         nGType = CPL_MSBWORD32( nGType );
     479                 : 
     480           20249 :     memcpy( pabyData + 1, &nGType, 4 );
     481                 :     
     482                 : /* -------------------------------------------------------------------- */
     483                 : /*      Copy in the raw data.                                           */
     484                 : /* -------------------------------------------------------------------- */
     485           20249 :     if( OGR_SWAP( eByteOrder ) )
     486                 :     {
     487                 :         int     nCount;
     488                 : 
     489              15 :         nCount = CPL_SWAP32( nRingCount );
     490              15 :         memcpy( pabyData+5, &nCount, 4 );
     491                 :     }
     492                 :     else
     493                 :     {
     494           20234 :         memcpy( pabyData+5, &nRingCount, 4 );
     495                 :     }
     496                 :     
     497           20249 :     nOffset = 9;
     498                 :     
     499                 : /* ==================================================================== */
     500                 : /*      Serialize each of the rings.                                    */
     501                 : /* ==================================================================== */
     502           41234 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
     503                 :     {
     504           62955 :         papoRings[iRing]->_exportToWkb( eByteOrder, b3D,
     505           83940 :                                         pabyData + nOffset );
     506                 : 
     507           20985 :         nOffset += papoRings[iRing]->_WkbSize(b3D);
     508                 :     }
     509                 :     
     510           20249 :     return OGRERR_NONE;
     511                 : }
     512                 : 
     513                 : /************************************************************************/
     514                 : /*                           importFromWkt()                            */
     515                 : /*                                                                      */
     516                 : /*      Instantiate from well known text format.  Currently this is     */
     517                 : /*      `POLYGON ((x y, x y, ...),(x y, ...),...)'.                     */
     518                 : /************************************************************************/
     519                 : 
     520           12687 : OGRErr OGRPolygon::importFromWkt( char ** ppszInput )
     521                 : 
     522                 : {
     523                 :     char        szToken[OGR_WKT_TOKEN_MAX];
     524           12687 :     const char  *pszInput = *ppszInput;
     525                 : 
     526                 : /* -------------------------------------------------------------------- */
     527                 : /*      Clear existing rings.                                           */
     528                 : /* -------------------------------------------------------------------- */
     529           12687 :     empty();
     530                 : 
     531                 : /* -------------------------------------------------------------------- */
     532                 : /*      Read and verify the ``POLYGON'' keyword token.                  */
     533                 : /* -------------------------------------------------------------------- */
     534           12687 :     pszInput = OGRWktReadToken( pszInput, szToken );
     535                 : 
     536           12687 :     if( !EQUAL(szToken,"POLYGON") )
     537               0 :         return OGRERR_CORRUPT_DATA;
     538                 : 
     539                 : /* -------------------------------------------------------------------- */
     540                 : /*      Check for EMPTY ...                                             */
     541                 : /* -------------------------------------------------------------------- */
     542                 :     const char *pszPreScan;
     543           12687 :     int bHasZ = FALSE, bHasM = FALSE;
     544                 : 
     545           12687 :     pszPreScan = OGRWktReadToken( pszInput, szToken );
     546           12687 :     if( EQUAL(szToken,"EMPTY") )
     547                 :     {
     548              21 :         *ppszInput = (char *) pszPreScan;
     549              21 :         empty();
     550              21 :         return OGRERR_NONE;
     551                 :     }
     552                 : 
     553                 : /* -------------------------------------------------------------------- */
     554                 : /*      Check for Z, M or ZM. Will ignore the Measure                   */
     555                 : /* -------------------------------------------------------------------- */
     556           12666 :     else if( EQUAL(szToken,"Z") )
     557                 :     {
     558              15 :         bHasZ = TRUE;
     559                 :     }
     560           12651 :     else if( EQUAL(szToken,"M") )
     561                 :     {
     562               2 :         bHasM = TRUE;
     563                 :     }
     564           12649 :     else if( EQUAL(szToken,"ZM") )
     565                 :     {
     566               2 :         bHasZ = TRUE;
     567               2 :         bHasM = TRUE;
     568                 :     }
     569                 : 
     570           12666 :     if (bHasZ || bHasM)
     571                 :     {
     572              19 :         pszInput = pszPreScan;
     573              19 :         pszPreScan = OGRWktReadToken( pszInput, szToken );
     574              19 :         if( EQUAL(szToken,"EMPTY") )
     575                 :         {
     576               4 :             *ppszInput = (char *) pszPreScan;
     577               4 :             empty();
     578                 :             /* FIXME?: In theory we should store the dimension and M presence */
     579                 :             /* if we want to allow round-trip with ExportToWKT v1.2 */
     580               4 :             return OGRERR_NONE;
     581                 :         }
     582                 :     }
     583                 : 
     584           12662 :     if( !EQUAL(szToken,"(") )
     585               4 :         return OGRERR_CORRUPT_DATA;
     586                 : 
     587           12658 :     if ( !bHasZ && !bHasM )
     588                 :     {
     589                 :         /* Test for old-style POLYGON(EMPTY) */
     590           12645 :         pszPreScan = OGRWktReadToken( pszPreScan, szToken );
     591           12645 :         if( EQUAL(szToken,"EMPTY") )
     592                 :         {
     593               7 :             pszPreScan = OGRWktReadToken( pszPreScan, szToken );
     594                 : 
     595               7 :             if( EQUAL(szToken,",") )
     596                 :             {
     597                 :                 /* This is OK according to SFSQL SPEC. */
     598                 :             }
     599               4 :             else if( !EQUAL(szToken,")") )
     600               1 :                 return OGRERR_CORRUPT_DATA;
     601                 :             else
     602                 :             {
     603               3 :                 *ppszInput = (char *) pszPreScan;
     604               3 :                 empty();
     605               3 :                 return OGRERR_NONE;
     606                 :             }
     607                 :         }
     608                 :     }
     609                 : 
     610                 :     /* Skip first '(' */
     611           12654 :     pszInput = OGRWktReadToken( pszInput, szToken );
     612                 : 
     613                 : /* ==================================================================== */
     614                 : /*      Read each ring in turn.  Note that we try to reuse the same     */
     615                 : /*      point list buffer from ring to ring to cut down on              */
     616                 : /*      allocate/deallocate overhead.                                   */
     617                 : /* ==================================================================== */
     618           12654 :     OGRRawPoint *paoPoints = NULL;
     619           12654 :     int         nMaxPoints = 0, nMaxRings = 0;
     620           12654 :     double      *padfZ = NULL;
     621                 : 
     622           12654 :     nCoordDimension = 2;
     623                 :     
     624           12691 :     do
     625                 :     {
     626           12714 :         int     nPoints = 0;
     627                 : 
     628           12714 :         const char* pszNext = OGRWktReadToken( pszInput, szToken );
     629           12714 :         if (EQUAL(szToken,"EMPTY"))
     630                 :         {
     631                 : /* -------------------------------------------------------------------- */
     632                 : /*      Do we need to grow the ring array?                              */
     633                 : /* -------------------------------------------------------------------- */
     634              10 :             if( nRingCount == nMaxRings )
     635                 :             {
     636               8 :                 nMaxRings = nMaxRings * 2 + 1;
     637                 :                 papoRings = (OGRLinearRing **)
     638               8 :                     CPLRealloc(papoRings, nMaxRings * sizeof(OGRLinearRing*));
     639                 :             }
     640              10 :             papoRings[nRingCount] = new OGRLinearRing();
     641              10 :             nRingCount++;
     642                 : 
     643              10 :             pszInput = OGRWktReadToken( pszNext, szToken );
     644              10 :             if ( !EQUAL(szToken, ",") )
     645               5 :                 break;
     646                 : 
     647               5 :             continue;
     648                 :         }
     649                 : 
     650                 : /* -------------------------------------------------------------------- */
     651                 : /*      Read points for one ring from input.                            */
     652                 : /* -------------------------------------------------------------------- */
     653                 :         pszInput = OGRWktReadPoints( pszInput, &paoPoints, &padfZ, &nMaxPoints,
     654           12704 :                                      &nPoints );
     655                 : 
     656           12704 :         if( pszInput == NULL || nPoints == 0 )
     657                 :         {
     658              18 :             CPLFree( paoPoints );
     659              18 :             return OGRERR_CORRUPT_DATA;
     660                 :         }
     661                 :         
     662                 : /* -------------------------------------------------------------------- */
     663                 : /*      Do we need to grow the ring array?                              */
     664                 : /* -------------------------------------------------------------------- */
     665           12686 :         if( nRingCount == nMaxRings )
     666                 :         {
     667           12680 :             nMaxRings = nMaxRings * 2 + 1;
     668                 :             papoRings = (OGRLinearRing **)
     669           12680 :                 CPLRealloc(papoRings, nMaxRings * sizeof(OGRLinearRing*));
     670                 :         }
     671                 : 
     672                 : /* -------------------------------------------------------------------- */
     673                 : /*      Create the new ring, and assign to ring list.                   */
     674                 : /* -------------------------------------------------------------------- */
     675           12686 :         papoRings[nRingCount] = new OGRLinearRing();
     676                 :         /* Ignore Z array when we have a POLYGON M */
     677           12689 :         if (bHasM && !bHasZ)
     678               1 :             papoRings[nRingCount]->setPoints( nPoints, paoPoints, NULL );
     679                 :         else
     680           12685 :             papoRings[nRingCount]->setPoints( nPoints, paoPoints, padfZ );
     681                 : 
     682           12686 :         nRingCount++;
     683                 : 
     684           12686 :         if( padfZ && !(bHasM && !bHasZ) )
     685              66 :             nCoordDimension = 3;
     686                 : 
     687                 : /* -------------------------------------------------------------------- */
     688                 : /*      Read the delimeter following the ring.                          */
     689                 : /* -------------------------------------------------------------------- */
     690                 :         
     691           12686 :         pszInput = OGRWktReadToken( pszInput, szToken );
     692           12691 :     } while( szToken[0] == ',' );
     693                 : 
     694                 : /* -------------------------------------------------------------------- */
     695                 : /*      freak if we don't get a closing bracket.                        */
     696                 : /* -------------------------------------------------------------------- */
     697           12636 :     CPLFree( paoPoints );
     698           12636 :     CPLFree( padfZ );
     699                 : 
     700           12636 :     if( szToken[0] != ')' )
     701               4 :         return OGRERR_CORRUPT_DATA;
     702                 :     
     703           12632 :     *ppszInput = (char *) pszInput;
     704           12632 :     return OGRERR_NONE;
     705                 : }
     706                 : 
     707                 : /************************************************************************/
     708                 : /*                            exportToWkt()                             */
     709                 : /*                                                                      */
     710                 : /*      Translate this structure into it's well known text format       */
     711                 : /*      equivelent.  This could be made alot more CPU efficient!        */
     712                 : /************************************************************************/
     713                 : 
     714             522 : OGRErr OGRPolygon::exportToWkt( char ** ppszDstText ) const
     715                 : 
     716                 : {
     717                 :     char        **papszRings;
     718             522 :     int         iRing, nCumulativeLength = 0, nNonEmptyRings = 0;
     719                 :     OGRErr      eErr;
     720             522 :     int         bMustWriteComma = FALSE;
     721                 : 
     722                 : /* -------------------------------------------------------------------- */
     723                 : /*      If we have no valid exterior ring, return POLYGON EMPTY.        */
     724                 : /* -------------------------------------------------------------------- */
     725            1009 :     if (getExteriorRing() == NULL ||
     726             487 :         getExteriorRing()->IsEmpty())
     727                 :     {
     728              42 :         *ppszDstText = CPLStrdup("POLYGON EMPTY");
     729              42 :         return OGRERR_NONE;
     730                 :     }
     731                 : 
     732                 : /* -------------------------------------------------------------------- */
     733                 : /*      Build a list of strings containing the stuff for each ring.     */
     734                 : /* -------------------------------------------------------------------- */
     735             480 :     papszRings = (char **) CPLCalloc(sizeof(char *),nRingCount);
     736                 : 
     737            1016 :     for( iRing = 0; iRing < nRingCount; iRing++ )
     738                 :     {
     739             536 :         papoRings[iRing]->setCoordinateDimension( getCoordinateDimension() );
     740             536 :         if( papoRings[iRing]->getNumPoints() == 0 )
     741                 :         {
     742              12 :             papszRings[iRing] = NULL;
     743              12 :             continue;
     744                 :         }
     745                 : 
     746             524 :         eErr = papoRings[iRing]->exportToWkt( &(papszRings[iRing]) );
     747             524 :         if( eErr != OGRERR_NONE )
     748               0 :             goto error;
     749                 : 
     750             524 :         CPLAssert( EQUALN(papszRings[iRing],"LINEARRING (", 12) );
     751             524 :         nCumulativeLength += strlen(papszRings[iRing] + 11);
     752                 : 
     753             524 :         nNonEmptyRings++;
     754                 :     }
     755                 : 
     756                 : /* -------------------------------------------------------------------- */
     757                 : /*      Allocate exactly the right amount of space for the              */
     758                 : /*      aggregated string.                                              */
     759                 : /* -------------------------------------------------------------------- */
     760             480 :     *ppszDstText = (char *) VSIMalloc(nCumulativeLength + nNonEmptyRings + 11);
     761                 : 
     762             480 :     if( *ppszDstText == NULL )
     763                 :     {
     764               0 :         eErr = OGRERR_NOT_ENOUGH_MEMORY;
     765               0 :         goto error;
     766                 :     }
     767                 : 
     768                 : /* -------------------------------------------------------------------- */
     769                 : /*      Build up the string, freeing temporary strings as we go.        */
     770                 : /* -------------------------------------------------------------------- */
     771             480 :     strcpy( *ppszDstText, "POLYGON (" );
     772             480 :     nCumulativeLength = strlen(*ppszDstText);
     773                 : 
     774            1016 :     for( iRing = 0; iRing < nRingCount; iRing++ )
     775                 :     {                                                           
     776             536 :         if( papszRings[iRing] == NULL )
     777                 :         {
     778              12 :             CPLDebug( "OGR", "OGRPolygon::exportToWkt() - skipping empty ring.");
     779              12 :             continue;
     780                 :         }
     781                 : 
     782             524 :         if( bMustWriteComma )
     783              44 :             (*ppszDstText)[nCumulativeLength++] = ',';
     784             524 :         bMustWriteComma = TRUE;
     785                 :         
     786             524 :         int nRingLen = strlen(papszRings[iRing] + 11);
     787             524 :         memcpy( *ppszDstText + nCumulativeLength, papszRings[iRing] + 11, nRingLen );
     788             524 :         nCumulativeLength += nRingLen;
     789             524 :         VSIFree( papszRings[iRing] );
     790                 :     }
     791                 : 
     792             480 :     (*ppszDstText)[nCumulativeLength++] = ')';
     793             480 :     (*ppszDstText)[nCumulativeLength] = '\0';
     794                 : 
     795             480 :     CPLFree( papszRings );
     796                 : 
     797             480 :     return OGRERR_NONE;
     798                 : 
     799                 : error:
     800               0 :     for( iRing = 0; iRing < nRingCount; iRing++ )
     801               0 :         CPLFree(papszRings[iRing]);
     802               0 :     CPLFree(papszRings);
     803               0 :     return eErr;
     804                 : }
     805                 : 
     806                 : /************************************************************************/
     807                 : /*                           PointOnSurface()                           */
     808                 : /************************************************************************/
     809                 : 
     810               0 : int OGRPolygon::PointOnSurface( OGRPoint *poPoint ) const
     811                 : 
     812                 : {
     813               0 :     if( poPoint == NULL )
     814               0 :         return OGRERR_FAILURE;
     815                 : 
     816               0 :     OGRGeometryH hInsidePoint = OGR_G_PointOnSurface( (OGRGeometryH) this );
     817               0 :     if( hInsidePoint == NULL )
     818               0 :         return OGRERR_FAILURE;
     819                 : 
     820               0 :     OGRPoint *poInsidePoint = (OGRPoint *) hInsidePoint;
     821               0 :     if( poInsidePoint->IsEmpty() )
     822               0 :         poPoint->empty();
     823                 :     else
     824                 :     {
     825               0 :         poPoint->setX( poInsidePoint->getX() );
     826               0 :         poPoint->setY( poInsidePoint->getY() );
     827                 :     }
     828                 : 
     829               0 :     return OGRERR_NONE;
     830                 : }
     831                 : 
     832                 : 
     833                 : /************************************************************************/
     834                 : /*                            getEnvelope()                             */
     835                 : /************************************************************************/
     836                 : 
     837           74901 : void OGRPolygon::getEnvelope( OGREnvelope * psEnvelope ) const
     838                 : 
     839                 : {
     840           74901 :     OGREnvelope         oRingEnv;
     841           74901 :     int                 bExtentSet = FALSE;
     842                 : 
     843          150887 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
     844                 :     {
     845           75986 :         if (!papoRings[iRing]->IsEmpty())
     846                 :         {
     847           75986 :             if (!bExtentSet)
     848                 :             {
     849           74897 :                 papoRings[iRing]->getEnvelope( psEnvelope );
     850           74897 :                 bExtentSet = TRUE;
     851                 :             }
     852                 :             else
     853                 :             {
     854            1089 :                 papoRings[iRing]->getEnvelope( &oRingEnv );
     855                 : 
     856            1089 :                 if( psEnvelope->MinX > oRingEnv.MinX )
     857               5 :                     psEnvelope->MinX = oRingEnv.MinX;
     858            1089 :                 if( psEnvelope->MinY > oRingEnv.MinY )
     859               4 :                     psEnvelope->MinY = oRingEnv.MinY;
     860            1089 :                 if( psEnvelope->MaxX < oRingEnv.MaxX )
     861               6 :                     psEnvelope->MaxX = oRingEnv.MaxX;
     862            1089 :                 if( psEnvelope->MaxY < oRingEnv.MaxY )
     863               6 :                     psEnvelope->MaxY = oRingEnv.MaxY;
     864                 :             }
     865                 :         }
     866                 :     }
     867                 : 
     868           74901 :     if (!bExtentSet)
     869                 :     {
     870               4 :         psEnvelope->MinX = psEnvelope->MinY = 0;
     871               4 :         psEnvelope->MaxX = psEnvelope->MaxY = 0;
     872                 :     }
     873           74901 : }
     874                 : 
     875                 : /************************************************************************/
     876                 : /*                            getEnvelope()                             */
     877                 : /************************************************************************/
     878                 :  
     879              89 : void OGRPolygon::getEnvelope( OGREnvelope3D * psEnvelope ) const
     880                 : 
     881                 : {
     882              89 :     OGREnvelope3D       oRingEnv;
     883              89 :     int                 bExtentSet = FALSE;
     884                 : 
     885             178 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
     886                 :     {
     887              89 :         if (!papoRings[iRing]->IsEmpty())
     888                 :         {
     889              89 :             if (!bExtentSet)
     890                 :             {
     891              88 :                 papoRings[iRing]->getEnvelope( psEnvelope );
     892              88 :                 bExtentSet = TRUE;
     893                 :             }
     894                 :             else
     895                 :             {
     896               1 :                 papoRings[iRing]->getEnvelope( &oRingEnv );
     897                 : 
     898               1 :                 if( psEnvelope->MinX > oRingEnv.MinX )
     899               0 :                     psEnvelope->MinX = oRingEnv.MinX;
     900               1 :                 if( psEnvelope->MinY > oRingEnv.MinY )
     901               0 :                     psEnvelope->MinY = oRingEnv.MinY;
     902               1 :                 if( psEnvelope->MaxX < oRingEnv.MaxX )
     903               0 :                     psEnvelope->MaxX = oRingEnv.MaxX;
     904               1 :                 if( psEnvelope->MaxY < oRingEnv.MaxY )
     905               0 :                     psEnvelope->MaxY = oRingEnv.MaxY;
     906                 : 
     907               1 :                 if( psEnvelope->MinZ > oRingEnv.MinZ )
     908               1 :                     psEnvelope->MinZ = oRingEnv.MinZ;
     909               1 :                 if( psEnvelope->MaxZ < oRingEnv.MaxZ )
     910               0 :                     psEnvelope->MaxZ = oRingEnv.MaxZ;
     911                 :             }
     912                 :         }
     913                 :     }
     914                 : 
     915              89 :     if (!bExtentSet)
     916                 :     {
     917               1 :         psEnvelope->MinX = psEnvelope->MinY = psEnvelope->MinZ = 0;
     918               1 :         psEnvelope->MaxX = psEnvelope->MaxY = psEnvelope->MaxZ = 0;
     919                 :     }
     920              89 : }
     921                 : 
     922                 : /************************************************************************/
     923                 : /*                               Equal()                                */
     924                 : /************************************************************************/
     925                 : 
     926           37919 : OGRBoolean OGRPolygon::Equals( OGRGeometry * poOther ) const
     927                 : 
     928                 : {
     929           37919 :     OGRPolygon *poOPoly = (OGRPolygon *) poOther;
     930                 : 
     931           37919 :     if( poOPoly == this )
     932               0 :         return TRUE;
     933                 :     
     934           37919 :     if( poOther->getGeometryType() != getGeometryType() )
     935               0 :         return FALSE;
     936                 : 
     937           37919 :     if( getNumInteriorRings() != poOPoly->getNumInteriorRings() )
     938            1396 :         return FALSE;
     939                 : 
     940           36523 :     if( getExteriorRing() == NULL && poOPoly->getExteriorRing() == NULL )
     941                 :         /* ok */;
     942           36523 :     else if( getExteriorRing() == NULL || poOPoly->getExteriorRing() == NULL )
     943               0 :         return FALSE;
     944           36523 :     else if( !getExteriorRing()->Equals( poOPoly->getExteriorRing() ) )
     945           23031 :         return FALSE;
     946                 :     
     947                 :     // we should eventually test the SRS.
     948                 : 
     949           13589 :     for( int iRing = 0; iRing < getNumInteriorRings(); iRing++ )
     950                 :     {
     951              97 :         if( !getInteriorRing(iRing)->Equals(poOPoly->getInteriorRing(iRing)) )
     952               0 :             return FALSE;
     953                 :     }
     954                 : 
     955           13492 :     return TRUE;
     956                 : }
     957                 : 
     958                 : /************************************************************************/
     959                 : /*                             transform()                              */
     960                 : /************************************************************************/
     961                 : 
     962              27 : OGRErr OGRPolygon::transform( OGRCoordinateTransformation *poCT )
     963                 : 
     964                 : {
     965                 : #ifdef DISABLE_OGRGEOM_TRANSFORM
     966                 :     return OGRERR_FAILURE;
     967                 : #else
     968              55 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
     969                 :     {
     970                 :         OGRErr  eErr;
     971                 : 
     972              28 :         eErr = papoRings[iRing]->transform( poCT );
     973              28 :         if( eErr != OGRERR_NONE )
     974                 :         {
     975               0 :             if( iRing != 0 )
     976                 :             {
     977                 :                 CPLDebug("OGR", 
     978                 :                          "OGRPolygon::transform() failed for a ring other\n"
     979                 :                          "than the first, meaning some rings are transformed\n"
     980               0 :                          "and some are not!\n" );
     981                 : 
     982               0 :                 return OGRERR_FAILURE;
     983                 :             }
     984                 : 
     985               0 :             return eErr;
     986                 :         }
     987                 :     }
     988                 : 
     989              27 :     assignSpatialReference( poCT->GetTargetCS() );
     990                 : 
     991              27 :     return OGRERR_NONE;
     992                 : #endif
     993                 : }
     994                 : 
     995                 : /************************************************************************/
     996                 : /*                           IsPointOnSurface()                           */
     997                 : /************************************************************************/
     998                 : 
     999               0 : OGRBoolean OGRPolygon::IsPointOnSurface( const OGRPoint * pt) const
    1000                 : {
    1001               0 :     if ( NULL == pt)
    1002               0 :         return 0;
    1003                 : 
    1004               0 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
    1005                 :     {
    1006               0 :         if ( papoRings[iRing]->isPointInRing(pt) )
    1007                 :         {
    1008               0 :             return 1;
    1009                 :         }
    1010                 :     }
    1011                 : 
    1012               0 :     return 0;
    1013                 : }
    1014                 : 
    1015                 : /************************************************************************/
    1016                 : /*                             closeRings()                             */
    1017                 : /************************************************************************/
    1018                 : 
    1019             204 : void OGRPolygon::closeRings()
    1020                 : 
    1021                 : {
    1022             408 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
    1023             204 :         papoRings[iRing]->closeRings();
    1024             204 : }
    1025                 : 
    1026                 : /************************************************************************/
    1027                 : /*                              get_Area()                              */
    1028                 : /************************************************************************/
    1029                 : 
    1030                 : /**
    1031                 :  * \brief Compute area of polygon.
    1032                 :  *
    1033                 :  * The area is computed as the area of the outer ring less the area of all
    1034                 :  * internal rings. 
    1035                 :  *
    1036                 :  * @return computed area.
    1037                 :  */
    1038                 : 
    1039            1754 : double OGRPolygon::get_Area() const
    1040                 : 
    1041                 : {
    1042            1754 :     double dfArea = 0.0;
    1043                 : 
    1044            1754 :     if( getExteriorRing() != NULL )
    1045                 :     {
    1046                 :         int iRing;
    1047                 : 
    1048            1754 :         dfArea = getExteriorRing()->get_Area();
    1049                 : 
    1050            1756 :         for( iRing = 0; iRing < getNumInteriorRings(); iRing++ )
    1051               2 :             dfArea -= getInteriorRing( iRing )->get_Area();
    1052                 :     }
    1053                 : 
    1054            1754 :     return dfArea;
    1055                 : }
    1056                 : 
    1057                 : /************************************************************************/
    1058                 : /*                       setCoordinateDimension()                       */
    1059                 : /************************************************************************/
    1060                 : 
    1061             613 : void OGRPolygon::setCoordinateDimension( int nNewDimension )
    1062                 : 
    1063                 : {
    1064            1209 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
    1065             596 :         papoRings[iRing]->setCoordinateDimension( nNewDimension );
    1066                 : 
    1067             613 :     OGRGeometry::setCoordinateDimension( nNewDimension );
    1068             613 : }
    1069                 : 
    1070                 : 
    1071                 : /************************************************************************/
    1072                 : /*                               IsEmpty()                              */
    1073                 : /************************************************************************/
    1074                 : 
    1075           14885 : OGRBoolean OGRPolygon::IsEmpty(  ) const
    1076                 : {
    1077           14886 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
    1078           14868 :         if (papoRings[iRing]->IsEmpty() == FALSE)
    1079           14867 :             return FALSE;
    1080              18 :     return TRUE;
    1081                 : }
    1082                 : 
    1083                 : /************************************************************************/
    1084                 : /*                       OGRPolygon::segmentize()                       */
    1085                 : /************************************************************************/
    1086                 : 
    1087              10 : void OGRPolygon::segmentize( double dfMaxLength )
    1088                 : {
    1089              20 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
    1090              10 :         papoRings[iRing]->segmentize(dfMaxLength);
    1091              10 : }
    1092                 : 
    1093                 : /************************************************************************/
    1094                 : /*                               swapXY()                               */
    1095                 : /************************************************************************/
    1096                 : 
    1097              24 : void OGRPolygon::swapXY()
    1098                 : {
    1099              48 :     for( int iRing = 0; iRing < nRingCount; iRing++ )
    1100              24 :         papoRings[iRing]->swapXY();
    1101              24 : }

Generated by: LCOV version 1.7