📄 rfc6_sqlgeom.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>GDAL: RFC 6: Geometry and Feature Style as OGR Special Fields</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="pages.html"><span>Related Pages</span></a></li> </ul></div><h1><a class="anchor" name="rfc6_sqlgeom">RFC 6: Geometry and Feature Style as OGR Special Fields</a></h1>Author: Tamas Szekeres<br> Contact: <a href="mailto:szekerest@gmail.com">szekerest@gmail.com</a><br> Status: Adopted<br><h2><a class="anchor" name="rfc6_summary">Summary</a></h2>This proposal addresses and issue have been discovered long ago, and OGR provides no equivalent solution so far.<p>Some of the supported formats like Mapinfo.tab may contain multiple geometry types and style information. In order to hanlde this kind of data sources properly a support for selecting the layers by geometry type or by the style info would be highly required. For more details see the following MapServer related bugs later in this document.<p>All of the proposed changes can be found at the tracking bug of this RFC referenced later in this document.<h2><a class="anchor" name="rfc6_main">Main concepts</a></h2>The most reasonable way to support this feature is to extend the currently existing 'special field' approach to allow specifying more than one fields. Along with the already definied 'FID' field we will add the following ones:<p><ul><li>'OGR_GEOMETRY' containing the geometry type like 'POINT' or 'POLYGON'.<p></li><li>'OGR_STYLE' containing the style string.<p></li><li>'OGR_GEOM_WKT' containing the full WKT of the geometry.<p></li></ul><p>By providing the aforementioned fields one can make for example the following selections:<p><ul><li>select FID, OGR_GEOMETRY, OGR_STYLE, OGR_GEOM_WKT, * from MyTable where OGR_GEOMETRY='POINT' OR OGR_GEOMETRY='POLYGON'<p></li><li>select FID, OGR_GEOMETRY, OGR_STYLE, OGR_GEOM_WKT, * from MyTable where OGR_STYLE LIKE 'BRUSH'<p></li><li>select FID, OGR_GEOMETRY, OGR_STYLE, OGR_GEOM_WKT, * from MyTable where OGR_GEOM_WKT LIKE 'POLYGON'<p></li><li>select distinct OGR_GEOMETRY from MyTable order by OGR_GEOMETRY desc<p></li></ul><h2><a class="anchor" name="rfc5_implementation">Implementation</a></h2>There are two distinct areas where this feature plays a role<p><ul><li>Feature query implemented at ogrfeaturequery.cpp<p></li><li>SQL based selection implemented at ogr_gensql.cpp and ogrdatasource.cpp<p></li></ul><p>To specify arbitrary number of special fields we will declare an array for the field names and types in ogrfeaturequery.cpp as<p><pre></pre><p><pre>char* SpecialFieldNames[SPECIAL_FIELD_COUNT] = {"FID", "OGR_GEOMETRY", "OGR_STYLE", "OGR_GEOM_WKT"};swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT] = {SWQ_INTEGER, SWQ_STRING, SWQ_STRING, SWQ_STRING};</pre><p><pre></pre><p>So as to make this array accessible to the other files the followings will be added to ogr_p.h<p><pre></pre><p><pre>CPL_C_STARTinclude "swq.h"CPL_C_END</pre><p><pre>define SPF_FID 0define SPF_OGR_GEOMETRY 1define SPF_OGR_STYLE 2define SPF_OGR_GEOM_WKT 3define SPECIAL_FIELD_COUNT 4</pre><p><pre>extern char* SpecialFieldNames[SPECIAL_FIELD_COUNT];extern swq_field_type SpecialFieldTypes[SPECIAL_FIELD_COUNT];</pre><p><pre></pre><p>In ogrfeature.cpp the field accessor functions (GetFieldAsString, GetFieldAsInteger, GetFieldAsDouble) will be modified providing the values of the special fields by the field index<p>The following code will be added to the beginning of OGRFeature::GetFieldAsInteger:<p><pre></pre><p><pre>int iSpecialField = iField - poDefn->GetFieldCount();if (iSpecialField >= 0){// special field value accessors switch (iSpecialField) { case SPF_FID: return GetFID(); default: return 0; }}</pre><p><pre></pre><p>The following code will be added to the beginning of OGRFeature::GetFieldAsDouble:<p><pre></pre><p><pre>int iSpecialField = iField - poDefn->GetFieldCount();if (iSpecialField >= 0){// special field value accessors switch (iSpecialField) { case SPF_FID: return GetFID(); default: return 0.0; }}</pre><p><pre></pre><p>The following code will be added to the beginning of OGRFeature::GetFieldAsString:<p><pre></pre><p><pre>int iSpecialField = iField - poDefn->GetFieldCount();if (iSpecialField >= 0){// special field value accessors switch (iSpecialField) { case SPF_FID: sprintf( szTempBuffer, "%d", GetFID() ); return m_pszTmpFieldValue = CPLStrdup( szTempBuffer ); case SPF_OGR_GEOMETRY: return poGeometry->getGeometryName(); case SPF_OGR_STYLE: return GetStyleString(); case SPF_OGR_GEOM_WKT: { if (poGeometry->exportToWkt( &m_pszTmpFieldValue ) == OGRERR_NONE ) return m_pszTmpFieldValue; else return ""; } default: return ""; }}</pre><p><pre></pre><p>The current implementation of OGRFeature::GetFieldAsString uses a static string to hold the const char* return value that is highly avoidable and makes the code thread unsafe. In this regard the 'static char szTempBuffer[80]' will be changed to non static and a new member will be added to OGRFeature in ogrfeature.h as:<p><pre></pre><p><pre>char * m_pszTmpFieldValue;</pre><p><pre></pre><p>This member will be initialized to NULL at the constructor, and will be freed using CPLFree() at the destructor of OGRFeature.<p>In OGRFeature::GetFieldAsString all of the occurrences of 'return szTempBuffer;' will be changed to 'return m_pszTmpFieldValue = CPLStrdup( szTempBuffer );'<p>OGRFeature::GetFieldAsString is responsible to destroy the old value of m_pszTmpFieldValue at the beginning of the function:<p><pre></pre><p><pre>CPLFree(m_pszTmpFieldValue);m_pszTmpFieldValue = NULL;</pre><p><pre></pre><p>In ogrfeaturequery.cpp we should change OGRFeatureQuery::Compile to add the special fields like:<p><pre></pre><p><pre>iField = 0;while (iField < SPECIAL_FIELD_COUNT){ papszFieldNames[poDefn->GetFieldCount() + iField] = SpecialFieldNames[iField]; paeFieldTypes[poDefn->GetFieldCount() + iField] = SpecialFieldTypes[iField]; ++iField;}</pre><p><pre></pre><p>In ogrfeaturequery.cpp OGRFeatureQueryEvaluator() should be modifyed according to the field specific actions like<p><pre></pre><p><pre>int iSpecialField = op->field_index - poFeature->GetDefnRef()->GetFieldCount();if( iSpecialField >= 0 ){ if ( iSpecialField < SPECIAL_FIELD_COUNT ) { switch ( SpecialFieldTypes[iSpecialField] ) { case SWQ_INTEGER: sField.Integer = poFeature->GetFieldAsInteger( op->field_index ); case SWQ_STRING: sField.String = (char*) poFeature->GetFieldAsString( op->field_index ); } } else { CPLDebug( "OGRFeatureQuery", "Illegal special field index."); return FALSE; } psField = }else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -