[mapguide-internals] PATCH: OGR Provider, slight speedup and override of projections

Kenneth, GEOGRAF A/S ks at geograf.dk
Wed Oct 3 07:13:22 EDT 2007


The attached file contains an improvement to the OGR Provider.
The patch will avoid checking intersection in cases where the query type 
is a EnvelopIntersect.
The current intersection check was added to ensure that the AJAX Viewers 
select and tooltip operations works.
However, this check slows down the renderer because it performs an 
actual intersection test, which is not required for rendering.

Aditionally I have removed all "printf" commands from a non-debug build.

Lastly, I have added an option to supply coordinate system overrides on 
the provider.
This is necessary for certain MI_TAB files, which use non standard WKT 
projections.
It will read in a file named "projections.txt" from the server folder.
The "projections.txt" file should be constructed like this (wkt is 
supposed to be full):

#System 34 S
PROJCS["unnamed" ....... 1.0]]
PROJCS["DenmarkS34-S" ....... 1.0 ]]

Any blank line or line starting with # is ignored.
Every two accepted lines are treated as a pair, where the first line is 
the WKT translated from, and the second line is the WKT translated to.
It uses a std::map which will run in O(1) to find the projections.

-- 
Regards, Kenneth, GEOGRAF A/S


-------------- next part --------------
Index: OgrFdoUtil.cpp
===================================================================
--- OgrFdoUtil.cpp	(revision 3347)
+++ OgrFdoUtil.cpp	(working copy)
@@ -48,8 +48,9 @@
 
     dot2tilde(wname);
 
+#if DEBUG
     printf ("Feature class name: %s\n", name);
-
+#endif
     FdoPtr<FdoFeatureClass> fc = FdoFeatureClass::Create(wname, L"");
 
     FdoPtr<FdoPropertyDefinitionCollection> pdc = fc->GetProperties();
@@ -62,9 +63,9 @@
         OGRFieldDefn* field = fdefn->GetFieldDefn(j);
         const char* name = field->GetNameRef();
         A2W(name);
-
+#if DEBUG
         printf("Attribute : %s\n", name);
-
+#endif
         FdoDataType dt;
         OGRFieldType etype = field->GetType();
         bool add = true;
@@ -111,7 +112,9 @@
     //if it's on the list or there was no list at all, then add the property
     if (!requestedProps || requestedProps->GetCount() == 0 || (requestedProps && found.p))
     {
+#if DEBUG
         printf ("Geometry column : %s\n", geomname);
+#endif
 
         FdoPtr<FdoGeometricPropertyDefinition> gpd = FdoGeometricPropertyDefinition::Create(wgeomname, L"");
 
@@ -142,9 +145,9 @@
     const char* idname = layer->GetFIDColumn();
     if (*idname == 0) idname = "FID";
     A2W(idname);
-
+#if DEBUG
     printf ("Identity column : %s\n", idname);
-
+#endif
     //check if property is on the optional requested property list
     found = (requestedProps) ? requestedProps->FindItem(widname) : NULL;
 
@@ -302,11 +305,14 @@
 //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)
+void OgrFdoUtil::ApplyFilter(OGRLayer* layer, FdoFilter* filter, bool* isbbox)
 {
     FdoFilter* spatial = NULL;
     FdoFilter* attr = NULL;
 
+    if (isbbox != NULL)
+        (*isbbox) = false;
+
     //zero out the filters
     layer->SetAttributeFilter(NULL);
     layer->SetSpatialFilter(NULL);
@@ -344,11 +350,12 @@
         layer->SetAttributeFilter(mbattrsql);
     }
 
-    //set spatial query -- assumes EnvelopeIntersects
+    //set spatial query
     if (spatial)
     {
         FdoSpatialCondition* sc = (FdoSpatialCondition*)spatial;
 
+        //Simple envelope can be handled faster, ad is used by map renders
         if (sc->GetOperation() == FdoSpatialOperations_EnvelopeIntersects)
         {
             FdoPtr<FdoExpression> expr = sc->GetGeometry();
@@ -365,6 +372,7 @@
                     envelope->GetMinY(),
                     envelope->GetMaxX(),
                     envelope->GetMaxY());
+                (*isbbox) = true;
             }
         }
         else if (sc->GetOperation() == FdoSpatialOperations_Intersects)
@@ -387,8 +395,10 @@
 
                 if (geom)
                     layer->SetSpatialFilter(geom);
+#if DEBUG
                 else
                     printf ("failed to convert intersects spatial filter geometry value");
+#endif
 
                 OGRFree(geom);
             }
Index: OgrFdoUtil.h
===================================================================
--- OgrFdoUtil.h	(revision 3347)
+++ 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);
+    static void ApplyFilter(OGRLayer* layer, FdoFilter* filter, bool* isbbox);
     static int Fgf2Wkb(const unsigned char* fgf, unsigned char* wkb);
     static int Wkb2Fgf(const unsigned char* wkb, unsigned char* fgf);
 
@@ -38,65 +38,65 @@
 class OgrBinaryReader
 {
 public:
-	OgrBinaryReader(const unsigned char* stream)
-		: m_stream((unsigned char*)stream)
-	{
-	}
+    OgrBinaryReader(const unsigned char* stream)
+        : m_stream((unsigned char*)stream)
+    {
+    }
 
-	inline unsigned char ReadByte()
-	{
-		return *m_stream++;
-	}
+    inline unsigned char ReadByte()
+    {
+        return *m_stream++;
+    }
 
-	inline int ReadInt()
-	{
-		int ret = *(int*)m_stream;
-		m_stream += sizeof(int);
-		return ret;
-	}
+    inline int ReadInt()
+    {
+        int ret = *(int*)m_stream;
+        m_stream += sizeof(int);
+        return ret;
+    }
 
-	inline double ReadDouble()
-	{
-		double ret = *(double*)m_stream;
-		m_stream += sizeof(double);
-		return ret;
-	}
+    inline double ReadDouble()
+    {
+        double ret = *(double*)m_stream;
+        m_stream += sizeof(double);
+        return ret;
+    }
 
-	unsigned char* m_stream;
+    unsigned char* m_stream;
 };
 
 
 class OgrBinaryWriter
 {
 public:
-	OgrBinaryWriter(unsigned char* stream /*, int len*/)
-		: m_stream(stream),
-		m_begin(stream)
-	{
-	}
+    OgrBinaryWriter(unsigned char* stream /*, int len*/)
+        : m_stream(stream),
+        m_begin(stream)
+    {
+    }
 
-	inline void WriteByte(unsigned char b)
-	{
-		*m_stream++ = b;
-	}
+    inline void WriteByte(unsigned char b)
+    {
+        *m_stream++ = b;
+    }
 
-	inline void WriteInt(int i)
-	{
-		*((int*)m_stream) = i;
-		m_stream += sizeof(int);
-	}
+    inline void WriteInt(int i)
+    {
+        *((int*)m_stream) = i;
+        m_stream += sizeof(int);
+    }
 
-	inline void WriteDouble(double d)
-	{
-		*((double*)m_stream) = d;
-		m_stream += sizeof(double);
-	}
+    inline void WriteDouble(double d)
+    {
+        *((double*)m_stream) = d;
+        m_stream += sizeof(double);
+    }
 
-	inline int GetLength() 
-	{
-		return (int)(m_stream - m_begin);
-	}
+    inline int GetLength() 
+    {
+        return (int)(m_stream - m_begin);
+    }
 
-	unsigned char* m_begin;
-	unsigned char* m_stream;
+    unsigned char* m_begin;
+    unsigned char* m_stream;
 };
Index: OgrProvider.cpp
===================================================================
--- OgrProvider.cpp	(revision 3347)
+++ OgrProvider.cpp	(working copy)
@@ -24,6 +24,7 @@
 #include "stdafx.h"
 #include "OgrProvider.h"
 #include "OgrFdoUtil.h"
+#include "ProjConverter.h"
 
 
 #define PROP_NAME_DATASOURCE L"DataSource"
@@ -60,6 +61,7 @@
         StaticInit()
         {
             OGRRegisterAll(); 
+            ProjConverter::ProjectionConverter = new ProjConverter();
         }
 };
 StaticInit si;
@@ -69,7 +71,6 @@
 {
     m_poDS = NULL;
     m_pSchema = NULL;
-    
     m_mProps = new std::map<std::wstring, std::wstring>();
     m_connState = FdoConnectionState_Closed;
 }
@@ -88,11 +89,15 @@
     //we inherit in the OgrConnection object
     if (((FdoIConnection*)this)->GetRefCount() == 0)
     {
+#if DEBUG
         printf("destroying connection\n");
+#endif
         delete this;
     }
+#if DEBUG
     else
         printf("Dispose() called by multiply inherited object\n");
+#endif
 }
 
 //----------------------------------------------------------------
@@ -173,8 +178,10 @@
     
     W2A(dsw);
     
+#if DEBUG
     printf ("Attempt OGR connect to %s \n", mbdsw);
     printf ("ReadOnly %d\n", (int)readonly);
+#endif
     
     m_poDS = OGRSFDriverRegistrar::Open(mbdsw, !readonly);
     if( m_poDS == NULL )
@@ -185,7 +192,6 @@
         A2W(x);
         throw FdoConnectionException::Create(wx);
     }
-    
     m_connState = FdoConnectionState_Open;
     
     return m_connState;
@@ -193,8 +199,10 @@
 
 void OgrConnection::Close()
 {
+#if DEBUG
     printf ("Close OGR connection\n");
-    
+#endif
+
     if (m_poDS)
     {
         OGRDataSource::DestroyDataSource(m_poDS);
@@ -386,6 +394,7 @@
 
 FdoIFeatureReader* OgrConnection::Select(FdoIdentifier* fcname, FdoFilter* filter, FdoIdentifierCollection* props)
 {
+    bool bbox = false;
     FdoString* fc = fcname->GetName();
     W2A(fc);
 
@@ -393,9 +402,9 @@
     
     OGRLayer* layer = m_poDS->GetLayerByName(mbfc);
 
-    OgrFdoUtil::ApplyFilter(layer, filter);
+    OgrFdoUtil::ApplyFilter(layer, filter, &bbox);
 
-    return new OgrFeatureReader(this, layer, props);
+    return new OgrFeatureReader(this, layer, props, bbox);
 }
 
 FdoIDataReader* OgrConnection::SelectAggregates(FdoIdentifier* fcname, 
@@ -420,8 +429,9 @@
         W2A(pname);
         
         sprintf(sql, "SELECT DISTINCT %s FROM %s", mbpname, mbfc);
+#if DEBUG
         printf (" select distinct: %s\n", sql);
-        
+#endif
         OGRLayer* lr = m_poDS->ExecuteSQL(sql, NULL, NULL);
         
         return new OgrDataReader(this, lr, NULL); 
@@ -438,8 +448,9 @@
         char sql[512];
         
         sprintf(sql, "SELECT %s FROM %s", mbexprs, mbfc);
+#if DEBUG
         printf (" select distinct: %s\n", sql);
- 
+#endif
         OGRLayer* lr = m_poDS->ExecuteSQL(sql, NULL, NULL);
 
         return new OgrDataReader(this, lr, properties); 
@@ -464,7 +475,7 @@
     if (!canDo)
         throw FdoCommandException::Create(L"Current OGR connection does not support update of existing features.");
     
-    OgrFdoUtil::ApplyFilter(layer, filter);
+    OgrFdoUtil::ApplyFilter(layer, filter, NULL);
 
     OGRFeature* feature = NULL;
     
@@ -498,7 +509,7 @@
     if (!canDo)
         throw FdoCommandException::Create(L"Current OGR connection does not support delete.");
 
-    OgrFdoUtil::ApplyFilter(layer, filter);
+    OgrFdoUtil::ApplyFilter(layer, filter, NULL);
 
     std::vector<long> ids; //list of FIDs of features to delete
     
@@ -557,7 +568,7 @@
         char filter[32];
         snprintf(filter, 32, "FID=%d", fid);
         layer->SetAttributeFilter(filter);
-        return new OgrFeatureReader(this, layer, NULL);
+        return new OgrFeatureReader(this, layer, NULL, false);
     }
 
     throw FdoCommandException::Create(L"Insert of feature failed.");
@@ -621,7 +632,7 @@
     m_wkt = wwkt;
     
     OGRFree (wkt);
-    return m_wkt.c_str();
+    return ProjConverter::ProjectionConverter->TranslateProjection(m_wkt.c_str());
 }
 
 FdoSpatialContextExtentType OgrSpatialContextReader::GetExtentType()
@@ -695,7 +706,7 @@
 //
 //---------------------------------------------------------------------
 
-OgrFeatureReader::OgrFeatureReader(OgrConnection* connection, OGRLayer* layer, FdoIdentifierCollection* props)
+OgrFeatureReader::OgrFeatureReader(OgrConnection* connection, OGRLayer* layer, FdoIdentifierCollection* props, bool bboxquery)
 {
     m_connection = connection;
     ((FdoIConnection*)m_connection)->AddRef();
@@ -710,6 +721,7 @@
     m_fgflen = 64;
     m_fgf = new unsigned char[m_fgflen*2];
     m_wkb = new unsigned char[m_fgflen];
+    m_bboxquery = bboxquery;
 }
 
 OgrFeatureReader::~OgrFeatureReader()
@@ -729,6 +741,8 @@
 FdoClassDefinition* OgrFeatureReader::GetClassDefinition()
 {
     //TODO: cache the result of this
+    //also this always returns all properties regardless
+    //of what was given in the select command
     return OgrFdoUtil::ConvertClass(m_poLayer, m_props);
 }
 
@@ -870,23 +884,33 @@
 
 bool OgrFeatureReader::ReadNext()
 {    
-    m_sprops.clear();
-    
-    if (m_poFeature)
-        OGRFeature::DestroyFeature(m_poFeature);
-    
-    m_poFeature = m_poLayer->GetNextFeature();
+    try
+    {
+        m_sprops.clear();
+        
+        if (m_poFeature)
+            OGRFeature::DestroyFeature(m_poFeature);
+        
+        m_poFeature = m_poLayer->GetNextFeature();
 
-    //Ugly hack to fix broken providers, with BBOX only testing
-    OGRGeometry* spfilter = m_poLayer->GetSpatialFilter();
-    if (spfilter != NULL)
-        while (m_poFeature != NULL && m_poFeature->GetGeometryRef() != NULL && !spfilter->Intersects(m_poFeature->GetGeometryRef()))
+        //Ugly hack to fix broken providers, with BBOX only testing
+        if (!m_bboxquery)
         {
-            OGRFeature::DestroyFeature(m_poFeature);
-            m_poFeature = m_poLayer->GetNextFeature();
+            OGRGeometry* spfilter = m_poLayer->GetSpatialFilter();
+            if (spfilter != NULL)
+                while (m_poFeature != NULL && m_poFeature->GetGeometryRef() != NULL && !spfilter->Intersects(m_poFeature->GetGeometryRef()))
+                {
+                    OGRFeature::DestroyFeature(m_poFeature);
+                    m_poFeature = m_poLayer->GetNextFeature();
+                }
         }
 
-    return (m_poFeature != NULL);
+        return (m_poFeature != NULL);
+    }
+    catch(...)
+    {
+        return false;
+    }
 }
 
 void OgrFeatureReader::Close()
@@ -1176,7 +1200,14 @@
 //
 //---------------------------------------------------------------------
 
-int main(void){}
+int main(void)
+{
+    OGRDataSource* ds = OGRSFDriverRegistrar::Open("C:\\Documents and Settings\\Kenneth\\Skrivebord\\bo", TRUE);
+    /*FdoIConnection* con = CreateConnection();
+    con->SetConnectionString(new FdoString(_L"
+    con->Open(*/
+    return 0;
+}
 
 ////HACK This function has a lot of refcount leaks in order
 ////to make the code more concise !!!
Index: OgrProvider.h
===================================================================
--- OgrProvider.h	(revision 3347)
+++ OgrProvider.h	(working copy)
@@ -16,6 +16,7 @@
 //  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 //  
 
+#include "ProjConverter.h"
 
 //fwd decl
 class OGRDataSource;
@@ -168,7 +169,9 @@
     OGR_API virtual FdoInt64 GetMaximumDataValueLength(FdoDataType dataType) { return -1; }
     OGR_API virtual FdoInt32 GetMaximumDecimalPrecision()                    { return -1; }
     OGR_API virtual FdoInt32 GetMaximumDecimalScale()                        { return -1; }
+#ifndef FDO_31
     OGR_API virtual FdoInt32 GetNameSizeLimit(FdoSchemaElementNameType name) { return -1; }
+#endif
     OGR_API virtual FdoString* GetReservedCharactersForName()                { return NULL; }
     
     OGR_API virtual FdoDataType* GetSupportedAutoGeneratedTypes(FdoInt32& length)
@@ -499,12 +502,13 @@
         { return L"3.3.0.0"; }
     OGR_API virtual FdoIConnectionPropertyDictionary* GetConnectionProperties()
         { return FDO_SAFE_ADDREF((FdoIConnectionPropertyDictionary*)this); }
-    
+
+#ifndef FDO_31
     //TODO: in the OGR case this varies -- we could find out the correct answer
     //once the connection properties are set
     OGR_API virtual FdoProviderDatastoreType GetProviderDatastoreType() 
         { return FdoProviderDatastoreType_Unknown; } 
-
+#endif
     //TODO: in the OGR case this varies -- we could find out the correct answer
     //once the connection properties are set
     OGR_API virtual FdoStringCollection* GetDependentFileNames()
@@ -993,7 +997,7 @@
 {
     public:
         OGR_API OgrFeatureReader(OgrConnection* connection,
-                                 OGRLayer* layer, FdoIdentifierCollection* props);
+                                 OGRLayer* layer, FdoIdentifierCollection* props, bool bboxquery);
 
     protected:
         OGR_API virtual ~OgrFeatureReader();
@@ -1045,6 +1049,7 @@
         unsigned char* m_fgf;
         unsigned char* m_wkb;
         size_t m_fgflen;
+        bool m_bboxquery;
 };
 
 
Index: OGRProvider.vcproj
===================================================================
--- OGRProvider.vcproj	(revision 3347)
+++ OGRProvider.vcproj	(working copy)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="Windows-1252"?>
 <VisualStudioProject
 	ProjectType="Visual C++"
-	Version="8.00"
+	Version="8,00"
 	Name="OGRProvider"
 	ProjectGUID="{967D184A-B00F-4C80-9382-58AEC6CBA16A}"
 	RootNamespace="OGRProvider"
@@ -195,6 +195,14 @@
 			>
 		</File>
 		<File
+			RelativePath=".\ProjConverter.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\ProjConverter.h"
+			>
+		</File>
+		<File
 			RelativePath=".\stdafx.h"
 			>
 		</File>
Index: ProjConverter.cpp
===================================================================
--- ProjConverter.cpp	(revision 0)
+++ ProjConverter.cpp	(revision 0)
@@ -0,0 +1,99 @@
+// 
+//  
+//  Copyright (C) 2007 Autodesk Inc.
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//  
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//  
+
+#include "stdafx.h"
+#include "ProjConverter.h"
+#include <iostream>
+#include <fstream>
+using namespace std;
+
+const wchar_t* ProjConverter::TranslateProjection(const wchar_t* proj)
+{
+    //Quick return if no translations are installed
+    if (m_translations.size() == 0)
+        return proj;
+
+    W2A(proj);
+    string s(mbproj);
+
+    std::map<std::string, std::string>::iterator res = m_translations.find(s);
+    if (res != m_translations.end())
+    {
+#if DEBUG
+        printf("Converted projection from %s to %s\", mbproj, res->second.c_str());
+#endif
+        const char* y = res->second.c_str();
+        A2W(y);
+        proj = wy;
+    }
+
+    return proj;
+}
+
+bool ProjConverter::GetLine(ifstream& infile, char* dest, std::streamsize buffersize)
+{
+    while(infile.good())
+    {
+        infile.getline(dest, buffersize);
+
+        int p = 0;
+        char c = dest[p];
+
+        while ((c == ' ' || c == '\t') && p < buffersize)
+            c = dest[p++];
+
+        //Filter blanks and comments
+        if (dest[p] == '#' || dest[p] == '\n' || dest[p] == '\r')
+            continue;
+
+        return true;
+    }
+    return false;
+}
+
+ProjConverter::ProjConverter()
+{
+    ifstream infile;
+    try
+    {
+        char fromline[8096];
+        char toline[8096];
+
+        infile.open ("projections.txt", ifstream::in);
+        do
+        {
+            if (GetLine(infile, fromline, 8096) && GetLine(infile, toline, 8096))
+                m_translations.insert(make_pair(fromline, toline));
+            else
+                break;
+                
+        } while(true);
+    }
+    catch (...)
+    {
+    }
+#if DEBUG
+    printf("OGR Provider loaded %d projections\n",  m_translations.size());
+#endif
+}
+
+ProjConverter::~ProjConverter()
+{
+}
+
+ProjConverter* ProjConverter::ProjectionConverter = NULL;
Index: ProjConverter.h
===================================================================
--- ProjConverter.h	(revision 0)
+++ ProjConverter.h	(revision 0)
@@ -0,0 +1,36 @@
+// 
+//  
+//  Copyright (C) 2007 Autodesk Inc.
+//  
+//  This library is free software; you can redistribute it and/or
+//  modify it under the terms of version 2.1 of the GNU Lesser
+//  General Public License as published by the Free Software Foundation.
+//  
+//  This library is distributed in the hope that it will be useful,
+//  but WITHOUT ANY WARRANTY; without even the implied warranty of
+//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//  Lesser General Public License for more details.
+//  
+//  You should have received a copy of the GNU Lesser General Public
+//  License along with this library; if not, write to the Free Software
+//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+//  
+
+#pragma once
+#include <windows.h>
+#include <map>
+#include <string>
+
+class ProjConverter
+{
+    private:
+        std::map<std::string, std::string> m_translations;
+        bool GetLine(std::ifstream& infile, char* dest, std::streamsize buffersize);
+
+    public:
+        ProjConverter();
+        virtual ~ProjConverter();
+        const wchar_t* TranslateProjection(const wchar_t* proj);
+        static ProjConverter* ProjectionConverter;
+
+};


More information about the mapguide-internals mailing list