ThinkGeo.com    |     Documentation    |     Premium Support

Multiple Ellipse Shapes Drawing Slowly

 Hello,


 


I need to represent 1000 lat/lon points on our map.  We have objects that that hold the data for each point.  The points need to be represented as circles of various diameters, filled in with various colors, and have an outline of various colors and various widths, all dictated by the data.


 


Right now I am creating a PointShape for the lat/lon, then creating an EllipseShape using the PointShape, and the required circle width.  I am then creating a new InMemoryFeatureLayer, and adding the EllipseShape to its InternalFeatures.  I then set the layer's DefaultAreaStyle.FillSolidBrush.Color, DefaultAreaStyle.OutlinePen.Color, and DefaultAreaStyle.OutlinePen.Width based on the data for the point, and add the InMemoryFeatureLayer to a LayerOverlay.


 


The problem comes when the map draws this LayerOverlay.  It takes quite a long time, upwards of 15 seconds to show up.  This delay is also apparent every time the map is moved or scaled.  I imagine that is due to the fact that each point/ellipse is in a layer of its own, and not features within a single layer.  The need to draw them with different color combinations and outline pen widths seems to necessitate the multiple layers.


 


What is the best way for me to get this on screen with a faster draw rate?  Can I somehow use columns, or is there another solution?  I am considereing creating a new InMemoryFeatureLayer whenever a new fill color/outline pen color/outline pen width is encountered, and making sure each ellipse gets put into that corresponding layer.  That should reduce the amount of InMemoryFeatureLayers greatly.


 


Any thoughts would be helpful


 


Thanks, 


Dib



I’m a long-time customer and huge fan of ThinkGeo.  I hope I’m not butting in, but we do exactly the type of thing that you are doing, except we draw several thousand of these symbols, theme by color and size, with our app.    
  
 If you have a collection of business objects, I would: 
  
 1)  Create a custom layer (deriving from Layer) 
  
 2) Make the layer operate off of the collection of your business objects as its data source. 
  
 3) Explicitly draw the symbols for each business object within the DrawCore method of the layer.   You’ll know the colors and widths because of the properties that are on your business objects.   So, just use the canvase.DrawEllipse method with styles built from that info. 
  
 We use this approach, and can render 50,000 business objects in 1 to 3 seconds. 
  
 This is really very easy to do… but, as you are not deriving from a FeatureLayer, you’ll loose any ability to use the built in query tools.    If that is important, and you do not want to build your own query support, then derive a new class from a FeatureSource.    And implement the class to work directly off of your business objects, instead of copying them to in-memory feature layers.   Then, you can use the standard styles, etc, but it will be quite a bit slower.   I don’t think the ThinkGeo styles framework is optimized for rendering huge numbers of objects when the styles are determined from scalar values in the Feature objects.

Loading them as features into specific layers made a huge difference.  Seems to be working well that way.

 Thank you very much, Ted, I guess you gave a good answer here. Another option could be “ClassBreakStyle”, we use the “ClassBreakStyle” and created 2000 ellipses, and the drawing time is only 904.2727ms on our end. The code just looks like:




  private void DisplayMap_Load(object sender, EventArgs e)
        {
           …………
            InMemoryFeatureLayer inmLayer = new InMemoryFeatureLayer();
            inmLayer.Open();
            inmLayer.ZoomLevelSet.ZoomLevel01.ApplyUntilZoomLevel = ApplyUntilZoomLevel.Level20;
            ClassBreakStyle classBreakStyle = new ClassBreakStyle("index");
            inmLayer.ZoomLevelSet.ZoomLevel01.CustomStyles.Add(classBreakStyle);
            inmLayer.Columns.Add(new FeatureSourceColumn("index"));

            Random random = new Random();
            for (int i = 0; i < 2000; i++)
            {
                PointShape pointshape = new PointShape(random.Next(0, 100), random.Next(0, 100));
                EllipseShape ellipseShape = new EllipseShape(pointshape, random.Next(1, 3));
                Feature ellipseFeature = new Feature(ellipseShape);
                ellipseFeature.ColumnValues.Add("index", i.ToString());
                inmLayer.InternalFeatures.Add(ellipseFeature);
                ClassBreak classBreak = new ClassBreak(i, new AreaStyle(new GeoPen(GeoColor.GetRandomGeoColor(RandomColorType.All)), new GeoSolidBrush(GeoColor.GetRandomGeoColor(RandomColorType.All))));
                classBreakStyle.ClassBreaks.Add(classBreak);
            }
          …….
        }



Please take a check.


Thanks,


Johnny



 Very interesting.    I've never used ClassBreak with that kind of volume.    I would be interested in seeing your performance with what I think you call a ValueBreak style?   Somthing that breaks on a scalar value, and than make you Index attribute be a double.


 



By the way, if using the InMemoryFeatureLayer, I guess it should be faster after building spatial index for it by calling "BuildIndex()" method. Please have try. 
  
 Thanks, 
 Johnny