ogrgrasslayer.cpp

来自「支持各种栅格图像和矢量图像读取的库」· C++ 代码 · 共 1,059 行 · 第 1/2 页

CPP
1,059
字号
/****************************************************************************** * $Id: ogrgrasslayer.cpp 10646 2007-01-18 02:38:10Z warmerdam $ * * Project:  OpenGIS Simple Features Reference Implementation * Purpose:  Implements OGRGRASSLayer class. * Author:   Radim Blazek, radim.blazek@gmail.com  * ****************************************************************************** * Copyright (c) 2005, Radim Blazek <radim.blazek@gmail.com> * * 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 <signal.h>#include "ogrgrass.h"#include "cpl_conv.h"CPL_CVSID("$Id: ogrgrasslayer.cpp 10646 2007-01-18 02:38:10Z warmerdam $");/************************************************************************//*                           OGRGRASSLayer()                            *//************************************************************************/OGRGRASSLayer::OGRGRASSLayer( int layerIndex,  struct Map_info * map ){    CPLDebug ( "GRASS", "OGRGRASSLayer::OGRGRASSLayer layerIndex = %d", layerIndex );        iLayerIndex = layerIndex;    poMap = map;     poSRS = NULL;    iNextId = 0;    poPoints = Vect_new_line_struct();    poCats = Vect_new_cats_struct();    pszQuery = NULL;    paQueryMatch = NULL;    paSpatialMatch = NULL;    iLayer = Vect_cidx_get_field_number ( poMap, iLayerIndex);    CPLDebug ( "GRASS", "iLayer = %d", iLayer );        poLink = Vect_get_field ( poMap, iLayer ); // May be NULL if not defined    // Layer name    if ( poLink && poLink->name )    {	pszName = CPLStrdup( poLink->name );	    }    else    {		char buf[20]; 	sprintf ( buf, "%d", iLayer ); 	pszName = CPLStrdup( buf );    }    // Because we don't represent centroids as any simple feature, we have to scan    // category index and create index of feature IDs pointing to category index    nTotalCount = Vect_cidx_get_type_count(poMap,iLayer, GV_POINT|GV_LINES|GV_AREA);    CPLDebug ( "GRASS", "nTotalCount = %d", nTotalCount );    paFeatureIndex = (int *) CPLMalloc ( nTotalCount * sizeof(int) );        int n = Vect_cidx_get_type_count(poMap,iLayer, GV_POINTS|GV_LINES|GV_AREA);    int cnt = 0;    for ( int i = 0; i < n; i++ )     {	int cat,type, id;		Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, i, &cat, &type, &id );    	if ( !( type & (GV_POINT|GV_LINES|GV_AREA) ) ) continue;	paFeatureIndex[cnt++] = i;    }    poFeatureDefn = new OGRFeatureDefn( pszName );    poFeatureDefn->Reference();    // Get type definition    int nTypes = Vect_cidx_get_num_types_by_index ( poMap, iLayerIndex );    int types = 0;    for ( int i = 0; i < nTypes; i++ ) {	int type, count;	Vect_cidx_get_type_count_by_index ( poMap, iLayerIndex, i, &type, &count);	if ( !(type & (GV_POINT|GV_LINES|GV_AREA) ) ) continue;	types |= type;        CPLDebug ( "GRASS", "type = %d types = %d", type, types );    }    if ( types == GV_LINE || types == GV_BOUNDARY || types == GV_LINES )     {        poFeatureDefn->SetGeomType ( wkbLineString );    }     else if ( types == GV_POINT )    {	poFeatureDefn->SetGeomType ( wkbPoint );    }    else if ( types == GV_AREA )    {        CPLDebug ( "GRASS", "set wkbPolygon" );	poFeatureDefn->SetGeomType ( wkbPolygon );    }    // Get attributes definition    poDbString = (dbString*) CPLMalloc ( sizeof(dbString) );    poCursor = (dbCursor*) CPLMalloc ( sizeof(dbCursor) );    bCursorOpened = FALSE;    poDriver = NULL;    bHaveAttributes = false;    db_init_string ( poDbString );    if ( poLink )     {	if ( StartDbDriver() ) 	{	    db_set_string ( poDbString, poLink->table );	    dbTable *table;	    if ( db_describe_table ( poDriver, poDbString, &table) == DB_OK )	    {		nFields = db_get_table_number_of_columns ( table );		iCatField = -1;		for ( int i = 0; i < nFields; i++) 		{		    dbColumn *column = db_get_table_column ( table, i );		    int ctype = db_sqltype_to_Ctype ( db_get_column_sqltype(column) );    		    OGRFieldType ogrFtype = OFTInteger; 	     	    switch ( ctype ) {			 case DB_C_TYPE_INT:			    ogrFtype = OFTInteger;			    break; 			 case DB_C_TYPE_DOUBLE:			    ogrFtype = OFTReal;			    break; 			 case DB_C_TYPE_STRING:			    ogrFtype = OFTString;			    break; 			 case DB_C_TYPE_DATETIME:			    ogrFtype = OFTDateTime;			    break; 		    }		    CPLDebug ( "GRASS", "column = %s type = %d", 			       db_get_column_name(column), ctype );		    		    OGRFieldDefn oField ( db_get_column_name(column), ogrFtype );		    poFeatureDefn->AddFieldDefn( &oField );		    if ( G_strcasecmp(db_get_column_name(column),poLink->key) == 0 )		    {			iCatField = i;		    }		}		if ( iCatField >= 0  ) 		{    		    bHaveAttributes = true;		}		else		{		    CPLError( CE_Failure, CPLE_AppDefined, "Cannot find key field" );		    db_close_database_shutdown_driver ( poDriver );		    poDriver = NULL;		}	    }	    else	    {		CPLError( CE_Failure, CPLE_AppDefined, "Cannot describe table %s", 			  poLink->table );	    }	    db_close_database_shutdown_driver ( poDriver );	    poDriver = NULL;	}    } 	    if ( !bHaveAttributes && iLayer > 0 ) // Because features in layer 0 have no cats      {	OGRFieldDefn oField("cat", OFTInteger);	poFeatureDefn->AddFieldDefn( &oField );    }    if ( getenv("GISBASE") )  // We have some projection info in GISBASE    {        struct Key_Value *projinfo, *projunits;	// Note: we dont have to reset GISDBASE and LOCATION_NAME because 	// OGRGRASSLayer constructor is called from OGRGRASSDataSource::Open	// where those variables are set        projinfo = G_get_projinfo();	projunits = G_get_projunits();	char *srsWkt = GPJ_grass_to_wkt ( projinfo, projunits, 0, 0);	if ( srsWkt ) 	{	    poSRS = new OGRSpatialReference ( srsWkt );	    CPLFree ( srsWkt );	}    }}/************************************************************************//*                           ~OGRGRASSLayer()                           *//************************************************************************/OGRGRASSLayer::~OGRGRASSLayer(){    if ( bCursorOpened )     {	db_close_cursor ( poCursor);    }    if ( poDriver )     {	StopDbDriver();    }        if ( pszName ) CPLFree ( pszName );    if ( poFeatureDefn )        poFeatureDefn->Release();    if ( poSRS )        poSRS->Release();    if ( pszQuery ) CPLFree ( pszQuery );        if ( paFeatureIndex ) CPLFree ( paFeatureIndex );        if ( poLink ) CPLFree ( poLink );        Vect_destroy_line_struct ( poPoints );    Vect_destroy_cats_struct ( poCats );    db_free_string ( poDbString );    CPLFree ( poDbString );    CPLFree ( poCursor );    if ( paSpatialMatch ) CPLFree ( paSpatialMatch );    if ( paQueryMatch ) CPLFree ( paQueryMatch );}/************************************************************************//*                            StartDbDriver                             *//************************************************************************/bool OGRGRASSLayer::StartDbDriver(){    CPLDebug ( "GRASS", "StartDbDriver()" );     bCursorOpened = false;	        if ( !poLink )     {	return false;    }    poDriver = db_start_driver_open_database ( poLink->driver, poLink->database );        if ( poDriver == NULL)     {	CPLError( CE_Failure, CPLE_AppDefined, "Cannot open database %s by driver %s, "		  "check if GISBASE enviroment variable is set, the driver is available "		  " and the database is accessible.", poLink->driver, poLink->database );	return false;    }     return true;}/************************************************************************//*                            StopDbDriver                              *//************************************************************************/bool OGRGRASSLayer::StopDbDriver(){    if ( !poDriver )     {	CPLError( CE_Failure, CPLE_AppDefined, "Driver is not started" );	return true; // I think that true is OK here    }    // TODO!!!: Because of bug in GRASS library it is impossible     // to stop drivers in FIFO order. Until this is fixed     // we have to use kill    CPLDebug ( "GRASS", "driver PID = %d", poDriver->pid ); #if defined(_WIN32) || defined(__WIN32__)    db_close_database_shutdown_driver ( poDriver );#else    if ( kill (poDriver->pid, SIGINT) != 0 )     {	if ( kill (poDriver->pid, SIGKILL) != 0 ) 	{	    CPLError( CE_Failure, CPLE_AppDefined, "Cannot stop database "		      "driver pid = %d", poDriver->pid );	}    }#endif	        bCursorOpened = false;        return true;}/************************************************************************//*                            ResetReading()                            *//************************************************************************/void OGRGRASSLayer::ResetReading(){    iNextId = 0;        if ( bCursorOpened ) {	ResetSequentialCursor();    }}/************************************************************************//*                           SetNextByIndex()                           *//*                                                                      *//*      If we already have an FID list, we can easily resposition       *//*      ourselves in it.                                                *//************************************************************************/OGRErr OGRGRASSLayer::SetNextByIndex( long nIndex ){    if( m_poFilterGeom != NULL || m_poAttrQuery != NULL )     {	iNextId = 0;	int count = 0;		while ( true ) {	    if( iNextId >= nTotalCount ) break;	    if ( count == nIndex ) break;	    // Attributes	    if( pszQuery != NULL && !paQueryMatch[iNextId] ) {		iNextId++;		continue;	    }	    // Spatial	    if( m_poFilterGeom && !paSpatialMatch[iNextId] ) {		iNextId++;		continue;	    }	    count++;	}    }    iNextId = nIndex;    return OGRERR_NONE;}/************************************************************************//*                           SetAttributeFilter                         *//************************************************************************/OGRErr OGRGRASSLayer::SetAttributeFilter( const char *query ){    CPLDebug ( "GRASS", "SetAttributeFilter: %s", query  );    if ( query == NULL ) {	// Release old if any	if ( pszQuery ) {	    CPLFree ( pszQuery );	    pszQuery = NULL;	}	if ( paQueryMatch ) {	    CPLFree ( paQueryMatch );	    paQueryMatch = NULL;	}	return OGRERR_NONE;    }    paQueryMatch = (char *) CPLMalloc ( nTotalCount );    memset ( paQueryMatch, 0x0, nTotalCount );    pszQuery = strdup ( query );    OGRLayer::SetAttributeFilter(query); // Otherwise crash on delete    if ( bHaveAttributes ) {	if ( !poDriver ) 	{	    StartDbDriver();	}	if ( poDriver ) 	{	    if ( bCursorOpened )	    {		db_close_cursor ( poCursor ); 		bCursorOpened = false;	    }	    OpenSequentialCursor();	    if ( bCursorOpened )	    {		SetQueryMatch();		db_close_cursor ( poCursor );		bCursorOpened = false;	    }	    else	    {		CPLFree ( pszQuery );		pszQuery = NULL;		return OGRERR_FAILURE;	    }	    db_close_database_shutdown_driver ( poDriver );	    poDriver = NULL;	}	else	{	    CPLFree ( pszQuery );	    pszQuery = NULL;	    return OGRERR_FAILURE;	}    }    else    {	// Use OGR to evaluate category match	for ( int i = 0; i < nTotalCount; i++ ) 	{	    OGRFeature *feature = GetFeature(i); 	    CPLDebug ( "GRASS", "i = %d eval = %d", i, m_poAttrQuery->Evaluate ( feature ) );	    if ( m_poAttrQuery->Evaluate ( feature ) )	    {		paQueryMatch[i] = 1;	    }	}    }        return OGRERR_NONE;}/************************************************************************//*                           SetQueryMatch                              *//************************************************************************/bool OGRGRASSLayer::SetQueryMatch(){    CPLDebug ( "GRASS", "SetQueryMatch" );    // NOTE: we don't have to call ResetSequentialCursor() first because    // this method is called immediately after OpenSequentialCursor()        if ( !bCursorOpened ) {	CPLError( CE_Failure, CPLE_AppDefined, "Cursor is not opened.");	return false;    }    int more;    int cidx = 0; // index to category index    int fidx = 0; // index to feature index (paFeatureIndex)    // number of categories in category index    int ncats = Vect_cidx_get_num_cats_by_index ( poMap, iLayerIndex );    dbTable *table = db_get_cursor_table ( poCursor );    while ( true ) {	if( db_fetch ( poCursor, DB_NEXT, &more) != DB_OK ) 	{	    CPLError( CE_Failure, CPLE_AppDefined, "Cannot fetch attributes.");	    return false;	}	if ( !more ) break;	dbColumn *column = db_get_table_column ( table, iCatField );	dbValue *value = db_get_column_value ( column );	int cat = db_get_value_int ( value );	// NOTE: because of bug in GRASS library it is impossible to use	//       Vect_cidx_find_next		// Go through category index until first record of current category 	// is found or a category > current is found	int cidxcat, type, id;	while ( cidx < ncats ) {	    Vect_cidx_get_cat_by_index ( poMap, iLayerIndex, cidx, 		                         &cidxcat, &type, &id );	    if ( cidxcat < cat ) {	    	cidx++;		continue;	    }	    if ( cidxcat > cat ) break; // Not found	    	    // We have the category we want, check type	    if ( !(type & (GV_POINT|GV_LINES|GV_AREA)) )	    {	    	cidx++;		continue;	    }	    // Both category and type match -> find feature and set it on	    while ( true ) {		if ( fidx > nTotalCount || paFeatureIndex[fidx] > cidx ) { 		    // should not happen		    break;		}		    		if ( paFeatureIndex[fidx] == cidx ) {		    paQueryMatch[fidx] = 1;		    fidx++;		    break;		}		fidx++;	    }	    cidx++;	}	if ( id < 0 ) continue; // not found    }    return true;}    /************************************************************************//*                           OpenSequentialCursor                       *//************************************************************************/bool OGRGRASSLayer::OpenSequentialCursor(){    CPLDebug ( "GRASS", "OpenSequentialCursor: %s", pszQuery  );    if ( !poDriver )     {	CPLError( CE_Failure, CPLE_AppDefined, "Driver not opened.");	return false;    }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?