ThinkGeo.com    |     Documentation    |     Premium Support

Idx (index) files?

Hello,


 When adding feature layers in version 3.0, I have to set 'RequireIndex' to false in order for it to load, because we don't have any idx files. Can you please let me know if there is any way of generating these indexes, as I believe it may be useful in speeding up the map for our application.


 Thanks 

 



There is a static method in ShapeFileFeatureLayer which builds the index. 
  
 ShapeFileFeatureLayer.BuildIndexFile("c:\shapeFile.shp") 
  
 With Index, the querying will be greatly speeded up and I’m sure you can feel the performance improvements after that. 
  
 Ben.

OK, thanks for that. 
  
 I have run a little program to generate index files for the shape files that we have, however for some of them it is throwing an exception, 
 System.IO.IOException: 
 “The spatial index generation failed for an unknown reason.    Please see the inner exception.” 
  
 and the inner exception is a System.NullReferenceException (‘Object reference not set to an instance of an object’) 
 at: 
    at ThinkGeo.MapSuite.Core.xa65d8a7495fb9e05.Flush() 
    at ThinkGeo.MapSuite.Core.x5ebd7b97ce5cba6c.Flush() 
    at ThinkGeo.MapSuite.Core.ShapeFileFeatureSource.BuildIndexFile(String shapePathFilename, String indexPathFilename, Projection projection, String columnName, String regexExpression, BuildIndexMode buildIndexMode) 
  
 It seems that for most of the important ones it has generated it ok, but just wondering if this is something you would like to know about. 


I’ve tried it using the generated index files and it’s still slow. 
 Strangely it is not much faster with a much smaller set of files which I have filtered to a particular geographic area. 
 The layers I have got on the map are: 00, 01, …, 07, 08 (roads), wa (water areas), and rr (railways), the largest file of which is 47MB, this is the 06 file (local roads). A zoom in, zoom out, or pan operation will cause an approx. 3 to 4 second wait for the map to refresh. Should it be this slow or do you suspect something is amiss? 
  
 This is hte code which I am using: 
 public partial class Window1 : Window 
 { 
  private const string path = @“c:\teleatlasdata”; 
  private readonly List<string> files; 
  public Window1() 
  { 
  InitializeComponent(); 
  files = new List<string>(Directory.GetFiles(path, “*.shp”)); 
  Loaded += delegate 
             { 
  AddRoadLayer(“08”, “LocalRoad4”); 
  AddRoadLayer(“07”, “LocalRoad4”); 
  AddRoadLayer(“06”, “LocalRoad3”); 
  AddRoadLayer(“05”, “LocalRoad3”); 
  AddRoadLayer(“04”, “MajorRoad3”); 
  AddRoadLayer(“03”, “MajorRoad1”); 
  AddRoadLayer(“02”, “SecondaryRoad1”); 
  AddRoadLayer(“01”, “SecondaryRoad1”); 
  AddRoadLayer(“00”, “Highway5”); 
  AddWaterLayer(“wa”); 
  AddRailwayLayer(“rr”); 
  map.CurrentExtent = new RectangleShape(new PointShape(-1.268, 53.140), new PointShape(-1.220, 53.118)); 
  map.Refresh(); 
             }; 
  } 
  
  private void AddRoadLayer(string suffix, string lineStyle) 
  { 
  Debug.WriteLine("Adding " + suffix); 
  foreach (var filename in from f in files where f.EndsWith(suffix + “.shp”) select f) 
  { 
  
  var lineStylesMethod = typeof (LineStyles).GetProperty(lineStyle, BindingFlags.Static | BindingFlags.Public); 
  var shapeLayer = new ShapeFileFeatureLayer(filename, ShapeFileReadWriteMode.ReadOnly); 
  
  shapeLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = (LineStyle) lineStylesMethod.GetValue(null, new object[0]); 
  
  shapeLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; 
  map.StaticOverlay.Layers.Add(shapeLayer); 
  
  var textStylesMethod = typeof (TextStyles).GetMethod(lineStyle, BindingFlags.Static | BindingFlags.Public); 
  var labelNameLayer = new ShapeFileFeatureLayer(filename, ShapeFileReadWriteMode.ReadOnly); 
  
  labelNameLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = (TextStyle) textStylesMethod.Invoke(null, new[] {“NAME”}); 
  
  labelNameLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; 
  map.StaticOverlay.Layers.Add(labelNameLayer); 
  } 
  } 
  
  private void AddWaterLayer(string suffix) 
  { 
  foreach (var filename in from f in files where f.EndsWith(suffix + “.shp”) select f) 
  { 
  var shapeLayer = new ShapeFileFeatureLayer(filename, ShapeFileReadWriteMode.ReadOnly); 
  shapeLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.River1; 
  shapeLayer.ZoomLevelSet.ZoomLevel01.DefaultAreaStyle = AreaStyles.Water1; 
  shapeLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; 
  map.StaticOverlay.Layers.Add(shapeLayer); 
  
  var labelLayer = new ShapeFileFeatureLayer(filename, ShapeFileReadWriteMode.ReadOnly); 
  labelLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.Water1(“NAME”); 
  labelLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; 
  map.StaticOverlay.Layers.Add(labelLayer); 
  } 
  
  } 
  
  private void AddRailwayLayer(string suffix) 
  { 
  foreach (var filename in from f in files where f.EndsWith(suffix + “.shp”) select f) 
  { 
  var shapeLayer = new ShapeFileFeatureLayer(filename, ShapeFileReadWriteMode.ReadOnly); 
  shapeLayer.ZoomLevelSet.ZoomLevel01.DefaultLineStyle = LineStyles.Railway1; 
  shapeLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; 
  map.StaticOverlay.Layers.Add(shapeLayer); 
  
  var labelLayer = new ShapeFileFeatureLayer(filename, ShapeFileReadWriteMode.ReadOnly); 
  labelLayer.ZoomLevelSet.ZoomLevel01.DefaultTextStyle = TextStyles.Railway1(“NAME”); 
  labelLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20; 
  map.StaticOverlay.Layers.Add(labelLayer); 
  } 
  } 
 }

Thanks for your code!  Ben 


Can you try the following steps to see where the time-consuming part is?
1, Get the latest Beta (3.0.131, will be released tomorrow) which did some improvements for building index, please make sure every shape file has its idx/ids files. Or to be safe, remove all the idx/ids and build index again.
 
2, Get the elapsed time for Map.Refresh(). I saw you are using reflection, which usually doesn’t take that much time, but still want to make sure most time is consumed on drawing the map. The code may be like this:
 

using System.Diagnostics;
// ……
Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();
        map.Refresh();
        Debug.WriteLine(stopWatch.ElapsedMilliseconds + “ms”);

3, If most time is consumed in map.Refresh(), please print out the drawing time for every layer, you can do it with the following function.
 

  private void PrintLayersDrawingTime()
        {
            foreach (ShapeFileFeatureLayer layer in winformsMap1.StaticOverlay.Layers)
            {
                System.Diagnostics.Debug.WriteLine(layer.ShapePathFileName + ": " + layer.DrawingTime.Milliseconds + "ms");
            }
        }

 
4, Analyze the result. In most cases there is only one or two layer which takes extremely longer drawing time. Can you just draw those layers with other layers commented out. If possible, can you send me a snapshot of the map in that case or send the data to me for a further investigation.
 
Let us know for any more queries.
 
Ben