📄 ogr_apitut.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1"><title>OGR: OGR API Tutorial</title><link href="doxygen.css" rel="stylesheet" type="text/css"><link href="tabs.css" rel="stylesheet" type="text/css"></head><body><!-- Generated by Doxygen 1.5.1 --><div class="tabs"> <ul> <li><a href="index.html"><span>Main Page</span></a></li> <li><a href="annotated.html"><span>Classes</span></a></li> <li><a href="files.html"><span>Files</span></a></li> <li><a href="dirs.html"><span>Directories</span></a></li> <li><a href="pages.html"><span>Related Pages</span></a></li> </ul></div><h1><a class="anchor" name="ogr_apitut">OGR API Tutorial</a></h1>This document is intended to document using the OGR C++ classes to read and write data from a file. It is strongly advised that the read first review the <a href="ogr_arch.html">OGR Architecture</a> document describing the key classes and their roles in OGR.<h2><a class="anchor" name="ogr_apitut_read">Reading From OGR</a></h2>For purposes of demonstrating reading with OGR, we will constuct a small utility for dumping point layers from an OGR data source to stdout in comma-delimited format.<p>Initially it is necessary to register all the format drivers that are desired. This is normally accomplished by calling <a class="el" href="ogr__api_8h.html#e904632d0bc86ba5501921ca594e18da">OGRRegisterAll()</a> which registers all format drivers built into GDAL/OGR.<p><div class="fragment"><pre class="fragment"><span class="preprocessor">#include "<a class="code" href="ogrsf__frmts_8h.html">ogrsf_frmts.h</a>"</span><span class="keywordtype">int</span> main(){ <a class="code" href="ogr__api_8h.html#e904632d0bc86ba5501921ca594e18da">OGRRegisterAll</a>();</pre></div><p>Next we need to open the input OGR datasource. Datasources can be files, RDBMSes, directories full of files, or even remote web services depending on the driver being used. However, the datasource name is always a single string. In this case we are hardcoded to open a particular shapefile. The second argument (FALSE) tells the <a class="el" href="classOGRSFDriverRegistrar.html#5ee13e09d55d146f45bb5417fa524f54">OGRSFDriverRegistrar::Open()</a> method that we don't require update access. On failure NULL is returned, and we report an error.<p><div class="fragment"><pre class="fragment"> <a class="code" href="classOGRDataSource.html">OGRDataSource</a> *poDS; poDS = <a class="code" href="classOGRSFDriverRegistrar.html#5ee13e09d55d146f45bb5417fa524f54">OGRSFDriverRegistrar::Open</a>( <span class="stringliteral">"point.shp"</span>, FALSE ); <span class="keywordflow">if</span>( poDS == NULL ) { printf( <span class="stringliteral">"Open failed.\n"</span> ); exit( 1 ); }</pre></div><p>An <a class="el" href="classOGRDataSource.html">OGRDataSource</a> can potentially have many layers associated with it. The number of layers available can be queried with <a class="el" href="classOGRDataSource.html#031694429394662fd50353c5e2b68692">OGRDataSource::GetLayerCount()</a> and individual layers fetched by index using <a class="el" href="classOGRDataSource.html#618c2fdb1067c9357ca2de9fa6cd5962">OGRDataSource::GetLayer()</a>. However, we wil just fetch the layer by name.<p><div class="fragment"><pre class="fragment"> <a class="code" href="classOGRLayer.html">OGRLayer</a> *poLayer; poLayer = poDS-><a class="code" href="classOGRDataSource.html#a0fafafc83084ad140ecdf17d9e139f9">GetLayerByName</a>( <span class="stringliteral">"point"</span> );</pre></div><p>Now we want to start reading features from the layer. Before we start we could assign an attribute or spatial filter to the layer to restrict the set of feature we get back, but for now we are interested in getting all features.<p>While it isn't strictly necessary in this circumstance since we are starting fresh with the layer, it is often wise to call <a class="el" href="classOGRLayer.html#ad0f2cd7f0587584b8f382c6a913583c">OGRLayer::ResetReading()</a> to ensure we are starting at the beginning of the layer. We iterate through all the features in the layer using <a class="el" href="classOGRLayer.html#47d21ff33b32d14fa4e9885b9edecad6">OGRLayer::GetNextFeature()</a>. It will return NULL when we run out of features.<p><div class="fragment"><pre class="fragment"> <a class="code" href="classOGRFeature.html">OGRFeature</a> *poFeature; poLayer-><a class="code" href="classOGRLayer.html#ad0f2cd7f0587584b8f382c6a913583c">ResetReading</a>(); <span class="keywordflow">while</span>( (poFeature = poLayer-><a class="code" href="classOGRLayer.html#47d21ff33b32d14fa4e9885b9edecad6">GetNextFeature</a>()) != NULL ) {</pre></div><p>In order to dump all the attribute fields of the feature, it is helpful to get the <a class="el" href="classOGRFeatureDefn.html">OGRFeatureDefn</a>. This is an object, associated with the layer, containing the definitions of all the fields. We loop over all the fields, and fetch and report the attributes based on their type.<p><div class="fragment"><pre class="fragment"> <a class="code" href="classOGRFeatureDefn.html">OGRFeatureDefn</a> *poFDefn = poLayer-><a class="code" href="classOGRLayer.html#80473bcfd11341e70dd35bebe94026cf">GetLayerDefn</a>(); <span class="keywordtype">int</span> iField; <span class="keywordflow">for</span>( iField = 0; iField < poFDefn-><a class="code" href="classOGRFeatureDefn.html#b400f9106e7544ebafa30b1fe59869b1">GetFieldCount</a>(); iField++ ) { <a class="code" href="classOGRFieldDefn.html">OGRFieldDefn</a> *poFieldDefn = poFDefn-><a class="code" href="classOGRFeatureDefn.html#43b95ce699bbca73acb453cc959378e7">GetFieldDefn</a>( iField ); <span class="keywordflow">if</span>( poFieldDefn->GetType() == OFTInteger ) printf( <span class="stringliteral">"%d,"</span>, poFeature-><a class="code" href="classOGRFeature.html#dd319b68ea27a4ee0602d3aa460ca3b5">GetFieldAsInteger</a>( iField ) ); <span class="keywordflow">else</span> <span class="keywordflow">if</span>( poFieldDefn->GetType() == OFTReal ) printf( <span class="stringliteral">"%.3f,"</span>, poFeature-><a class="code" href="classOGRFeature.html#b8a57c94e8bb8ffac5e7048d896254b4">GetFieldAsDouble</a>(iField) ); <span class="keywordflow">else</span> <span class="keywordflow">if</span>( poFieldDefn->GetType() == OFTString ) printf( <span class="stringliteral">"%s,"</span>, poFeature-><a class="code" href="classOGRFeature.html#c7a0224e13dce1f9479a6bf2111ea766">GetFieldAsString</a>(iField) ); <span class="keywordflow">else</span> printf( <span class="stringliteral">"%s,"</span>, poFeature-><a class="code" href="classOGRFeature.html#c7a0224e13dce1f9479a6bf2111ea766">GetFieldAsString</a>(iField) ); }</pre></div><p>There are a few more field types than those explicitly handled above, but a reasonable representation of them can be fetched with the <a class="el" href="classOGRFeature.html#c7a0224e13dce1f9479a6bf2111ea766">OGRFeature::GetFieldAsString()</a> method. In fact we could shorten the above by using <a class="el" href="classOGRFeature.html#c7a0224e13dce1f9479a6bf2111ea766">OGRFeature::GetFieldAsString()</a> for all the types.<p>Next we want to extract the geometry from the feature, and write out the point geometry x and y. Geometries are returned as a generic <a class="el" href="classOGRGeometry.html">OGRGeometry</a> pointer. We then determine the specific geometry type, and if it is a point, we cast it to point and operate on it. If it is something else we write placeholders.<p><div class="fragment"><pre class="fragment"> <a class="code" href="classOGRGeometry.html">OGRGeometry</a> *poGeometry; poGeometry = poFeature-><a class="code" href="classOGRFeature.html#cc966ce8c10ae3ddf9f14c2736fdce9a">GetGeometryRef</a>(); <span class="keywordflow">if</span>( poGeometry != NULL && wkbFlatten(poGeometry-><a class="code" href="classOGRGeometry.html#26fef0fc5e95c9e8e526922476c778bd">getGeometryType</a>()) == wkbPoint ) { <a class="code" href="classOGRPoint.html">OGRPoint</a> *poPoint = (<a class="code" href="classOGRPoint.html">OGRPoint</a> *) poGeometry; printf( <span class="stringliteral">"%.3f,%3.f\n"</span>, poPoint-><a class="code" href="classOGRPoint.html#5170ea70ce7458059e4395f852fce687">getX</a>(), poPoint-><a class="code" href="classOGRPoint.html#dbb341223a71d4563315a587f0454f66">getY</a>() ); } <span class="keywordflow">else</span> { printf( <span class="stringliteral">"no point geometry\n"</span> ); } </pre></div><p>The wkbFlatten() macro is used above to to convert the type for a wkbPoint25D (a point with a z coordinate) into the base 2D geometry type code (wkbPoint). For each 2D geometry type there is a corresponding 2.5D type code; however, there is only a C++ class for both the 2D and 3D cases. So our code will handle 2D or 3D cases properly.<p>Note that <a class="el" href="classOGRFeature.html#cc966ce8c10ae3ddf9f14c2736fdce9a">OGRFeature::GetGeometryRef()</a> returns a pointer to the internal geometry owned by the <a class="el" href="classOGRFeature.html">OGRFeature</a>. There we don't actually deleted the return geometry. However, the <a class="el" href="classOGRLayer.html#47d21ff33b32d14fa4e9885b9edecad6">OGRLayer::GetNextFeature()</a> method returns a copy of the feature that is now owned by us. So at the end of use we must free the feature. We could just "delete" it, but this can cause problems in windows builds where the GDAL DLL has a different "heap" from the main program. To be on the safe side we use a GDAL function to delete the feature.<p><div class="fragment"><pre class="fragment"> <a class="code" href="classOGRFeature.html#5d2602d11f21567119da0ca6b6c5ad45">OGRFeature::DestroyFeature</a>( poFeature ); }</pre></div><p>The <a class="el" href="classOGRLayer.html">OGRLayer</a> returned by <a class="el" href="classOGRDataSource.html#a0fafafc83084ad140ecdf17d9e139f9">OGRDataSource::GetLayerByName()</a> is also a reference to an internal layer owned by the <a class="el" href="classOGRDataSource.html">OGRDataSource</a> so we don't need to delete it. But we do need to delete the datasource in order to close the input file. Once again we do this with a custom delete method to avoid special win32 heap issus.<p><div class="fragment"><pre class="fragment"> OGRDataSource::DestroyDataSource( poDS );}</pre></div><p>All together our program looks like this.<p><div class="fragment"><pre class="fragment"><span class="preprocessor">#include "<a class="code" href="ogrsf__frmts_8h.html">ogrsf_frmts.h</a>"</span><span class="keywordtype">int</span> main(){ <a class="code" href="ogr__api_8h.html#e904632d0bc86ba5501921ca594e18da">OGRRegisterAll</a>(); <a class="code" href="classOGRDataSource.html">OGRDataSource</a> *poDS; poDS = <a class="code" href="classOGRSFDriverRegistrar.html#5ee13e09d55d146f45bb5417fa524f54">OGRSFDriverRegistrar::Open</a>( <span class="stringliteral">"point.shp"</span>, FALSE ); <span class="keywordflow">if</span>( poDS == NULL ) { printf( <span class="stringliteral">"Open failed.\n%s"</span> ); exit( 1 ); } <a class="code" href="classOGRLayer.html">OGRLayer</a> *poLayer; poLayer = poDS-><a class="code" href="classOGRDataSource.html#a0fafafc83084ad140ecdf17d9e139f9">GetLayerByName</a>( <span class="stringliteral">"point"</span> ); <a class="code" href="classOGRFeature.html">OGRFeature</a> *poFeature; poLayer-><a class="code" href="classOGRLayer.html#ad0f2cd7f0587584b8f382c6a913583c">ResetReading</a>(); <span class="keywordflow">while</span>( (poFeature = poLayer-><a class="code" href="classOGRLayer.html#47d21ff33b32d14fa4e9885b9edecad6">GetNextFeature</a>()) != NULL ) { <a class="code" href="classOGRFeatureDefn.html">OGRFeatureDefn</a> *poFDefn = poLayer-><a class="code" href="classOGRLayer.html#80473bcfd11341e70dd35bebe94026cf">GetLayerDefn</a>(); <span class="keywordtype">int</span> iField; <span class="keywordflow">for</span>( iField = 0; iField < poFDefn-><a class="code" href="classOGRFeatureDefn.html#b400f9106e7544ebafa30b1fe59869b1">GetFieldCount</a>(); iField++ ) { <a class="code" href="classOGRFieldDefn.html">OGRFieldDefn</a> *poFieldDefn = poFDefn-><a class="code" href="classOGRFeatureDefn.html#43b95ce699bbca73acb453cc959378e7">GetFieldDefn</a>( iField ); <span class="keywordflow">if</span>( poFieldDefn->GetType() == OFTInteger ) printf( <span class="stringliteral">"%d,"</span>, poFeature-><a class="code" href="classOGRFeature.html#dd319b68ea27a4ee0602d3aa460ca3b5">GetFieldAsInteger</a>( iField ) ); <span class="keywordflow">else</span> <span class="keywordflow">if</span>( poFieldDefn->GetType() == OFTReal ) printf( <span class="stringliteral">"%.3f,"</span>, poFeature-><a class="code" href="classOGRFeature.html#b8a57c94e8bb8ffac5e7048d896254b4">GetFieldAsDouble</a>(iField) ); <span class="keywordflow">else</span> <span class="keywordflow">if</span>( poFieldDefn->GetType() == OFTString ) printf( <span class="stringliteral">"%s,"</span>, poFeature-><a class="code" href="classOGRFeature.html#c7a0224e13dce1f9479a6bf2111ea766">GetFieldAsString</a>(iField) ); <span class="keywordflow">else</span> printf( <span class="stringliteral">"%s,"</span>, poFeature-><a class="code" href="classOGRFeature.html#c7a0224e13dce1f9479a6bf2111ea766">GetFieldAsString</a>(iField) ); } <a class="code" href="classOGRGeometry.html">OGRGeometry</a> *poGeometry; poGeometry = poFeature-><a class="code" href="classOGRFeature.html#cc966ce8c10ae3ddf9f14c2736fdce9a">GetGeometryRef</a>(); <span class="keywordflow">if</span>( poGeometry != NULL && wkbFlatten(poGeometry->getGeometryType()) == wkbPoint ) { <a class="code" href="classOGRPoint.html">OGRPoint</a> *poPoint = (<a class="code" href="classOGRPoint.html">OGRPoint</a> *) poGeometry; printf( <span class="stringliteral">"%.3f,%3.f\n"</span>, poPoint-><a class="code" href="classOGRPoint.html#5170ea70ce7458059e4395f852fce687">getX</a>(), poPoint-><a class="code" href="classOGRPoint.html#dbb341223a71d4563315a587f0454f66">getY</a>() ); } <span class="keywordflow">else</span> { printf( <span class="stringliteral">"no point geometry\n"</span> ); } <a class="code" href="classOGRFeature.html#5d2602d11f21567119da0ca6b6c5ad45">OGRFeature::DestroyFeature</a>( poFeature ); } OGRDataSource::DestroyDataSource( poDS );}</pre></div><h2><a class="anchor" name="ogr_apitut_write">Writing To OGR</a></h2>As an example of writing through OGR, we will do roughly the opposite of the above. A short program that reads comma seperated values from input text will be written to a point shapefile via OGR.<p>As usual, we start by registering all the drivers, and then fetch the Shapefile driver as we will need it to create our output file.<p><div class="fragment"><pre class="fragment"><span class="preprocessor">#include "<a class="code" href="ogrsf__frmts_8h.html">ogrsf_frmts.h</a>"</span><span class="keywordtype">int</span> main(){ <span class="keyword">const</span> <span class="keywordtype">char</span> *pszDriverName = <span class="stringliteral">"ESRI Shapefile"</span>; <a class="code" href="classOGRSFDriver.html">OGRSFDriver</a> *poDriver;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -