📄 ogrshapelayer.cpp
字号:
/****************************************************************************** * $Id: ogrshapelayer.cpp,v 1.34 2006/09/21 21:04:42 fwarmerdam Exp $ * * Project: OpenGIS Simple Features Reference Implementation * Purpose: Implements OGRShapeLayer 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: ogrshapelayer.cpp,v $ * Revision 1.34 2006/09/21 21:04:42 fwarmerdam * Don't put out "normalization" messages unless something is changing. * * Revision 1.33 2006/08/28 15:17:57 mloskot * Added comment about NULL values passed to SetGeometry* functions. Added assert to GetNextFeature() of shape driver. * * Revision 1.32 2006/08/28 14:27:51 mloskot * Added additional tests to ogrshapelayer.cpp supplementary to my last commit. * * Revision 1.31 2006/07/26 11:08:06 mloskot * Fixed Bug 1250. Thanks to Bart van den Eijnden for reporting it. * * Revision 1.30 2006/06/21 20:43:02 fwarmerdam * support datasets without dbf: bug 1211 * * Revision 1.29 2006/06/16 22:52:18 fwarmerdam * Added logic to assign spatial reference to geometries per email on * gdal-dev from Cho Hyun-Kee. * * Revision 1.28 2006/04/10 17:00:35 fwarmerdam * Report ability to delete features in TestCapability. * * Revision 1.27 2006/04/02 18:46:54 fwarmerdam * updated date support * * Revision 1.26 2006/02/19 21:42:05 mloskot * [WCE] Include wce_errno.h - a specific errno.h version for Windows CE * * Revision 1.25 2006/02/15 04:26:55 fwarmerdam * added date support * * Revision 1.24 2006/01/10 16:40:19 fwarmerdam * Free panRecordsToDelete. * * Revision 1.23 2006/01/10 16:37:57 fwarmerdam * implemented REPACK support * * Revision 1.22 2006/01/05 02:15:39 fwarmerdam * implement DeleteFeature support * * Revision 1.21 2005/09/21 00:53:20 fwarmerdam * fixup OGRFeatureDefn and OGRSpatialReference refcount handling * * Revision 1.20 2005/09/10 22:32:34 fwarmerdam * Make GetNextShape() more bulletproof if SHPReadOGRFeature() fails. * * Revision 1.19 2005/02/22 12:51:56 fwarmerdam * use OGRLayer base spatial filter support * * Revision 1.18 2005/02/02 20:01:02 fwarmerdam * added SetNextByIndex support * * Revision 1.17 2005/01/04 03:43:41 fwarmerdam * added support for creating and destroying spatial indexes * * Revision 1.16 2005/01/03 22:26:21 fwarmerdam * updated to use spatial indexing * * Revision 1.15 2003/05/21 04:03:54 warmerda * expand tabs * * Revision 1.14 2003/04/21 19:03:20 warmerda * added SyncToDisk support * * Revision 1.13 2003/04/15 20:45:54 warmerda * Added code to update the feature count in CreateFeature(). * * Revision 1.12 2003/03/05 05:09:41 warmerda * initialize panMatchingFIDs * * Revision 1.11 2003/03/04 05:49:05 warmerda * added attribute indexing support * * Revision 1.10 2002/10/09 14:13:40 warmerda * ensure width is at least 1 * * Revision 1.9 2002/04/05 19:59:37 warmerda * Output file was getting different geometries in some cases. * * Revision 1.8 2002/03/27 21:04:38 warmerda * Added support for reading, and creating lone .dbf files for wkbNone geometry * layers. Added support for creating a single .shp file instead of a directory * if a path ending in .shp is passed to the data source create method. * * Revision 1.7 2001/09/04 15:35:14 warmerda * add support for deferring geometry type selection till first feature * * Revision 1.6 2001/08/21 21:44:27 warmerda * fixed count logic if attribute query in play * * Revision 1.5 2001/07/18 04:55:16 warmerda * added CPL_CSVID * * Revision 1.4 2001/06/19 15:50:23 warmerda * added feature attribute query support * * Revision 1.3 2001/03/16 22:16:10 warmerda * added support for ESRI .prj files * * Revision 1.2 2001/03/15 04:21:50 danmo * Added GetExtent() * * Revision 1.1 1999/11/04 21:16:11 warmerda * New * */#include "ogrshape.h"#include "cpl_conv.h"#include "cpl_string.h"#if defined(_WIN32_WCE)# include <wce_errno.h>#endifCPL_CVSID("$Id: ogrshapelayer.cpp,v 1.34 2006/09/21 21:04:42 fwarmerdam Exp $");/************************************************************************//* OGRShapeLayer() *//************************************************************************/OGRShapeLayer::OGRShapeLayer( const char * pszName, SHPHandle hSHPIn, DBFHandle hDBFIn, OGRSpatialReference *poSRSIn, int bUpdate, OGRwkbGeometryType eReqType ){ poSRS = poSRSIn; pszFullName = CPLStrdup(pszName); hSHP = hSHPIn; hDBF = hDBFIn; bUpdateAccess = bUpdate; iNextShapeId = 0; panMatchingFIDs = NULL; bCheckedForQIX = FALSE; fpQIX = NULL; bHeaderDirty = FALSE; if( hSHP != NULL ) nTotalShapeCount = hSHP->nRecords; else nTotalShapeCount = hDBF->nRecords; poFeatureDefn = SHPReadOGRFeatureDefn( CPLGetBasename(pszName), hSHP, hDBF ); eRequestedGeomType = eReqType;}/************************************************************************//* ~OGRShapeLayer() *//************************************************************************/OGRShapeLayer::~OGRShapeLayer(){ if( m_nFeaturesRead > 0 && poFeatureDefn != NULL ) { CPLDebug( "Shape", "%d features read on layer '%s'.", (int) m_nFeaturesRead, poFeatureDefn->GetName() ); } CPLFree( panMatchingFIDs ); panMatchingFIDs = NULL; CPLFree( pszFullName ); poFeatureDefn->Release(); poSRS->Release(); if( hDBF != NULL ) DBFClose( hDBF ); if( hSHP != NULL ) SHPClose( hSHP ); if( fpQIX != NULL ) VSIFClose( fpQIX );}/************************************************************************//* CheckForQIX() *//************************************************************************/int OGRShapeLayer::CheckForQIX(){ const char *pszQIXFilename; if( bCheckedForQIX ) return fpQIX != NULL; pszQIXFilename = CPLResetExtension( pszFullName, "qix" ); fpQIX = VSIFOpen( pszQIXFilename, "rb" ); bCheckedForQIX = TRUE; return fpQIX != NULL;}/************************************************************************//* ScanIndices() *//* *//* Utilize optional spatial and attribute indices if they are *//* available. *//************************************************************************/int OGRShapeLayer::ScanIndices(){ iMatchingFID = 0;/* -------------------------------------------------------------------- *//* Utilize attribute index if appropriate. *//* -------------------------------------------------------------------- */ if( m_poAttrQuery != NULL ) { CPLAssert( panMatchingFIDs == NULL ); panMatchingFIDs = m_poAttrQuery->EvaluateAgainstIndices( this, NULL ); }/* -------------------------------------------------------------------- *//* Check for spatial index if we have a spatial query. *//* -------------------------------------------------------------------- */ if( m_poFilterGeom != NULL && !bCheckedForQIX ) CheckForQIX();/* -------------------------------------------------------------------- *//* Utilize spatial index if appropriate. *//* -------------------------------------------------------------------- */ if( m_poFilterGeom && fpQIX ) { int nSpatialFIDCount, *panSpatialFIDs; double adfBoundsMin[4], adfBoundsMax[4]; OGREnvelope oEnvelope; m_poFilterGeom->getEnvelope( &oEnvelope ); adfBoundsMin[0] = oEnvelope.MinX; adfBoundsMin[1] = oEnvelope.MinY; adfBoundsMin[2] = 0.0; adfBoundsMin[3] = 0.0; adfBoundsMax[0] = oEnvelope.MaxX; adfBoundsMax[1] = oEnvelope.MaxY; adfBoundsMax[2] = 0.0; adfBoundsMax[3] = 0.0; panSpatialFIDs = SHPSearchDiskTree( fpQIX, adfBoundsMin, adfBoundsMax, &nSpatialFIDCount ); CPLDebug( "SHAPE", "Used spatial index, got %d matches.", nSpatialFIDCount ); // Use resulting list as matching FID list (but reallocate and // terminate with OGRNullFID). if( panMatchingFIDs == NULL ) { int i; panMatchingFIDs = (long *) CPLMalloc(sizeof(long) * (nSpatialFIDCount+1) ); for( i = 0; i < nSpatialFIDCount; i++ ) panMatchingFIDs[i] = (long) panSpatialFIDs[i]; panMatchingFIDs[nSpatialFIDCount] = OGRNullFID; free( panSpatialFIDs ); } // Cull attribute index matches based on those in the spatial index // result set. We assume that the attribute results are in sorted // order. else { int iRead, iWrite=0, iSpatial=0; for( iRead = 0; panMatchingFIDs[iRead] != OGRNullFID; iRead++ ) { while( iSpatial < nSpatialFIDCount && panSpatialFIDs[iSpatial] < panMatchingFIDs[iRead] ) iSpatial++; if( iSpatial == nSpatialFIDCount ) continue; if( panSpatialFIDs[iSpatial] == panMatchingFIDs[iRead] ) panMatchingFIDs[iWrite++] = panMatchingFIDs[iRead]; } panMatchingFIDs[iWrite] = OGRNullFID; } } return TRUE;}/************************************************************************//* ResetReading() *//************************************************************************/void OGRShapeLayer::ResetReading(){/* -------------------------------------------------------------------- *//* Clear previous index search result, if any. *//* -------------------------------------------------------------------- */ CPLFree( panMatchingFIDs ); panMatchingFIDs = NULL; iMatchingFID = 0; iNextShapeId = 0; if( bHeaderDirty ) SyncToDisk();}/************************************************************************//* SetNextByIndex() *//* *//* If we already have an FID list, we can easily resposition *//* ourselves in it. *//************************************************************************/OGRErr OGRShapeLayer::SetNextByIndex( long nIndex ){ // Eventually we should try to use panMatchingFIDs list // if available and appropriate. if( m_poFilterGeom != NULL || m_poAttrQuery != NULL ) return OGRLayer::SetNextByIndex( nIndex ); iNextShapeId = nIndex; return OGRERR_NONE;}/************************************************************************//* GetNextFeature() *//************************************************************************/OGRFeature *OGRShapeLayer::GetNextFeature(){ OGRFeature *poFeature = NULL;/* -------------------------------------------------------------------- *//* Collect a matching list if we have attribute or spatial *//* indices. Only do this on the first request for a given pass *//* of course. *//* -------------------------------------------------------------------- */ if( (m_poAttrQuery != NULL || m_poFilterGeom != NULL) && iNextShapeId == 0 && panMatchingFIDs == NULL ) { ScanIndices(); } /* -------------------------------------------------------------------- *//* Loop till we find a feature matching our criteria. *//* -------------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -