[fdo-internals] PATCH: OGR provider fixed to use FDO spatial test, rather than GEOS

Kenneth Skovhede, GEOGRAF A/S ks at geograf.dk
Sat May 17 07:35:58 EDT 2008


Attached is a diff agains the trunk version of the OGR provider.
It all works in my tests, but I would appreciate it if someone would 
review the changes to see that there are no unintentional memory leaks, 
or places where there should be a copy rather than a reference.

-- 
Regards, Kenneth Skovhede, GEOGRAF A/S

-------------- next part --------------
Index: OgrFdoUtil.cpp
===================================================================
--- OgrFdoUtil.cpp	(revision 3962)
+++ OgrFdoUtil.cpp	(working copy)
@@ -305,14 +305,11 @@
 //This function assumes MapGuide style queries -- either 
 //an attribute filter or a simple spatial filter or a binary
 //combination of the two
-void OgrFdoUtil::ApplyFilter(OGRLayer* layer, FdoFilter* filter, bool* isbbox)
+void OgrFdoUtil::ApplyFilter(OGRLayer* layer, FdoFilter* filter)
 {
     FdoFilter* spatial = NULL;
     FdoFilter* attr = NULL;
 
-    if (isbbox != NULL)
-        (*isbbox) = false;
-
     //zero out the filters
     layer->SetAttributeFilter(NULL);
     layer->SetSpatialFilter(NULL);
@@ -372,7 +369,6 @@
                     envelope->GetMinY(),
                     envelope->GetMaxX(),
                     envelope->GetMaxY());
-                (*isbbox) = true;
             }
         }
         else if (sc->GetOperation() == FdoSpatialOperations_Intersects)
@@ -612,4 +608,3 @@
     return dst.GetLength();
 }
 
-
Index: OgrFdoUtil.h
===================================================================
--- OgrFdoUtil.h	(revision 3962)
+++ OgrFdoUtil.h	(working copy)
@@ -27,7 +27,7 @@
 
     static FdoClassDefinition* ConvertClass(OGRLayer* layer, FdoIdentifierCollection* requestedProps = NULL);
     static void ConvertFeature(FdoPropertyValueCollection* src, OGRFeature* dst, OGRLayer* layer);
-    static void ApplyFilter(OGRLayer* layer, FdoFilter* filter, bool* isbbox);
+    static void ApplyFilter(OGRLayer* layer, FdoFilter* filter);
     static int Fgf2Wkb(const unsigned char* fgf, unsigned char* wkb);
     static int Wkb2Fgf(const unsigned char* wkb, unsigned char* fgf);
 
Index: OgrProvider.cpp
===================================================================
--- OgrProvider.cpp	(revision 3962)
+++ OgrProvider.cpp	(working copy)
@@ -25,6 +25,7 @@
 #include "OgrProvider.h"
 #include "OgrFdoUtil.h"
 #include "ProjConverter.h"
+#include "FdoSpatial.h"
 
 
 #define PROP_NAME_DATASOURCE L"DataSource"
@@ -178,7 +179,7 @@
     
     size_t slen = wcslen(dsw);
     if (dsw[slen - 1] == '\\')
-       slen--;
+        slen--;
 
     wchar_t* tmp = new wchar_t[slen + 1];
     wcsncpy(tmp, dsw, slen);
@@ -412,9 +413,9 @@
     
     OGRLayer* layer = m_poDS->GetLayerByName(mbfc);
 
-    OgrFdoUtil::ApplyFilter(layer, filter, &bbox);
+    OgrFdoUtil::ApplyFilter(layer, filter);
 
-    return new OgrFeatureReader(this, layer, props, bbox);
+    return new OgrFeatureReader(this, layer, props, filter);
 }
 
 FdoIDataReader* OgrConnection::SelectAggregates(FdoIdentifier* fcname, 
@@ -501,7 +502,7 @@
     if (!canDo)
         throw FdoCommandException::Create(L"Current OGR connection does not support update of existing features.");
     
-    OgrFdoUtil::ApplyFilter(layer, filter, NULL);
+    OgrFdoUtil::ApplyFilter(layer, filter);
 
     OGRFeature* feature = NULL;
     
@@ -535,7 +536,7 @@
     if (!canDo)
         throw FdoCommandException::Create(L"Current OGR connection does not support delete.");
 
-    OgrFdoUtil::ApplyFilter(layer, filter, NULL);
+    OgrFdoUtil::ApplyFilter(layer, filter);
 
     std::vector<long> ids; //list of FIDs of features to delete
     
@@ -732,7 +733,7 @@
 //
 //---------------------------------------------------------------------
 
-OgrFeatureReader::OgrFeatureReader(OgrConnection* connection, OGRLayer* layer, FdoIdentifierCollection* props, bool bboxquery)
+OgrFeatureReader::OgrFeatureReader(OgrConnection* connection, OGRLayer* layer, FdoIdentifierCollection* props, FdoFilter* filter)
 {
     m_connection = connection;
     ((FdoIConnection*)m_connection)->AddRef();
@@ -747,7 +748,20 @@
     m_fgflen = 64;
     m_fgf = new unsigned char[m_fgflen*2];
     m_wkb = new unsigned char[m_fgflen];
-    m_bboxquery = bboxquery;
+    
+    FdoPtr<FdoFgfGeometryFactory> gf = FdoFgfGeometryFactory::GetInstance();
+
+    m_geomFilter = NULL;
+    if (dynamic_cast<FdoSpatialCondition*>(filter))
+    {
+        FdoSpatialCondition* sc = (FdoSpatialCondition*)filter;
+        m_spatialOperation = sc->GetOperation();
+        if (m_spatialOperation != FdoSpatialOperations_EnvelopeIntersects)
+        {
+             FdoPtr<FdoExpression> geomExpr = sc->GetGeometry();
+             m_geomFilter = gf->CreateGeometryFromFgf(((FdoGeometryValue*)(geomExpr.p))->GetGeometry());
+        }
+    }
 }
 
 OgrFeatureReader::~OgrFeatureReader()
@@ -757,6 +771,10 @@
     ((FdoIConnection*)m_connection)->Release();
     delete [] m_fgf;
     delete [] m_wkb;
+    
+    //TODO: Will the smart pointer release itself?
+    /*if (m_geomFilter != NULL)
+        FDO_SAFE_RELEASE(m_geomFilter);*/
 }
 
 void OgrFeatureReader::Dispose()
@@ -876,10 +894,8 @@
     return FdoByteArray::Create((unsigned char*)ptr, len);
 }
 
-const FdoByte* OgrFeatureReader::GetGeometry(FdoString* propertyName, FdoInt32* len)
+const FdoByte* OgrFeatureReader::GetGeometry(OGRGeometry* geom, FdoInt32* len)
 {
-    OGRGeometry* geom = m_poFeature->GetGeometryRef();
-
     if (geom)
     {    
         size_t wkblen = geom->WkbSize();
@@ -903,6 +919,11 @@
     throw FdoException::Create(L"Geometry is null.");
 }
 
+const FdoByte* OgrFeatureReader::GetGeometry(FdoString* propertyName, FdoInt32* len)
+{
+    return this->GetGeometry(m_poFeature->GetGeometryRef(), len);
+}
+
 FdoIRaster* OgrFeatureReader::GetRaster(FdoString* propertyName)
 {
     return NULL;
@@ -919,17 +940,26 @@
         
         m_poFeature = m_poLayer->GetNextFeature();
 
-        //Ugly hack to fix broken providers, with BBOX only testing
-        if (!m_bboxquery)
-        {
-            OGRGeometry* spfilter = m_poLayer->GetSpatialFilter();
-            if (spfilter != NULL)
-                while (m_poFeature != NULL && m_poFeature->GetGeometryRef() != NULL && !spfilter->Intersects(m_poFeature->GetGeometryRef()))
+        //OGR uses envelope intersection testing only, this breaks tooltips and selection
+        //If the actual selection was not for envelope intersection, the geometry filtering is done here instead
+        if (m_geomFilter != NULL)
+            while (m_poFeature != NULL && m_poFeature->GetGeometryRef() != NULL)
+            {
+                FdoPtr<FdoFgfGeometryFactory> gf = FdoFgfGeometryFactory::GetInstance();
+                FdoInt32 fgfLen;
+                const FdoByte* fgf = this->GetGeometry(m_poFeature->GetGeometryRef(), &fgfLen);
+                FdoPtr<FdoIGeometry> featureGeom = gf->CreateGeometryFromFgf(fgf, fgfLen);
+
+                //call on the geometry utility to evaluate the spatial operation
+                if (FdoSpatialUtility::Evaluate(m_geomFilter, m_spatialOperation, featureGeom))
+                    break;
+                else
                 {
+                    //Goto next
                     OGRFeature::DestroyFeature(m_poFeature);
                     m_poFeature = m_poLayer->GetNextFeature();
                 }
-        }
+            }
 
         return (m_poFeature != NULL);
     }
Index: OgrProvider.h
===================================================================
--- OgrProvider.h	(revision 3962)
+++ OgrProvider.h	(working copy)
@@ -997,7 +997,7 @@
 {
     public:
         OGR_API OgrFeatureReader(OgrConnection* connection,
-                                 OGRLayer* layer, FdoIdentifierCollection* props, bool bboxquery);
+                                 OGRLayer* layer, FdoIdentifierCollection* props, FdoFilter* filter);
 
     protected:
         OGR_API virtual ~OgrFeatureReader();
@@ -1038,18 +1038,22 @@
         virtual FdoDataType GetDataType( FdoString* propertyName ); 
 
     private:
+
+        virtual const FdoByte* GetGeometry(OGRGeometry* geom, FdoInt32* len);
+
         OgrConnection* m_connection;
         FdoIdentifierCollection* m_props;
 
         OGRLayer* m_poLayer;
         OGRFeature* m_poFeature;
+        FdoPtr<FdoIGeometry> m_geomFilter;
+        FdoSpatialOperations m_spatialOperation;
 
         std::map<long, std::wstring> m_sprops;
         
         unsigned char* m_fgf;
         unsigned char* m_wkb;
         size_t m_fgflen;
-        bool m_bboxquery;
 };
 
 
Index: OGRProvider.vcproj
===================================================================
--- OGRProvider.vcproj	(revision 3962)
+++ OGRProvider.vcproj	(working copy)
@@ -61,7 +61,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="fdo.lib fdocommon.lib fdogeometry.lib wsock32.lib gdal_i.lib xerces-c_2D.lib"
+				AdditionalDependencies="fdo.lib fdocommon.lib fdogeometry.lib wsock32.lib gdal_i.lib xerces-c_2D.lib fdospatial.lib"
 				LinkIncremental="2"
 				AdditionalLibraryDirectories="..\..\Fdo\Unmanaged\lib\win32\Debug;&quot;$(FDOGDAL)\lib\win32\Debug&quot;;..\..\Thirdparty\gdal\lib\win32\Debug;&quot;..\..\Thirdparty\apache\xml-xerces\c\Build\Win32\VC8\Debug&quot;"
 				GenerateDebugInformation="true"
@@ -140,7 +140,7 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="fdo.lib fdocommon.lib fdogeometry.lib wsock32.lib gdal_i.lib xerces-c_2.lib"
+				AdditionalDependencies="fdo.lib fdocommon.lib fdogeometry.lib wsock32.lib gdal_i.lib xerces-c_2.lib fdospatial.lib"
 				LinkIncremental="1"
 				AdditionalLibraryDirectories="..\..\Fdo\Unmanaged\lib\win32\release;&quot;$(FDOGDAL)\lib\win32\Release&quot;;..\..\Thirdparty\gdal\lib\win32\release;&quot;..\..\Thirdparty\apache\xml-xerces\c\Build\Win32\VC8\Release&quot;"
 				GenerateManifest="true"


More information about the fdo-internals mailing list