mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-06-02 06:12:41 -06:00
5371 lines
174 KiB
C++
5371 lines
174 KiB
C++
/******************************************************************************
|
|
* $Id: ogrgeometry.cpp 28548 2015-02-24 17:30:15Z rouault $
|
|
*
|
|
* Project: OpenGIS Simple Features Reference Implementation
|
|
* Purpose: Implements a few base methods on OGRGeometry.
|
|
* Author: Frank Warmerdam, warmerdam@pobox.com
|
|
*
|
|
******************************************************************************
|
|
* Copyright (c) 1999, Frank Warmerdam
|
|
* Copyright (c) 2008-2013, Even Rouault <even dot rouault at mines-paris dot org>
|
|
*
|
|
* 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_api.h"
|
|
#include "ogr_p.h"
|
|
#include "ogr_geos.h"
|
|
#include "cpl_multiproc.h"
|
|
#include <assert.h>
|
|
|
|
CPL_CVSID("$Id: ogrgeometry.cpp 28548 2015-02-24 17:30:15Z rouault $");
|
|
|
|
int OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER = FALSE;
|
|
|
|
#ifdef HAVE_GEOS
|
|
static void OGRGEOSErrorHandler(const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
CPLErrorV( CE_Failure, CPLE_AppDefined, fmt, args );
|
|
va_end(args);
|
|
}
|
|
|
|
static void OGRGEOSWarningHandler(const char *fmt, ...)
|
|
{
|
|
va_list args;
|
|
|
|
va_start(args, fmt);
|
|
CPLErrorV( CE_Warning, CPLE_AppDefined, fmt, args );
|
|
va_end(args);
|
|
}
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/* OGRGeometry() */
|
|
/************************************************************************/
|
|
|
|
OGRGeometry::OGRGeometry()
|
|
|
|
{
|
|
poSRS = NULL;
|
|
nCoordDimension = 2;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ~OGRGeometry() */
|
|
/************************************************************************/
|
|
|
|
OGRGeometry::~OGRGeometry()
|
|
|
|
{
|
|
if( poSRS != NULL )
|
|
poSRS->Release();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* dumpReadable() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Dump geometry in well known text format to indicated output file.
|
|
*
|
|
* A few options can be defined to change the default dump :
|
|
* <ul>
|
|
* <li>DISPLAY_GEOMETRY=NO : to hide the dump of the geometry</li>
|
|
* <li>DISPLAY_GEOMETRY=WKT or YES (default) : dump the geometry as a WKT</li>
|
|
* <li>DISPLAY_GEOMETRY=SUMMARY : to get only a summary of the geometry</li>
|
|
* </ul>
|
|
*
|
|
* This method is the same as the C function OGR_G_DumpReadable().
|
|
*
|
|
* @param fp the text file to write the geometry to.
|
|
* @param pszPrefix the prefix to put on each line of output.
|
|
* @param papszOptions NULL terminated list of options (may be NULL)
|
|
*/
|
|
|
|
void OGRGeometry::dumpReadable( FILE * fp, const char * pszPrefix, char** papszOptions ) const
|
|
|
|
{
|
|
char *pszWkt = NULL;
|
|
|
|
if( pszPrefix == NULL )
|
|
pszPrefix = "";
|
|
|
|
if( fp == NULL )
|
|
fp = stdout;
|
|
|
|
const char* pszDisplayGeometry =
|
|
CSLFetchNameValue(papszOptions, "DISPLAY_GEOMETRY");
|
|
if (pszDisplayGeometry != NULL && EQUAL(pszDisplayGeometry, "SUMMARY"))
|
|
{
|
|
OGRLineString *poLine;
|
|
OGRCurvePolygon *poPoly;
|
|
OGRCurve *poRing;
|
|
OGRGeometryCollection *poColl;
|
|
fprintf( fp, "%s%s : ", pszPrefix, getGeometryName() );
|
|
switch( getGeometryType() )
|
|
{
|
|
case wkbUnknown:
|
|
case wkbNone:
|
|
case wkbPoint:
|
|
case wkbPoint25D:
|
|
fprintf( fp, "\n");
|
|
break;
|
|
case wkbLineString:
|
|
case wkbLineString25D:
|
|
case wkbCircularString:
|
|
case wkbCircularStringZ:
|
|
poLine = (OGRLineString*)this;
|
|
fprintf( fp, "%d points\n", poLine->getNumPoints() );
|
|
break;
|
|
case wkbPolygon:
|
|
case wkbPolygon25D:
|
|
case wkbCurvePolygon:
|
|
case wkbCurvePolygonZ:
|
|
{
|
|
int ir;
|
|
int nRings;
|
|
poPoly = (OGRCurvePolygon*)this;
|
|
poRing = poPoly->getExteriorRingCurve();
|
|
nRings = poPoly->getNumInteriorRings();
|
|
if (poRing == NULL)
|
|
fprintf( fp, "empty");
|
|
else
|
|
{
|
|
fprintf( fp, "%d points", poRing->getNumPoints() );
|
|
if( wkbFlatten(poRing->getGeometryType()) == wkbCompoundCurve )
|
|
{
|
|
fprintf( fp, " (");
|
|
poRing->dumpReadable(fp, NULL, papszOptions);
|
|
fprintf( fp, ")");
|
|
}
|
|
if (nRings)
|
|
{
|
|
fprintf( fp, ", %d inner rings (", nRings);
|
|
for( ir = 0; ir < nRings; ir++)
|
|
{
|
|
poRing = poPoly->getInteriorRingCurve(ir);
|
|
if (ir)
|
|
fprintf( fp, ", ");
|
|
fprintf( fp, "%d points", poRing->getNumPoints() );
|
|
if( wkbFlatten(poRing->getGeometryType()) == wkbCompoundCurve )
|
|
{
|
|
fprintf( fp, " (");
|
|
poRing->dumpReadable(fp, NULL, papszOptions);
|
|
fprintf( fp, ")");
|
|
}
|
|
}
|
|
fprintf( fp, ")");
|
|
}
|
|
}
|
|
fprintf( fp, "\n");
|
|
break;
|
|
}
|
|
case wkbCompoundCurve:
|
|
case wkbCompoundCurveZ:
|
|
{
|
|
OGRCompoundCurve* poCC = (OGRCompoundCurve* )this;
|
|
if( poCC->getNumCurves() == 0 )
|
|
fprintf( fp, "empty");
|
|
else
|
|
{
|
|
for(int i=0;i<poCC->getNumCurves();i++)
|
|
{
|
|
if (i)
|
|
fprintf( fp, ", ");
|
|
fprintf( fp, "%s (%d points)",
|
|
poCC->getCurve(i)->getGeometryName(),
|
|
poCC->getCurve(i)->getNumPoints() );
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case wkbMultiPoint:
|
|
case wkbMultiLineString:
|
|
case wkbMultiPolygon:
|
|
case wkbMultiCurve:
|
|
case wkbMultiSurface:
|
|
case wkbGeometryCollection:
|
|
case wkbMultiPoint25D:
|
|
case wkbMultiLineString25D:
|
|
case wkbMultiPolygon25D:
|
|
case wkbMultiCurveZ:
|
|
case wkbMultiSurfaceZ:
|
|
case wkbGeometryCollection25D:
|
|
{
|
|
int ig;
|
|
poColl = (OGRGeometryCollection*)this;
|
|
fprintf( fp, "%d geometries:\n", poColl->getNumGeometries() );
|
|
for ( ig = 0; ig < poColl->getNumGeometries(); ig++)
|
|
{
|
|
OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(ig);
|
|
fprintf( fp, "%s", pszPrefix);
|
|
poChild->dumpReadable( fp, pszPrefix, papszOptions );
|
|
}
|
|
break;
|
|
}
|
|
case wkbLinearRing:
|
|
break;
|
|
}
|
|
}
|
|
else if (pszDisplayGeometry == NULL || CSLTestBoolean(pszDisplayGeometry) ||
|
|
EQUAL(pszDisplayGeometry, "WKT"))
|
|
{
|
|
if( exportToWkt( &pszWkt ) == OGRERR_NONE )
|
|
{
|
|
fprintf( fp, "%s%s\n", pszPrefix, pszWkt );
|
|
CPLFree( pszWkt );
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_DumpReadable() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Dump geometry in well known text format to indicated output file.
|
|
*
|
|
* This method is the same as the CPP method OGRGeometry::dumpReadable.
|
|
*
|
|
* @param hGeom handle on the geometry to dump.
|
|
* @param fp the text file to write the geometry to.
|
|
* @param pszPrefix the prefix to put on each line of output.
|
|
*/
|
|
|
|
void OGR_G_DumpReadable( OGRGeometryH hGeom, FILE *fp, const char *pszPrefix )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hGeom, "OGR_G_DumpReadable" );
|
|
|
|
((OGRGeometry *) hGeom)->dumpReadable( fp, pszPrefix );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* assignSpatialReference() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \fn void OGRGeometry::assignSpatialReference( OGRSpatialReference * poSR );
|
|
*
|
|
* \brief Assign spatial reference to this object.
|
|
*
|
|
* Any existing spatial reference
|
|
* is replaced, but under no circumstances does this result in the object
|
|
* being reprojected. It is just changing the interpretation of the existing
|
|
* geometry. Note that assigning a spatial reference increments the
|
|
* reference count on the OGRSpatialReference, but does not copy it.
|
|
*
|
|
* This is similar to the SFCOM IGeometry::put_SpatialReference() method.
|
|
*
|
|
* This method is the same as the C function OGR_G_AssignSpatialReference().
|
|
*
|
|
* @param poSR new spatial reference system to apply.
|
|
*/
|
|
|
|
void OGRGeometry::assignSpatialReference( OGRSpatialReference * poSR )
|
|
|
|
{
|
|
if( poSRS != NULL )
|
|
poSRS->Release();
|
|
|
|
poSRS = poSR;
|
|
if( poSRS != NULL )
|
|
poSRS->Reference();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_AssignSpatialReference() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Assign spatial reference to this object.
|
|
*
|
|
* Any existing spatial reference
|
|
* is replaced, but under no circumstances does this result in the object
|
|
* being reprojected. It is just changing the interpretation of the existing
|
|
* geometry. Note that assigning a spatial reference increments the
|
|
* reference count on the OGRSpatialReference, but does not copy it.
|
|
*
|
|
* This is similar to the SFCOM IGeometry::put_SpatialReference() method.
|
|
*
|
|
* This function is the same as the CPP method
|
|
* OGRGeometry::assignSpatialReference.
|
|
*
|
|
* @param hGeom handle on the geometry to apply the new spatial reference
|
|
* system.
|
|
* @param hSRS handle on the new spatial reference system to apply.
|
|
*/
|
|
|
|
void OGR_G_AssignSpatialReference( OGRGeometryH hGeom,
|
|
OGRSpatialReferenceH hSRS )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hGeom, "OGR_G_AssignSpatialReference" );
|
|
|
|
((OGRGeometry *) hGeom)->assignSpatialReference( (OGRSpatialReference *)
|
|
hSRS );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Intersects() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Do these features intersect?
|
|
*
|
|
* Determines whether two geometries intersect. If GEOS is enabled, then
|
|
* this is done in rigerous fashion otherwise TRUE is returned if the
|
|
* envelopes (bounding boxes) of the two features overlap.
|
|
*
|
|
* The poOtherGeom argument may be safely NULL, but in this case the method
|
|
* will always return TRUE. That is, a NULL geometry is treated as being
|
|
* everywhere.
|
|
*
|
|
* This method is the same as the C function OGR_G_Intersects().
|
|
*
|
|
* @param poOtherGeom the other geometry to test against.
|
|
*
|
|
* @return TRUE if the geometries intersect, otherwise FALSE.
|
|
*/
|
|
|
|
OGRBoolean OGRGeometry::Intersects( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
OGREnvelope oEnv1, oEnv2;
|
|
|
|
if( this == NULL || poOtherGeom == NULL )
|
|
return TRUE;
|
|
|
|
this->getEnvelope( &oEnv1 );
|
|
poOtherGeom->getEnvelope( &oEnv2 );
|
|
|
|
if( oEnv1.MaxX < oEnv2.MinX
|
|
|| oEnv1.MaxY < oEnv2.MinY
|
|
|| oEnv2.MaxX < oEnv1.MinX
|
|
|| oEnv2.MaxY < oEnv1.MinY )
|
|
return FALSE;
|
|
|
|
#ifndef HAVE_GEOS
|
|
|
|
// Without GEOS we assume that envelope overlap is equivelent to
|
|
// actual intersection.
|
|
return TRUE;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
|
|
OGRBoolean bResult = FALSE;
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
if( GEOSIntersects_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom ) != 0 )
|
|
bResult = TRUE;
|
|
else
|
|
bResult = FALSE;
|
|
}
|
|
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return bResult;
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
// Old API compatibility function.
|
|
|
|
OGRBoolean OGRGeometry::Intersect( OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
return Intersects( poOtherGeom );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Intersects() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Do these features intersect?
|
|
*
|
|
* Currently this is not implemented in a rigerous fashion, and generally
|
|
* just tests whether the envelopes of the two features intersect. Eventually
|
|
* this will be made rigerous.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::Intersects.
|
|
*
|
|
* @param hGeom handle on the first geometry.
|
|
* @param hOtherGeom handle on the other geometry to test against.
|
|
*
|
|
* @return TRUE if the geometries intersect, otherwise FALSE.
|
|
*/
|
|
|
|
int OGR_G_Intersects( OGRGeometryH hGeom, OGRGeometryH hOtherGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_Intersects", FALSE );
|
|
VALIDATE_POINTER1( hOtherGeom, "OGR_G_Intersects", FALSE );
|
|
|
|
return ((OGRGeometry *) hGeom)->Intersects( (const OGRGeometry *) hOtherGeom );
|
|
}
|
|
|
|
int OGR_G_Intersect( OGRGeometryH hGeom, OGRGeometryH hOtherGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_Intersect", FALSE );
|
|
VALIDATE_POINTER1( hOtherGeom, "OGR_G_Intersect", FALSE );
|
|
|
|
return ((OGRGeometry *) hGeom)->Intersects( (const OGRGeometry *) hOtherGeom );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* transformTo() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Transform geometry to new spatial reference system.
|
|
*
|
|
* This method will transform the coordinates of a geometry from
|
|
* their current spatial reference system to a new target spatial
|
|
* reference system. Normally this means reprojecting the vectors,
|
|
* but it could include datum shifts, and changes of units.
|
|
*
|
|
* This method will only work if the geometry already has an assigned
|
|
* spatial reference system, and if it is transformable to the target
|
|
* coordinate system.
|
|
*
|
|
* Because this method requires internal creation and initialization of an
|
|
* OGRCoordinateTransformation object it is significantly more expensive to
|
|
* use this method to transform many geometries than it is to create the
|
|
* OGRCoordinateTransformation in advance, and call transform() with that
|
|
* transformation. This method exists primarily for convenience when only
|
|
* transforming a single geometry.
|
|
*
|
|
* This method is the same as the C function OGR_G_TransformTo().
|
|
*
|
|
* @param poSR spatial reference system to transform to.
|
|
*
|
|
* @return OGRERR_NONE on success, or an error code.
|
|
*/
|
|
|
|
OGRErr OGRGeometry::transformTo( OGRSpatialReference *poSR )
|
|
|
|
{
|
|
#ifdef DISABLE_OGRGEOM_TRANSFORM
|
|
return OGRERR_FAILURE;
|
|
#else
|
|
OGRCoordinateTransformation *poCT;
|
|
OGRErr eErr;
|
|
|
|
if( getSpatialReference() == NULL || poSR == NULL )
|
|
return OGRERR_FAILURE;
|
|
|
|
poCT = OGRCreateCoordinateTransformation( getSpatialReference(), poSR );
|
|
if( poCT == NULL )
|
|
return OGRERR_FAILURE;
|
|
|
|
eErr = transform( poCT );
|
|
|
|
delete poCT;
|
|
|
|
return eErr;
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_TransformTo() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Transform geometry to new spatial reference system.
|
|
*
|
|
* This function will transform the coordinates of a geometry from
|
|
* their current spatial reference system to a new target spatial
|
|
* reference system. Normally this means reprojecting the vectors,
|
|
* but it could include datum shifts, and changes of units.
|
|
*
|
|
* This function will only work if the geometry already has an assigned
|
|
* spatial reference system, and if it is transformable to the target
|
|
* coordinate system.
|
|
*
|
|
* Because this function requires internal creation and initialization of an
|
|
* OGRCoordinateTransformation object it is significantly more expensive to
|
|
* use this function to transform many geometries than it is to create the
|
|
* OGRCoordinateTransformation in advance, and call transform() with that
|
|
* transformation. This function exists primarily for convenience when only
|
|
* transforming a single geometry.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::transformTo.
|
|
*
|
|
* @param hGeom handle on the geometry to apply the transform to.
|
|
* @param hSRS handle on the spatial reference system to apply.
|
|
*
|
|
* @return OGRERR_NONE on success, or an error code.
|
|
*/
|
|
|
|
OGRErr OGR_G_TransformTo( OGRGeometryH hGeom, OGRSpatialReferenceH hSRS )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_TransformTo", OGRERR_FAILURE );
|
|
|
|
return ((OGRGeometry *) hGeom)->transformTo((OGRSpatialReference *) hSRS);
|
|
}
|
|
|
|
/**
|
|
* \fn OGRErr OGRGeometry::transform( OGRCoordinateTransformation *poCT );
|
|
*
|
|
* \brief Apply arbitrary coordinate transformation to geometry.
|
|
*
|
|
* This method will transform the coordinates of a geometry from
|
|
* their current spatial reference system to a new target spatial
|
|
* reference system. Normally this means reprojecting the vectors,
|
|
* but it could include datum shifts, and changes of units.
|
|
*
|
|
* Note that this method does not require that the geometry already
|
|
* have a spatial reference system. It will be assumed that they can
|
|
* be treated as having the source spatial reference system of the
|
|
* OGRCoordinateTransformation object, and the actual SRS of the geometry
|
|
* will be ignored. On successful completion the output OGRSpatialReference
|
|
* of the OGRCoordinateTransformation will be assigned to the geometry.
|
|
*
|
|
* This method is the same as the C function OGR_G_Transform().
|
|
*
|
|
* @param poCT the transformation to apply.
|
|
*
|
|
* @return OGRERR_NONE on success or an error code.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Transform() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Apply arbitrary coordinate transformation to geometry.
|
|
*
|
|
* This function will transform the coordinates of a geometry from
|
|
* their current spatial reference system to a new target spatial
|
|
* reference system. Normally this means reprojecting the vectors,
|
|
* but it could include datum shifts, and changes of units.
|
|
*
|
|
* Note that this function does not require that the geometry already
|
|
* have a spatial reference system. It will be assumed that they can
|
|
* be treated as having the source spatial reference system of the
|
|
* OGRCoordinateTransformation object, and the actual SRS of the geometry
|
|
* will be ignored. On successful completion the output OGRSpatialReference
|
|
* of the OGRCoordinateTransformation will be assigned to the geometry.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::transform.
|
|
*
|
|
* @param hGeom handle on the geometry to apply the transform to.
|
|
* @param hTransform handle on the transformation to apply.
|
|
*
|
|
* @return OGRERR_NONE on success or an error code.
|
|
*/
|
|
|
|
OGRErr OGR_G_Transform( OGRGeometryH hGeom,
|
|
OGRCoordinateTransformationH hTransform )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_Transform", OGRERR_FAILURE );
|
|
|
|
return ((OGRGeometry *) hGeom)->transform(
|
|
(OGRCoordinateTransformation *) hTransform );
|
|
}
|
|
|
|
/**
|
|
* \fn int OGRGeometry::getDimension() const;
|
|
*
|
|
* \brief Get the dimension of this object.
|
|
*
|
|
* This method corresponds to the SFCOM IGeometry::GetDimension() method.
|
|
* It indicates the dimension of the object, but does not indicate the
|
|
* dimension of the underlying space (as indicated by
|
|
* OGRGeometry::getCoordinateDimension()).
|
|
*
|
|
* This method is the same as the C function OGR_G_GetDimension().
|
|
*
|
|
* @return 0 for points, 1 for lines and 2 for surfaces.
|
|
*/
|
|
|
|
|
|
/**
|
|
* \brief Get the geometry type that conforms with ISO SQL/MM Part3
|
|
*
|
|
* @return the geometry type that conforms with ISO SQL/MM Part3
|
|
*/
|
|
OGRwkbGeometryType OGRGeometry::getIsoGeometryType() const
|
|
{
|
|
OGRwkbGeometryType nGType = wkbFlatten(getGeometryType());
|
|
|
|
if ( getCoordinateDimension() == 3 )
|
|
nGType = (OGRwkbGeometryType)(nGType + 1000);
|
|
|
|
return nGType;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRGeometry::segmentize() */
|
|
/************************************************************************/
|
|
/**
|
|
*
|
|
* \brief Modify the geometry such it has no segment longer then the given distance.
|
|
*
|
|
* Interpolated points will have Z and M values (if needed) set to 0.
|
|
* Distance computation is performed in 2d only
|
|
*
|
|
* This function is the same as the C function OGR_G_Segmentize()
|
|
*
|
|
* @param dfMaxLength the maximum distance between 2 points after segmentization
|
|
*/
|
|
|
|
void OGRGeometry::segmentize( CPL_UNUSED double dfMaxLength )
|
|
{
|
|
/* Do nothing */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Segmentize() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
*
|
|
* \brief Modify the geometry such it has no segment longer then the given distance.
|
|
*
|
|
* Interpolated points will have Z and M values (if needed) set to 0.
|
|
* Distance computation is performed in 2d only
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::segmentize().
|
|
*
|
|
* @param hGeom handle on the geometry to segmentize
|
|
* @param dfMaxLength the maximum distance between 2 points after segmentization
|
|
*/
|
|
|
|
void CPL_DLL OGR_G_Segmentize(OGRGeometryH hGeom, double dfMaxLength )
|
|
{
|
|
VALIDATE_POINTER0( hGeom, "OGR_G_Segmentize" );
|
|
|
|
if (dfMaxLength <= 0)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"dfMaxLength must be strictly positive");
|
|
return;
|
|
}
|
|
((OGRGeometry *) hGeom)->segmentize( dfMaxLength );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_GetDimension() */
|
|
/************************************************************************/
|
|
/**
|
|
*
|
|
* \brief Get the dimension of this geometry.
|
|
*
|
|
* This function corresponds to the SFCOM IGeometry::GetDimension() method.
|
|
* It indicates the dimension of the geometry, but does not indicate the
|
|
* dimension of the underlying space (as indicated by
|
|
* OGR_G_GetCoordinateDimension() function).
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::getDimension().
|
|
*
|
|
* @param hGeom handle on the geometry to get the dimension from.
|
|
* @return 0 for points, 1 for lines and 2 for surfaces.
|
|
*/
|
|
|
|
int OGR_G_GetDimension( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_GetDimension", 0 );
|
|
|
|
return ((OGRGeometry *) hGeom)->getDimension();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* getCoordinateDimension() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Get the dimension of the coordinates in this object.
|
|
*
|
|
* This method corresponds to the SFCOM IGeometry::GetDimension() method.
|
|
*
|
|
* This method is the same as the C function OGR_G_GetCoordinateDimension().
|
|
*
|
|
* @return in practice this will return 2 or 3. It can also return 0 in the
|
|
* case of an empty point.
|
|
*/
|
|
|
|
int OGRGeometry::getCoordinateDimension() const
|
|
|
|
{
|
|
return nCoordDimension;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_GetCoordinateDimension() */
|
|
/************************************************************************/
|
|
/**
|
|
*
|
|
* \brief Get the dimension of the coordinates in this geometry.
|
|
*
|
|
* This function corresponds to the SFCOM IGeometry::GetDimension() method.
|
|
*
|
|
* This function is the same as the CPP method
|
|
* OGRGeometry::getCoordinateDimension().
|
|
*
|
|
* @param hGeom handle on the geometry to get the dimension of the
|
|
* coordinates from.
|
|
*
|
|
* @return in practice this will return 2 or 3. It can also return 0 in the
|
|
* case of an empty point.
|
|
*/
|
|
|
|
int OGR_G_GetCoordinateDimension( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_GetCoordinateDimension", 0 );
|
|
|
|
return ((OGRGeometry *) hGeom)->getCoordinateDimension();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* setCoordinateDimension() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Set the coordinate dimension.
|
|
*
|
|
* This method sets the explicit coordinate dimension. Setting the coordinate
|
|
* dimension of a geometry to 2 should zero out any existing Z values. Setting
|
|
* the dimension of a geometry collection will not necessarily affect the
|
|
* children geometries.
|
|
*
|
|
* @param nNewDimension New coordinate dimension value, either 2 or 3.
|
|
*/
|
|
|
|
void OGRGeometry::setCoordinateDimension( int nNewDimension )
|
|
|
|
{
|
|
nCoordDimension = nNewDimension;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_SetCoordinateDimension() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Set the coordinate dimension.
|
|
*
|
|
* This method sets the explicit coordinate dimension. Setting the coordinate
|
|
* dimension of a geometry to 2 should zero out any existing Z values. Setting
|
|
* the dimension of a geometry collection will not necessarily affect the
|
|
* children geometries.
|
|
*
|
|
* @param hGeom handle on the geometry to set the dimension of the
|
|
* coordinates.
|
|
* @param nNewDimension New coordinate dimension value, either 2 or 3.
|
|
*/
|
|
|
|
void OGR_G_SetCoordinateDimension( OGRGeometryH hGeom, int nNewDimension)
|
|
|
|
{
|
|
VALIDATE_POINTER0( hGeom, "OGR_G_SetCoordinateDimension" );
|
|
|
|
((OGRGeometry *) hGeom)->setCoordinateDimension( nNewDimension );
|
|
}
|
|
|
|
/**
|
|
* \fn int OGRGeometry::Equals( OGRGeometry *poOtherGeom ) const;
|
|
*
|
|
* \brief Returns TRUE if two geometries are equivalent.
|
|
*
|
|
* This method is the same as the C function OGR_G_Equals().
|
|
*
|
|
* @return TRUE if equivalent or FALSE otherwise.
|
|
*/
|
|
|
|
|
|
// Backward compatibility method.
|
|
|
|
int OGRGeometry::Equal( OGRGeometry *poOtherGeom ) const
|
|
{
|
|
return Equals( poOtherGeom );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Equals() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Returns TRUE if two geometries are equivalent.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::Equals() method.
|
|
*
|
|
* @param hGeom handle on the first geometry.
|
|
* @param hOther handle on the other geometry to test against.
|
|
* @return TRUE if equivalent or FALSE otherwise.
|
|
*/
|
|
|
|
int OGR_G_Equals( OGRGeometryH hGeom, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_Equals", FALSE );
|
|
|
|
if (hGeom == NULL) {
|
|
CPLError ( CE_Failure, CPLE_ObjectNull, "hGeom was NULL in OGR_G_Equals");
|
|
return 0;
|
|
}
|
|
|
|
if (hOther == NULL) {
|
|
CPLError ( CE_Failure, CPLE_ObjectNull, "hOther was NULL in OGR_G_Equals");
|
|
return 0;
|
|
}
|
|
|
|
return ((OGRGeometry *) hGeom)->Equals( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
int OGR_G_Equal( OGRGeometryH hGeom, OGRGeometryH hOther )
|
|
|
|
{
|
|
if (hGeom == NULL) {
|
|
CPLError ( CE_Failure, CPLE_ObjectNull, "hGeom was NULL in OGR_G_Equal");
|
|
return 0;
|
|
}
|
|
|
|
if (hOther == NULL) {
|
|
CPLError ( CE_Failure, CPLE_ObjectNull, "hOther was NULL in OGR_G_Equal");
|
|
return 0;
|
|
}
|
|
|
|
return ((OGRGeometry *) hGeom)->Equals( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
|
|
/**
|
|
* \fn int OGRGeometry::WkbSize() const;
|
|
*
|
|
* \brief Returns size of related binary representation.
|
|
*
|
|
* This method returns the exact number of bytes required to hold the
|
|
* well known binary representation of this geometry object. Its computation
|
|
* may be slightly expensive for complex geometries.
|
|
*
|
|
* This method relates to the SFCOM IWks::WkbSize() method.
|
|
*
|
|
* This method is the same as the C function OGR_G_WkbSize().
|
|
*
|
|
* @return size of binary representation in bytes.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_WkbSize() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Returns size of related binary representation.
|
|
*
|
|
* This function returns the exact number of bytes required to hold the
|
|
* well known binary representation of this geometry object. Its computation
|
|
* may be slightly expensive for complex geometries.
|
|
*
|
|
* This function relates to the SFCOM IWks::WkbSize() method.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::WkbSize().
|
|
*
|
|
* @param hGeom handle on the geometry to get the binary size from.
|
|
* @return size of binary representation in bytes.
|
|
*/
|
|
|
|
int OGR_G_WkbSize( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_WkbSize", 0 );
|
|
|
|
return ((OGRGeometry *) hGeom)->WkbSize();
|
|
}
|
|
|
|
/**
|
|
* \fn void OGRGeometry::getEnvelope(OGREnvelope *psEnvelope) const;
|
|
*
|
|
* \brief Computes and returns the bounding envelope for this geometry in the passed psEnvelope structure.
|
|
*
|
|
* This method is the same as the C function OGR_G_GetEnvelope().
|
|
*
|
|
* @param psEnvelope the structure in which to place the results.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_GetEnvelope() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Computes and returns the bounding envelope for this geometry in the passed psEnvelope structure.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::getEnvelope().
|
|
*
|
|
* @param hGeom handle of the geometry to get envelope from.
|
|
* @param psEnvelope the structure in which to place the results.
|
|
*/
|
|
|
|
void OGR_G_GetEnvelope( OGRGeometryH hGeom, OGREnvelope *psEnvelope )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hGeom, "OGR_G_GetEnvelope" );
|
|
|
|
((OGRGeometry *) hGeom)->getEnvelope( psEnvelope );
|
|
}
|
|
|
|
/**
|
|
* \fn void OGRGeometry::getEnvelope(OGREnvelope3D *psEnvelope) const;
|
|
*
|
|
* \brief Computes and returns the bounding envelope (3D) for this geometry in the passed psEnvelope structure.
|
|
*
|
|
* This method is the same as the C function OGR_G_GetEnvelope3D().
|
|
*
|
|
* @param psEnvelope the structure in which to place the results.
|
|
*
|
|
* @since OGR 1.9.0
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_GetEnvelope3D() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Computes and returns the bounding envelope (3D) for this geometry in the passed psEnvelope structure.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::getEnvelope().
|
|
*
|
|
* @param hGeom handle of the geometry to get envelope from.
|
|
* @param psEnvelope the structure in which to place the results.
|
|
*
|
|
* @since OGR 1.9.0
|
|
*/
|
|
|
|
void OGR_G_GetEnvelope3D( OGRGeometryH hGeom, OGREnvelope3D *psEnvelope )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hGeom, "OGR_G_GetEnvelope3D" );
|
|
|
|
((OGRGeometry *) hGeom)->getEnvelope( psEnvelope );
|
|
}
|
|
|
|
/**
|
|
* \fn OGRErr OGRGeometry::importFromWkb( unsigned char * pabyData, int nSize, OGRwkbVariant eWkbVariant =wkbVariantOldOgc );
|
|
*
|
|
* \brief Assign geometry from well known binary data.
|
|
*
|
|
* The object must have already been instantiated as the correct derived
|
|
* type of geometry object to match the binaries type. This method is used
|
|
* by the OGRGeometryFactory class, but not normally called by application
|
|
* code.
|
|
*
|
|
* This method relates to the SFCOM IWks::ImportFromWKB() method.
|
|
*
|
|
* This method is the same as the C function OGR_G_ImportFromWkb().
|
|
*
|
|
* @param pabyData the binary input data.
|
|
* @param nSize the size of pabyData in bytes, or zero if not known.
|
|
* @param eWkbVariant if wkbVariantPostGIS1, special interpretation is done for curve geometries code
|
|
*
|
|
* @return OGRERR_NONE if all goes well, otherwise any of
|
|
* OGRERR_NOT_ENOUGH_DATA, OGRERR_UNSUPPORTED_GEOMETRY_TYPE, or
|
|
* OGRERR_CORRUPT_DATA may be returned.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ImportFromWkb() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Assign geometry from well known binary data.
|
|
*
|
|
* The object must have already been instantiated as the correct derived
|
|
* type of geometry object to match the binaries type.
|
|
*
|
|
* This function relates to the SFCOM IWks::ImportFromWKB() method.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::importFromWkb().
|
|
*
|
|
* @param hGeom handle on the geometry to assign the well know binary data to.
|
|
* @param pabyData the binary input data.
|
|
* @param nSize the size of pabyData in bytes, or zero if not known.
|
|
*
|
|
* @return OGRERR_NONE if all goes well, otherwise any of
|
|
* OGRERR_NOT_ENOUGH_DATA, OGRERR_UNSUPPORTED_GEOMETRY_TYPE, or
|
|
* OGRERR_CORRUPT_DATA may be returned.
|
|
*/
|
|
|
|
OGRErr OGR_G_ImportFromWkb( OGRGeometryH hGeom,
|
|
unsigned char *pabyData, int nSize )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_ImportFromWkb", OGRERR_FAILURE );
|
|
|
|
return ((OGRGeometry *) hGeom)->importFromWkb( pabyData, nSize );
|
|
}
|
|
|
|
/**
|
|
* \fn OGRErr OGRGeometry::exportToWkb( OGRwkbByteOrder eByteOrder,
|
|
unsigned char * pabyData,
|
|
OGRwkbVariant eWkbVariant=wkbVariantOldOgc ) const
|
|
*
|
|
* \brief Convert a geometry into well known binary format.
|
|
*
|
|
* This method relates to the SFCOM IWks::ExportToWKB() method.
|
|
*
|
|
* This method is the same as the C function OGR_G_ExportToWkb() or OGR_G_ExportToIsoWkb(),
|
|
* depending on the value of eWkbVariant.
|
|
*
|
|
* @param eByteOrder One of wkbXDR or wkbNDR indicating MSB or LSB byte order
|
|
* respectively.
|
|
* @param pabyData a buffer into which the binary representation is
|
|
* written. This buffer must be at least
|
|
* OGRGeometry::WkbSize() byte in size.
|
|
* @param eWkbVariant What standard to use when exporting geometries with
|
|
* three dimensions (or more). The default wkbVariantOldOgc is
|
|
* the historical OGR variant. wkbVariantIso is the
|
|
* variant defined in ISO SQL/MM and adopted by OGC
|
|
* for SFSQL 1.2.
|
|
*
|
|
* @return Currently OGRERR_NONE is always returned.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ExportToWkb() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Convert a geometry well known binary format
|
|
*
|
|
* This function relates to the SFCOM IWks::ExportToWKB() method.
|
|
*
|
|
* For backward compatibility purposes, it exports the Old-style 99-402
|
|
* extended dimension (Z) WKB types for types Point, LineString, Polygon,
|
|
* MultiPoint, MultiLineString, MultiPolygon and GeometryCollection.
|
|
* For other geometry types, it is equivalent to OGR_G_ExportToIsoWkb().
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *, OGRwkbVariant)
|
|
* with eWkbVariant = wkbVariantOldOgc.
|
|
*
|
|
* @param hGeom handle on the geometry to convert to a well know binary
|
|
* data from.
|
|
* @param eOrder One of wkbXDR or wkbNDR indicating MSB or LSB byte order
|
|
* respectively.
|
|
* @param pabyDstBuffer a buffer into which the binary representation is
|
|
* written. This buffer must be at least
|
|
* OGR_G_WkbSize() byte in size.
|
|
*
|
|
* @return Currently OGRERR_NONE is always returned.
|
|
*/
|
|
|
|
OGRErr OGR_G_ExportToWkb( OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
|
|
unsigned char *pabyDstBuffer )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_ExportToWkb", OGRERR_FAILURE );
|
|
|
|
return ((OGRGeometry *) hGeom)->exportToWkb( eOrder, pabyDstBuffer );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ExportToIsoWkb() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known binary format
|
|
*
|
|
* This function relates to the SFCOM IWks::ExportToWKB() method.
|
|
* It exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M) WKB types
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::exportToWkb(OGRwkbByteOrder, unsigned char *, OGRwkbVariant)
|
|
* with eWkbVariant = wkbVariantIso.
|
|
*
|
|
* @param hGeom handle on the geometry to convert to a well know binary
|
|
* data from.
|
|
* @param eOrder One of wkbXDR or wkbNDR indicating MSB or LSB byte order
|
|
* respectively.
|
|
* @param pabyDstBuffer a buffer into which the binary representation is
|
|
* written. This buffer must be at least
|
|
* OGR_G_WkbSize() byte in size.
|
|
*
|
|
* @return Currently OGRERR_NONE is always returned.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRErr OGR_G_ExportToIsoWkb( OGRGeometryH hGeom, OGRwkbByteOrder eOrder,
|
|
unsigned char *pabyDstBuffer )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_ExportToIsoWkb", OGRERR_FAILURE );
|
|
|
|
return ((OGRGeometry *) hGeom)->exportToWkb( eOrder, pabyDstBuffer, wkbVariantIso );
|
|
}
|
|
|
|
/**
|
|
* \fn OGRErr OGRGeometry::importFromWkt( char ** ppszInput );
|
|
*
|
|
* \brief Assign geometry from well known text data.
|
|
*
|
|
* The object must have already been instantiated as the correct derived
|
|
* type of geometry object to match the text type. This method is used
|
|
* by the OGRGeometryFactory class, but not normally called by application
|
|
* code.
|
|
*
|
|
* This method relates to the SFCOM IWks::ImportFromWKT() method.
|
|
*
|
|
* This method is the same as the C function OGR_G_ImportFromWkt().
|
|
*
|
|
* @param ppszInput pointer to a pointer to the source text. The pointer is
|
|
* updated to pointer after the consumed text.
|
|
*
|
|
* @return OGRERR_NONE if all goes well, otherwise any of
|
|
* OGRERR_NOT_ENOUGH_DATA, OGRERR_UNSUPPORTED_GEOMETRY_TYPE, or
|
|
* OGRERR_CORRUPT_DATA may be returned.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ImportFromWkt() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Assign geometry from well known text data.
|
|
*
|
|
* The object must have already been instantiated as the correct derived
|
|
* type of geometry object to match the text type.
|
|
*
|
|
* This function relates to the SFCOM IWks::ImportFromWKT() method.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::importFromWkt().
|
|
*
|
|
* @param hGeom handle on the geometry to assign well know text data to.
|
|
* @param ppszSrcText pointer to a pointer to the source text. The pointer is
|
|
* updated to pointer after the consumed text.
|
|
*
|
|
* @return OGRERR_NONE if all goes well, otherwise any of
|
|
* OGRERR_NOT_ENOUGH_DATA, OGRERR_UNSUPPORTED_GEOMETRY_TYPE, or
|
|
* OGRERR_CORRUPT_DATA may be returned.
|
|
*/
|
|
|
|
OGRErr OGR_G_ImportFromWkt( OGRGeometryH hGeom, char ** ppszSrcText )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_ImportFromWkt", OGRERR_FAILURE );
|
|
|
|
return ((OGRGeometry *) hGeom)->importFromWkt( ppszSrcText );
|
|
}
|
|
|
|
|
|
/************************************************************************/
|
|
/* importPreambuleFromWkt() */
|
|
/************************************************************************/
|
|
|
|
/* Returns -1 if processing must continue */
|
|
OGRErr OGRGeometry::importPreambuleFromWkt( char ** ppszInput,
|
|
int* pbHasZ, int* pbHasM )
|
|
{
|
|
char szToken[OGR_WKT_TOKEN_MAX];
|
|
const char *pszInput = *ppszInput;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Clear existing Geoms. */
|
|
/* -------------------------------------------------------------------- */
|
|
empty();
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Read and verify the type keyword, and ensure it matches the */
|
|
/* actual type of this container. */
|
|
/* -------------------------------------------------------------------- */
|
|
pszInput = OGRWktReadToken( pszInput, szToken );
|
|
|
|
if( !EQUAL(szToken,getGeometryName()) )
|
|
return OGRERR_CORRUPT_DATA;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Check for EMPTY ... */
|
|
/* -------------------------------------------------------------------- */
|
|
const char *pszPreScan;
|
|
int bHasZ = FALSE, bHasM = FALSE;
|
|
|
|
pszPreScan = OGRWktReadToken( pszInput, szToken );
|
|
if( EQUAL(szToken,"EMPTY") )
|
|
{
|
|
*ppszInput = (char *) pszPreScan;
|
|
empty();
|
|
return OGRERR_NONE;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Check for Z, M or ZM. Will ignore the Measure */
|
|
/* -------------------------------------------------------------------- */
|
|
else if( EQUAL(szToken,"Z") )
|
|
{
|
|
bHasZ = TRUE;
|
|
}
|
|
else if( EQUAL(szToken,"M") )
|
|
{
|
|
bHasM = TRUE;
|
|
}
|
|
else if( EQUAL(szToken,"ZM") )
|
|
{
|
|
bHasZ = TRUE;
|
|
bHasM = TRUE;
|
|
}
|
|
*pbHasZ = bHasZ;
|
|
*pbHasM = bHasM;
|
|
|
|
if (bHasZ || bHasM)
|
|
{
|
|
pszInput = pszPreScan;
|
|
pszPreScan = OGRWktReadToken( pszInput, szToken );
|
|
if( EQUAL(szToken,"EMPTY") )
|
|
{
|
|
*ppszInput = (char *) pszPreScan;
|
|
empty();
|
|
if( bHasZ )
|
|
setCoordinateDimension(3);
|
|
|
|
/* FIXME?: In theory we should store the M presence */
|
|
/* if we want to allow round-trip with ExportToWKT v1.2 */
|
|
return OGRERR_NONE;
|
|
}
|
|
}
|
|
|
|
if( !EQUAL(szToken,"(") )
|
|
return OGRERR_CORRUPT_DATA;
|
|
|
|
if ( !bHasZ && !bHasM )
|
|
{
|
|
/* Test for old-style XXXXXXXXX(EMPTY) */
|
|
pszPreScan = OGRWktReadToken( pszPreScan, szToken );
|
|
if( EQUAL(szToken,"EMPTY") )
|
|
{
|
|
pszPreScan = OGRWktReadToken( pszPreScan, szToken );
|
|
|
|
if( EQUAL(szToken,",") )
|
|
{
|
|
/* This is OK according to SFSQL SPEC. */
|
|
}
|
|
else if( !EQUAL(szToken,")") )
|
|
return OGRERR_CORRUPT_DATA;
|
|
else
|
|
{
|
|
*ppszInput = (char *) pszPreScan;
|
|
empty();
|
|
return OGRERR_NONE;
|
|
}
|
|
}
|
|
}
|
|
|
|
*ppszInput = (char*) pszInput;
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
/**
|
|
* \fn OGRErr OGRGeometry::exportToWkt( char ** ppszDstText, OGRwkbVariant eWkbVariant = wkbVariantOldOgc ) const;
|
|
*
|
|
* \brief Convert a geometry into well known text format.
|
|
*
|
|
* This method relates to the SFCOM IWks::ExportToWKT() method.
|
|
*
|
|
* This method is the same as the C function OGR_G_ExportToWkt().
|
|
*
|
|
* @param ppszDstText a text buffer is allocated by the program, and assigned
|
|
* to the passed pointer. After use, *ppszDstText should be
|
|
* freed with OGRFree().
|
|
* @param eWkbVariant the specification that must be conformed too :
|
|
* - wbkVariantOgc for old-style 99-402 extended dimension (Z) WKB types
|
|
* - wbkVariantIso for SFSQL 1.2 and ISO SQL/MM Part 3
|
|
*
|
|
* @return Currently OGRERR_NONE is always returned.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ExportToWkt() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Convert a geometry into well known text format.
|
|
*
|
|
* This function relates to the SFCOM IWks::ExportToWKT() method.
|
|
*
|
|
* For backward compatibility purposes, it exports the Old-style 99-402
|
|
* extended dimension (Z) WKB types for types Point, LineString, Polygon,
|
|
* MultiPoint, MultiLineString, MultiPolygon and GeometryCollection.
|
|
* For other geometry types, it is equivalent to OGR_G_ExportToIsoWkt().
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::exportToWkt().
|
|
*
|
|
* @param hGeom handle on the geometry to convert to a text format from.
|
|
* @param ppszSrcText a text buffer is allocated by the program, and assigned
|
|
* to the passed pointer. After use, *ppszDstText should be
|
|
* freed with OGRFree().
|
|
*
|
|
* @return Currently OGRERR_NONE is always returned.
|
|
*/
|
|
|
|
OGRErr OGR_G_ExportToWkt( OGRGeometryH hGeom, char **ppszSrcText )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_ExportToWkt", OGRERR_FAILURE );
|
|
|
|
return ((OGRGeometry *) hGeom)->exportToWkt( ppszSrcText );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ExportToIsoWkt() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Convert a geometry into SFSQL 1.2 / ISO SQL/MM Part 3 well known text format
|
|
*
|
|
* This function relates to the SFCOM IWks::ExportToWKT() method.
|
|
* It exports the SFSQL 1.2 and ISO SQL/MM Part 3 extended dimension (Z&M) WKB types
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::exportToWkt(,wkbVariantIso).
|
|
*
|
|
* @param hGeom handle on the geometry to convert to a text format from.
|
|
* @param ppszSrcText a text buffer is allocated by the program, and assigned
|
|
* to the passed pointer. After use, *ppszDstText should be
|
|
* freed with OGRFree().
|
|
*
|
|
* @return Currently OGRERR_NONE is always returned.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRErr OGR_G_ExportToIsoWkt( OGRGeometryH hGeom, char **ppszSrcText )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_ExportToIsoWkt", OGRERR_FAILURE );
|
|
|
|
return ((OGRGeometry *) hGeom)->exportToWkt( ppszSrcText, wkbVariantIso );
|
|
}
|
|
|
|
/**
|
|
* \fn OGRwkbGeometryType OGRGeometry::getGeometryType() const;
|
|
*
|
|
* \brief Fetch geometry type.
|
|
*
|
|
* Note that the geometry type may include the 2.5D flag. To get a 2D
|
|
* flattened version of the geometry type apply the wkbFlatten() macro
|
|
* to the return result.
|
|
*
|
|
* This method is the same as the C function OGR_G_GetGeometryType().
|
|
*
|
|
* @return the geometry type code.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_GetGeometryType() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Fetch geometry type.
|
|
*
|
|
* Note that the geometry type may include the 2.5D flag. To get a 2D
|
|
* flattened version of the geometry type apply the wkbFlatten() macro
|
|
* to the return result.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::getGeometryType().
|
|
*
|
|
* @param hGeom handle on the geometry to get type from.
|
|
* @return the geometry type code.
|
|
*/
|
|
|
|
OGRwkbGeometryType OGR_G_GetGeometryType( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_GetGeometryType", wkbUnknown );
|
|
|
|
return ((OGRGeometry *) hGeom)->getGeometryType();
|
|
}
|
|
|
|
/**
|
|
* \fn const char * OGRGeometry::getGeometryName() const;
|
|
*
|
|
* \brief Fetch WKT name for geometry type.
|
|
*
|
|
* There is no SFCOM analog to this method.
|
|
*
|
|
* This method is the same as the C function OGR_G_GetGeometryName().
|
|
*
|
|
* @return name used for this geometry type in well known text format. The
|
|
* returned pointer is to a static internal string and should not be modified
|
|
* or freed.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_GetGeometryName() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Fetch WKT name for geometry type.
|
|
*
|
|
* There is no SFCOM analog to this function.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::getGeometryName().
|
|
*
|
|
* @param hGeom handle on the geometry to get name from.
|
|
* @return name used for this geometry type in well known text format.
|
|
*/
|
|
|
|
const char *OGR_G_GetGeometryName( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_GetGeometryName", "" );
|
|
|
|
return ((OGRGeometry *) hGeom)->getGeometryName();
|
|
}
|
|
|
|
/**
|
|
* \fn OGRGeometry *OGRGeometry::clone() const;
|
|
*
|
|
* \brief Make a copy of this object.
|
|
*
|
|
* This method relates to the SFCOM IGeometry::clone() method.
|
|
*
|
|
* This method is the same as the C function OGR_G_Clone().
|
|
*
|
|
* @return a new object instance with the same geometry, and spatial
|
|
* reference system as the original.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Clone() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Make a copy of this object.
|
|
*
|
|
* This function relates to the SFCOM IGeometry::clone() method.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::clone().
|
|
*
|
|
* @param hGeom handle on the geometry to clone from.
|
|
* @return an handle on the copy of the geometry with the spatial
|
|
* reference system as the original.
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_Clone( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_Clone", NULL );
|
|
|
|
return (OGRGeometryH) ((OGRGeometry *) hGeom)->clone();
|
|
}
|
|
|
|
/**
|
|
* \fn OGRSpatialReference *OGRGeometry::getSpatialReference();
|
|
*
|
|
* \brief Returns spatial reference system for object.
|
|
*
|
|
* This method relates to the SFCOM IGeometry::get_SpatialReference() method.
|
|
*
|
|
* This method is the same as the C function OGR_G_GetSpatialReference().
|
|
*
|
|
* @return a reference to the spatial reference object. The object may be
|
|
* shared with many geometry objects, and should not be modified.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_GetSpatialReference() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Returns spatial reference system for geometry.
|
|
*
|
|
* This function relates to the SFCOM IGeometry::get_SpatialReference() method.
|
|
*
|
|
* This function is the same as the CPP method
|
|
* OGRGeometry::getSpatialReference().
|
|
*
|
|
* @param hGeom handle on the geometry to get spatial reference from.
|
|
* @return a reference to the spatial reference geometry.
|
|
*/
|
|
|
|
OGRSpatialReferenceH OGR_G_GetSpatialReference( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_GetSpatialReference", NULL );
|
|
|
|
return (OGRSpatialReferenceH)
|
|
((OGRGeometry *) hGeom)->getSpatialReference();
|
|
}
|
|
|
|
/**
|
|
* \fn void OGRGeometry::empty();
|
|
*
|
|
* \brief Clear geometry information.
|
|
* This restores the geometry to it's initial
|
|
* state after construction, and before assignment of actual geometry.
|
|
*
|
|
* This method relates to the SFCOM IGeometry::Empty() method.
|
|
*
|
|
* This method is the same as the C function OGR_G_Empty().
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Empty() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Clear geometry information.
|
|
* This restores the geometry to it's initial
|
|
* state after construction, and before assignment of actual geometry.
|
|
*
|
|
* This function relates to the SFCOM IGeometry::Empty() method.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::empty().
|
|
*
|
|
* @param hGeom handle on the geometry to empty.
|
|
*/
|
|
|
|
void OGR_G_Empty( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hGeom, "OGR_G_Empty" );
|
|
|
|
((OGRGeometry *) hGeom)->empty();
|
|
}
|
|
|
|
/**
|
|
* \fn OGRBoolean OGRGeometry::IsEmpty() const;
|
|
*
|
|
* \brief Returns TRUE (non-zero) if the object has no points.
|
|
*
|
|
* Normally this
|
|
* returns FALSE except between when an object is instantiated and points
|
|
* have been assigned.
|
|
*
|
|
* This method relates to the SFCOM IGeometry::IsEmpty() method.
|
|
*
|
|
* @return TRUE if object is empty, otherwise FALSE.
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_IsEmpty() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test if the geometry is empty.
|
|
*
|
|
* This method is the same as the CPP method OGRGeometry::IsEmpty().
|
|
*
|
|
* @param hGeom The Geometry to test.
|
|
*
|
|
* @return TRUE if the geometry has no points, otherwise FALSE.
|
|
*/
|
|
|
|
int OGR_G_IsEmpty( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_IsEmpty", TRUE );
|
|
|
|
return ((OGRGeometry *) hGeom)->IsEmpty();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IsValid() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test if the geometry is valid.
|
|
*
|
|
* This method is the same as the C function OGR_G_IsValid().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always return
|
|
* FALSE.
|
|
*
|
|
*
|
|
* @return TRUE if the geometry has no points, otherwise FALSE.
|
|
*/
|
|
|
|
OGRBoolean
|
|
OGRGeometry::IsValid( ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
OGRBoolean bResult = FALSE;
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
|
|
if( hThisGeosGeom != NULL )
|
|
{
|
|
bResult = GEOSisValid_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
}
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return bResult;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_IsValid() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test if the geometry is valid.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::IsValid().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always return
|
|
* FALSE.
|
|
*
|
|
* @param hGeom The Geometry to test.
|
|
*
|
|
* @return TRUE if the geometry has no points, otherwise FALSE.
|
|
*/
|
|
|
|
int OGR_G_IsValid( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_IsValid", FALSE );
|
|
|
|
return ((OGRGeometry *) hGeom)->IsValid();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IsSimple() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test if the geometry is simple.
|
|
*
|
|
* This method is the same as the C function OGR_G_IsSimple().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always return
|
|
* FALSE.
|
|
*
|
|
*
|
|
* @return TRUE if the geometry has no points, otherwise FALSE.
|
|
*/
|
|
|
|
OGRBoolean
|
|
OGRGeometry::IsSimple( ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
OGRBoolean bResult = FALSE;
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
|
|
if( hThisGeosGeom != NULL )
|
|
{
|
|
bResult = GEOSisSimple_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
}
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return bResult;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Returns TRUE if the geometry is simple.
|
|
*
|
|
* Returns TRUE if the geometry has no anomalous geometric points, such
|
|
* as self intersection or self tangency. The description of each
|
|
* instantiable geometric class will include the specific conditions that
|
|
* cause an instance of that class to be classified as not simple.
|
|
*
|
|
* This function is the same as the c++ method OGRGeometry::IsSimple() method.
|
|
*
|
|
* If OGR is built without the GEOS library, this function will always return
|
|
* FALSE.
|
|
*
|
|
* @param hGeom The Geometry to test.
|
|
*
|
|
* @return TRUE if object is simple, otherwise FALSE.
|
|
*/
|
|
|
|
int OGR_G_IsSimple( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_IsSimple", TRUE );
|
|
|
|
return ((OGRGeometry *) hGeom)->IsSimple();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* IsRing() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test if the geometry is a ring
|
|
*
|
|
* This method is the same as the C function OGR_G_IsRing().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always return
|
|
* FALSE.
|
|
*
|
|
*
|
|
* @return TRUE if the geometry has no points, otherwise FALSE.
|
|
*/
|
|
|
|
OGRBoolean
|
|
OGRGeometry::IsRing( ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
OGRBoolean bResult = FALSE;
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
|
|
if( hThisGeosGeom != NULL )
|
|
{
|
|
bResult = GEOSisRing_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
}
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return bResult;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_IsRing() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test if the geometry is a ring
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::IsRing().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always return
|
|
* FALSE.
|
|
*
|
|
* @param hGeom The Geometry to test.
|
|
*
|
|
* @return TRUE if the geometry has no points, otherwise FALSE.
|
|
*/
|
|
|
|
int OGR_G_IsRing( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_IsRing", FALSE );
|
|
|
|
return ((OGRGeometry *) hGeom)->IsRing();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRFromOGCGeomType() */
|
|
/* Map OGCgeometry format type to corresponding */
|
|
/* OGR constants. */
|
|
/************************************************************************/
|
|
|
|
#define EQUALN_CST(var, cst) EQUALN(var, cst, strlen(cst))
|
|
|
|
OGRwkbGeometryType OGRFromOGCGeomType( const char *pszGeomType )
|
|
{
|
|
OGRwkbGeometryType eType;
|
|
int bConvertTo3D = FALSE;
|
|
if( *pszGeomType != '\0' )
|
|
{
|
|
char ch = pszGeomType[strlen(pszGeomType)-1];
|
|
if( ch == 'z' || ch == 'Z' )
|
|
{
|
|
bConvertTo3D = TRUE;
|
|
}
|
|
}
|
|
if ( EQUALN_CST(pszGeomType, "POINT") )
|
|
eType = wkbPoint;
|
|
else if ( EQUALN_CST(pszGeomType, "LINESTRING") )
|
|
eType = wkbLineString;
|
|
else if ( EQUALN_CST(pszGeomType, "POLYGON") )
|
|
eType = wkbPolygon;
|
|
else if ( EQUALN_CST(pszGeomType, "MULTIPOINT") )
|
|
eType = wkbMultiPoint;
|
|
else if ( EQUALN_CST(pszGeomType, "MULTILINESTRING") )
|
|
eType = wkbMultiLineString;
|
|
else if ( EQUALN_CST(pszGeomType, "MULTIPOLYGON") )
|
|
eType = wkbMultiPolygon;
|
|
else if ( EQUALN_CST(pszGeomType, "GEOMETRYCOLLECTION") )
|
|
eType = wkbGeometryCollection;
|
|
else if ( EQUALN_CST(pszGeomType, "CIRCULARSTRING") )
|
|
eType = wkbCircularString;
|
|
else if ( EQUALN_CST(pszGeomType, "COMPOUNDCURVE") )
|
|
eType = wkbCompoundCurve;
|
|
else if ( EQUALN_CST(pszGeomType, "CURVEPOLYGON") )
|
|
eType = wkbCurvePolygon;
|
|
else if ( EQUALN_CST(pszGeomType, "MULTICURVE") )
|
|
eType = wkbMultiCurve;
|
|
else if ( EQUALN_CST(pszGeomType, "MULTISURFACE") )
|
|
eType = wkbMultiSurface;
|
|
else
|
|
eType = wkbUnknown;
|
|
|
|
if( bConvertTo3D )
|
|
eType = wkbSetZ(eType);
|
|
|
|
return eType;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRToOGCGeomType() */
|
|
/* Map OGR geometry format constants to corresponding */
|
|
/* OGC geometry type */
|
|
/************************************************************************/
|
|
|
|
const char * OGRToOGCGeomType( OGRwkbGeometryType eGeomType )
|
|
{
|
|
switch ( wkbFlatten(eGeomType) )
|
|
{
|
|
case wkbUnknown:
|
|
return "GEOMETRY";
|
|
case wkbPoint:
|
|
return "POINT";
|
|
case wkbLineString:
|
|
return "LINESTRING";
|
|
case wkbPolygon:
|
|
return "POLYGON";
|
|
case wkbMultiPoint:
|
|
return "MULTIPOINT";
|
|
case wkbMultiLineString:
|
|
return "MULTILINESTRING";
|
|
case wkbMultiPolygon:
|
|
return "MULTIPOLYGON";
|
|
case wkbGeometryCollection:
|
|
return "GEOMETRYCOLLECTION";
|
|
case wkbCircularString:
|
|
return "CIRCULARSTRING";
|
|
case wkbCompoundCurve:
|
|
return "COMPOUNDCURVE";
|
|
case wkbCurvePolygon:
|
|
return "CURVEPOLYGON";
|
|
case wkbMultiCurve:
|
|
return "MULTICURVE";
|
|
case wkbMultiSurface:
|
|
return "MULTISURFACE";
|
|
default:
|
|
return "";
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRGeometryTypeToName() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Fetch a human readable name corresponding to an OGRwkbGeometryType value.
|
|
* The returned value should not be modified, or freed by the application.
|
|
*
|
|
* This function is C callable.
|
|
*
|
|
* @param eType the geometry type.
|
|
*
|
|
* @return internal human readable string, or NULL on failure.
|
|
*/
|
|
|
|
const char *OGRGeometryTypeToName( OGRwkbGeometryType eType )
|
|
|
|
{
|
|
bool b2D = wkbFlatten(eType) == eType;
|
|
|
|
switch( wkbFlatten(eType) )
|
|
{
|
|
case wkbUnknown:
|
|
if( b2D )
|
|
return "Unknown (any)";
|
|
else
|
|
return "3D Unknown (any)";
|
|
|
|
case wkbPoint:
|
|
if( b2D )
|
|
return "Point";
|
|
else
|
|
return "3D Point";
|
|
|
|
case wkbLineString:
|
|
if( b2D )
|
|
return "Line String";
|
|
else
|
|
return "3D Line String";
|
|
|
|
case wkbPolygon:
|
|
if( b2D )
|
|
return "Polygon";
|
|
else
|
|
return "3D Polygon";
|
|
|
|
case wkbMultiPoint:
|
|
if( b2D )
|
|
return "Multi Point";
|
|
else
|
|
return "3D Multi Point";
|
|
|
|
case wkbMultiLineString:
|
|
if( b2D )
|
|
return "Multi Line String";
|
|
else
|
|
return "3D Multi Line String";
|
|
|
|
case wkbMultiPolygon:
|
|
if( b2D )
|
|
return "Multi Polygon";
|
|
else
|
|
return "3D Multi Polygon";
|
|
|
|
case wkbGeometryCollection:
|
|
if( b2D )
|
|
return "Geometry Collection";
|
|
else
|
|
return "3D Geometry Collection";
|
|
|
|
case wkbCircularString:
|
|
if( b2D )
|
|
return "Circular String";
|
|
else
|
|
return "3D Circular String";
|
|
|
|
case wkbCompoundCurve:
|
|
if( b2D )
|
|
return "Compound Curve";
|
|
else
|
|
return "3D Compound Curve";
|
|
|
|
case wkbCurvePolygon:
|
|
if( b2D )
|
|
return "Curve Polygon";
|
|
else
|
|
return "3D Curve Polygon";
|
|
|
|
case wkbMultiCurve:
|
|
if( b2D )
|
|
return "Multi Curve";
|
|
else
|
|
return "3D Multi Curve";
|
|
|
|
case wkbMultiSurface:
|
|
if( b2D )
|
|
return "Multi Surface";
|
|
else
|
|
return "3D Multi Surface";
|
|
|
|
case wkbNone:
|
|
return "None";
|
|
|
|
default:
|
|
{
|
|
// OGRThreadSafety: This static is judged to be a very low risk
|
|
// for thread safety because it is only used in case of error,
|
|
// and the worst that can happen is reporting the wrong code
|
|
// in the generated message.
|
|
static char szWorkName[33];
|
|
sprintf( szWorkName, "Unrecognised: %d", (int) eType );
|
|
return szWorkName;
|
|
}
|
|
}
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRMergeGeometryTypes() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Find common geometry type.
|
|
*
|
|
* Given two geometry types, find the most specific common
|
|
* type. Normally used repeatedly with the geometries in a
|
|
* layer to try and establish the most specific geometry type
|
|
* that can be reported for the layer.
|
|
*
|
|
* NOTE: wkbUnknown is the "worst case" indicating a mixture of
|
|
* geometry types with nothing in common but the base geometry
|
|
* type. wkbNone should be used to indicate that no geometries
|
|
* have been encountered yet, and means the first geometry
|
|
* encounted will establish the preliminary type.
|
|
*
|
|
* @param eMain the first input geometry type.
|
|
* @param eExtra the second input geometry type.
|
|
*
|
|
* @return the merged geometry type.
|
|
*/
|
|
|
|
OGRwkbGeometryType
|
|
OGRMergeGeometryTypes( OGRwkbGeometryType eMain,
|
|
OGRwkbGeometryType eExtra )
|
|
|
|
{
|
|
return OGRMergeGeometryTypesEx(eMain, eExtra, FALSE);
|
|
}
|
|
|
|
/**
|
|
* \brief Find common geometry type.
|
|
*
|
|
* Given two geometry types, find the most specific common
|
|
* type. Normally used repeatedly with the geometries in a
|
|
* layer to try and establish the most specific geometry type
|
|
* that can be reported for the layer.
|
|
*
|
|
* NOTE: wkbUnknown is the "worst case" indicating a mixture of
|
|
* geometry types with nothing in common but the base geometry
|
|
* type. wkbNone should be used to indicate that no geometries
|
|
* have been encountered yet, and means the first geometry
|
|
* encounted will establish the preliminary type.
|
|
*
|
|
* If bAllowPromotingToCurves is set to TRUE, mixing Polygon and CurvePolygon
|
|
* will return CurvePolygon. Mixing LineString, CircularString, CompoundCurve
|
|
* will return CompoundCurve. Mixing MultiPolygon and MultiSurface will return
|
|
* MultiSurface. Mixing MultiCurve and MultiLineString will return MultiCurve.
|
|
*
|
|
* @param eMain the first input geometry type.
|
|
* @param eExtra the second input geometry type.
|
|
* @param bAllowPromotingToCurves determine if promotion to curve type must be done.
|
|
*
|
|
* @return the merged geometry type.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRwkbGeometryType
|
|
OGRMergeGeometryTypesEx( OGRwkbGeometryType eMain,
|
|
OGRwkbGeometryType eExtra,
|
|
int bAllowPromotingToCurves )
|
|
|
|
{
|
|
int bHasZ;
|
|
OGRwkbGeometryType eFMain = wkbFlatten(eMain);
|
|
OGRwkbGeometryType eFExtra = wkbFlatten(eExtra);
|
|
|
|
bHasZ = ( eFMain != eMain || eFExtra != eExtra );
|
|
|
|
if( eFMain == wkbUnknown || eFExtra == wkbUnknown )
|
|
return OGR_GT_SetModifier(wkbUnknown, bHasZ, FALSE);
|
|
|
|
if( eFMain == wkbNone )
|
|
return eExtra;
|
|
|
|
if( eFExtra == wkbNone )
|
|
return eMain;
|
|
|
|
if( eFMain == eFExtra )
|
|
{
|
|
return OGR_GT_SetModifier(eFMain, bHasZ, FALSE);
|
|
}
|
|
|
|
if( bAllowPromotingToCurves )
|
|
{
|
|
if( OGR_GT_IsCurve(eFMain) && OGR_GT_IsCurve(eFExtra) )
|
|
return OGR_GT_SetModifier(wkbCompoundCurve, bHasZ, FALSE);
|
|
|
|
if( OGR_GT_IsSubClassOf(eFMain, eFExtra) )
|
|
return OGR_GT_SetModifier(eFExtra, bHasZ, FALSE);
|
|
|
|
if( OGR_GT_IsSubClassOf(eFExtra, eFMain) )
|
|
return OGR_GT_SetModifier(eFMain, bHasZ, FALSE);
|
|
}
|
|
|
|
// Both are geometry collections.
|
|
if( OGR_GT_IsSubClassOf(eFMain, wkbGeometryCollection) &&
|
|
OGR_GT_IsSubClassOf(eFExtra, wkbGeometryCollection) )
|
|
{
|
|
return OGR_GT_SetModifier(wkbGeometryCollection, bHasZ, FALSE);
|
|
}
|
|
|
|
// Nothing apparently in common.
|
|
return OGR_GT_SetModifier(wkbUnknown, bHasZ, FALSE);
|
|
}
|
|
|
|
/**
|
|
* \fn void OGRGeometry::flattenTo2D();
|
|
*
|
|
* \brief Convert geometry to strictly 2D.
|
|
* In a sense this converts all Z coordinates
|
|
* to 0.0.
|
|
*
|
|
* This method is the same as the C function OGR_G_FlattenTo2D().
|
|
*/
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_FlattenTo2D() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Convert geometry to strictly 2D.
|
|
* In a sense this converts all Z coordinates
|
|
* to 0.0.
|
|
*
|
|
* This function is the same as the CPP method OGRGeometry::flattenTo2D().
|
|
*
|
|
* @param hGeom handle on the geometry to convert.
|
|
*/
|
|
|
|
void OGR_G_FlattenTo2D( OGRGeometryH hGeom )
|
|
|
|
{
|
|
((OGRGeometry *) hGeom)->flattenTo2D();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* exportToGML() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \fn char *OGRGeometry::exportToGML( const char* const * papszOptions = NULL ) const;
|
|
*
|
|
* \brief Convert a geometry into GML format.
|
|
*
|
|
* The GML geometry is expressed directly in terms of GML basic data
|
|
* types assuming the this is available in the gml namespace. The returned
|
|
* string should be freed with CPLFree() when no longer required.
|
|
*
|
|
* The supported options in OGR 1.8.0 are :
|
|
* <ul>
|
|
* <li> FORMAT=GML3. Otherwise it will default to GML 2.1.2 output.
|
|
* <li> GML3_LINESTRING_ELEMENT=curve. (Only valid for FORMAT=GML3) To use gml:Curve element for linestrings.
|
|
* Otherwise gml:LineString will be used .
|
|
* <li> GML3_LONGSRS=YES/NO. (Only valid for FORMAT=GML3) Default to YES. If YES, SRS with EPSG authority will
|
|
* be written with the "urn:ogc:def:crs:EPSG::" prefix.
|
|
* In the case, if the SRS is a geographic SRS without explicit AXIS order, but that the same SRS authority code
|
|
* imported with ImportFromEPSGA() should be treated as lat/long, then the function will take care of coordinate order swapping.
|
|
* If set to NO, SRS with EPSG authority will be written with the "EPSG:" prefix, even if they are in lat/long order.
|
|
* </ul>
|
|
*
|
|
* This method is the same as the C function OGR_G_ExportToGMLEx().
|
|
*
|
|
* @param papszOptions NULL-terminated list of options.
|
|
* @return A GML fragment or NULL in case of error.
|
|
*/
|
|
|
|
char *OGRGeometry::exportToGML( const char* const * papszOptions ) const
|
|
{
|
|
return OGR_G_ExportToGMLEx( (OGRGeometryH) this, (char**)papszOptions );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* exportToKML() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \fn char *OGRGeometry::exportToKML() const;
|
|
*
|
|
* \brief Convert a geometry into KML format.
|
|
*
|
|
* The returned string should be freed with CPLFree() when no longer required.
|
|
*
|
|
* This method is the same as the C function OGR_G_ExportToKML().
|
|
*
|
|
* @return A KML fragment or NULL in case of error.
|
|
*/
|
|
|
|
char *OGRGeometry::exportToKML() const
|
|
{
|
|
#ifndef _WIN32_WCE
|
|
#ifdef OGR_ENABLED
|
|
return OGR_G_ExportToKML( (OGRGeometryH) this, NULL );
|
|
#else
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"OGRGeometry::exportToKML() not supported in builds without OGR drivers." );
|
|
return NULL;
|
|
#endif
|
|
#else
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"OGRGeometry::exportToKML() not supported in the WinCE build." );
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* exportToJson() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \fn char *OGRGeometry::exportToJson() const;
|
|
*
|
|
* \brief Convert a geometry into GeoJSON format.
|
|
*
|
|
* The returned string should be freed with CPLFree() when no longer required.
|
|
*
|
|
* This method is the same as the C function OGR_G_ExportToJson().
|
|
*
|
|
* @return A GeoJSON fragment or NULL in case of error.
|
|
*/
|
|
|
|
char *OGRGeometry::exportToJson() const
|
|
{
|
|
#ifndef _WIN32_WCE
|
|
#ifdef OGR_ENABLED
|
|
OGRGeometry* poGeometry = const_cast<OGRGeometry*>(this);
|
|
return OGR_G_ExportToJson( (OGRGeometryH) (poGeometry) );
|
|
#else
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"OGRGeometry::exportToJson() not supported in builds without OGR drivers." );
|
|
return NULL;
|
|
#endif
|
|
#else
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"OGRGeometry::exportToJson() not supported in the WinCE build." );
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRSetGenerate_DB2_V72_BYTE_ORDER() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Special entry point to enable the hack for generating DB2 V7.2 style WKB.
|
|
*
|
|
* DB2 seems to have placed (and require) an extra 0x30 or'ed with the byte order in
|
|
* WKB. This entry point is used to turn on or off the
|
|
* generation of such WKB.
|
|
*/
|
|
OGRErr OGRSetGenerate_DB2_V72_BYTE_ORDER( int bGenerate_DB2_V72_BYTE_ORDER )
|
|
|
|
{
|
|
#if defined(HACK_FOR_IBM_DB2_V72)
|
|
OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER = bGenerate_DB2_V72_BYTE_ORDER;
|
|
return OGRERR_NONE;
|
|
#else
|
|
if( bGenerate_DB2_V72_BYTE_ORDER )
|
|
return OGRERR_FAILURE;
|
|
else
|
|
return OGRERR_NONE;
|
|
#endif
|
|
}
|
|
/************************************************************************/
|
|
/* OGRGetGenerate_DB2_V72_BYTE_ORDER() */
|
|
/* */
|
|
/* This is a special entry point to get the value of static flag */
|
|
/* OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER. */
|
|
/************************************************************************/
|
|
int OGRGetGenerate_DB2_V72_BYTE_ORDER()
|
|
{
|
|
return OGRGeometry::bGenerate_DB2_V72_BYTE_ORDER;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* createGEOSContext() */
|
|
/************************************************************************/
|
|
|
|
GEOSContextHandle_t OGRGeometry::createGEOSContext()
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
#else
|
|
return initGEOS_r( OGRGEOSWarningHandler, OGRGEOSErrorHandler );
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* freeGEOSContext() */
|
|
/************************************************************************/
|
|
|
|
void OGRGeometry::freeGEOSContext(GEOSContextHandle_t hGEOSCtxt)
|
|
{
|
|
#ifdef HAVE_GEOS
|
|
if( hGEOSCtxt != NULL )
|
|
{
|
|
finishGEOS_r( hGEOSCtxt );
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* exportToGEOS() */
|
|
/************************************************************************/
|
|
|
|
GEOSGeom OGRGeometry::exportToGEOS(GEOSContextHandle_t hGEOSCtxt) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
|
|
if( hGEOSCtxt == NULL )
|
|
return NULL;
|
|
|
|
/* POINT EMPTY is exported to WKB as if it were POINT(0 0) */
|
|
/* so that particular case is necessary */
|
|
if (wkbFlatten(getGeometryType()) == wkbPoint &&
|
|
IsEmpty())
|
|
{
|
|
return GEOSGeomFromWKT_r(hGEOSCtxt, "POINT EMPTY");
|
|
}
|
|
|
|
GEOSGeom hGeom = NULL;
|
|
size_t nDataSize;
|
|
unsigned char *pabyData = NULL;
|
|
|
|
const OGRGeometry* poLinearGeom = (hasCurveGeometry()) ? getLinearGeometry() : this;
|
|
nDataSize = poLinearGeom->WkbSize();
|
|
pabyData = (unsigned char *) CPLMalloc(nDataSize);
|
|
if( poLinearGeom->exportToWkb( wkbNDR, pabyData ) == OGRERR_NONE )
|
|
hGeom = GEOSGeomFromWKB_buf_r( hGEOSCtxt, pabyData, nDataSize );
|
|
|
|
CPLFree( pabyData );
|
|
|
|
if( poLinearGeom != this )
|
|
delete poLinearGeom;
|
|
|
|
return hGeom;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* hasCurveGeometry() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Returns if this geometry is or has curve geometry.
|
|
*
|
|
* Returns if a geometry is, contains or may contain a CIRCULARSTRING, COMPOUNDCURVE,
|
|
* CURVEPOLYGON, MULTICURVE or MULTISURFACE.
|
|
*
|
|
* If bLookForNonLinear is set to TRUE, it will be actually looked if the
|
|
* geometry or its subgeometries are or contain a non-linear geometry in them. In which
|
|
* case, if the method returns TRUE, it means that getLinearGeometry() would
|
|
* return an approximate version of the geometry. Otherwise, getLinearGeometry()
|
|
* would do a conversion, but with just converting container type, like
|
|
* COMPOUNDCURVE -> LINESTRING, MULTICURVE -> MULTILINESTRING or MULTISURFACE -> MULTIPOLYGON,
|
|
* resulting in a "loss-less" conversion.
|
|
*
|
|
* This method is the same as the C function OGR_G_HasCurveGeometry().
|
|
*
|
|
* @param bLookForNonLinear set it to TRUE to check if the geometry is or contains
|
|
* a CIRCULARSTRING.
|
|
*
|
|
* @return TRUE if this geometry is or has curve geometry.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRBoolean OGRGeometry::hasCurveGeometry(CPL_UNUSED int bLookForNonLinear) const
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* getLinearGeometry() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Return, possibly approximate, non-curve version of this geometry.
|
|
*
|
|
* Returns a geometry that has no CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
|
|
* MULTICURVE or MULTISURFACE in it, by approximating curve geometries.
|
|
*
|
|
* The ownership of the returned geometry belongs to the caller.
|
|
*
|
|
* The reverse method is OGRGeometry::getCurveGeometry().
|
|
*
|
|
* This method is the same as the C function OGR_G_GetLinearGeometry().
|
|
*
|
|
* @param dfMaxAngleStepSizeDegrees the largest step in degrees along the
|
|
* arc, zero to use the default setting.
|
|
* @param papszOptions options as a null-terminated list of strings.
|
|
* See OGRGeometryFactory::curveToLineString() for valid options.
|
|
*
|
|
* @return a new geometry.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRGeometry* OGRGeometry::getLinearGeometry(CPL_UNUSED double dfMaxAngleStepSizeDegrees,
|
|
CPL_UNUSED const char* const* papszOptions) const
|
|
{
|
|
return clone();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* getCurveGeometry() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Return curve version of this geometry.
|
|
*
|
|
* Returns a geometry that has possibly CIRCULARSTRING, COMPOUNDCURVE, CURVEPOLYGON,
|
|
* MULTICURVE or MULTISURFACE in it, by de-approximating curve geometries.
|
|
*
|
|
* If the geometry has no curve portion, the returned geometry will be a clone
|
|
* of it.
|
|
*
|
|
* The ownership of the returned geometry belongs to the caller.
|
|
*
|
|
* The reverse method is OGRGeometry::getLinearGeometry().
|
|
*
|
|
* This function is the same as C function OGR_G_GetCurveGeometry().
|
|
*
|
|
* @param papszOptions options as a null-terminated list of strings.
|
|
* Unused for now. Must be set to NULL.
|
|
*
|
|
* @return a new geometry.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRGeometry* OGRGeometry::getCurveGeometry(CPL_UNUSED const char* const* papszOptions) const
|
|
{
|
|
return clone();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Distance() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute distance between two geometries.
|
|
*
|
|
* Returns the shortest distance between the two geometries. The distance is
|
|
* expressed into the same unit as the coordinates of the geometries.
|
|
*
|
|
* This method is the same as the C function OGR_G_Distance().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the other geometry to compare against.
|
|
*
|
|
* @return the distance between the geometries or -1 if an error occurs.
|
|
*/
|
|
|
|
double OGRGeometry::Distance( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
if( NULL == poOtherGeom )
|
|
{
|
|
CPLDebug( "OGR", "OGRGeometry::Distance called with NULL geometry pointer" );
|
|
return -1.0;
|
|
}
|
|
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return -1.0;
|
|
|
|
#else
|
|
|
|
// GEOSGeom is a pointer
|
|
GEOSGeom hThis = NULL;
|
|
GEOSGeom hOther = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hOther = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
hThis = exportToGEOS(hGEOSCtxt);
|
|
|
|
int bIsErr = 0;
|
|
double dfDistance = 0.0;
|
|
|
|
if( hThis != NULL && hOther != NULL )
|
|
{
|
|
bIsErr = GEOSDistance_r( hGEOSCtxt, hThis, hOther, &dfDistance );
|
|
}
|
|
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThis );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOther );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
if ( bIsErr > 0 )
|
|
{
|
|
return dfDistance;
|
|
}
|
|
|
|
/* Calculations error */
|
|
return -1.0;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Distance() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Compute distance between two geometries.
|
|
*
|
|
* Returns the shortest distance between the two geometries. The distance is
|
|
* expressed into the same unit as the coordinates of the geometries.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Distance().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hFirst the first geometry to compare against.
|
|
* @param hOther the other geometry to compare against.
|
|
*
|
|
* @return the distance between the geometries or -1 if an error occurs.
|
|
*/
|
|
|
|
|
|
double OGR_G_Distance( OGRGeometryH hFirst, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hFirst, "OGR_G_Distance", 0.0 );
|
|
|
|
return ((OGRGeometry *) hFirst)->Distance( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRGeometryRebuildCurves() */
|
|
/************************************************************************/
|
|
|
|
static OGRGeometry* OGRGeometryRebuildCurves(const OGRGeometry* poGeom,
|
|
const OGRGeometry* poOtherGeom,
|
|
OGRGeometry* poOGRProduct)
|
|
{
|
|
if( poOGRProduct != NULL &&
|
|
wkbFlatten(poOGRProduct->getGeometryType()) != wkbPoint &&
|
|
(poGeom->hasCurveGeometry() ||
|
|
(poOtherGeom && poOtherGeom->hasCurveGeometry())) )
|
|
{
|
|
OGRGeometry* poCurveGeom = poOGRProduct->getCurveGeometry();
|
|
delete poOGRProduct;
|
|
return poCurveGeom;
|
|
}
|
|
return poOGRProduct;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* ConvexHull() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute convex hull.
|
|
*
|
|
* A new geometry object is created and returned containing the convex
|
|
* hull of the geometry on which the method is invoked.
|
|
*
|
|
* This method is the same as the C function OGR_G_ConvexHull().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @return a newly allocated geometry now owned by the caller, or NULL on failure.
|
|
*/
|
|
|
|
OGRGeometry *OGRGeometry::ConvexHull() const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
|
|
GEOSGeom hGeosGeom = NULL;
|
|
GEOSGeom hGeosHull = NULL;
|
|
OGRGeometry *poOGRProduct = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
if( hGeosGeom != NULL )
|
|
{
|
|
hGeosHull = GEOSConvexHull_r( hGEOSCtxt, hGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
|
|
|
|
if( hGeosHull != NULL )
|
|
{
|
|
poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosHull);
|
|
if( poOGRProduct != NULL && getSpatialReference() != NULL )
|
|
poOGRProduct->assignSpatialReference(getSpatialReference());
|
|
poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosHull);
|
|
}
|
|
}
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return poOGRProduct;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_ConvexHull() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Compute convex hull.
|
|
*
|
|
* A new geometry object is created and returned containing the convex
|
|
* hull of the geometry on which the method is invoked.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::ConvexHull().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hTarget The Geometry to calculate the convex hull of.
|
|
*
|
|
* @return a handle to a newly allocated geometry now owned by the caller,
|
|
* or NULL on failure.
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_ConvexHull( OGRGeometryH hTarget )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hTarget, "OGR_G_ConvexHull", NULL );
|
|
|
|
return (OGRGeometryH) ((OGRGeometry *) hTarget)->ConvexHull();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Boundary() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute boundary.
|
|
*
|
|
* A new geometry object is created and returned containing the boundary
|
|
* of the geometry on which the method is invoked.
|
|
*
|
|
* This method is the same as the C function OGR_G_Boundary().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @return a newly allocated geometry now owned by the caller, or NULL on failure.
|
|
*
|
|
* @since OGR 1.8.0
|
|
*/
|
|
|
|
OGRGeometry *OGRGeometry::Boundary() const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
|
|
GEOSGeom hGeosGeom = NULL;
|
|
GEOSGeom hGeosProduct = NULL;
|
|
OGRGeometry *poOGRProduct = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
if( hGeosGeom != NULL )
|
|
{
|
|
hGeosProduct = GEOSBoundary_r( hGEOSCtxt, hGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
|
|
|
|
if( hGeosProduct != NULL )
|
|
{
|
|
poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
|
|
if( poOGRProduct != NULL && getSpatialReference() != NULL )
|
|
poOGRProduct->assignSpatialReference(getSpatialReference());
|
|
poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
|
|
}
|
|
}
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return poOGRProduct;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Compute boundary (deprecated)
|
|
*
|
|
* @deprecated
|
|
*
|
|
* @see Boundary()
|
|
*/
|
|
OGRGeometry *OGRGeometry::getBoundary() const
|
|
|
|
{
|
|
return Boundary();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Boundary() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Compute boundary.
|
|
*
|
|
* A new geometry object is created and returned containing the boundary
|
|
* of the geometry on which the method is invoked.
|
|
*
|
|
* This function is the same as the C++ method OGR_G_Boundary().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hTarget The Geometry to calculate the boundary of.
|
|
*
|
|
* @return a handle to a newly allocated geometry now owned by the caller,
|
|
* or NULL on failure.
|
|
*
|
|
* @since OGR 1.8.0
|
|
*/
|
|
OGRGeometryH OGR_G_Boundary( OGRGeometryH hTarget )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hTarget, "OGR_G_Boundary", NULL );
|
|
|
|
return (OGRGeometryH) ((OGRGeometry *) hTarget)->Boundary();
|
|
}
|
|
|
|
/**
|
|
* \brief Compute boundary (deprecated)
|
|
*
|
|
* @deprecated
|
|
*
|
|
* @see OGR_G_Boundary()
|
|
*/
|
|
OGRGeometryH OGR_G_GetBoundary( OGRGeometryH hTarget )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hTarget, "OGR_G_GetBoundary", NULL );
|
|
|
|
return (OGRGeometryH) ((OGRGeometry *) hTarget)->Boundary();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Buffer() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute buffer of geometry.
|
|
*
|
|
* Builds a new geometry containing the buffer region around the geometry
|
|
* on which it is invoked. The buffer is a polygon containing the region within
|
|
* the buffer distance of the original geometry.
|
|
*
|
|
* Some buffer sections are properly described as curves, but are converted to
|
|
* approximate polygons. The nQuadSegs parameter can be used to control how many
|
|
* segements should be used to define a 90 degree curve - a quadrant of a circle.
|
|
* A value of 30 is a reasonable default. Large values result in large numbers
|
|
* of vertices in the resulting buffer geometry while small numbers reduce the
|
|
* accuracy of the result.
|
|
*
|
|
* This method is the same as the C function OGR_G_Buffer().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param dfDist the buffer distance to be applied. Should be expressed into
|
|
* the same unit as the coordinates of the geometry.
|
|
*
|
|
* @param nQuadSegs the number of segments used to approximate a 90 degree (quadrant) of
|
|
* curvature.
|
|
*
|
|
* @return the newly created geometry, or NULL if an error occurs.
|
|
*/
|
|
|
|
OGRGeometry *OGRGeometry::Buffer( double dfDist, int nQuadSegs ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
|
|
GEOSGeom hGeosGeom = NULL;
|
|
GEOSGeom hGeosProduct = NULL;
|
|
OGRGeometry *poOGRProduct = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
if( hGeosGeom != NULL )
|
|
{
|
|
hGeosProduct = GEOSBuffer_r( hGEOSCtxt, hGeosGeom, dfDist, nQuadSegs );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
|
|
|
|
if( hGeosProduct != NULL )
|
|
{
|
|
poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
|
|
if( poOGRProduct != NULL && getSpatialReference() != NULL )
|
|
poOGRProduct->assignSpatialReference(getSpatialReference());
|
|
poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
|
|
}
|
|
}
|
|
freeGEOSContext(hGEOSCtxt);
|
|
|
|
return poOGRProduct;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Buffer() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute buffer of geometry.
|
|
*
|
|
* Builds a new geometry containing the buffer region around the geometry
|
|
* on which it is invoked. The buffer is a polygon containing the region within
|
|
* the buffer distance of the original geometry.
|
|
*
|
|
* Some buffer sections are properly described as curves, but are converted to
|
|
* approximate polygons. The nQuadSegs parameter can be used to control how many
|
|
* segements should be used to define a 90 degree curve - a quadrant of a circle.
|
|
* A value of 30 is a reasonable default. Large values result in large numbers
|
|
* of vertices in the resulting buffer geometry while small numbers reduce the
|
|
* accuracy of the result.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Buffer().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hTarget the geometry.
|
|
* @param dfDist the buffer distance to be applied. Should be expressed into
|
|
* the same unit as the coordinates of the geometry.
|
|
*
|
|
* @param nQuadSegs the number of segments used to approximate a 90 degree
|
|
* (quadrant) of curvature.
|
|
*
|
|
* @return the newly created geometry, or NULL if an error occurs.
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_Buffer( OGRGeometryH hTarget, double dfDist, int nQuadSegs )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hTarget, "OGR_G_Buffer", NULL );
|
|
|
|
return (OGRGeometryH) ((OGRGeometry *) hTarget)->Buffer( dfDist, nQuadSegs );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Intersection() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute intersection.
|
|
*
|
|
* Generates a new geometry which is the region of intersection of the
|
|
* two geometries operated on. The Intersects() method can be used to test if
|
|
* two geometries intersect.
|
|
*
|
|
* This method is the same as the C function OGR_G_Intersection().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the other geometry intersected with "this" geometry.
|
|
*
|
|
* @return a new geometry representing the intersection or NULL if there is
|
|
* no intersection or an error occurs.
|
|
*/
|
|
|
|
OGRGeometry *OGRGeometry::Intersection( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
GEOSGeom hGeosProduct = NULL;
|
|
OGRGeometry *poOGRProduct = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
hGeosProduct = GEOSIntersection_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
|
|
|
|
if( hGeosProduct != NULL )
|
|
{
|
|
poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
|
|
if( poOGRProduct != NULL && getSpatialReference() != NULL &&
|
|
poOtherGeom->getSpatialReference() != NULL &&
|
|
poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
|
|
{
|
|
poOGRProduct->assignSpatialReference(getSpatialReference());
|
|
}
|
|
poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
|
|
}
|
|
}
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return poOGRProduct;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Intersection() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute intersection.
|
|
*
|
|
* Generates a new geometry which is the region of intersection of the
|
|
* two geometries operated on. The OGR_G_Intersects() function can be used to
|
|
* test if two geometries intersect.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Intersection().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry.
|
|
* @param hOther the other geometry.
|
|
*
|
|
* @return a new geometry representing the intersection or NULL if there is
|
|
* no intersection or an error occurs.
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_Intersection( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_Intersection", NULL );
|
|
|
|
return (OGRGeometryH)
|
|
((OGRGeometry *) hThis)->Intersection( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Union() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute union.
|
|
*
|
|
* Generates a new geometry which is the region of union of the
|
|
* two geometries operated on.
|
|
*
|
|
* This method is the same as the C function OGR_G_Union().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the other geometry unioned with "this" geometry.
|
|
*
|
|
* @return a new geometry representing the union or NULL if an error occurs.
|
|
*/
|
|
|
|
OGRGeometry *OGRGeometry::Union( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
GEOSGeom hGeosProduct = NULL;
|
|
OGRGeometry *poOGRProduct = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
hGeosProduct = GEOSUnion_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
|
|
|
|
if( hGeosProduct != NULL )
|
|
{
|
|
poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
|
|
if( poOGRProduct != NULL && getSpatialReference() != NULL &&
|
|
poOtherGeom->getSpatialReference() != NULL &&
|
|
poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
|
|
{
|
|
poOGRProduct->assignSpatialReference(getSpatialReference());
|
|
}
|
|
poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
|
|
}
|
|
}
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return poOGRProduct;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Union() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute union.
|
|
*
|
|
* Generates a new geometry which is the region of union of the
|
|
* two geometries operated on.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Union().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry.
|
|
* @param hOther the other geometry.
|
|
*
|
|
* @return a new geometry representing the union or NULL if an error occurs.
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_Union( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_Union", NULL );
|
|
|
|
return (OGRGeometryH)
|
|
((OGRGeometry *) hThis)->Union( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* UnionCascaded() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute union using cascading.
|
|
*
|
|
* This method is the same as the C function OGR_G_UnionCascaded().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @return a new geometry representing the union or NULL if an error occurs.
|
|
*
|
|
* @since OGR 1.8.0
|
|
*/
|
|
|
|
OGRGeometry *OGRGeometry::UnionCascaded() const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
#else
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hGeosProduct = NULL;
|
|
OGRGeometry *poOGRProduct = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL )
|
|
{
|
|
hGeosProduct = GEOSUnionCascaded_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
|
|
if( hGeosProduct != NULL )
|
|
{
|
|
poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
|
|
if( poOGRProduct != NULL && getSpatialReference() != NULL )
|
|
poOGRProduct->assignSpatialReference(getSpatialReference());
|
|
poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
|
|
}
|
|
}
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return poOGRProduct;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_UnionCascaded() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute union using cascading.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::UnionCascaded().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry.
|
|
*
|
|
* @return a new geometry representing the union or NULL if an error occurs.
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_UnionCascaded( OGRGeometryH hThis )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_UnionCascaded", NULL );
|
|
|
|
return (OGRGeometryH)
|
|
((OGRGeometry *) hThis)->UnionCascaded();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Difference() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute difference.
|
|
*
|
|
* Generates a new geometry which is the region of this geometry with the
|
|
* region of the second geometry removed.
|
|
*
|
|
* This method is the same as the C function OGR_G_Difference().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the other geometry removed from "this" geometry.
|
|
*
|
|
* @return a new geometry representing the difference or NULL if the
|
|
* difference is empty or an error occurs.
|
|
*/
|
|
|
|
OGRGeometry *OGRGeometry::Difference( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
GEOSGeom hGeosProduct = NULL;
|
|
OGRGeometry *poOGRProduct = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
hGeosProduct = GEOSDifference_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
|
|
|
|
if( hGeosProduct != NULL )
|
|
{
|
|
poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
|
|
if( poOGRProduct != NULL && getSpatialReference() != NULL &&
|
|
poOtherGeom->getSpatialReference() != NULL &&
|
|
poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
|
|
{
|
|
poOGRProduct->assignSpatialReference(getSpatialReference());
|
|
}
|
|
poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
|
|
}
|
|
}
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return poOGRProduct;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Difference() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute difference.
|
|
*
|
|
* Generates a new geometry which is the region of this geometry with the
|
|
* region of the other geometry removed.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Difference().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry.
|
|
* @param hOther the other geometry.
|
|
*
|
|
* @return a new geometry representing the difference or NULL if the
|
|
* difference is empty or an error occurs.
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_Difference( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_Difference", NULL );
|
|
|
|
return (OGRGeometryH)
|
|
((OGRGeometry *) hThis)->Difference( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SymDifference() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute symmetric difference.
|
|
*
|
|
* Generates a new geometry which is the symmetric difference of this
|
|
* geometry and the second geometry passed into the method.
|
|
*
|
|
* This method is the same as the C function OGR_G_SymDifference().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the other geometry.
|
|
*
|
|
* @return a new geometry representing the symmetric difference or NULL if the
|
|
* difference is empty or an error occurs.
|
|
*
|
|
* @since OGR 1.8.0
|
|
*/
|
|
|
|
OGRGeometry *
|
|
OGRGeometry::SymDifference( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
GEOSGeom hGeosProduct = NULL;
|
|
OGRGeometry *poOGRProduct = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
hGeosProduct = GEOSSymDifference_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
|
|
|
|
if( hGeosProduct != NULL )
|
|
{
|
|
poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct);
|
|
if( poOGRProduct != NULL && getSpatialReference() != NULL &&
|
|
poOtherGeom->getSpatialReference() != NULL &&
|
|
poOtherGeom->getSpatialReference()->IsSame(getSpatialReference()) )
|
|
{
|
|
poOGRProduct->assignSpatialReference(getSpatialReference());
|
|
}
|
|
poOGRProduct = OGRGeometryRebuildCurves(this, poOtherGeom, poOGRProduct);
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
|
|
}
|
|
}
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return poOGRProduct;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
|
|
/**
|
|
* \brief Compute symmetric difference (deprecated)
|
|
*
|
|
* @deprecated
|
|
*
|
|
* @see OGRGeometry::SymDifference()
|
|
*/
|
|
OGRGeometry *
|
|
OGRGeometry::SymmetricDifference( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
return SymDifference( poOtherGeom );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_SymDifference() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute symmetric difference.
|
|
*
|
|
* Generates a new geometry which is the symmetric difference of this
|
|
* geometry and the other geometry.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::SymmetricDifference().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry.
|
|
* @param hOther the other geometry.
|
|
*
|
|
* @return a new geometry representing the symmetric difference or NULL if the
|
|
* difference is empty or an error occurs.
|
|
*
|
|
* @since OGR 1.8.0
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_SymDifference( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_SymDifference", NULL );
|
|
|
|
return (OGRGeometryH)
|
|
((OGRGeometry *) hThis)->SymDifference( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/**
|
|
* \brief Compute symmetric difference (deprecated)
|
|
*
|
|
* @deprecated
|
|
*
|
|
* @see OGR_G_SymmetricDifference()
|
|
*/
|
|
OGRGeometryH OGR_G_SymmetricDifference( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_SymmetricDifference", NULL );
|
|
|
|
return (OGRGeometryH)
|
|
((OGRGeometry *) hThis)->SymDifference( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Disjoint() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test for disjointness.
|
|
*
|
|
* Tests if this geometry and the other passed into the method are disjoint.
|
|
*
|
|
* This method is the same as the C function OGR_G_Disjoint().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the geometry to compare to this geometry.
|
|
*
|
|
* @return TRUE if they are disjoint, otherwise FALSE.
|
|
*/
|
|
|
|
OGRBoolean
|
|
OGRGeometry::Disjoint( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
OGRBoolean bResult = FALSE;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
bResult = GEOSDisjoint_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
|
|
}
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return bResult;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Disjoint() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test for disjointness.
|
|
*
|
|
* Tests if this geometry and the other geometry are disjoint.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Disjoint().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry to compare.
|
|
* @param hOther the other geometry to compare.
|
|
*
|
|
* @return TRUE if they are disjoint, otherwise FALSE.
|
|
*/
|
|
int OGR_G_Disjoint( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_Disjoint", FALSE );
|
|
|
|
return ((OGRGeometry *) hThis)->Disjoint( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Touches() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test for touching.
|
|
*
|
|
* Tests if this geometry and the other passed into the method are touching.
|
|
*
|
|
* This method is the same as the C function OGR_G_Touches().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the geometry to compare to this geometry.
|
|
*
|
|
* @return TRUE if they are touching, otherwise FALSE.
|
|
*/
|
|
|
|
OGRBoolean
|
|
OGRGeometry::Touches( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
OGRBoolean bResult = FALSE;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
bResult = GEOSTouches_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
|
|
}
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return bResult;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Touches() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Test for touching.
|
|
*
|
|
* Tests if this geometry and the other geometry are touching.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Touches().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry to compare.
|
|
* @param hOther the other geometry to compare.
|
|
*
|
|
* @return TRUE if they are touching, otherwise FALSE.
|
|
*/
|
|
|
|
int OGR_G_Touches( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_Touches", FALSE );
|
|
|
|
return ((OGRGeometry *) hThis)->Touches( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Crosses() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test for crossing.
|
|
*
|
|
* Tests if this geometry and the other passed into the method are crossing.
|
|
*
|
|
* This method is the same as the C function OGR_G_Crosses().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the geometry to compare to this geometry.
|
|
*
|
|
* @return TRUE if they are crossing, otherwise FALSE.
|
|
*/
|
|
|
|
OGRBoolean
|
|
OGRGeometry::Crosses( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
OGRBoolean bResult = FALSE;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
bResult = GEOSCrosses_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
|
|
}
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return bResult;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Crosses() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Test for crossing.
|
|
*
|
|
* Tests if this geometry and the other geometry are crossing.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Crosses().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry to compare.
|
|
* @param hOther the other geometry to compare.
|
|
*
|
|
* @return TRUE if they are crossing, otherwise FALSE.
|
|
*/
|
|
|
|
int OGR_G_Crosses( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_Crosses", FALSE );
|
|
|
|
return ((OGRGeometry *) hThis)->Crosses( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Within() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test for containment.
|
|
*
|
|
* Tests if actual geometry object is within the passed geometry.
|
|
*
|
|
* This method is the same as the C function OGR_G_Within().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the geometry to compare to this geometry.
|
|
*
|
|
* @return TRUE if poOtherGeom is within this geometry, otherwise FALSE.
|
|
*/
|
|
|
|
OGRBoolean
|
|
OGRGeometry::Within( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
OGRBoolean bResult = FALSE;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
bResult = GEOSWithin_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
|
|
}
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return bResult;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Within() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test for containment.
|
|
*
|
|
* Tests if this geometry is within the other geometry.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Within().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry to compare.
|
|
* @param hOther the other geometry to compare.
|
|
*
|
|
* @return TRUE if hThis is within hOther, otherwise FALSE.
|
|
*/
|
|
int OGR_G_Within( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_Within", FALSE );
|
|
|
|
return ((OGRGeometry *) hThis)->Within( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Contains() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test for containment.
|
|
*
|
|
* Tests if actual geometry object contains the passed geometry.
|
|
*
|
|
* This method is the same as the C function OGR_G_Contains().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the geometry to compare to this geometry.
|
|
*
|
|
* @return TRUE if poOtherGeom contains this geometry, otherwise FALSE.
|
|
*/
|
|
|
|
OGRBoolean
|
|
OGRGeometry::Contains( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
OGRBoolean bResult = FALSE;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
bResult = GEOSContains_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
|
|
}
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return bResult;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Contains() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test for containment.
|
|
*
|
|
* Tests if this geometry contains the other geometry.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Contains().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry to compare.
|
|
* @param hOther the other geometry to compare.
|
|
*
|
|
* @return TRUE if hThis contains hOther geometry, otherwise FALSE.
|
|
*/
|
|
int OGR_G_Contains( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_Contains", FALSE );
|
|
|
|
return ((OGRGeometry *) hThis)->Contains( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Overlaps() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Test for overlap.
|
|
*
|
|
* Tests if this geometry and the other passed into the method overlap, that is
|
|
* their intersection has a non-zero area.
|
|
*
|
|
* This method is the same as the C function OGR_G_Overlaps().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param poOtherGeom the geometry to compare to this geometry.
|
|
*
|
|
* @return TRUE if they are overlapping, otherwise FALSE.
|
|
*/
|
|
|
|
OGRBoolean
|
|
OGRGeometry::Overlaps( const OGRGeometry *poOtherGeom ) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return FALSE;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
OGRBoolean bResult = FALSE;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
hOtherGeosGeom = poOtherGeom->exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL && hOtherGeosGeom != NULL )
|
|
{
|
|
bResult = GEOSOverlaps_r( hGEOSCtxt, hThisGeosGeom, hOtherGeosGeom );
|
|
}
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return bResult;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Overlaps() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Test for overlap.
|
|
*
|
|
* Tests if this geometry and the other geometry overlap, that is their
|
|
* intersection has a non-zero area.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Overlaps().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry to compare.
|
|
* @param hOther the other geometry to compare.
|
|
*
|
|
* @return TRUE if they are overlapping, otherwise FALSE.
|
|
*/
|
|
|
|
int OGR_G_Overlaps( OGRGeometryH hThis, OGRGeometryH hOther )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_Overlaps", FALSE );
|
|
|
|
return ((OGRGeometry *) hThis)->Overlaps( (OGRGeometry *) hOther );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* closeRings() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Force rings to be closed.
|
|
*
|
|
* If this geometry, or any contained geometries has polygon rings that
|
|
* are not closed, they will be closed by adding the starting point at
|
|
* the end.
|
|
*/
|
|
|
|
void OGRGeometry::closeRings()
|
|
|
|
{
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_CloseRings() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Force rings to be closed.
|
|
*
|
|
* If this geometry, or any contained geometries has polygon rings that
|
|
* are not closed, they will be closed by adding the starting point at
|
|
* the end.
|
|
*
|
|
* @param hGeom handle to the geometry.
|
|
*/
|
|
|
|
void OGR_G_CloseRings( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER0( hGeom, "OGR_G_CloseRings" );
|
|
|
|
((OGRGeometry *) hGeom)->closeRings();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Centroid() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute the geometry centroid.
|
|
*
|
|
* The centroid location is applied to the passed in OGRPoint object.
|
|
* The centroid is not necessarily within the geometry.
|
|
*
|
|
* This method relates to the SFCOM ISurface::get_Centroid() method
|
|
* however the current implementation based on GEOS can operate on other
|
|
* geometry types such as multipoint, linestring, geometrycollection such as
|
|
* multipolygons.
|
|
* OGC SF SQL 1.1 defines the operation for surfaces (polygons).
|
|
* SQL/MM-Part 3 defines the operation for surfaces and multisurfaces (multipolygons).
|
|
*
|
|
* This function is the same as the C function OGR_G_Centroid().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @return OGRERR_NONE on success or OGRERR_FAILURE on error.
|
|
*
|
|
* @since OGR 1.8.0 as a OGRGeometry method (previously was restricted to OGRPolygon)
|
|
*/
|
|
|
|
int OGRGeometry::Centroid( OGRPoint *poPoint ) const
|
|
|
|
{
|
|
if( poPoint == NULL )
|
|
return OGRERR_FAILURE;
|
|
|
|
#ifndef HAVE_GEOS
|
|
// notdef ... not implemented yet.
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return OGRERR_FAILURE;
|
|
|
|
#else
|
|
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
|
|
if( hThisGeosGeom != NULL )
|
|
{
|
|
hOtherGeosGeom = GEOSGetCentroid_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
|
|
if( hOtherGeosGeom == NULL )
|
|
{
|
|
freeGEOSContext( hGEOSCtxt );
|
|
return OGRERR_FAILURE;
|
|
}
|
|
|
|
OGRGeometry *poCentroidGeom =
|
|
OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hOtherGeosGeom );
|
|
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
|
|
if (poCentroidGeom == NULL)
|
|
{
|
|
freeGEOSContext( hGEOSCtxt );
|
|
return OGRERR_FAILURE;
|
|
}
|
|
if (wkbFlatten(poCentroidGeom->getGeometryType()) != wkbPoint)
|
|
{
|
|
delete poCentroidGeom;
|
|
freeGEOSContext( hGEOSCtxt );
|
|
return OGRERR_FAILURE;
|
|
}
|
|
|
|
if( poCentroidGeom != NULL && getSpatialReference() != NULL )
|
|
poCentroidGeom->assignSpatialReference(getSpatialReference());
|
|
|
|
OGRPoint *poCentroid = (OGRPoint *) poCentroidGeom;
|
|
if( !poCentroid->IsEmpty() )
|
|
{
|
|
poPoint->setX( poCentroid->getX() );
|
|
poPoint->setY( poCentroid->getY() );
|
|
}
|
|
else
|
|
{
|
|
poPoint->empty();
|
|
}
|
|
|
|
delete poCentroidGeom;
|
|
|
|
freeGEOSContext( hGEOSCtxt );
|
|
return OGRERR_NONE;
|
|
}
|
|
else
|
|
{
|
|
freeGEOSContext( hGEOSCtxt );
|
|
return OGRERR_FAILURE;
|
|
}
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Centroid() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute the geometry centroid.
|
|
*
|
|
* The centroid location is applied to the passed in OGRPoint object.
|
|
* The centroid is not necessarily within the geometry.
|
|
*
|
|
* This method relates to the SFCOM ISurface::get_Centroid() method
|
|
* however the current implementation based on GEOS can operate on other
|
|
* geometry types such as multipoint, linestring, geometrycollection such as
|
|
* multipolygons.
|
|
* OGC SF SQL 1.1 defines the operation for surfaces (polygons).
|
|
* SQL/MM-Part 3 defines the operation for surfaces and multisurfaces (multipolygons).
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Centroid().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @return OGRERR_NONE on success or OGRERR_FAILURE on error.
|
|
*/
|
|
|
|
int OGR_G_Centroid( OGRGeometryH hGeom, OGRGeometryH hCentroidPoint )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_Centroid", OGRERR_FAILURE );
|
|
|
|
OGRGeometry *poGeom = ((OGRGeometry *) hGeom);
|
|
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;
|
|
}
|
|
|
|
return poGeom->Centroid( poCentroid );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_PointOnSurface() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Returns a point guaranteed to lie on the surface.
|
|
*
|
|
* This method relates to the SFCOM ISurface::get_PointOnSurface() method
|
|
* however the current implementation based on GEOS can operate on other
|
|
* geometry types than the types that are supported by SQL/MM-Part 3 :
|
|
* surfaces (polygons) and multisurfaces (multipolygons).
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hGeom the geometry to operate on.
|
|
* @return a point guaranteed to lie on the surface or NULL if an error
|
|
* occured.
|
|
*
|
|
* @since OGR 1.10
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_PointOnSurface( OGRGeometryH hGeom )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hGeom, "OGR_G_PointOnSurface", NULL );
|
|
|
|
#ifndef HAVE_GEOS
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
#else
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hOtherGeosGeom = NULL;
|
|
OGRGeometry* poThis = (OGRGeometry*) hGeom;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
|
|
hThisGeosGeom = poThis->exportToGEOS(hGEOSCtxt);
|
|
|
|
if( hThisGeosGeom != NULL )
|
|
{
|
|
hOtherGeosGeom = GEOSPointOnSurface_r( hGEOSCtxt, hThisGeosGeom );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
|
|
if( hOtherGeosGeom == NULL )
|
|
{
|
|
OGRGeometry::freeGEOSContext( hGEOSCtxt );
|
|
return NULL;
|
|
}
|
|
|
|
OGRGeometry *poInsidePointGeom = (OGRGeometry *)
|
|
OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hOtherGeosGeom );
|
|
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hOtherGeosGeom );
|
|
|
|
if (poInsidePointGeom == NULL)
|
|
{
|
|
OGRGeometry::freeGEOSContext( hGEOSCtxt );
|
|
return NULL;
|
|
}
|
|
if (wkbFlatten(poInsidePointGeom->getGeometryType()) != wkbPoint)
|
|
{
|
|
delete poInsidePointGeom;
|
|
OGRGeometry::freeGEOSContext( hGEOSCtxt );
|
|
return NULL;
|
|
}
|
|
|
|
if( poInsidePointGeom != NULL && poThis->getSpatialReference() != NULL )
|
|
poInsidePointGeom->assignSpatialReference(poThis->getSpatialReference());
|
|
|
|
OGRGeometry::freeGEOSContext( hGEOSCtxt );
|
|
return (OGRGeometryH) poInsidePointGeom;
|
|
}
|
|
else
|
|
{
|
|
OGRGeometry::freeGEOSContext( hGEOSCtxt );
|
|
return NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Simplify() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Simplify the geometry.
|
|
*
|
|
* This function is the same as the C function OGR_G_Simplify().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param dTolerance the distance tolerance for the simplification.
|
|
*
|
|
* @return the simplified geometry or NULL if an error occurs.
|
|
*
|
|
* @since OGR 1.8.0
|
|
*/
|
|
|
|
OGRGeometry *OGRGeometry::Simplify(double dTolerance) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hGeosProduct = NULL;
|
|
OGRGeometry *poOGRProduct = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL )
|
|
{
|
|
hGeosProduct = GEOSSimplify_r( hGEOSCtxt, hThisGeosGeom, dTolerance );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
if( hGeosProduct != NULL )
|
|
{
|
|
poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct );
|
|
if( poOGRProduct != NULL && getSpatialReference() != NULL )
|
|
poOGRProduct->assignSpatialReference(getSpatialReference());
|
|
poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
|
|
}
|
|
}
|
|
freeGEOSContext( hGEOSCtxt );
|
|
return poOGRProduct;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Simplify() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Compute a simplified geometry.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Simplify().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry.
|
|
* @param dTolerance the distance tolerance for the simplification.
|
|
*
|
|
* @return the simplified geometry or NULL if an error occurs.
|
|
*
|
|
* @since OGR 1.8.0
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_Simplify( OGRGeometryH hThis, double dTolerance )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_Simplify", NULL );
|
|
return (OGRGeometryH) ((OGRGeometry *) hThis)->Simplify( dTolerance );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* SimplifyPreserveTopology() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Simplify the geometry while preserving topology.
|
|
*
|
|
* This function is the same as the C function OGR_G_SimplifyPreserveTopology().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param dTolerance the distance tolerance for the simplification.
|
|
*
|
|
* @return the simplified geometry or NULL if an error occurs.
|
|
*
|
|
* @since OGR 1.9.0
|
|
*/
|
|
|
|
OGRGeometry *OGRGeometry::SimplifyPreserveTopology(double dTolerance) const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
GEOSGeom hThisGeosGeom = NULL;
|
|
GEOSGeom hGeosProduct = NULL;
|
|
OGRGeometry *poOGRProduct = NULL;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
hThisGeosGeom = exportToGEOS(hGEOSCtxt);
|
|
if( hThisGeosGeom != NULL )
|
|
{
|
|
hGeosProduct = GEOSTopologyPreserveSimplify_r( hGEOSCtxt, hThisGeosGeom, dTolerance );
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hThisGeosGeom );
|
|
if( hGeosProduct != NULL )
|
|
{
|
|
poOGRProduct = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosProduct );
|
|
if( poOGRProduct != NULL && getSpatialReference() != NULL )
|
|
poOGRProduct->assignSpatialReference(getSpatialReference());
|
|
poOGRProduct = OGRGeometryRebuildCurves(this, NULL, poOGRProduct);
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosProduct );
|
|
}
|
|
}
|
|
freeGEOSContext( hGEOSCtxt );
|
|
return poOGRProduct;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_SimplifyPreserveTopology() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Simplify the geometry while preserving topology.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::SimplifyPreserveTopology().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hThis the geometry.
|
|
* @param dTolerance the distance tolerance for the simplification.
|
|
*
|
|
* @return the simplified geometry or NULL if an error occurs.
|
|
*
|
|
* @since OGR 1.9.0
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_SimplifyPreserveTopology( OGRGeometryH hThis, double dTolerance )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hThis, "OGR_G_SimplifyPreserveTopology", NULL );
|
|
return (OGRGeometryH) ((OGRGeometry *) hThis)->SimplifyPreserveTopology( dTolerance );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Polygonize() */
|
|
/************************************************************************/
|
|
/* Contributor: Alessandro Furieri, a.furieri@lqt.it */
|
|
/* Developed for Faunalia (http://www.faunalia.it) with funding from */
|
|
/* Regione Toscana - Settore SISTEMA INFORMATIVO TERRITORIALE ED */
|
|
/* AMBIENTALE */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Polygonizes a set of sparse edges.
|
|
*
|
|
* A new geometry object is created and returned containing a collection
|
|
* of reassembled Polygons: NULL will be returned if the input collection
|
|
* doesn't corresponds to a MultiLinestring, or when reassembling Edges
|
|
* into Polygons is impossible due to topogical inconsistencies.
|
|
*
|
|
* This method is the same as the C function OGR_G_Polygonize().
|
|
*
|
|
* This method is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this method will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @return a newly allocated geometry now owned by the caller, or NULL on failure.
|
|
*
|
|
* @since OGR 1.9.0
|
|
*/
|
|
|
|
OGRGeometry *OGRGeometry::Polygonize() const
|
|
|
|
{
|
|
#ifndef HAVE_GEOS
|
|
|
|
CPLError( CE_Failure, CPLE_NotSupported,
|
|
"GEOS support not enabled." );
|
|
return NULL;
|
|
|
|
#else
|
|
|
|
OGRGeometryCollection *poColl = NULL;
|
|
if( wkbFlatten(getGeometryType()) == wkbGeometryCollection ||
|
|
wkbFlatten(getGeometryType()) == wkbMultiLineString )
|
|
poColl = (OGRGeometryCollection *)this;
|
|
else
|
|
return NULL;
|
|
|
|
int iCount = poColl->getNumGeometries();
|
|
|
|
GEOSGeom *hGeosGeomList = NULL;
|
|
GEOSGeom hGeosPolygs = NULL;
|
|
OGRGeometry *poPolygsOGRGeom = NULL;
|
|
int bError = FALSE;
|
|
|
|
GEOSContextHandle_t hGEOSCtxt = createGEOSContext();
|
|
|
|
hGeosGeomList = new GEOSGeom [iCount];
|
|
for ( int ig = 0; ig < iCount; ig++)
|
|
{
|
|
GEOSGeom hGeosGeom = NULL;
|
|
OGRGeometry * poChild = (OGRGeometry*)poColl->getGeometryRef(ig);
|
|
if( poChild == NULL ||
|
|
wkbFlatten(poChild->getGeometryType()) != wkbLineString )
|
|
bError = TRUE;
|
|
else
|
|
{
|
|
hGeosGeom = poChild->exportToGEOS(hGEOSCtxt);
|
|
if( hGeosGeom == NULL)
|
|
bError = TRUE;
|
|
}
|
|
*(hGeosGeomList + ig) = hGeosGeom;
|
|
}
|
|
|
|
if( bError == FALSE )
|
|
{
|
|
hGeosPolygs = GEOSPolygonize_r( hGEOSCtxt, hGeosGeomList, iCount );
|
|
|
|
if( hGeosPolygs != NULL )
|
|
{
|
|
poPolygsOGRGeom = OGRGeometryFactory::createFromGEOS(hGEOSCtxt, hGeosPolygs);
|
|
if( poPolygsOGRGeom != NULL && getSpatialReference() != NULL )
|
|
poPolygsOGRGeom->assignSpatialReference(getSpatialReference());
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosPolygs);
|
|
}
|
|
}
|
|
|
|
for ( int ig = 0; ig < iCount; ig++)
|
|
{
|
|
GEOSGeom hGeosGeom = *(hGeosGeomList + ig);
|
|
if( hGeosGeom != NULL)
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGeosGeom );
|
|
}
|
|
delete [] hGeosGeomList;
|
|
freeGEOSContext( hGEOSCtxt );
|
|
|
|
return poPolygsOGRGeom;
|
|
|
|
#endif /* HAVE_GEOS */
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_G_Polygonize() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Polygonizes a set of sparse edges.
|
|
*
|
|
* A new geometry object is created and returned containing a collection
|
|
* of reassembled Polygons: NULL will be returned if the input collection
|
|
* doesn't corresponds to a MultiLinestring, or when reassembling Edges
|
|
* into Polygons is impossible due to topogical inconsistencies.
|
|
*
|
|
* This function is the same as the C++ method OGRGeometry::Polygonize().
|
|
*
|
|
* This function is built on the GEOS library, check it for the definition
|
|
* of the geometry operation.
|
|
* If OGR is built without the GEOS library, this function will always fail,
|
|
* issuing a CPLE_NotSupported error.
|
|
*
|
|
* @param hTarget The Geometry to be polygonized.
|
|
*
|
|
* @return a handle to a newly allocated geometry now owned by the caller,
|
|
* or NULL on failure.
|
|
*
|
|
* @since OGR 1.9.0
|
|
*/
|
|
|
|
OGRGeometryH OGR_G_Polygonize( OGRGeometryH hTarget )
|
|
|
|
{
|
|
VALIDATE_POINTER1( hTarget, "OGR_G_Polygonize", NULL );
|
|
|
|
return (OGRGeometryH) ((OGRGeometry *) hTarget)->Polygonize();
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* swapXY() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Swap x and y coordinates.
|
|
*
|
|
* @since OGR 1.8.0
|
|
*/
|
|
|
|
void OGRGeometry::swapXY()
|
|
|
|
{
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* Prepared geometry API */
|
|
/************************************************************************/
|
|
|
|
/* GEOS >= 3.1.0 for prepared geometries */
|
|
#if defined(HAVE_GEOS)
|
|
#define HAVE_GEOS_PREPARED_GEOMETRY
|
|
#endif
|
|
|
|
#ifdef HAVE_GEOS_PREPARED_GEOMETRY
|
|
struct _OGRPreparedGeometry
|
|
{
|
|
GEOSContextHandle_t hGEOSCtxt;
|
|
GEOSGeom hGEOSGeom;
|
|
const GEOSPreparedGeometry* poPreparedGEOSGeom;
|
|
};
|
|
#endif
|
|
|
|
/************************************************************************/
|
|
/* OGRHasPreparedGeometrySupport() */
|
|
/************************************************************************/
|
|
|
|
int OGRHasPreparedGeometrySupport()
|
|
{
|
|
#ifdef HAVE_GEOS_PREPARED_GEOMETRY
|
|
return TRUE;
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRCreatePreparedGeometry() */
|
|
/************************************************************************/
|
|
|
|
OGRPreparedGeometry* OGRCreatePreparedGeometry( const OGRGeometry* poGeom )
|
|
{
|
|
#ifdef HAVE_GEOS_PREPARED_GEOMETRY
|
|
GEOSContextHandle_t hGEOSCtxt = OGRGeometry::createGEOSContext();
|
|
GEOSGeom hGEOSGeom = poGeom->exportToGEOS(hGEOSCtxt);
|
|
if( hGEOSGeom == NULL )
|
|
{
|
|
OGRGeometry::freeGEOSContext( hGEOSCtxt );
|
|
return NULL;
|
|
}
|
|
const GEOSPreparedGeometry* poPreparedGEOSGeom = GEOSPrepare_r(hGEOSCtxt, hGEOSGeom);
|
|
if( poPreparedGEOSGeom == NULL )
|
|
{
|
|
GEOSGeom_destroy_r( hGEOSCtxt, hGEOSGeom );
|
|
OGRGeometry::freeGEOSContext( hGEOSCtxt );
|
|
return NULL;
|
|
}
|
|
|
|
OGRPreparedGeometry* poPreparedGeom = new OGRPreparedGeometry;
|
|
poPreparedGeom->hGEOSCtxt = hGEOSCtxt;
|
|
poPreparedGeom->hGEOSGeom = hGEOSGeom;
|
|
poPreparedGeom->poPreparedGEOSGeom = poPreparedGEOSGeom;
|
|
|
|
return poPreparedGeom;
|
|
#else
|
|
return NULL;
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRDestroyPreparedGeometry() */
|
|
/************************************************************************/
|
|
|
|
void OGRDestroyPreparedGeometry( OGRPreparedGeometry* poPreparedGeom )
|
|
{
|
|
#ifdef HAVE_GEOS_PREPARED_GEOMETRY
|
|
if( poPreparedGeom != NULL )
|
|
{
|
|
GEOSPreparedGeom_destroy_r(poPreparedGeom->hGEOSCtxt, poPreparedGeom->poPreparedGEOSGeom);
|
|
GEOSGeom_destroy_r( poPreparedGeom->hGEOSCtxt, poPreparedGeom->hGEOSGeom );
|
|
OGRGeometry::freeGEOSContext( poPreparedGeom->hGEOSCtxt );
|
|
delete poPreparedGeom;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRPreparedGeometryIntersects() */
|
|
/************************************************************************/
|
|
|
|
int OGRPreparedGeometryIntersects( const OGRPreparedGeometry* poPreparedGeom,
|
|
const OGRGeometry* poOtherGeom )
|
|
{
|
|
#ifdef HAVE_GEOS_PREPARED_GEOMETRY
|
|
if( poPreparedGeom == NULL || poOtherGeom == NULL )
|
|
return FALSE;
|
|
|
|
GEOSGeom hGEOSOtherGeom = poOtherGeom->exportToGEOS(poPreparedGeom->hGEOSCtxt);
|
|
if( hGEOSOtherGeom == NULL )
|
|
return FALSE;
|
|
|
|
int bRet = GEOSPreparedIntersects_r(poPreparedGeom->hGEOSCtxt,
|
|
poPreparedGeom->poPreparedGEOSGeom,
|
|
hGEOSOtherGeom);
|
|
GEOSGeom_destroy_r( poPreparedGeom->hGEOSCtxt, hGEOSOtherGeom );
|
|
|
|
return bRet;
|
|
#else
|
|
return FALSE;
|
|
#endif
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRGeometryFromEWKB() */
|
|
/************************************************************************/
|
|
|
|
/* Flags for creating WKB format for PostGIS */
|
|
#define WKBZOFFSET 0x80000000
|
|
#define WKBMOFFSET 0x40000000
|
|
#define WKBSRIDFLAG 0x20000000
|
|
#define WKBBBOXFLAG 0x10000000
|
|
|
|
OGRGeometry *OGRGeometryFromEWKB( GByte *pabyWKB, int nLength, int* pnSRID,
|
|
int bIsPostGIS1_EWKB )
|
|
|
|
{
|
|
OGRGeometry *poGeometry = NULL;
|
|
unsigned int ewkbFlags = 0;
|
|
|
|
if (nLength < 5)
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"Invalid EWKB content : %d bytes", nLength );
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Detect XYZM variant of PostGIS EWKB */
|
|
/* */
|
|
/* OGR does not support parsing M coordinate, */
|
|
/* so we return NULL geometry. */
|
|
/* -------------------------------------------------------------------- */
|
|
memcpy(&ewkbFlags, pabyWKB+1, 4);
|
|
OGRwkbByteOrder eByteOrder = (pabyWKB[0] == 0 ? wkbXDR : wkbNDR);
|
|
if( OGR_SWAP( eByteOrder ) )
|
|
ewkbFlags= CPL_SWAP32(ewkbFlags);
|
|
|
|
if (ewkbFlags & WKBMOFFSET)
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"Reading EWKB with 4-dimensional coordinates (XYZM) is not supported" );
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* PostGIS EWKB format includes an SRID, but this won't be */
|
|
/* understood by OGR, so if the SRID flag is set, we remove the */
|
|
/* SRID (bytes at offset 5 to 8). */
|
|
/* -------------------------------------------------------------------- */
|
|
if( nLength > 9 &&
|
|
((pabyWKB[0] == 0 /* big endian */ && (pabyWKB[1] & 0x20) )
|
|
|| (pabyWKB[0] != 0 /* little endian */ && (pabyWKB[4] & 0x20))) )
|
|
{
|
|
if( pnSRID )
|
|
{
|
|
memcpy(pnSRID, pabyWKB+5, 4);
|
|
if( OGR_SWAP( eByteOrder ) )
|
|
*pnSRID = CPL_SWAP32(*pnSRID);
|
|
}
|
|
memmove( pabyWKB+5, pabyWKB+9, nLength-9 );
|
|
nLength -= 4;
|
|
if( pabyWKB[0] == 0 )
|
|
pabyWKB[1] &= (~0x20);
|
|
else
|
|
pabyWKB[4] &= (~0x20);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Try to ingest the geometry. */
|
|
/* -------------------------------------------------------------------- */
|
|
OGRGeometryFactory::createFromWkb( pabyWKB, NULL, &poGeometry, nLength,
|
|
(bIsPostGIS1_EWKB) ? wkbVariantPostGIS1 : wkbVariantOldOgc );
|
|
|
|
return poGeometry;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRGeometryFromHexEWKB() */
|
|
/************************************************************************/
|
|
|
|
OGRGeometry *OGRGeometryFromHexEWKB( const char *pszBytea, int* pnSRID,
|
|
int bIsPostGIS1_EWKB )
|
|
|
|
{
|
|
GByte *pabyWKB;
|
|
int nWKBLength=0;
|
|
OGRGeometry *poGeometry;
|
|
|
|
if( pszBytea == NULL )
|
|
return NULL;
|
|
|
|
pabyWKB = CPLHexToBinary(pszBytea, &nWKBLength);
|
|
|
|
poGeometry = OGRGeometryFromEWKB(pabyWKB, nWKBLength, pnSRID, bIsPostGIS1_EWKB);
|
|
|
|
CPLFree(pabyWKB);
|
|
|
|
return poGeometry;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGRGeometryToHexEWKB() */
|
|
/************************************************************************/
|
|
|
|
char* OGRGeometryToHexEWKB( OGRGeometry * poGeometry, int nSRSId,
|
|
int bIsPostGIS1_EWKB )
|
|
{
|
|
GByte *pabyWKB;
|
|
char *pszTextBuf;
|
|
char *pszTextBufCurrent;
|
|
char *pszHex;
|
|
|
|
int nWkbSize = poGeometry->WkbSize();
|
|
pabyWKB = (GByte *) CPLMalloc(nWkbSize);
|
|
|
|
if( poGeometry->exportToWkb( wkbNDR, pabyWKB,
|
|
bIsPostGIS1_EWKB ? wkbVariantPostGIS1 : wkbVariantOldOgc ) != OGRERR_NONE )
|
|
{
|
|
CPLFree( pabyWKB );
|
|
return CPLStrdup("");
|
|
}
|
|
|
|
/* When converting to hex, each byte takes 2 hex characters. In addition
|
|
we add in 8 characters to represent the SRID integer in hex, and
|
|
one for a null terminator */
|
|
|
|
int pszSize = nWkbSize*2 + 8 + 1;
|
|
pszTextBuf = (char *) CPLMalloc(pszSize);
|
|
pszTextBufCurrent = pszTextBuf;
|
|
|
|
/* Convert the 1st byte, which is the endianess flag, to hex. */
|
|
pszHex = CPLBinaryToHex( 1, pabyWKB );
|
|
strcpy(pszTextBufCurrent, pszHex );
|
|
CPLFree ( pszHex );
|
|
pszTextBufCurrent += 2;
|
|
|
|
/* Next, get the geom type which is bytes 2 through 5 */
|
|
GUInt32 geomType;
|
|
memcpy( &geomType, pabyWKB+1, 4 );
|
|
|
|
/* Now add the SRID flag if an SRID is provided */
|
|
if (nSRSId > 0)
|
|
{
|
|
/* Change the flag to wkbNDR (little) endianess */
|
|
GUInt32 nGSrsFlag = CPL_LSBWORD32( WKBSRIDFLAG );
|
|
/* Apply the flag */
|
|
geomType = geomType | nGSrsFlag;
|
|
}
|
|
|
|
/* Now write the geom type which is 4 bytes */
|
|
pszHex = CPLBinaryToHex( 4, (GByte*) &geomType );
|
|
strcpy(pszTextBufCurrent, pszHex );
|
|
CPLFree ( pszHex );
|
|
pszTextBufCurrent += 8;
|
|
|
|
/* Now include SRID if provided */
|
|
if (nSRSId > 0)
|
|
{
|
|
/* Force the srsid to wkbNDR (little) endianess */
|
|
GUInt32 nGSRSId = CPL_LSBWORD32( nSRSId );
|
|
pszHex = CPLBinaryToHex( sizeof(nGSRSId),(GByte*) &nGSRSId );
|
|
strcpy(pszTextBufCurrent, pszHex );
|
|
CPLFree ( pszHex );
|
|
pszTextBufCurrent += 8;
|
|
}
|
|
|
|
/* Copy the rest of the data over - subtract
|
|
5 since we already copied 5 bytes above */
|
|
pszHex = CPLBinaryToHex( nWkbSize - 5, pabyWKB + 5 );
|
|
strcpy(pszTextBufCurrent, pszHex );
|
|
CPLFree ( pszHex );
|
|
|
|
CPLFree( pabyWKB );
|
|
|
|
return pszTextBuf;
|
|
}
|
|
|
|
/**
|
|
* \fn void OGRGeometry::segmentize(double dfMaxLength);
|
|
*
|
|
* \brief Add intermediate vertices to a geometry.
|
|
*
|
|
* This method modifies the geometry to add intermediate vertices if necessary
|
|
* so that the maximum length between 2 consecutives vertices is lower than
|
|
* dfMaxLength.
|
|
*
|
|
* @param dfMaxLength maximum length between 2 consecutives vertices.
|
|
*/
|
|
|
|
|
|
/************************************************************************/
|
|
/* importPreambuleFromWkb() */
|
|
/************************************************************************/
|
|
|
|
OGRErr OGRGeometry::importPreambuleFromWkb( unsigned char * pabyData,
|
|
int nSize,
|
|
OGRwkbByteOrder& eByteOrder,
|
|
OGRBoolean& b3D,
|
|
OGRwkbVariant eWkbVariant )
|
|
{
|
|
if( nSize < 9 && nSize != -1 )
|
|
return OGRERR_NOT_ENOUGH_DATA;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Get the byte order byte. */
|
|
/* -------------------------------------------------------------------- */
|
|
eByteOrder = DB2_V72_FIX_BYTE_ORDER((OGRwkbByteOrder) *pabyData);
|
|
if (!( eByteOrder == wkbXDR || eByteOrder == wkbNDR ))
|
|
return OGRERR_CORRUPT_DATA;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Get the geometry feature type. */
|
|
/* -------------------------------------------------------------------- */
|
|
OGRwkbGeometryType eGeometryType;
|
|
OGRErr err = OGRReadWKBGeometryType( pabyData, eWkbVariant, &eGeometryType, &b3D );
|
|
|
|
if( err != OGRERR_NONE || eGeometryType != wkbFlatten(getGeometryType()) )
|
|
return OGRERR_CORRUPT_DATA;
|
|
|
|
return -1;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* importPreambuleOfCollectionFromWkb() */
|
|
/* */
|
|
/* Utility method for OGRSimpleCurve, OGRCompoundCurve, */
|
|
/* OGRCurvePolygon and OGRGeometryCollection. */
|
|
/************************************************************************/
|
|
|
|
OGRErr OGRGeometry::importPreambuleOfCollectionFromWkb( unsigned char * pabyData,
|
|
int& nSize,
|
|
int& nDataOffset,
|
|
OGRwkbByteOrder& eByteOrder,
|
|
int nMinSubGeomSize,
|
|
int& nGeomCount,
|
|
OGRwkbVariant eWkbVariant )
|
|
{
|
|
nGeomCount = 0;
|
|
OGRBoolean b3D = FALSE;
|
|
|
|
OGRErr eErr = importPreambuleFromWkb( pabyData, nSize, eByteOrder, b3D, eWkbVariant );
|
|
if( eErr >= 0 )
|
|
return eErr;
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Clear existing Geoms. */
|
|
/* -------------------------------------------------------------------- */
|
|
empty();
|
|
|
|
if( b3D )
|
|
setCoordinateDimension(3);
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Get the sub-geometry count. */
|
|
/* -------------------------------------------------------------------- */
|
|
memcpy( &nGeomCount, pabyData + 5, 4 );
|
|
|
|
if( OGR_SWAP( eByteOrder ) )
|
|
nGeomCount = CPL_SWAP32(nGeomCount);
|
|
|
|
if (nGeomCount < 0 || nGeomCount > INT_MAX / 4)
|
|
{
|
|
nGeomCount = 0;
|
|
return OGRERR_CORRUPT_DATA;
|
|
}
|
|
|
|
/* Each ring has a minimum of nMinSubGeomSize bytes */
|
|
if (nSize != -1 && nSize - 9 < nGeomCount * nMinSubGeomSize)
|
|
{
|
|
CPLError( CE_Failure, CPLE_AppDefined,
|
|
"Length of input WKB is too small" );
|
|
nGeomCount = 0;
|
|
return OGRERR_NOT_ENOUGH_DATA;
|
|
}
|
|
|
|
nDataOffset = 9;
|
|
if( nSize != -1 )
|
|
nSize -= nDataOffset;
|
|
|
|
return -1;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* importCurveCollectionFromWkt() */
|
|
/* */
|
|
/* Utility method for OGRCompoundCurve, OGRCurvePolygon and */
|
|
/* OGRMultiCurve. */
|
|
/************************************************************************/
|
|
|
|
OGRErr OGRGeometry::importCurveCollectionFromWkt( char ** ppszInput,
|
|
int bAllowEmptyComponent,
|
|
int bAllowLineString,
|
|
int bAllowCurve,
|
|
int bAllowCompoundCurve,
|
|
OGRErr (*pfnAddCurveDirectly)(OGRGeometry* poSelf, OGRCurve* poCurve) )
|
|
|
|
{
|
|
int bHasZ = FALSE, bHasM = FALSE;
|
|
OGRErr eErr = importPreambuleFromWkt(ppszInput, &bHasZ, &bHasM);
|
|
if( eErr >= 0 )
|
|
return eErr;
|
|
|
|
if( bHasZ )
|
|
setCoordinateDimension(3);
|
|
|
|
char szToken[OGR_WKT_TOKEN_MAX];
|
|
const char *pszInput = *ppszInput;
|
|
eErr = OGRERR_NONE;
|
|
|
|
/* Skip first '(' */
|
|
pszInput = OGRWktReadToken( pszInput, szToken );
|
|
|
|
/* ==================================================================== */
|
|
/* Read each curve in turn. Note that we try to reuse the same */
|
|
/* point list buffer from curve to curve to cut down on */
|
|
/* allocate/deallocate overhead. */
|
|
/* ==================================================================== */
|
|
OGRRawPoint *paoPoints = NULL;
|
|
int nMaxPoints = 0;
|
|
double *padfZ = NULL;
|
|
|
|
do
|
|
{
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Get the first token, which should be the geometry type. */
|
|
/* -------------------------------------------------------------------- */
|
|
const char* pszInputBefore = pszInput;
|
|
pszInput = OGRWktReadToken( pszInput, szToken );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Do the import. */
|
|
/* -------------------------------------------------------------------- */
|
|
OGRCurve* poCurve = NULL;
|
|
if (EQUAL(szToken,"("))
|
|
{
|
|
OGRLineString* poLine = new OGRLineString();
|
|
poCurve = poLine;
|
|
pszInput = pszInputBefore;
|
|
eErr = poLine->importFromWKTListOnly( (char**)&pszInput, bHasZ, bHasM,
|
|
paoPoints, nMaxPoints, padfZ );
|
|
}
|
|
else if (bAllowEmptyComponent && EQUAL(szToken, "EMPTY") )
|
|
{
|
|
poCurve = new OGRLineString();
|
|
}
|
|
/* We accept LINESTRING() but this is an extension to the BNF, also */
|
|
/* accepted by PostGIS */
|
|
else if ( (bAllowLineString && EQUAL(szToken,"LINESTRING")) ||
|
|
(bAllowCurve && !EQUAL(szToken,"LINESTRING") &&
|
|
!EQUAL(szToken,"COMPOUNDCURVE") && OGR_GT_IsCurve(OGRFromOGCGeomType(szToken))) ||
|
|
(bAllowCompoundCurve && EQUAL(szToken,"COMPOUNDCURVE")) )
|
|
{
|
|
OGRGeometry* poGeom = NULL;
|
|
pszInput = pszInputBefore;
|
|
eErr = OGRGeometryFactory::createFromWkt( (char **) &pszInput,
|
|
NULL, &poGeom );
|
|
poCurve = (OGRCurve*) poGeom;
|
|
}
|
|
else
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined, "Unexpected token : %s", szToken);
|
|
eErr = OGRERR_CORRUPT_DATA;
|
|
}
|
|
|
|
if( eErr == OGRERR_NONE )
|
|
eErr = pfnAddCurveDirectly( this, poCurve );
|
|
if( eErr != OGRERR_NONE )
|
|
{
|
|
delete poCurve;
|
|
break;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* Read the delimeter following the surface. */
|
|
/* -------------------------------------------------------------------- */
|
|
pszInput = OGRWktReadToken( pszInput, szToken );
|
|
|
|
} while( szToken[0] == ',' && eErr == OGRERR_NONE );
|
|
|
|
CPLFree( paoPoints );
|
|
CPLFree( padfZ );
|
|
|
|
/* -------------------------------------------------------------------- */
|
|
/* freak if we don't get a closing bracket. */
|
|
/* -------------------------------------------------------------------- */
|
|
|
|
if( eErr != OGRERR_NONE )
|
|
return eErr;
|
|
|
|
if( szToken[0] != ')' )
|
|
return OGRERR_CORRUPT_DATA;
|
|
|
|
*ppszInput = (char *) pszInput;
|
|
return OGRERR_NONE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_Flatten() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Returns the 2D geometry type corresponding to the passed geometry type.
|
|
*
|
|
* This function is intended to work with geometry types as old-style 99-402
|
|
* extended dimension (Z) WKB types, as well as with newer SFSQL 1.2 and
|
|
* ISO SQL/MM Part 3 extended dimension (Z&M) WKB types.
|
|
*
|
|
* @param eType Input geometry type
|
|
*
|
|
* @return 2D geometry type corresponding to the passed geometry type.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRwkbGeometryType OGR_GT_Flatten( OGRwkbGeometryType eType )
|
|
{
|
|
eType = (OGRwkbGeometryType) (eType & (~wkb25DBitInternalUse));
|
|
if( eType >= 1001 && eType < 2000 ) /* ISO Z */
|
|
return (OGRwkbGeometryType) (eType - 1000);
|
|
if( eType >= 2000 && eType < 3000 ) /* ISO M */
|
|
return (OGRwkbGeometryType) (eType - 2000);
|
|
if( eType >= 3000 && eType < 4000 ) /* ISO ZM */
|
|
return (OGRwkbGeometryType) (eType - 3000);
|
|
return eType;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_HasZ() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Return if the geometry type is a 3D geometry type.
|
|
*
|
|
* @param eType Input geometry type
|
|
*
|
|
* @return TRUE if the geometry type is a 3D geometry type.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
int OGR_GT_HasZ( OGRwkbGeometryType eType )
|
|
{
|
|
if( eType & wkb25DBitInternalUse )
|
|
return TRUE;
|
|
if( eType >= 1001 && eType < 2000 )
|
|
return TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_SetZ() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Returns the 3D geometry type corresponding to the passed geometry type.
|
|
*
|
|
* @param eType Input geometry type
|
|
*
|
|
* @return 3D geometry type corresponding to the passed geometry type.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRwkbGeometryType OGR_GT_SetZ( OGRwkbGeometryType eType )
|
|
{
|
|
if( OGR_GT_HasZ(eType) || eType == wkbNone )
|
|
return eType;
|
|
if( eType >= wkbUnknown && eType <= wkbGeometryCollection )
|
|
return (OGRwkbGeometryType)(eType | wkb25DBitInternalUse);
|
|
else
|
|
return (OGRwkbGeometryType)(eType + 1000);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_SetModifier() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Returns a 2D or 3D geometry type depending on parameter.
|
|
*
|
|
* @param eType Input geometry type
|
|
* @param bHasZ TRUE if the output geometry type must be 3D.
|
|
* @param bHasM Must be set to FALSE currently.
|
|
*
|
|
* @return Output geometry type.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRwkbGeometryType OGR_GT_SetModifier( OGRwkbGeometryType eType, int bHasZ,
|
|
CPL_UNUSED int bHasM )
|
|
{
|
|
if( bHasZ )
|
|
return OGR_GT_SetZ(eType);
|
|
else
|
|
return wkbFlatten(eType);
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_IsSubClassOf) */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Returns if a type is a subclass of another one
|
|
*
|
|
* @param eType Type.
|
|
* @param eSuperType Super type
|
|
*
|
|
* @return TRUE if eType is a subclass of eSuperType.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
int OGR_GT_IsSubClassOf( OGRwkbGeometryType eType,
|
|
OGRwkbGeometryType eSuperType )
|
|
{
|
|
eSuperType = wkbFlatten(eSuperType);
|
|
eType = wkbFlatten(eType);
|
|
|
|
if( eSuperType == eType || eSuperType == wkbUnknown )
|
|
return TRUE;
|
|
|
|
if( eSuperType == wkbGeometryCollection )
|
|
return eType == wkbMultiPoint || eType == wkbMultiLineString ||
|
|
eType == wkbMultiPolygon || eType == wkbMultiCurve ||
|
|
eType == wkbMultiSurface;
|
|
|
|
if( eSuperType == wkbCurvePolygon )
|
|
return eType == wkbPolygon;
|
|
|
|
if( eSuperType == wkbMultiCurve )
|
|
return eType == wkbMultiLineString;
|
|
|
|
if( eSuperType == wkbMultiSurface )
|
|
return eType == wkbMultiPolygon;
|
|
|
|
if( eSuperType == wkbCurve )
|
|
return eType == wkbLineString || eType == wkbCircularString ||
|
|
eType == wkbCompoundCurve;
|
|
|
|
if( eSuperType == wkbSurface )
|
|
return eType == wkbCurvePolygon || eType == wkbPolygon;
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_GetCollection() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Returns the collection type that can contain the passed geometry type
|
|
*
|
|
* Handled conversions are : wkbNone->wkbNone, wkbPoint -> wkbMultiPoint,
|
|
* wkbLineString->wkbMultiLineString, wkbPolygon->wkbMultiPolygon,
|
|
* wkbCircularString->wkbMultiCurve, wkbCompoundCurve->wkbMultiCurve,
|
|
* wkbCurvePolygon->wkbMultiSurface.
|
|
* In other cases, wkbUnknown is returned
|
|
*
|
|
* Passed Z flag is preserved.
|
|
*
|
|
* @param eType Input geometry type
|
|
*
|
|
* @return the collection type that can contain the passed geometry type or wkbUnknown
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRwkbGeometryType OGR_GT_GetCollection( OGRwkbGeometryType eType )
|
|
{
|
|
if( eType == wkbNone )
|
|
return wkbNone;
|
|
OGRwkbGeometryType eFGType = wkbFlatten(eType);
|
|
if( eFGType == wkbPoint )
|
|
eType = wkbMultiPoint;
|
|
|
|
else if( eFGType == wkbLineString )
|
|
eType = wkbMultiLineString;
|
|
|
|
else if( eFGType == wkbPolygon )
|
|
eType = wkbMultiPolygon;
|
|
|
|
else if( OGR_GT_IsCurve(eFGType) )
|
|
eType = wkbMultiCurve;
|
|
|
|
else if( OGR_GT_IsSurface(eFGType) )
|
|
eType = wkbMultiSurface;
|
|
|
|
else
|
|
return wkbUnknown;
|
|
|
|
if( wkbHasZ(eType) )
|
|
eType = wkbSetZ(eType);
|
|
|
|
return eType;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_GetCurve() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Returns the curve geometry type that can contain the passed geometry type
|
|
*
|
|
* Handled conversions are : wkbPolygon -> wkbCurvePolygon,
|
|
* wkbLineString->wkbCompoundCurve, wkbMultiPolygon->wkbMultiSurface
|
|
* and wkbMultiLineString->wkbMultiCurve.
|
|
* In other cases, the passed geometry is returned.
|
|
*
|
|
* Passed Z flag is preserved.
|
|
*
|
|
* @param eType Input geometry type
|
|
*
|
|
* @return the curve type that can contain the passed geometry type
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRwkbGeometryType OGR_GT_GetCurve( OGRwkbGeometryType eType )
|
|
{
|
|
OGRwkbGeometryType eFGType = wkbFlatten(eType);
|
|
|
|
if( eFGType == wkbLineString )
|
|
eType = wkbCompoundCurve;
|
|
|
|
else if( eFGType == wkbPolygon )
|
|
eType = wkbCurvePolygon;
|
|
|
|
else if( eFGType == wkbMultiLineString )
|
|
eType = wkbMultiCurve;
|
|
|
|
else if( eFGType == wkbMultiPolygon )
|
|
eType = wkbMultiSurface;
|
|
|
|
if( wkbHasZ(eType) )
|
|
eType = wkbSetZ(eType);
|
|
|
|
return eType;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_GetLinear() */
|
|
/************************************************************************/
|
|
/**
|
|
* \brief Returns the non-curve geometry type that can contain the passed geometry type
|
|
*
|
|
* Handled conversions are : wkbCurvePolygon -> wkbPolygon,
|
|
* wkbCircularString->wkbLineString, wkbCompoundCurve->wkbLineString,
|
|
* wkbMultiSurface->wkbMultiPolygon and wkbMultiCurve->wkbMultiLineString.
|
|
* In other cases, the passed geometry is returned.
|
|
*
|
|
* Passed Z flag is preserved.
|
|
*
|
|
* @param eType Input geometry type
|
|
*
|
|
* @return the non-curve type that can contain the passed geometry type
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
OGRwkbGeometryType OGR_GT_GetLinear( OGRwkbGeometryType eType )
|
|
{
|
|
OGRwkbGeometryType eFGType = wkbFlatten(eType);
|
|
|
|
if( OGR_GT_IsCurve(eFGType) )
|
|
eType = wkbLineString;
|
|
|
|
else if( OGR_GT_IsSurface(eFGType) )
|
|
eType = wkbPolygon;
|
|
|
|
else if( eFGType == wkbMultiCurve )
|
|
eType = wkbMultiLineString;
|
|
|
|
else if( eFGType == wkbMultiSurface )
|
|
eType = wkbMultiPolygon;
|
|
|
|
if( wkbHasZ(eType) )
|
|
eType = wkbSetZ(eType);
|
|
|
|
return eType;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_IsCurve() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Return if a geometry type is an instance of Curve
|
|
*
|
|
* Such geometry type are wkbLineString, wkbCircularString, wkbCompoundCurve
|
|
* and their 3D variant.
|
|
*
|
|
* @param eGeomType the geometry type
|
|
* @return TRUE if the geometry type is an instance of Curve
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
int OGR_GT_IsCurve( OGRwkbGeometryType eGeomType )
|
|
{
|
|
return OGR_GT_IsSubClassOf( eGeomType, wkbCurve );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_IsSurface() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Return if a geometry type is an instance of Surface
|
|
*
|
|
* Such geometry type are wkbCurvePolygon and wkbPolygon
|
|
* and their 3D variant.
|
|
*
|
|
* @param eGeomType the geometry type
|
|
* @return TRUE if the geometry type is an instance of Surface
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
int OGR_GT_IsSurface( OGRwkbGeometryType eGeomType )
|
|
{
|
|
return OGR_GT_IsSubClassOf( eGeomType, wkbSurface );
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* OGR_GT_IsNonLinear() */
|
|
/************************************************************************/
|
|
|
|
/**
|
|
* \brief Return if a geometry type is a non-linear geometry type.
|
|
*
|
|
* Such geometry type are wkbCircularString, wkbCompoundCurve, wkbCurvePolygon,
|
|
* wkbMultiCurve, wkbMultiSurface and their 3D variant.
|
|
*
|
|
* @param eGeomType the geometry type
|
|
* @return TRUE if the geometry type is a non-linear geometry type.
|
|
*
|
|
* @since GDAL 2.0
|
|
*/
|
|
|
|
int OGR_GT_IsNonLinear( OGRwkbGeometryType eGeomType )
|
|
{
|
|
OGRwkbGeometryType eFGeomType = wkbFlatten(eGeomType);
|
|
return eFGeomType == wkbCircularString || eFGeomType == wkbCompoundCurve ||
|
|
eFGeomType == wkbCurvePolygon || eFGeomType == wkbMultiCurve ||
|
|
eFGeomType == wkbMultiSurface;
|
|
}
|
|
|
|
/************************************************************************/
|
|
/* CastToError() */
|
|
/************************************************************************/
|
|
|
|
OGRGeometry* OGRGeometry::CastToError(OGRGeometry* poGeom)
|
|
{
|
|
CPLError(CE_Failure, CPLE_AppDefined,
|
|
"%s found. Conversion impossible", poGeom->getGeometryName());
|
|
delete poGeom;
|
|
return NULL;
|
|
}
|