ThinkGeo.com    |     Documentation    |     Premium Support

Using in-memory spatial index

Hello,


I am trying to use an in-memory spatial index and got into trouble.


File-based RtreeSpatialIndex works without errors but it is too slow for our needs, so I thought of handling StreamLoading event and assigning a MemoryStream to args.AlternateStream. This approach fails when I try to open the index:


 


  System.IndexOutOfRangeException occurred
  HResult=-2146233080
  Message=Index was outside the bounds of the array.
  Source=MapSuiteCore
  StackTrace:
       at hxQ=.RU4=.khQ=(BinaryReader SU4=)

Extended stack trace:
  MapSuiteCore.dll!hxQ=.RU4=.khQ=(System.IO.BinaryReader SU4=) + 0x10c bytes
  MapSuiteCore.dll!hxQ=.h0A=.khQ=() + 0x90 bytes
  MapSuiteCore.dll!hxQ=.PjY=.VzY=() + 0x14 bytes
  MapSuiteCore.dll!hxQ=.PjY=.Dxg=(string UzY=, bool VDY=, ThinkGeo.MapSuite.Core.RtreeSpatialIndex.q0Y= VTY=) + 0x97 bytes
  MapSuiteCore.dll!ThinkGeo.MapSuite.Core.RtreeSpatialIndex.OpenCore() + 0x7f bytes
  MapSuiteCore.dll!ThinkGeo.MapSuite.Core.SpatialIndex.Open() + 0x22 bytes
 
I also tried to use RtreeSpatialIndex.CreatePointSpatialIndex(filePath,...) and initialize the memory stream with the content of the .idx file. That got me past Open() but failed on Add():

  System.NullReferenceException occurred
  HResult=-2147467261
  Message=Object reference not set to an instance of an object.
  Source=MapSuiteCore
  StackTrace:
       at hxQ=.YE4=.bE4=(String bU4=)
       at ThinkGeo.MapSuite.Core.RtreeSpatialIndex.bUY=(Double bkY=, Double b0Y=, String cEY=)
       at ThinkGeo.MapSuite.Core.RtreeSpatialIndex.bUY=(PointShape cUY=, String ckY=)
       at ThinkGeo.MapSuite.Core.RtreeSpatialIndex.AddCore(Feature feature)
       at ThinkGeo.MapSuite.Core.SpatialIndex.Add(BaseShape baseShape)
 
I also looked for samples or at least posts on handling Rtree's StreamLoading event but didn't find any.
Any suggestions would be appreciated. 
 
Thanks in advance,
Raul
 

 



 


Hi Raul,
Welcome to Map Suite discussion forum and thanks for your posts.
I guess maybe there are 2 problems here shown as following:
1.       In MapSuiteCore.dll, all the MemoryStream used here should follow the .idx data format. Otherwise, it will throw the exception.
2.       I guess your workaround is really a workable way, but missed setting the “rTreeIndex.ReadWriteMode =RtreeSpatialIndexReadWriteMode.ReadWrite;”. Please check the demo code shown below:
 


        public TestForm()
        {
            InitializeComponent();
        }
        string idxFilePath;
        private void TestForm_Load(object sender, EventArgs e)
        {
            idxFilePath =  @"..\..\~.idx";
            RtreeSpatialIndex rTreeIndex = new RtreeSpatialIndex(idxFilePath, RtreeSpatialIndexReadWriteMode.ReadOnly);
            rTreeIndex.StreamLoading += new EventHandler<StreamLoadingEventArgs>(rTreeIndex_StreamLoading);
            RtreeSpatialIndex.CreateRectangleSpatialIndex(idxFilePath, RtreeSpatialIndexPageSize.EightKilobytes);
            rTreeIndex.ReadWriteMode = RtreeSpatialIndexReadWriteMode.ReadWrite;
            rTreeIndex.Open();
            rTreeIndex.Add(new PointShape(0, 0));
        }

        void rTreeIndex_StreamLoading(object sender, StreamLoadingEventArgs e)
        {
            FileStream fs = new FileStream(idxFilePath, FileMode.Open, FileAccess.ReadWrite);
            byte[] bytes = new byte[fs.Length];
            fs.Read(bytes, 0, (int)fs.Length);
            MemoryStream memoryStream = new MemoryStream(bytes);
            e.AlternateStream = memoryStream;
        }



 
Thanks,
Johnny

Hey Johnny,

Thanks a lot for your reply, the sample code you provided worked with a small correction: creating MemoryStream(byte[]) creates a non-resizable stream based on that byte array. Instead, we'd like something like 


    var memoryStream = new MemoryStream();
    memoryStream.Write(bytes, 0, bytes.Length);



Regards,

Raul

That’s great, any question please feel free to let us know. 
  
 Thanks, 
 Johnny