[fdo-commits] r831 - in branches/3.2.x/Utilities/Common: Inc Src

svn_fdo at osgeo.org svn_fdo at osgeo.org
Fri Mar 9 13:32:29 EST 2007


Author: badreddinekaroui
Date: 2007-03-09 13:32:29 -0500 (Fri, 09 Mar 2007)
New Revision: 831

Modified:
   branches/3.2.x/Utilities/Common/Inc/FdoCommonFilterExecutor.h
   branches/3.2.x/Utilities/Common/Src/FdoCommonFilterExecutor.cpp
Log:
Merge ticket #21 fix from 2.1.1 branch to 2.1.x

Modified: branches/3.2.x/Utilities/Common/Inc/FdoCommonFilterExecutor.h
===================================================================
--- branches/3.2.x/Utilities/Common/Inc/FdoCommonFilterExecutor.h	2007-03-09 18:04:06 UTC (rev 830)
+++ branches/3.2.x/Utilities/Common/Inc/FdoCommonFilterExecutor.h	2007-03-09 18:32:29 UTC (rev 831)
@@ -79,6 +79,14 @@
     /// 
 	static void ValidateFilter( FdoClassDefinition *cls, FdoFilter *filter, FdoIdentifierCollection *selIds = NULL, FdoIFilterCapabilities *filterCapabilities = NULL);
 
+	/// \brief
+    /// Attempt to optimize the input filter by producing a new more efficient filter.
+    /// 
+    /// \return
+	/// Return a new refcounted filter that may be the same input filter with an extra addref.
+    /// 
+	static FdoFilter* OptimizeFilter( FdoFilter *filter );
+
     /// \brief
     /// Increase the reference count.
     /// 

Modified: branches/3.2.x/Utilities/Common/Src/FdoCommonFilterExecutor.cpp
===================================================================
--- branches/3.2.x/Utilities/Common/Src/FdoCommonFilterExecutor.cpp	2007-03-09 18:04:06 UTC (rev 830)
+++ branches/3.2.x/Utilities/Common/Src/FdoCommonFilterExecutor.cpp	2007-03-09 18:32:29 UTC (rev 831)
@@ -3973,3 +3973,156 @@
     filter->Process( &validator ); 
 }
 
+FdoFilter* FdoCommonFilterExecutor::OptimizeFilter( FdoFilter *filter )
+{
+	// This is mostly a place holder for potential filter optimization
+
+	// For now we just reduce a simple case with potentiel significant performance improvement
+	// This is the case where a filter has 2 and'ed spatial conditions that can be reduced to a 
+	// single spatial condition.
+ class FdoCommonFilterOptimizer :  public virtual FdoIFilterProcessor
+    {
+    private:
+        FdoPtr<FdoFilter>	 m_newFilter;
+		bool				 m_isOptimized;
+		FdoPtr<FdoIGeometry> m_geomRight;
+		FdoPtr<FdoIGeometry> m_geomLeft;
+
+    protected:
+        void HandleFilter( FdoFilter *filter )
+        {
+            filter->Process( this );
+        }
+    public:
+
+		FdoCommonFilterOptimizer( ): m_isOptimized(false),m_newFilter(NULL)
+        {
+        }
+
+		bool IsOptimized() { return m_isOptimized; }
+
+		FdoFilter* OptimizedFilter() { return FDO_SAFE_ADDREF(m_newFilter.p); }
+
+        virtual void Dispose() { delete this; }
+       
+        virtual void ProcessBinaryLogicalOperator(FdoBinaryLogicalOperator& filter)
+        {
+			if( filter.GetOperation() != FdoBinaryLogicalOperations_And )
+			{
+				m_isOptimized = false;
+				return;
+			}
+            HandleFilter( FdoPtr<FdoFilter>(filter.GetLeftOperand()) );
+            HandleFilter( FdoPtr<FdoFilter>(filter.GetRightOperand()) );
+        }
+        virtual void ProcessComparisonCondition(FdoComparisonCondition& filter)
+        {
+            m_isOptimized = false;
+			return;
+        }
+        virtual void ProcessDistanceCondition(FdoDistanceCondition& filter)
+		{  
+			m_isOptimized = false;
+			return;
+		}
+
+        virtual void ProcessInCondition(FdoInCondition& filter)
+        {
+			m_isOptimized = false;
+			return;
+        }
+        virtual void ProcessNullCondition(FdoNullCondition& filter)
+        {
+            m_isOptimized = false;
+			return;
+        }
+        virtual void ProcessSpatialCondition(FdoSpatialCondition& filter)
+		{  
+			bool isleft = ( m_geomLeft == NULL );
+			
+			FdoPtr<FdoExpression> exprRight = filter.GetGeometry ();
+			FdoGeometryValue* gv = dynamic_cast<FdoGeometryValue*>(exprRight.p);
+			if (!gv)
+			{
+				m_isOptimized = false;
+				return;
+			}
+
+			if( filter.GetOperation() == FdoSpatialOperations_Disjoint )
+			{
+				m_isOptimized = false;
+				return;
+			}
+
+			FdoPtr<FdoByteArray> ba = gv->GetGeometry ();
+			FdoPtr<FdoFgfGeometryFactory> gf = FdoFgfGeometryFactory::GetInstance ();
+			if( isleft )
+			{
+				m_geomLeft = gf->CreateGeometryFromFgf (ba);
+				m_newFilter = FDO_SAFE_ADDREF(&filter);
+			}
+			else
+			{
+				m_geomRight = gf->CreateGeometryFromFgf (ba);
+
+			
+				bool ret = FdoSpatialUtility::Evaluate (m_geomLeft, FdoSpatialOperations_Inside, m_geomRight);
+				if( ret )
+				{
+					m_isOptimized = true;
+					return;
+				}
+				ret = FdoSpatialUtility::Evaluate (m_geomRight, FdoSpatialOperations_Inside, m_geomLeft );
+				if( ret )
+				{
+					m_isOptimized = true;
+					m_newFilter = FDO_SAFE_ADDREF(&filter);
+					return;
+				}
+				ret = FdoSpatialUtility::Evaluate (m_geomRight, FdoSpatialOperations_Disjoint, m_geomLeft );
+				if( ret )
+				{
+					// If the condition do not overlap, then replace it with a filter that returns 0 features.
+					double small_dbl  =(double)(-9223372036854775807i64 - 1);
+					m_isOptimized = true;
+					FdoPtr<FdoFgfGeometryFactory> gf = FdoFgfGeometryFactory::GetInstance();
+
+					double coords[] = { small_dbl, small_dbl, 
+										small_dbl, small_dbl, 
+										small_dbl, small_dbl, 
+										small_dbl, small_dbl, 
+										small_dbl, small_dbl }; 
+
+					FdoPtr<FdoILinearRing> outer = gf->CreateLinearRing(0, 10, coords);
+
+					FdoPtr<FdoIPolygon> poly = gf->CreatePolygon(outer, NULL);
+
+					FdoPtr<FdoByteArray> polyfgf = gf->GetFgf(poly);
+					FdoPtr<FdoGeometryValue> gv = FdoGeometryValue::Create(polyfgf);
+					m_newFilter = FdoSpatialCondition::Create(FdoPtr<FdoIdentifier>(filter.GetPropertyName())->GetName(), FdoSpatialOperations_EnvelopeIntersects, gv);
+					return;
+				}
+
+				// Otherwise we make sure that the condition with the FdoSpatialOperations_EnvelopeIntersects is the left condition
+				if( filter.GetOperation() == FdoSpatialOperations_EnvelopeIntersects )
+				{
+					// Let's re-arrage the filter to favor evaluating the envelope intersect first.
+					m_newFilter = FdoFilter::Combine( &filter  , FdoBinaryLogicalOperations_And,  m_newFilter );
+					m_isOptimized = true;
+					return;
+				}
+			}
+		}
+
+        virtual void ProcessUnaryLogicalOperator(FdoUnaryLogicalOperator& filter)
+        {
+            m_isOptimized = false;
+			return;
+        }
+    };
+
+    FdoCommonFilterOptimizer  optimizer;
+    filter->Process( &optimizer ); 
+
+	return optimizer.IsOptimized()?optimizer.OptimizedFilter():FDO_SAFE_ADDREF(filter);
+}
\ No newline at end of file



More information about the fdo-commits mailing list