ThinkGeo.com    |     Documentation    |     Premium Support

SQLite Layer

Following on from an earlier discussion I have been trying out using SQLite for a custom layer (just lines and polygons at the moment).  I based my new layer on the example ExtendingMapSuiteFeatureSource and it works really well however my new layer does not appear to have a bounding box.  As a guess I tried overriding GetBoundingBoxCore in the new feature source class but that didn’t help as it doesn’t seem to get called from anywhere.



Could you help me with setting the bounding box for my new layer?



Regards,

Jonathan

Hi Jonathan, 
  
 Sorry I haven’t find original post, and if I misunderstand your question please let me know. 
  
 Do you meant you modify our sample ExtendingMapSuiteFeatureSource to render your layer, and your layer data is saved in SQLite. 
  
 This layer can be render well, but GetBoundingBox function don’t works, is that right? 
  
 Any sample or more exactly information should be helpful. 
  
 Regards, 
  
 Don

Don,



Your description is exactly right.  The layer renders well but get bounding box for the layer returns an error as the bounding box is not defined.



The code for the feature source layer is:

(Not I added the override to GetBoundingBoxCore as an attempt to fix the getBoundingBox error.




using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Data.SQLite;
using ThinkGeo.MapSuite.Core;
 
namespace PTSimpleMapper
{
    class clsPearFeatureSource : FeatureSource
    {
 
        private SQLiteConnection pearConnection = new SQLiteConnection();
 
        // Default constructor
        // Should chain to a more complex constructor when add more functionality
        public clsPearFeatureSource() { }
 
        // OVERRIDE STANDARD FUNCTIONS
 
        // Open core 
        protected override void OpenCore()
        {
            pearConnection = new SQLiteConnection(@“Data Source=C:\Users\Jonathan\Documents\Visual Studio 2008\Projects\TestSQLite\TestSQLite\bin\Debug\myTestDB.db”);
            pearConnection.Open();
        }
 
        // Close core
        protected override void CloseCore()
        {
            pearConnection.Close();
        }
 
        protected override Collection<Feature> GetAllFeaturesCore(IEnumerable<string> returningColumnNames)
        {
 
            Collection<Feature> rtn = new Collection<Feature>();
            string theSQL = “SELECT Key, Value FROM Setting”;
            SQLiteCommand getAllFeatures = new SQLiteCommand(theSQL, pearConnection);
 
            try
            {
                using (SQLiteDataReader reader = getAllFeatures.ExecuteReader())
                {
                    while (reader.Read())
                    { rtn.Add(new Feature(reader[“Value”].ToString())); }
                }
            }
            finally
            {
                if (!getAllFeatures.Equals(null)) { getAllFeatures.Dispose(); }
            }
 
            return rtn;
        }
 
        protected override Collection<Feature> GetFeaturesInsideBoundingBoxCore(RectangleShape boundingBox, IEnumerable<string> returningColumnNames)
        {
 
            Collection<Feature> rtn = new Collection<Feature>();
            string theSQL = string.Format(“SELECT Key, Value FROM Setting WHERE”
                " NOT (LR_Y >= {0}) AND NOT (UL_Y <= {1}) AND NOT (LR_X <= {2}) AND NOT (UL_X >= {3})",
                boundingBox.UpperLeftPoint.Y,
                boundingBox.LowerRightPoint.Y,
                boundingBox.UpperLeftPoint.X,
                boundingBox.LowerRightPoint.X);
 
            SQLiteCommand getAllFeatures = new SQLiteCommand(theSQL, pearConnection);
 
            try
            {
                using (SQLiteDataReader reader = getAllFeatures.ExecuteReader())
                {
                    while (reader.Read())
                    { rtn.Add(new Feature(reader[“Value”].ToString())); }
                }
            }
            finally
            {
                if (!getAllFeatures.Equals(null)) { getAllFeatures.Dispose(); }
            }
 
            return rtn;
        }
 
        protected override RectangleShape GetBoundingBoxCore()
        {
 
            RectangleShape rtn = new RectangleShape();
 
            string[] theSQL = new string[4] {
                “SELECT MAX(UL_Y) FROM Settings”,
                “SELECT MIN(LR_Y) FROM Settings”,
                “SELECT MAX(LR_X) FROM Settings”,
                “SELECT MIN(UL_X) FROM Settings”};
 
            double[] theLimits = new double[4] { 0, 0, 0, 0 };
 
            try
            {
                theLimits[0] = Convert.ToInt32(new SQLiteCommand(theSQL[0], pearConnection).ExecuteScalar());
                theLimits[1] = Convert.ToInt32(new SQLiteCommand(theSQL[1], pearConnection).ExecuteScalar());
                theLimits[2] = Convert.ToInt32(new SQLiteCommand(theSQL[2], pearConnection).ExecuteScalar());
                theLimits[3] = Convert.ToInt32(new SQLiteCommand(theSQL[3], pearConnection).ExecuteScalar());
 
                PointShape ul = new PointShape(theLimits[4], theLimits[1]);
                PointShape lr = new PointShape(theLimits[3], theLimits[2]);
 
                rtn = new RectangleShape(ul, lr);
 
            }
            finally
            {
            }
 
            return rtn;
        }
 
        protected override int GetCountCore()
        {
            int rtn = 0;
            string theSQL = “SELECT COUNT(*) FROM Setting”;
            SQLiteCommand getCount = new SQLiteCommand(theSQL, pearConnection);
 
            try
            
                rtn = Convert.ToInt32(getCount.ExecuteScalar()); 
            }
            finally
            {
                if (!getCount.Equals(null)) { getCount.Dispose(); }
            }
 
            return rtn;
        }
 
    }
}

The error I get when trying “theMap.CurrentExtent = theOverlay.Layers.First().GetBoundingBox();” is:



System.NotSupportedException was unhandled
  Message=“This Layer doesn’t have a boundingBox.”
  Source=“MapSuiteCore”
  StackTrace:
       at ohM=.TFA=.ZVE=(Boolean ZlE=)
       at ThinkGeo.MapSuite.Core.Layer.GetBoundingBox()
       at PTSimpleMapper.clsProjectSupport.findFirstBoundingBox(WinformsMap& theMap, LayerOverlay& theOverlay) in C:\Users\Jonathan\Documents\Visual Studio 2008\Projects\simpleMapper\simpleMapper\MapProject\clsProjectSupport.cs:line 383
       at PTSimpleMapper.clsProjectSupport.showFullExtent(WinformsMap& theMap, LayerOverlay& theOverlay) in C:\Users\Jonathan\Documents\Visual Studio 2008\Projects\simpleMapper\simpleMapper\MapProject\clsProjectSupport.cs:line 368
       at PTSimpleMapper.clsProjectSupport.showFullExtent(WinformsMap& theMap) in C:\Users\Jonathan\Documents\Visual Studio 2008\Projects\simpleMapper\simpleMapper\MapProject\clsProjectSupport.cs:line 478
       at PTSimpleMapper.frmMap.anyNavigationButton_Click(Object sender, EventArgs e) in C:\Users\Jonathan\Documents\Visual Studio 2008\Projects\simpleMapper\simpleMapper\Forms and Dialogs\frmMap.cs:line 1103
       at System.Windows.Forms.Control.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnClick(EventArgs e)
       at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
       at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
       at System.Windows.Forms.Control.WndProc(Message& m)
       at System.Windows.Forms.ButtonBase.WndProc(Message& m)
       at System.Windows.Forms.Button.WndProc(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
       at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
       at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
       at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
       at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
       at System.Windows.Forms.Application.Run(Form mainForm)
       at PTSimpleMapper.Program.Main() in C:\Users\Jonathan\Documents\Visual Studio 2008\Projects\simpleMapper\simpleMapper\Program.cs:line 18
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException: 



Regards,

Jonathan

I may have solved this one, but I would like to know if I’m going about it the right way? 
  
 In the featureLayer I did a simple override of HasBoundingBox to return TRUE.  This resulted in the FeatureSource function GetBoundingBoxCore being called.  There were a few errors in my code for this function but they were quite easy to fix. 
  
 Is it OK to simply return TRUS? or should I be doing some sort of check or something for HasBoundingBox? 
  
 Regards, 
 Jonathan

Hi Jonathan, 
  
 I think you are right, as below is the description about HasBoundingBox: 
  
 This property indicates whether a Layer has a BoundingBox or not. If it has no BoundingBox, it will throw an exception when you call the GetBoundingBox() and GetFullExtent() APIs. 
  
 So just override HasBoundingBox is OK. 
  
   public override bool HasBoundingBox 
         { 
             get { return true; } 
         } 
  
 Regards, 
  
 Don 


Don, 
  
 OK, thanks.  I did think I might put in one simple check and only return true for HasBoundingBox if the count of features is not zero. 
  
 All the best, 
 Jonathan

Jonathan, 
  
 You can just return a new RectangleShape if the feature number is zero in GetBoundingBoxCore. 
  
 Regards, 
  
 Don

Don, 
  
 Thank you, that makes good sense. 
  
 Regards, 
 Jonathan

Jonathan, 
  
 I am glad to know my reply helpful, any question please let us know. 
  
 Reagards, 
  
 Don