/*! \page sfc_tutorial
Most of the classes
are based on the ATL OLE DB consumer templates. To fully understand the
classes it is critical to also review the Microsoft provided information
on these classes. It can be accessed in the
In general terms, the OpenGIS SF COM interface specification requires
geographic data providers to make their datasets look like a database.
A data source (usually a single data file, or group of related data
files) can contain one or more spatial tables which roughly correspond to
what be called layers in most systems. Each table has a schema defining the
set of attributes (table fields) that apply to each feature in that table
(layer). Each record in the table corresponds to a features, with a
set of attributes, and some geometry. The geometry is stored in one field
of the table as a BLOB (binary large object) encoded in a particular format
(OpenGIS SF Well Known Binary Format).
The Simple Features Client classes help model the different parts of this
data model:
Example Client
The console program SFCDUMP is intended to be an example of how to use
the client api (as well as being a useful debugging tool in it's own
right). The full source should be available in
gdal/ogr/sfcdump.cpp.SFCEnumerator: Finding a Provider
The SFCEnumerator class is used to identify all the installed OLE DB
providers (drivers) installed on a system. It essentially makes the
list of OLE DB providers appear to be a table. The following code
sequence demonstrates how to create an SFCEnumerator, loop through all
the records, and print out some information for each record.
static void SFCDumpProviders()
{
SFCEnumerator oEnum;
printf( "Available OLE DB Providers\n" );
printf( "==========================\n" );
if( FAILED(oEnum.Open()) )
{
printf( "Failed to initialize SFCEnumerator.\n" );
return;
}
while( oEnum.MoveNext() == S_OK )
{
printf( "%S: %S\n",
oEnum.m_szName, oEnum.m_szDescription );
if( oEnum.IsOGISProvider() )
printf( " (OGISDataProvider)\n" );
printf( "\n" );
}
}
Some things to note are that:
Opening a Simple Features File
In order to open a file with OGIS simple features information in it, the
following steps should be followed. First, it is necessary to identify the
provider to use. In this example the user gives the provider name as a
string, perhaps after having reviewed a list of possible providers from
SFCDumpProviders(). Second, the filename is needed for the creation of
an SFCDataStore.
static SFCDataSource * SFCOpenDataSource( const char * pszProvider,
const char * pszDataSource )
{
SFCEnumerator oEnumerator;
if( FAILED(oEnumerator.Open()) )
{
printf( "Can't open ole db enumerator.\n" );
return NULL;
}
if( !oEnumerator.Find((char*) pszProvider) )
{
printf( "Can't find OLE DB provider `%s'.\n", pszProvider );
return NULL;
}
SFCDataSource *poDS;
poDS = new SFCDataSource;
if( FAILED(poDS->Open( oEnumerator, pszDataSource )) )
{
delete poDS;
printf( "Attempt to access datasource %s failed.\n",
pszDataSource );
return NULL;
}
else
return poDS;
}
Some interesting things to note are that:
Accessing an SFCTable
The SFCDataSource that we opened could have a number of spatial, and non
spatial tables in it. Eventually the SFCDataSource will include methods for
identifying these. For the time being it is necessary to know apriori what
the table (layer) to access is called. The following code shows how to
instantiate an SFCTable from within a data store.
SFCDataSource *poDS;
poDS = SFCOpenDataSource( pszProvider, pszDataSource );
if( poDS == NULL )
goto CleanupAndExit;
SFCTable *poTable;
poTable = poDS->CreateSFCTable( pszTable );
delete poDS;
if( poTable == NULL )
{
printf( "Failed to open table %s.\n", pszTable );
goto CleanupAndExit;
}
Things to note are:
Reading the Features
The following example shows reading through all the records in a
simple features table, and reading back just the geometry column.
It is instantiated into a geometry object, which is then dumped
to stdout.
static void SFCDumpTableGeometry( SFCTable * poTable )
{
HRESULT hr;
while( !FAILED((hr = poTable->MoveNext())) )
{
OGRGeometry * poGeom;
poGeom = poTable->GetOGRGeometry();
poTable->ReleaseIUnknowns();
if( poGeom == NULL )
{
printf( "Failed to reconstitute geometry!\n" );
break;
}
else
{
poGeom->dumpReadable( stdout );
delete poGeom;
}
}
}
Things to note:
Items to add:
*/