www.pudn.com > mitab.rar > ogrlayer.cpp
/******************************************************************************
* $Id: ogrlayer.cpp,v 1.24 2005/02/22 12:47:47 fwarmerdam Exp $
*
* Project: OpenGIS Simple Features Reference Implementation
* Purpose: The generic portions of the OGRSFLayer class.
* Author: Frank Warmerdam, warmerdam@pobox.com
*
******************************************************************************
* Copyright (c) 1999, Les Technologies SoftMap Inc.
*
* 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.
******************************************************************************
*
* $Log: ogrlayer.cpp,v $
* Revision 1.24 2005/02/22 12:47:47 fwarmerdam
* use haveGEOS() test, instead of HAVE_GEOS
*
* Revision 1.23 2005/02/22 12:42:18 fwarmerdam
* Added OGRLayer SetSpatialFilter(), and GetSpatialFilter() methods as well
* as code to help implement fast bounding box spatial tests.
*
* Revision 1.22 2005/02/02 20:00:29 fwarmerdam
* added SetNextByIndex support
*
* Revision 1.21 2005/01/03 22:17:00 fwarmerdam
* added OGRLayer::SetSpatialFilterRect()
*
* Revision 1.20 2004/08/17 15:41:31 warmerda
* dont compute extents for wkbNone layers
*
* Revision 1.19 2003/10/09 15:30:07 warmerda
* added OGRLayer::DeleteFeature() support
*
* Revision 1.18 2003/05/28 19:18:04 warmerda
* fixup argument names for docs
*
* Revision 1.17 2003/05/21 04:54:29 warmerda
* avoid warnings about unused formal parameters and possibly uninit variables
*
* Revision 1.16 2003/04/22 19:36:04 warmerda
* Added SyncToDisk
*
* Revision 1.15 2003/03/19 20:35:05 warmerda
* added reference counting support
*
* Revision 1.14 2003/03/04 17:45:16 warmerda
* Ensure m_poAttrIndex is initialized.
*
* Revision 1.13 2003/03/04 05:48:05 warmerda
* added index initialize support
*
* Revision 1.12 2002/09/26 18:16:19 warmerda
* added C entry points
*
* Revision 1.11 2002/03/27 21:25:25 warmerda
* added working default implementation of GetFeature()
*
* Revision 1.10 2001/11/15 21:19:21 warmerda
* added transaction semantics
*
* Revision 1.9 2001/10/02 14:16:21 warmerda
* fix handling of case where a query is being cleared
*
* Revision 1.8 2001/07/19 18:26:42 warmerda
* expand tabs
*
* Revision 1.7 2001/07/18 04:55:16 warmerda
* added CPL_CSVID
*
* Revision 1.6 2001/06/19 15:53:49 warmerda
* Added attribute query support
*
* Revision 1.5 2001/03/15 04:01:43 danmo
* Added OGRLayer::GetExtent()
*
* Revision 1.4 1999/11/04 21:10:30 warmerda
* Added CreateField() method.
*
* Revision 1.3 1999/07/27 00:51:39 warmerda
* added GetInfo(), fixed args for other methods
*
* Revision 1.2 1999/07/26 13:59:06 warmerda
* added feature writing api
*
* Revision 1.1 1999/07/08 20:05:13 warmerda
* New
*
*/
#include "ogrsf_frmts.h"
#include "ogr_api.h"
#include "ogr_p.h"
#include "ogr_attrind.h"
CPL_CVSID("$Id: ogrlayer.cpp,v 1.24 2005/02/22 12:47:47 fwarmerdam Exp $");
/************************************************************************/
/* OGRLayer() */
/************************************************************************/
OGRLayer::OGRLayer()
{
m_poStyleTable = NULL;
m_poAttrQuery = NULL;
m_poAttrIndex = NULL;
m_nRefCount = 0;
m_nFeaturesRead = 0;
m_poFilterGeom = NULL;
m_bFilterIsEnvelope = FALSE;
}
/************************************************************************/
/* ~OGRLayer() */
/************************************************************************/
OGRLayer::~OGRLayer()
{
if( m_poAttrIndex != NULL )
{
delete m_poAttrIndex;
m_poAttrIndex = NULL;
}
if( m_poAttrQuery != NULL )
{
delete m_poAttrQuery;
m_poAttrQuery = NULL;
}
if( m_poFilterGeom )
{
delete m_poFilterGeom;
m_poFilterGeom = NULL;
}
}
/************************************************************************/
/* Reference() */
/************************************************************************/
int OGRLayer::Reference()
{
return ++m_nRefCount;
}
/************************************************************************/
/* OGR_L_Reference() */
/************************************************************************/
int OGR_L_Reference( OGRLayerH hLayer )
{
return ((OGRLayer *) hLayer)->Reference();
}
/************************************************************************/
/* Dereference() */
/************************************************************************/
int OGRLayer::Dereference()
{
return --m_nRefCount;
}
/************************************************************************/
/* OGR_L_Dereference() */
/************************************************************************/
int OGR_L_Dereference( OGRLayerH hLayer )
{
return ((OGRLayer *) hLayer)->Dereference();
}
/************************************************************************/
/* GetRefCount() */
/************************************************************************/
int OGRLayer::GetRefCount() const
{
return m_nRefCount;
}
/************************************************************************/
/* OGR_L_GetRefCount() */
/************************************************************************/
int OGR_L_GetRefCount( OGRLayerH hLayer )
{
return ((OGRLayer *) hLayer)->GetRefCount();
}
/************************************************************************/
/* GetFeatureCount() */
/************************************************************************/
int OGRLayer::GetFeatureCount( int bForce )
{
OGRFeature *poFeature;
int nFeatureCount = 0;
if( !bForce )
return -1;
ResetReading();
while( (poFeature = GetNextFeature()) != NULL )
{
nFeatureCount++;
delete poFeature;
}
ResetReading();
return nFeatureCount;
}
/************************************************************************/
/* OGR_L_GetFeatureCount() */
/************************************************************************/
int OGR_L_GetFeatureCount( OGRLayerH hLayer, int bForce )
{
return ((OGRLayer *) hLayer)->GetFeatureCount(bForce);
}
/************************************************************************/
/* GetExtent() */
/************************************************************************/
OGRErr OGRLayer::GetExtent(OGREnvelope *psExtent, int bForce )
{
OGRFeature *poFeature;
OGREnvelope oEnv;
GBool bExtentSet = FALSE;
/* -------------------------------------------------------------------- */
/* If this layer has a none geometry type, then we can */
/* reasonably assume there are not extents available. */
/* -------------------------------------------------------------------- */
if( GetLayerDefn()->GetGeomType() == wkbNone )
{
psExtent->MinX = 0.0;
psExtent->MaxX = 0.0;
psExtent->MinY = 0.0;
psExtent->MaxY = 0.0;
return OGRERR_FAILURE;
}
/* -------------------------------------------------------------------- */
/* If not forced, we should avoid having to scan all the */
/* features and just return a failure. */
/* -------------------------------------------------------------------- */
if( !bForce )
return OGRERR_FAILURE;
/* -------------------------------------------------------------------- */
/* OK, we hate to do this, but go ahead and read through all */
/* the features to collect geometries and build extents. */
/* -------------------------------------------------------------------- */
ResetReading();
while( (poFeature = GetNextFeature()) != NULL )
{
OGRGeometry *poGeom = poFeature->GetGeometryRef();
if (poGeom && !bExtentSet)
{
poGeom->getEnvelope(psExtent);
bExtentSet = TRUE;
}
else if (poGeom)
{
poGeom->getEnvelope(&oEnv);
if (oEnv.MinX < psExtent->MinX)
psExtent->MinX = oEnv.MinX;
if (oEnv.MinY < psExtent->MinY)
psExtent->MinY = oEnv.MinY;
if (oEnv.MaxX > psExtent->MaxX)
psExtent->MaxX = oEnv.MaxX;
if (oEnv.MaxY > psExtent->MaxY)
psExtent->MaxY = oEnv.MaxY;
}
delete poFeature;
}
ResetReading();
return (bExtentSet ? OGRERR_NONE : OGRERR_FAILURE);
}
/************************************************************************/
/* OGR_L_GetExtent() */
/************************************************************************/
OGRErr OGR_L_GetExtent( OGRLayerH hLayer, OGREnvelope *psExtent, int bForce )
{
return ((OGRLayer *) hLayer)->GetExtent( psExtent, bForce );
}
/************************************************************************/
/* SetAttributeFilter() */
/************************************************************************/
OGRErr OGRLayer::SetAttributeFilter( const char *pszQuery )
{
/* -------------------------------------------------------------------- */
/* Are we just clearing any existing query? */
/* -------------------------------------------------------------------- */
if( pszQuery == NULL || strlen(pszQuery) == 0 )
{
if( m_poAttrQuery )
{
delete m_poAttrQuery;
m_poAttrQuery = NULL;
ResetReading();
}
return OGRERR_NONE;
}
/* -------------------------------------------------------------------- */
/* Or are we installing a new query? */
/* -------------------------------------------------------------------- */
OGRErr eErr;
if( !m_poAttrQuery )
m_poAttrQuery = new OGRFeatureQuery();
eErr = m_poAttrQuery->Compile( GetLayerDefn(), pszQuery );
if( eErr != OGRERR_NONE )
{
delete m_poAttrQuery;
m_poAttrQuery = NULL;
}
ResetReading();
return eErr;
}
/************************************************************************/
/* OGR_L_SetAttributeFilter() */
/************************************************************************/
OGRErr OGR_L_SetAttributeFilter( OGRLayerH hLayer, const char *pszQuery )
{
return ((OGRLayer *) hLayer)->SetAttributeFilter( pszQuery );
}
/************************************************************************/
/* GetFeature() */
/************************************************************************/
OGRFeature *OGRLayer::GetFeature( long nFID )
{
OGRFeature *poFeature;
ResetReading();
while( (poFeature = GetNextFeature()) != NULL )
{
if( poFeature->GetFID() == nFID )
return poFeature;
else
delete poFeature;
}
return NULL;
}
/************************************************************************/
/* OGR_L_GetFeature() */
/************************************************************************/
OGRFeatureH OGR_L_GetFeature( OGRLayerH hLayer, long nFeatureId )
{
return (OGRFeatureH) ((OGRLayer *)hLayer)->GetFeature( nFeatureId );
}
/************************************************************************/
/* SetNextByIndex() */
/************************************************************************/
OGRErr OGRLayer::SetNextByIndex( long nIndex )
{
OGRFeature *poFeature;
ResetReading();
while( nIndex-- > 0 )
{
poFeature = GetNextFeature();
if( poFeature == NULL )
return OGRERR_FAILURE;
delete poFeature;
}
return OGRERR_NONE;
}
/************************************************************************/
/* OGR_L_SetNextByIndex() */
/************************************************************************/
OGRErr OGR_L_SetNextByIndex( OGRLayerH hLayer, long nIndex )
{
return ((OGRLayer *)hLayer)->SetNextByIndex( nIndex );
}
/************************************************************************/
/* OGR_L_GetNextFeature() */
/************************************************************************/
OGRFeatureH OGR_L_GetNextFeature( OGRLayerH hLayer )
{
return (OGRFeatureH) ((OGRLayer *)hLayer)->GetNextFeature();
}
/************************************************************************/
/* SetFeature() */
/************************************************************************/
OGRErr OGRLayer::SetFeature( OGRFeature * )
{
return OGRERR_UNSUPPORTED_OPERATION;
}
/************************************************************************/
/* OGR_L_SetFeature() */
/************************************************************************/
OGRErr OGR_L_SetFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
{
return ((OGRLayer *)hLayer)->SetFeature( (OGRFeature *) hFeat );
}
/************************************************************************/
/* CreateFeature() */
/************************************************************************/
OGRErr OGRLayer::CreateFeature( OGRFeature * )
{
return OGRERR_UNSUPPORTED_OPERATION;
}
/************************************************************************/
/* OGR_L_CreateFeature() */
/************************************************************************/
OGRErr OGR_L_CreateFeature( OGRLayerH hLayer, OGRFeatureH hFeat )
{
return ((OGRLayer *) hLayer)->CreateFeature( (OGRFeature *) hFeat );
}
/************************************************************************/
/* GetInfo() */
/************************************************************************/
const char *OGRLayer::GetInfo( const char * pszTag )
{
(void) pszTag;
return NULL;
}
/************************************************************************/
/* CreateField() */
/************************************************************************/
OGRErr OGRLayer::CreateField( OGRFieldDefn * poField, int bApproxOK )
{
(void) poField;
(void) bApproxOK;
CPLError( CE_Failure, CPLE_NotSupported,
"CreateField() not supported by this layer.\n" );
return OGRERR_UNSUPPORTED_OPERATION;
}
/************************************************************************/
/* OGR_L_CreateField() */
/************************************************************************/
OGRErr OGR_L_CreateField( OGRLayerH hLayer, OGRFieldDefnH hField,
int bApproxOK )
{
return ((OGRLayer *) hLayer)->CreateField( (OGRFieldDefn *) hField,
bApproxOK );
}
/************************************************************************/
/* StartTransaction() */
/************************************************************************/
OGRErr OGRLayer::StartTransaction()
{
return OGRERR_NONE;
}
/************************************************************************/
/* OGR_L_StartTransaction() */
/************************************************************************/
OGRErr OGR_L_StartTransaction( OGRLayerH hLayer )
{
return ((OGRLayer *)hLayer)->StartTransaction();
}
/************************************************************************/
/* CommitTransaction() */
/************************************************************************/
OGRErr OGRLayer::CommitTransaction()
{
return OGRERR_NONE;
}
/************************************************************************/
/* OGR_L_CommitTransaction() */
/************************************************************************/
OGRErr OGR_L_CommitTransaction( OGRLayerH hLayer )
{
return ((OGRLayer *)hLayer)->CommitTransaction();
}
/************************************************************************/
/* RollbackTransaction() */
/************************************************************************/
OGRErr OGRLayer::RollbackTransaction()
{
return OGRERR_UNSUPPORTED_OPERATION;
}
/************************************************************************/
/* OGR_L_RollbackTransaction() */
/************************************************************************/
OGRErr OGR_L_RollbackTransaction( OGRLayerH hLayer )
{
return ((OGRLayer *)hLayer)->RollbackTransaction();
}
/************************************************************************/
/* OGR_L_GetLayerDefn() */
/************************************************************************/
OGRFeatureDefnH OGR_L_GetLayerDefn( OGRLayerH hLayer )
{
return (OGRFeatureDefnH) ((OGRLayer *)hLayer)->GetLayerDefn();
}
/************************************************************************/
/* OGR_L_GetSpatialRef() */
/************************************************************************/
OGRSpatialReferenceH OGR_L_GetSpatialRef( OGRLayerH hLayer )
{
return (OGRSpatialReferenceH) ((OGRLayer *) hLayer)->GetSpatialRef();
}
/************************************************************************/
/* OGR_L_TestCapability() */
/************************************************************************/
int OGR_L_TestCapability( OGRLayerH hLayer, const char *pszCap )
{
return ((OGRLayer *) hLayer)->TestCapability( pszCap );
}
/************************************************************************/
/* GetSpatialFilter() */
/************************************************************************/
OGRGeometry *OGRLayer::GetSpatialFilter()
{
return m_poFilterGeom;
}
/************************************************************************/
/* OGR_L_GetSpatialFilter() */
/************************************************************************/
OGRGeometryH OGR_L_GetSpatialFilter( OGRLayerH hLayer )
{
return (OGRGeometryH) ((OGRLayer *) hLayer)->GetSpatialFilter();
}
/************************************************************************/
/* SetSpatialFilter() */
/************************************************************************/
void OGRLayer::SetSpatialFilter( OGRGeometry * poGeomIn )
{
if( InstallFilter( poGeomIn ) )
ResetReading();
}
/************************************************************************/
/* OGR_L_SetSpatialFilter() */
/************************************************************************/
void OGR_L_SetSpatialFilter( OGRLayerH hLayer, OGRGeometryH hGeom )
{
((OGRLayer *) hLayer)->SetSpatialFilter( (OGRGeometry *) hGeom );
}
/************************************************************************/
/* SetSpatialFilterRect() */
/************************************************************************/
void OGRLayer::SetSpatialFilterRect( double dfMinX, double dfMinY,
double dfMaxX, double dfMaxY )
{
OGRLinearRing oRing;
OGRPolygon oPoly;
oRing.addPoint( dfMinX, dfMinY );
oRing.addPoint( dfMinX, dfMaxY );
oRing.addPoint( dfMaxX, dfMaxY );
oRing.addPoint( dfMaxX, dfMinY );
oRing.addPoint( dfMinX, dfMinY );
oPoly.addRing( &oRing );
SetSpatialFilter( &oPoly );
}
/************************************************************************/
/* OGR_L_SetSpatialFilterRect() */
/************************************************************************/
void OGR_L_SetSpatialFilterRect( OGRLayerH hLayer,
double dfMinX, double dfMinY,
double dfMaxX, double dfMaxY )
{
((OGRLayer *) hLayer)->SetSpatialFilterRect( dfMinX, dfMinY,
dfMaxX, dfMaxY );
}
/************************************************************************/
/* InstallFilter() */
/* */
/* This method is only intended to be used from within */
/* drivers, normally from the SetSpatialFilter() method. */
/* It installs a filter, and also tests it to see if it is */
/* rectangular. If so, it this is kept track of alongside the */
/* filter geometry itself so we can do cheaper comparisons in */
/* the FilterGeometry() call. */
/* */
/* Returns TRUE if the newly installed filter differs in some */
/* way from the current one. */
/************************************************************************/
int OGRLayer::InstallFilter( OGRGeometry * poFilter )
{
if( m_poFilterGeom == NULL && poFilter == NULL )
return FALSE;
/* -------------------------------------------------------------------- */
/* Replace the existing filter. */
/* -------------------------------------------------------------------- */
if( m_poFilterGeom != NULL )
{
delete m_poFilterGeom;
m_poFilterGeom = NULL;
}
if( poFilter != NULL )
m_poFilterGeom = poFilter->clone();
m_bFilterIsEnvelope = FALSE;
if( m_poFilterGeom == NULL )
return TRUE;
if( m_poFilterGeom != NULL )
m_poFilterGeom->getEnvelope( &m_sFilterEnvelope );
/* -------------------------------------------------------------------- */
/* Now try to determine if the filter is really a rectangle. */
/* -------------------------------------------------------------------- */
if( wkbFlatten(m_poFilterGeom->getGeometryType()) != wkbPolygon )
return TRUE;
OGRPolygon *poPoly = (OGRPolygon *) m_poFilterGeom;
if( poPoly->getNumInteriorRings() != 0 )
return TRUE;
OGRLinearRing *poRing = poPoly->getExteriorRing();
if( poRing->getNumPoints() > 5 || poRing->getNumPoints() < 4 )
return TRUE;
// If the ring has 5 points, the last should be the first.
if( poRing->getNumPoints() == 5
&& ( poRing->getX(0) != poRing->getX(4)
|| poRing->getY(0) != poRing->getY(4) ) )
return TRUE;
// Polygon with first segment in "y" direction.
if( poRing->getX(0) == poRing->getX(1)
&& poRing->getY(1) == poRing->getY(2)
&& poRing->getX(2) == poRing->getX(3)
&& poRing->getY(3) == poRing->getY(0) )
m_bFilterIsEnvelope = TRUE;
// Polygon with first segment in "x" direction.
if( poRing->getY(0) == poRing->getY(1)
&& poRing->getX(1) == poRing->getX(2)
&& poRing->getY(2) == poRing->getY(3)
&& poRing->getX(3) == poRing->getX(0) )
m_bFilterIsEnvelope = TRUE;
return TRUE;
}
/************************************************************************/
/* FilterGeometry() */
/* */
/* Compare the passed in geometry to the currently installed */
/* filter. Optimize for case where filter is just an */
/* envelope. */
/************************************************************************/
int OGRLayer::FilterGeometry( OGRGeometry *poGeometry )
{
/* -------------------------------------------------------------------- */
/* In trivial cases of new filter or target geometry, we accept */
/* an intersection. No geometry is taken to mean "the whole */
/* world". */
/* -------------------------------------------------------------------- */
if( m_poFilterGeom == NULL )
return TRUE;
if( poGeometry == NULL )
return TRUE;
/* -------------------------------------------------------------------- */
/* Compute the target geometry envelope, and if there is no */
/* intersection between the envelopes we are sure not to have */
/* any intersection. */
/* -------------------------------------------------------------------- */
OGREnvelope sGeomEnv;
poGeometry->getEnvelope( &sGeomEnv );
if( sGeomEnv.MaxX < m_sFilterEnvelope.MinX
|| sGeomEnv.MaxY < m_sFilterEnvelope.MinY
|| m_sFilterEnvelope.MaxX < sGeomEnv.MinX
|| m_sFilterEnvelope.MaxY < sGeomEnv.MinY )
return FALSE;
/* -------------------------------------------------------------------- */
/* Fallback to full intersect test (using GEOS) if we still */
/* don't know for sure. */
/* -------------------------------------------------------------------- */
if( m_bFilterIsEnvelope )
return TRUE;
else
{
if( OGRGeometryFactory::haveGEOS() )
return m_poFilterGeom->Intersects( poGeometry );
else
return TRUE;
}
}
/************************************************************************/
/* OGR_L_ResetReading() */
/************************************************************************/
void OGR_L_ResetReading( OGRLayerH hLayer )
{
((OGRLayer *) hLayer)->ResetReading();
}
/************************************************************************/
/* InitializeIndexSupport() */
/* */
/* This is only intended to be called by driver layer */
/* implementations but we don't make it protected so that the */
/* datasources can do it too if that is more appropriate. */
/************************************************************************/
OGRErr OGRLayer::InitializeIndexSupport( const char *pszFilename )
{
OGRErr eErr;
m_poAttrIndex = OGRCreateDefaultLayerIndex();
eErr = m_poAttrIndex->Initialize( pszFilename, this );
if( eErr != OGRERR_NONE )
{
delete m_poAttrIndex;
m_poAttrIndex = NULL;
}
return eErr;
}
/************************************************************************/
/* SyncToDisk() */
/************************************************************************/
OGRErr OGRLayer::SyncToDisk()
{
return OGRERR_NONE;
}
/************************************************************************/
/* OGR_L_SyncToDisk() */
/************************************************************************/
OGRErr OGR_L_SyncToDisk( OGRLayerH hDS )
{
return ((OGRLayer *) hDS)->SyncToDisk();
}
/************************************************************************/
/* DeleteFeature() */
/************************************************************************/
OGRErr OGRLayer::DeleteFeature( long nFID )
{
return OGRERR_UNSUPPORTED_OPERATION;
}
/************************************************************************/
/* OGR_L_DeleteFeature() */
/************************************************************************/
OGRErr OGR_L_DeleteFeature( OGRLayerH hDS, long nFID )
{
return ((OGRLayer *) hDS)->DeleteFeature( nFID );
}
/************************************************************************/
/* GetFeaturesRead() */
/************************************************************************/
GIntBig OGRLayer::GetFeaturesRead()
{
return m_nFeaturesRead;
}
/************************************************************************/
/* OGR_L_GetFeaturesRead() */
/************************************************************************/
GIntBig OGR_L_GetFeaturesRead( OGRLayerH hLayer )
{
return ((OGRLayer *) hLayer)->GetFeaturesRead();
}