📄 ogrshapedatasource.cpp
字号:
/****************************************************************************** * $Id: ogrshapedatasource.cpp,v 1.33 2006/04/05 20:34:57 fwarmerdam Exp $ * * Project: OpenGIS Simple Features Reference Implementation * Purpose: Implements OGRShapeDataSource 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: ogrshapedatasource.cpp,v $ * Revision 1.33 2006/04/05 20:34:57 fwarmerdam * ensure only-dbf errors are cleared: Bug 1115 * * Revision 1.32 2006/03/28 23:22:08 fwarmerdam * update contact info * * Revision 1.31 2006/01/11 03:03:19 fwarmerdam * Assign .prj filename to temporary string. * * Revision 1.30 2006/01/10 16:37:57 fwarmerdam * implemented REPACK support * * Revision 1.29 2006/01/06 19:07:37 fwarmerdam * Pass wkbNone to OGRShapeLayer as the requested type when opening * existing files so their type won't get reset by the "first feature" * logic in CreateFeature() when appending to empty shapefiles. * * Revision 1.28 2005/12/14 16:17:52 fwarmerdam * Fixed wkbMultiPolygon to map to POLYGON, not POLYGONZ. * * Revision 1.27 2005/11/07 17:05:26 fwarmerdam * Ensure morphToESRI() is used on spatial reference before writing .prj file. * * Revision 1.26 2005/01/04 03:43:22 fwarmerdam * added support for create/destroy spatial index sql commands * * Revision 1.25 2005/01/03 22:26:21 fwarmerdam * updated to use spatial indexing * * Revision 1.24 2004/03/01 18:41:00 warmerda * added fix for bug 493: ignore pc arcinfo coverages * * Revision 1.23 2003/07/13 23:06:28 warmerda * Added case for wkbMultiPoint25D to SHPT_MULTIPOINTZ. * * Revision 1.22 2003/05/27 21:39:53 warmerda * added support for writing MULTILINESTRINGs as ARCs * * Revision 1.21 2003/05/21 04:03:54 warmerda * expand tabs * * Revision 1.20 2003/03/27 22:12:14 warmerda * Yow ... fix to second last fix. * * Revision 1.19 2003/03/27 22:11:39 warmerda * Fixed similar bug to the last. * * Revision 1.18 2003/03/27 22:09:43 warmerda * fixed shallow copy problem with return result from CPLGetBasename() * as per http://bugzilla.remotesensing.org/show_bug.cgi?id=310. * * Revision 1.17 2003/03/20 19:11:30 warmerda * free pszBasename after it is used * * Revision 1.16 2003/03/04 05:49:05 warmerda * added attribute indexing support */#include "ogrshape.h"#include "cpl_conv.h"#include "cpl_string.h"CPL_CVSID("$Id: ogrshapedatasource.cpp,v 1.33 2006/04/05 20:34:57 fwarmerdam Exp $");/************************************************************************//* OGRShapeDataSource() *//************************************************************************/OGRShapeDataSource::OGRShapeDataSource(){ pszName = NULL; papoLayers = NULL; nLayers = 0; bSingleNewFile = FALSE;}/************************************************************************//* ~OGRShapeDataSource() *//************************************************************************/OGRShapeDataSource::~OGRShapeDataSource(){ CPLFree( pszName ); for( int i = 0; i < nLayers; i++ ) delete papoLayers[i]; CPLFree( papoLayers );}/************************************************************************//* Open() *//************************************************************************/int OGRShapeDataSource::Open( const char * pszNewName, int bUpdate, int bTestOpen, int bSingleNewFileIn ){ VSIStatBuf stat; CPLAssert( nLayers == 0 ); pszName = CPLStrdup( pszNewName ); bDSUpdate = bUpdate; bSingleNewFile = bSingleNewFileIn;/* -------------------------------------------------------------------- *//* If bSingleNewFile is TRUE we don't try to do anything else. *//* This is only utilized when the OGRShapeDriver::Create() *//* method wants to create a stub OGRShapeDataSource for a *//* single shapefile. The driver will take care of creating the *//* file by calling CreateLayer(). *//* -------------------------------------------------------------------- */ if( bSingleNewFile ) return TRUE; /* -------------------------------------------------------------------- *//* Is the given path a directory or a regular file? *//* -------------------------------------------------------------------- */ if( CPLStat( pszNewName, &stat ) != 0 || (!VSI_ISDIR(stat.st_mode) && !VSI_ISREG(stat.st_mode)) ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_AppDefined, "%s is neither a file or directory, Shape access failed.\n", pszNewName ); return FALSE; } /* -------------------------------------------------------------------- *//* Build a list of filenames we figure are Shape files. *//* -------------------------------------------------------------------- */ if( VSI_ISREG(stat.st_mode) ) { if( !OpenFile( pszNewName, bUpdate, bTestOpen ) ) { if( !bTestOpen ) CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open shapefile %s.\n" "It may be corrupt.\n", pszNewName ); return FALSE; } return TRUE; } else { char **papszCandidates = CPLReadDir( pszNewName ); int iCan, nCandidateCount = CSLCount( papszCandidates ); int bMightBeOldCoverage = FALSE; for( iCan = 0; iCan < nCandidateCount; iCan++ ) { char *pszFilename; const char *pszCandidate = papszCandidates[iCan]; if( EQUAL(pszCandidate,"ARC") ) bMightBeOldCoverage = TRUE; if( strlen(pszCandidate) < 4 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".shp") ) continue; pszFilename = CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL)); if( !OpenFile( pszFilename, bUpdate, bTestOpen ) && !bTestOpen ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open shapefile %s.\n" "It may be corrupt.\n", pszFilename ); CPLFree( pszFilename ); return FALSE; } CPLFree( pszFilename ); } // Try and .dbf files without apparent associated shapefiles. for( iCan = 0; iCan < nCandidateCount; iCan++ ) { char *pszFilename; const char *pszCandidate = papszCandidates[iCan]; const char *pszLayerName; int iLayer, bGotAlready = FALSE; // We don't consume .dbf files in a directory that looks like // an old style Arc/Info (for PC?) that unless we found at least // some shapefiles. See Bug 493. if( bMightBeOldCoverage && nLayers == 0 ) continue; if( strlen(pszCandidate) < 4 || !EQUAL(pszCandidate+strlen(pszCandidate)-4,".dbf") ) continue; pszLayerName = CPLGetBasename(pszCandidate); for( iLayer = 0; iLayer < nLayers; iLayer++ ) { if( EQUAL(pszLayerName, GetLayer(iLayer)->GetLayerDefn()->GetName()) ) bGotAlready = TRUE; } if( bGotAlready ) continue; // We don't want to access .dbf files with an associated .tab // file, or it will never get recognised as a mapinfo dataset. int iCan2, bFoundTAB = FALSE; for( iCan2 = 0; iCan2 < nCandidateCount; iCan2++ ) { const char *pszCandidate2 = papszCandidates[iCan2]; if( EQUALN(pszCandidate2,pszLayerName,strlen(pszLayerName)) && EQUAL(pszCandidate2 + strlen(pszLayerName), ".tab") ) bFoundTAB = TRUE; } if( bFoundTAB ) continue; pszFilename = CPLStrdup(CPLFormFilename(pszNewName, pszCandidate, NULL)); if( !OpenFile( pszFilename, bUpdate, bTestOpen ) && !bTestOpen ) { CPLError( CE_Failure, CPLE_OpenFailed, "Failed to open dbf file %s.\n" "It may be corrupt.\n", pszFilename ); CPLFree( pszFilename ); return FALSE; } CPLFree( pszFilename ); } CSLDestroy( papszCandidates ); if( !bTestOpen && nLayers == 0 && !bUpdate ) { CPLError( CE_Failure, CPLE_OpenFailed, "No Shapefiles found in directory %s\n", pszNewName ); } } return nLayers > 0 || bUpdate;}/************************************************************************//* OpenFile() *//************************************************************************/int OGRShapeDataSource::OpenFile( const char *pszNewName, int bUpdate, int bTestOpen ){ SHPHandle hSHP; DBFHandle hDBF; const char *pszExtension = CPLGetExtension( pszNewName ); (void) bTestOpen; if( !EQUAL(pszExtension,"shp") && !EQUAL(pszExtension,"shx") && !EQUAL(pszExtension,"dbf") ) return FALSE;/* -------------------------------------------------------------------- *//* SHPOpen() should include better (CPL based) error reporting, *//* and we should be trying to distinquish at this point whether *//* failure is a result of trying to open a non-shapefile, or *//* whether it was a shapefile and we want to report the error *//* up. *//* *//* Care is taken to suppress the error and only reissue it if *//* we think it is appropriate. *//* -------------------------------------------------------------------- */ CPLPushErrorHandler( CPLQuietErrorHandler ); if( bUpdate ) hSHP = SHPOpen( pszNewName, "r+" ); else hSHP = SHPOpen( pszNewName, "r" ); CPLPopErrorHandler(); if( hSHP == NULL && (!EQUAL(CPLGetExtension(pszNewName),"dbf") || strstr(CPLGetLastErrorMsg(),".shp") == NULL) ) { CPLString osMsg = CPLGetLastErrorMsg(); CPLError( CE_Failure, CPLE_OpenFailed, "%s", osMsg.c_str() ); return FALSE; } CPLErrorReset(); /* -------------------------------------------------------------------- *//* Open the .dbf file, if it exists. To open a dbf file, the *//* filename has to either refer to a successfully opened shp *//* file or has to refer to the actual .dbf file. *//* -------------------------------------------------------------------- */ if( hSHP != NULL || EQUAL(CPLGetExtension(pszNewName),"dbf") ) { if( bUpdate ) hDBF = DBFOpen( pszNewName, "r+" ); else hDBF = DBFOpen( pszNewName, "r" ); } else hDBF = NULL; if( hDBF == NULL && hSHP == NULL ) return FALSE;/* -------------------------------------------------------------------- *//* Is there an associated .prj file we can read? *//* -------------------------------------------------------------------- */ OGRSpatialReference *poSRS = NULL; const char *pszPrjFile = CPLResetExtension( pszNewName, "prj" ); FILE *fp; fp = VSIFOpen( pszPrjFile, "r" ); if( fp != NULL ) { char **papszLines; VSIFClose( fp ); papszLines = CSLLoad( pszPrjFile ); poSRS = new OGRSpatialReference(); if( poSRS->importFromESRI( papszLines ) != OGRERR_NONE ) { delete poSRS; poSRS = NULL; } CSLDestroy( papszLines ); }/* -------------------------------------------------------------------- *//* Create the layer object. *//* -------------------------------------------------------------------- */ OGRShapeLayer *poLayer; poLayer = new OGRShapeLayer( pszNewName, hSHP, hDBF, poSRS, bUpdate, wkbNone ); poLayer->InitializeIndexSupport( pszNewName );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -