ultimatepp/bazaar/plugin/geotiff/libgeotiff/ogr/ogrpolygon.cpp
cxl b67920c1ca bazaar: plugin/geotiff
git-svn-id: svn://ultimatepp.org/upp/trunk@7587 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2014-08-12 18:56:26 +00:00

1039 lines
33 KiB
C++

/******************************************************************************
* $Id: ogrpolygon.cpp 14881 2008-07-10 20:30:19Z rouault $
*
* Project: OpenGIS Simple Features Reference Implementation
* Purpose: The OGRPolygon geometry class.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Frank Warmerdam
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
****************************************************************************/
#include "ogr_geometry.h"
#include "ogr_p.h"
#include "ogr_geos.h"
#include "ogr_api.h"
CPL_CVSID("$Id: ogrpolygon.cpp 14881 2008-07-10 20:30:19Z rouault $");
/************************************************************************/
/* OGRPolygon() */
/************************************************************************/
/**
* Create an empty polygon.
*/
OGRPolygon::OGRPolygon()
{
nRingCount = 0;
papoRings = NULL;
}
/************************************************************************/
/* ~OGRPolygon() */
/************************************************************************/
OGRPolygon::~OGRPolygon()
{
empty();
}
/************************************************************************/
/* clone() */
/************************************************************************/
OGRGeometry *OGRPolygon::clone() const
{
OGRPolygon *poNewPolygon;
poNewPolygon = new OGRPolygon;
poNewPolygon->assignSpatialReference( getSpatialReference() );
for( int i = 0; i < nRingCount; i++ )
{
poNewPolygon->addRing( papoRings[i] );
}
return poNewPolygon;
}
/************************************************************************/
/* empty() */
/************************************************************************/
void OGRPolygon::empty()
{
if( papoRings != NULL )
{
for( int i = 0; i < nRingCount; i++ )
{
delete papoRings[i];
}
OGRFree( papoRings );
}
papoRings = NULL;
nRingCount = 0;
}
/************************************************************************/
/* getGeometryType() */
/************************************************************************/
OGRwkbGeometryType OGRPolygon::getGeometryType() const
{
if( getCoordinateDimension() == 3 )
return wkbPolygon25D;
else
return wkbPolygon;
}
/************************************************************************/
/* getDimension() */
/************************************************************************/
int OGRPolygon::getDimension() const
{
return 2;
}
/************************************************************************/
/* flattenTo2D() */
/************************************************************************/
void OGRPolygon::flattenTo2D()
{
for( int iRing = 0; iRing < nRingCount; iRing++ )
papoRings[iRing]->flattenTo2D();
nCoordDimension = 2;
}
/************************************************************************/
/* getGeometryName() */
/************************************************************************/
const char * OGRPolygon::getGeometryName() const
{
return "POLYGON";
}
/************************************************************************/
/* getExteriorRing() */
/************************************************************************/
/**
* Fetch reference to external polygon ring.
*
* Note that the returned ring pointer is to an internal data object of
* the OGRPolygon. It should not be modified or deleted by the application,
* and the pointer is only valid till the polygon is next modified. Use
* the OGRGeometry::clone() method to make a separate copy within the
* application.
*
* Relates to the SFCOM IPolygon::get_ExteriorRing() method.
*
* @return pointer to external ring. May be NULL if the OGRPolygon is empty.
*/
OGRLinearRing *OGRPolygon::getExteriorRing()
{
if( nRingCount > 0 )
return papoRings[0];
else
return NULL;
}
const OGRLinearRing *OGRPolygon::getExteriorRing() const
{
if( nRingCount > 0 )
return papoRings[0];
else
return NULL;
}
/************************************************************************/
/* getNumInteriorRings() */
/************************************************************************/
/**
* Fetch the number of internal rings.
*
* Relates to the SFCOM IPolygon::get_NumInteriorRings() method.
*
* @return count of internal rings, zero or more.
*/
int OGRPolygon::getNumInteriorRings() const
{
if( nRingCount > 0 )
return nRingCount-1;
else
return 0;
}
/************************************************************************/
/* getInteriorRing() */
/************************************************************************/
/**
* Fetch reference to indicated internal ring.
*
* Note that the returned ring pointer is to an internal data object of
* the OGRPolygon. It should not be modified or deleted by the application,
* and the pointer is only valid till the polygon is next modified. Use
* the OGRGeometry::clone() method to make a separate copy within the
* application.
*
* Relates to the SFCOM IPolygon::get_InternalRing() method.
*
* @param iRing internal ring index from 0 to getNumInternalRings() - 1.
*
* @return pointer to external ring. May be NULL if the OGRPolygon is empty.
*/
OGRLinearRing *OGRPolygon::getInteriorRing( int iRing )
{
if( iRing < 0 || iRing >= nRingCount-1 )
return NULL;
else
return papoRings[iRing+1];
}
const OGRLinearRing *OGRPolygon::getInteriorRing( int iRing ) const
{
if( iRing < 0 || iRing >= nRingCount-1 )
return NULL;
else
return papoRings[iRing+1];
}
/************************************************************************/
/* addRing() */
/************************************************************************/
/**
* Add a ring to a polygon.
*
* If the polygon has no external ring (it is empty) this will be used as
* the external ring, otherwise it is used as an internal ring. The passed
* OGRLinearRing remains the responsibility of the caller (an internal copy
* is made).
*
* This method has no SFCOM analog.
*
* @param poNewRing ring to be added to the polygon.
*/
void OGRPolygon::addRing( OGRLinearRing * poNewRing )
{
papoRings = (OGRLinearRing **) OGRRealloc( papoRings,
sizeof(void*) * (nRingCount+1));
papoRings[nRingCount] = new OGRLinearRing( poNewRing );
nRingCount++;
if( poNewRing->getCoordinateDimension() == 3 )
nCoordDimension = 3;
}
/************************************************************************/
/* addRingDirectly() */
/************************************************************************/
/**
* Add a ring to a polygon.
*
* If the polygon has no external ring (it is empty) this will be used as
* the external ring, otherwise it is used as an internal ring. Ownership
* of the passed ring is assumed by the OGRPolygon, but otherwise this
* method operates the same as OGRPolygon::AddRing().
*
* This method has no SFCOM analog.
*
* @param poNewRing ring to be added to the polygon.
*/
void OGRPolygon::addRingDirectly( OGRLinearRing * poNewRing )
{
papoRings = (OGRLinearRing **) OGRRealloc( papoRings,
sizeof(void*) * (nRingCount+1));
papoRings[nRingCount] = poNewRing;
nRingCount++;
if( poNewRing->getCoordinateDimension() == 3 )
nCoordDimension = 3;
}
/************************************************************************/
/* WkbSize() */
/* */
/* Return the size of this object in well known binary */
/* representation including the byte order, and type information. */
/************************************************************************/
int OGRPolygon::WkbSize() const
{
int nSize = 9;
int b3D = getCoordinateDimension() == 3;
for( int i = 0; i < nRingCount; i++ )
{
nSize += papoRings[i]->_WkbSize( b3D );
}
return nSize;
}
/************************************************************************/
/* importFromWkb() */
/* */
/* Initialize from serialized stream in well known binary */
/* format. */
/************************************************************************/
OGRErr OGRPolygon::importFromWkb( unsigned char * pabyData,
int nSize )
{
OGRwkbByteOrder eByteOrder;
int nDataOffset, b3D;
if( nSize < 9 && nSize != -1 )
return OGRERR_NOT_ENOUGH_DATA;
/* -------------------------------------------------------------------- */
/* Get the byte order byte. */
/* -------------------------------------------------------------------- */
eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
CPLAssert( eByteOrder == wkbXDR || eByteOrder == wkbNDR );
/* -------------------------------------------------------------------- */
/* Get the geometry feature type. For now we assume that */
/* geometry type is between 0 and 255 so we only have to fetch */
/* one byte. */
/* -------------------------------------------------------------------- */
#ifdef DEBUG
OGRwkbGeometryType eGeometryType;
if( eByteOrder == wkbNDR )
eGeometryType = (OGRwkbGeometryType) pabyData[1];
else
eGeometryType = (OGRwkbGeometryType) pabyData[4];
CPLAssert( eGeometryType == wkbPolygon );
#endif
if( eByteOrder == wkbNDR )
b3D = pabyData[4] & 0x80 || pabyData[2] & 0x80;
else
b3D = pabyData[1] & 0x80 || pabyData[3] & 0x80;
if( b3D )
nCoordDimension = 3;
else
nCoordDimension = 2;
/* -------------------------------------------------------------------- */
/* Do we already have some rings? */
/* -------------------------------------------------------------------- */
if( nRingCount != 0 )
{
for( int iRing = 0; iRing < nRingCount; iRing++ )
delete papoRings[iRing];
OGRFree( papoRings );
papoRings = NULL;
}
/* -------------------------------------------------------------------- */
/* Get the ring count. */
/* -------------------------------------------------------------------- */
memcpy( &nRingCount, pabyData + 5, 4 );
if( OGR_SWAP( eByteOrder ) )
nRingCount = CPL_SWAP32(nRingCount);
papoRings = (OGRLinearRing **) OGRMalloc(sizeof(void*) * nRingCount);
nDataOffset = 9;
if( nSize != -1 )
nSize -= nDataOffset;
/* -------------------------------------------------------------------- */
/* Get the rings. */
/* -------------------------------------------------------------------- */
for( int iRing = 0; iRing < nRingCount; iRing++ )
{
OGRErr eErr;
papoRings[iRing] = new OGRLinearRing();
eErr = papoRings[iRing]->_importFromWkb( eByteOrder, b3D,
pabyData + nDataOffset,
nSize );
if( eErr != OGRERR_NONE )
{
nRingCount = iRing;
return eErr;
}
if( nSize != -1 )
nSize -= papoRings[iRing]->_WkbSize( b3D );
nDataOffset += papoRings[iRing]->_WkbSize( b3D );
}
return OGRERR_NONE;
}
/************************************************************************/
/* exportToWkb() */
/* */
/* Build a well known binary representation of this object. */
/************************************************************************/
OGRErr OGRPolygon::exportToWkb( OGRwkbByteOrder eByteOrder,
unsigned char * pabyData ) const
{
int nOffset;
int b3D = getCoordinateDimension() == 3;
/* -------------------------------------------------------------------- */
/* Set the byte order. */
/* -------------------------------------------------------------------- */
pabyData[0] = DB2_V72_UNFIX_BYTE_ORDER((unsigned char) eByteOrder);
/* -------------------------------------------------------------------- */
/* Set the geometry feature type. */
/* -------------------------------------------------------------------- */
GUInt32 nGType = getGeometryType();
if( eByteOrder == wkbNDR )
nGType = CPL_LSBWORD32( nGType );
else
nGType = CPL_MSBWORD32( nGType );
memcpy( pabyData + 1, &nGType, 4 );
/* -------------------------------------------------------------------- */
/* Copy in the raw data. */
/* -------------------------------------------------------------------- */
if( OGR_SWAP( eByteOrder ) )
{
int nCount;
nCount = CPL_SWAP32( nRingCount );
memcpy( pabyData+5, &nCount, 4 );
}
else
{
memcpy( pabyData+5, &nRingCount, 4 );
}
nOffset = 9;
/* ==================================================================== */
/* Serialize each of the rings. */
/* ==================================================================== */
for( int iRing = 0; iRing < nRingCount; iRing++ )
{
papoRings[iRing]->_exportToWkb( eByteOrder, b3D,
pabyData + nOffset );
nOffset += papoRings[iRing]->_WkbSize(b3D);
}
return OGRERR_NONE;
}
/************************************************************************/
/* importFromWkt() */
/* */
/* Instantiate from well known text format. Currently this is */
/* `POLYGON ((x y, x y, ...),(x y, ...),...)'. */
/************************************************************************/
OGRErr OGRPolygon::importFromWkt( char ** ppszInput )
{
char szToken[OGR_WKT_TOKEN_MAX];
const char *pszInput = *ppszInput;
int iRing;
/* -------------------------------------------------------------------- */
/* Clear existing rings. */
/* -------------------------------------------------------------------- */
if( nRingCount > 0 )
{
for( iRing = 0; iRing < nRingCount; iRing++ )
delete papoRings[iRing];
nRingCount = 0;
CPLFree( papoRings );
}
/* -------------------------------------------------------------------- */
/* Read and verify the ``POLYGON'' keyword token. */
/* -------------------------------------------------------------------- */
pszInput = OGRWktReadToken( pszInput, szToken );
if( !EQUAL(szToken,"POLYGON") )
return OGRERR_CORRUPT_DATA;
/* -------------------------------------------------------------------- */
/* The next character should be a ( indicating the start of the */
/* list of rings. We also need to support POLYGON EMPTY and */
/* POLYGON(EMPTY). */
/* -------------------------------------------------------------------- */
pszInput = OGRWktReadToken( pszInput, szToken );
if( EQUAL(szToken,"EMPTY") )
{
*ppszInput = (char *) pszInput;
return OGRERR_NONE;
}
if( szToken[0] != '(' )
return OGRERR_CORRUPT_DATA;
OGRWktReadToken( pszInput, szToken );
if( EQUAL(szToken,"EMPTY") )
{
pszInput = OGRWktReadToken( pszInput, szToken );
pszInput = OGRWktReadToken( pszInput, szToken );
*ppszInput = (char *) pszInput;
if( !EQUAL(szToken,")") )
return OGRERR_CORRUPT_DATA;
else
return OGRERR_NONE;
}
/* ==================================================================== */
/* Read each ring in turn. Note that we try to reuse the same */
/* point list buffer from ring to ring to cut down on */
/* allocate/deallocate overhead. */
/* ==================================================================== */
OGRRawPoint *paoPoints = NULL;
int nMaxPoints = 0, nMaxRings = 0;
double *padfZ = NULL;
nCoordDimension = 2;
do
{
int nPoints = 0;
/* -------------------------------------------------------------------- */
/* Read points for one ring from input. */
/* -------------------------------------------------------------------- */
pszInput = OGRWktReadPoints( pszInput, &paoPoints, &padfZ, &nMaxPoints,
&nPoints );
if( pszInput == NULL )
{
CPLFree( paoPoints );
return OGRERR_CORRUPT_DATA;
}
/* -------------------------------------------------------------------- */
/* Do we need to grow the ring array? */
/* -------------------------------------------------------------------- */
if( nRingCount == nMaxRings )
{
nMaxRings = nMaxRings * 2 + 1;
papoRings = (OGRLinearRing **)
CPLRealloc(papoRings, nMaxRings * sizeof(OGRLinearRing*));
}
/* -------------------------------------------------------------------- */
/* Create the new ring, and assign to ring list. */
/* -------------------------------------------------------------------- */
papoRings[nRingCount] = new OGRLinearRing();
papoRings[nRingCount]->setPoints( nPoints, paoPoints, padfZ );
nRingCount++;
if( padfZ )
nCoordDimension = 3;
/* -------------------------------------------------------------------- */
/* Read the delimeter following the ring. */
/* -------------------------------------------------------------------- */
pszInput = OGRWktReadToken( pszInput, szToken );
} while( szToken[0] == ',' );
/* -------------------------------------------------------------------- */
/* freak if we don't get a closing bracket. */
/* -------------------------------------------------------------------- */
CPLFree( paoPoints );
CPLFree( padfZ );
if( szToken[0] != ')' )
return OGRERR_CORRUPT_DATA;
*ppszInput = (char *) pszInput;
return OGRERR_NONE;
}
/************************************************************************/
/* exportToWkt() */
/* */
/* Translate this structure into it's well known text format */
/* equivelent. This could be made alot more CPU efficient! */
/************************************************************************/
OGRErr OGRPolygon::exportToWkt( char ** ppszDstText ) const
{
char **papszRings;
int iRing, nCumulativeLength = 0, nNonEmptyRings = 0;
OGRErr eErr;
/* -------------------------------------------------------------------- */
/* If we have no valid exterior ring, return POLYGON EMPTY. */
/* -------------------------------------------------------------------- */
if (getExteriorRing() == NULL ||
getExteriorRing()->IsEmpty())
{
*ppszDstText = CPLStrdup("POLYGON EMPTY");
return OGRERR_NONE;
}
/* -------------------------------------------------------------------- */
/* Build a list of strings containing the stuff for each ring. */
/* -------------------------------------------------------------------- */
papszRings = (char **) CPLCalloc(sizeof(char *),nRingCount);
for( iRing = 0; iRing < nRingCount; iRing++ )
{
papoRings[iRing]->setCoordinateDimension( getCoordinateDimension() );
if( papoRings[iRing]->getNumPoints() == 0 )
{
papszRings[iRing] = NULL;
continue;
}
eErr = papoRings[iRing]->exportToWkt( &(papszRings[iRing]) );
if( eErr != OGRERR_NONE )
return eErr;
CPLAssert( EQUALN(papszRings[iRing],"LINEARRING (", 12) );
nCumulativeLength += strlen(papszRings[iRing] + 11);
nNonEmptyRings++;
}
/* -------------------------------------------------------------------- */
/* Allocate exactly the right amount of space for the */
/* aggregated string. */
/* -------------------------------------------------------------------- */
*ppszDstText = (char *) VSIMalloc(nCumulativeLength + nNonEmptyRings + 11);
if( *ppszDstText == NULL )
return OGRERR_NOT_ENOUGH_MEMORY;
/* -------------------------------------------------------------------- */
/* Build up the string, freeing temporary strings as we go. */
/* -------------------------------------------------------------------- */
strcpy( *ppszDstText, "POLYGON (" );
for( iRing = 0; iRing < nRingCount; iRing++ )
{
if( papszRings[iRing] == NULL )
{
CPLDebug( "OGR", "OGRPolygon::exportToWkt() - skipping empty ring.");
continue;
}
if( iRing > 0 )
strcat( *ppszDstText, "," );
strcat( *ppszDstText, papszRings[iRing] + 11 );
VSIFree( papszRings[iRing] );
}
strcat( *ppszDstText, ")" );
CPLFree( papszRings );
return OGRERR_NONE;
}
/************************************************************************/
/* Centroid() */
/************************************************************************/
/**
* Compute the polygon centroid.
*
* The centroid location is applied to the passed in OGRPoint object.
*
* @return OGRERR_NONE on success or OGRERR_FAILURE on error.
*/
int OGRPolygon::Centroid( OGRPoint *poPoint ) const
{
if( poPoint == NULL )
return OGRERR_FAILURE;
#ifndef HAVE_GEOS
// notdef ... not implemented yet.
return OGRERR_FAILURE;
#else
GEOSGeom hThisGeosGeom = NULL;
GEOSGeom hOtherGeosGeom = NULL;
hThisGeosGeom = exportToGEOS();
if( hThisGeosGeom != NULL )
{
hOtherGeosGeom = GEOSGetCentroid( hThisGeosGeom );
OGRPoint *poCentroid = (OGRPoint *)
OGRGeometryFactory::createFromGEOS( hOtherGeosGeom );
GEOSGeom_destroy( hThisGeosGeom );
GEOSGeom_destroy( hOtherGeosGeom );
if( poPoint == NULL
|| wkbFlatten(poPoint->getGeometryType()) != wkbPoint )
return OGRERR_FAILURE;
poPoint->setX( poCentroid->getX() );
poPoint->setY( poCentroid->getY() );
delete poCentroid;
return OGRERR_NONE;
}
else
{
return OGRERR_FAILURE;
}
#endif /* HAVE_GEOS */
}
/************************************************************************/
/* OGR_G_Centroid() */
/************************************************************************/
int OGR_G_Centroid( OGRGeometryH hPolygon, OGRGeometryH hCentroidPoint )
{
OGRPolygon *poPoly = ((OGRPolygon *) hPolygon);
OGRPoint *poCentroid = ((OGRPoint *) hCentroidPoint);
if( poCentroid == NULL )
return OGRERR_FAILURE;
if( wkbFlatten(poCentroid->getGeometryType()) != wkbPoint )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Passed wrong geometry type as centroid argument." );
return OGRERR_FAILURE;
}
if( wkbFlatten(poPoly->getGeometryType()) != wkbPolygon )
{
CPLError( CE_Failure, CPLE_AppDefined,
"Invoked Centroid() on non-Polygon." );
return OGRERR_FAILURE;
}
return poPoly->Centroid( poCentroid );
}
/************************************************************************/
/* PointOnSurface() */
/************************************************************************/
int OGRPolygon::PointOnSurface( OGRPoint *poPoint ) const
{
if( poPoint == NULL )
return OGRERR_FAILURE;
#ifndef HAVE_GEOS
return OGRERR_FAILURE;
#else
GEOSGeom hThisGeosGeom = NULL;
GEOSGeom hOtherGeosGeom = NULL;
hThisGeosGeom = exportToGEOS();
if( hThisGeosGeom != NULL )
{
hOtherGeosGeom = GEOSPointOnSurface( hThisGeosGeom );
OGRPoint *poInsidePoint = (OGRPoint *)
OGRGeometryFactory::createFromGEOS( hOtherGeosGeom );
GEOSGeom_destroy( hThisGeosGeom );
GEOSGeom_destroy( hOtherGeosGeom );
if( poPoint == NULL
|| wkbFlatten(poPoint->getGeometryType()) != wkbPoint )
return OGRERR_FAILURE;
poPoint->setX( poInsidePoint->getX() );
poPoint->setY( poInsidePoint->getY() );
delete poInsidePoint;
return OGRERR_NONE;
}
else
{
return OGRERR_FAILURE;
}
#endif /* HAVE_GEOS */
}
/************************************************************************/
/* getEnvelope() */
/************************************************************************/
void OGRPolygon::getEnvelope( OGREnvelope * psEnvelope ) const
{
OGREnvelope oRingEnv;
if( nRingCount == 0 )
return;
papoRings[0]->getEnvelope( psEnvelope );
for( int iRing = 1; iRing < nRingCount; iRing++ )
{
papoRings[iRing]->getEnvelope( &oRingEnv );
if( psEnvelope->MinX > oRingEnv.MinX )
psEnvelope->MinX = oRingEnv.MinX;
if( psEnvelope->MinY > oRingEnv.MinY )
psEnvelope->MinY = oRingEnv.MinY;
if( psEnvelope->MaxX < oRingEnv.MaxX )
psEnvelope->MaxX = oRingEnv.MaxX;
if( psEnvelope->MaxY < oRingEnv.MaxY )
psEnvelope->MaxY = oRingEnv.MaxY;
}
}
/************************************************************************/
/* Equal() */
/************************************************************************/
OGRBoolean OGRPolygon::Equals( OGRGeometry * poOther ) const
{
OGRPolygon *poOPoly = (OGRPolygon *) poOther;
if( poOPoly == this )
return TRUE;
if( poOther->getGeometryType() != getGeometryType() )
return FALSE;
if( getNumInteriorRings() != poOPoly->getNumInteriorRings() )
return FALSE;
if( getExteriorRing() == NULL && poOPoly->getExteriorRing() == NULL )
/* ok */;
else if( getExteriorRing() == NULL || poOPoly->getExteriorRing() == NULL )
return FALSE;
else if( !getExteriorRing()->Equals( poOPoly->getExteriorRing() ) )
return FALSE;
// we should eventually test the SRS.
for( int iRing = 0; iRing < getNumInteriorRings(); iRing++ )
{
if( !getInteriorRing(iRing)->Equals(poOPoly->getInteriorRing(iRing)) )
return FALSE;
}
return TRUE;
}
/************************************************************************/
/* transform() */
/************************************************************************/
OGRErr OGRPolygon::transform( OGRCoordinateTransformation *poCT )
{
#ifdef DISABLE_OGRGEOM_TRANSFORM
return OGRERR_FAILURE;
#else
for( int iRing = 0; iRing < nRingCount; iRing++ )
{
OGRErr eErr;
eErr = papoRings[iRing]->transform( poCT );
if( eErr != OGRERR_NONE )
{
if( iRing != 0 )
{
CPLDebug("OGR",
"OGRPolygon::transform() failed for a ring other\n"
"than the first, meaning some rings are transformed\n"
"and some are not!\n" );
return OGRERR_FAILURE;
}
return eErr;
}
}
assignSpatialReference( poCT->GetTargetCS() );
return OGRERR_NONE;
#endif
}
/************************************************************************/
/* IsPointOnSurface() */
/************************************************************************/
OGRBoolean OGRPolygon::IsPointOnSurface( const OGRPoint * pt) const
{
if ( NULL == pt)
return 0;
for( int iRing = 0; iRing < nRingCount; iRing++ )
{
if ( papoRings[iRing]->isPointInRing(pt) )
{
return 1;
}
}
return 0;
}
/************************************************************************/
/* closeRings() */
/************************************************************************/
void OGRPolygon::closeRings()
{
for( int iRing = 0; iRing < nRingCount; iRing++ )
papoRings[iRing]->closeRings();
}
/************************************************************************/
/* get_Area() */
/************************************************************************/
/**
* Compute area of polygon.
*
* The area is computed as the area of the outer ring less the area of all
* internal rings.
*
* @return computed area.
*/
double OGRPolygon::get_Area() const
{
double dfArea = 0.0;
if( getExteriorRing() != NULL )
{
int iRing;
dfArea = getExteriorRing()->get_Area();
for( iRing = 0; iRing < getNumInteriorRings(); iRing++ )
dfArea -= getInteriorRing( iRing )->get_Area();
}
return dfArea;
}
/************************************************************************/
/* setCoordinateDimension() */
/************************************************************************/
void OGRPolygon::setCoordinateDimension( int nNewDimension )
{
for( int iRing = 0; iRing < nRingCount; iRing++ )
papoRings[iRing]->setCoordinateDimension( nNewDimension );
OGRGeometry::setCoordinateDimension( nNewDimension );
}
/************************************************************************/
/* IsEmpty() */
/************************************************************************/
OGRBoolean OGRPolygon::IsEmpty( ) const
{
for( int iRing = 0; iRing < nRingCount; iRing++ )
if (papoRings[iRing]->IsEmpty() == FALSE)
return FALSE;
return TRUE;
}
/************************************************************************/
/* OGRPolygon::segmentize() */
/************************************************************************/
void OGRPolygon::segmentize( double dfMaxLength )
{
for( int iRing = 0; iRing < nRingCount; iRing++ )
papoRings[iRing]->segmentize(dfMaxLength);
}