protected void AssignFastDrawnStates()
 {
     _drawnStatesNeeded = true;
     _drawnStates = new FastDrawnState[DataSet.ShapeIndices.Count];
     _selection = new IndexSelection(this); // update the new drawn-states;
     _selection.Changed += SelectedFeaturesChanged;
     // Fastest when no categories are used because we don't need DataTable at all
     List<IFeatureCategory> categories = _scheme.GetCategories().ToList();
     IFeatureCategory deflt = null;
     if(categories.Count > 0 && categories[0].FilterExpression == null) deflt = categories[0];
     for (int i = 0; i < DataSet.ShapeIndices.Count; i++)
     {
         _drawnStates[i] = new FastDrawnState();
         _drawnStates[i].Category = deflt;
     }
     if(categories.Count == 1 && categories[0].FilterExpression == null) return;
     bool containsFID = false;
     DataTable table = DataSet.DataTable;
     foreach (var category in categories)
     {
         if (category.FilterExpression != null && category.FilterExpression.Contains("[FID]"))
         {
             containsFID = true;
         }
     }
     if(containsFID && table.Columns.Contains("FID") == false)
     {
         table.Columns.Add("FID");
         for(int i = 0; i < table.Rows.Count; i++)
         {
             table.Rows[i]["FID"] = i;
         }
     }
     foreach (var category in categories)
     {
         DataRow[] result = table.Select(category.FilterExpression);
         foreach (DataRow row in result)
         {
             _drawnStates[table.Rows.IndexOf(row)].Category = category;
         }
     }
     if(containsFID)table.Columns.Remove("FID");
     
 }
        // This draws the individual line features
        private void DrawFeatures(MapArgs e, IEnumerable<int> indices)
        {
            Graphics g = e.Device ?? Graphics.FromImage(_backBuffer);

            double minX = e.MinX;
            double maxY = e.MaxY;
            double dx = e.Dx;
            double dy = e.Dy;
            if(!DrawnStatesNeeded)
            {
                if(Symbology == null || Symbology.Categories.Count == 0) return;
                FastDrawnState state = new FastDrawnState(false, Symbology.Categories[0]);
                IPointCategory pc = state.Category as IPointCategory;
                IPointSymbolizer ps = null;
                if(pc != null && pc.Symbolizer !=null) ps = pc.Symbolizer;
                if (ps == null) return;
                g.SmoothingMode = ps.Smoothing ? SmoothingMode.AntiAlias : SmoothingMode.None;
                double[] vertices = DataSet.Vertex;
                foreach (int index in indices)
                {
                    if(!DrawnStates[index].Visible) continue;
                    if(DataSet.FeatureType == FeatureTypes.Point)
                    {
                        System.Drawing.Point pt = new System.Drawing.Point();
                        pt.X = Convert.ToInt32((vertices[index * 2] - minX) * dx);
                        pt.Y = Convert.ToInt32((maxY - vertices[index * 2 + 1]) * dy);
                        double scaleSize = 1;
                        if (ps.ScaleMode == ScaleModes.Geographic)
                        {
                            scaleSize = e.ImageRectangle.Width / e.GeographicExtents.Width;
                        }
                        Matrix old = g.Transform;
                        Matrix shift = g.Transform;
                        shift.Translate(pt.X, pt.Y);
                        g.Transform = shift;
                        ps.Draw(g, scaleSize);
                        g.Transform = old;
                    }
                    else
                    {
                        // multi-point
                        ShapeRange range = DataSet.ShapeIndices[index];
                        for (int i = range.StartIndex; i <= range.EndIndex(); i++)
                        {
                            System.Drawing.Point pt = new System.Drawing.Point();
                            pt.X = Convert.ToInt32((vertices[i * 2 ] - minX) * dx);
                            pt.Y = Convert.ToInt32((maxY - vertices[i * 2 + 1]) * dy);
                            double scaleSize = 1;
                            if (ps.ScaleMode == ScaleModes.Geographic)
                            {
                                scaleSize = e.ImageRectangle.Width / e.GeographicExtents.Width;
                            }
                            Matrix old = g.Transform;
                            Matrix shift = g.Transform;
                            shift.Translate(pt.X, pt.Y);
                            g.Transform = shift;
                            ps.Draw(g, scaleSize);
                            g.Transform = old;

                        }
                    }
                }
            }
            else
            {
                FastDrawnState[] states = DrawnStates;
                double[] vertices = DataSet.Vertex;
                foreach (IPointCategory category in Symbology.Categories)
                {
                    if (category.Symbolizer == null) continue;
                    
                    double scaleSize = 1;
                    if (category.Symbolizer.ScaleMode == ScaleModes.Geographic)
                    {
                        scaleSize = e.ImageRectangle.Width / e.GeographicExtents.Width;
                    }
                    Size2D size = category.Symbolizer.GetSize();
                    if (size.Width * scaleSize < 1 || size.Height * scaleSize < 1) continue;
                    

                    Bitmap normalSymbol = new Bitmap((int)(size.Width * scaleSize), (int)(size.Height * scaleSize));
                    Graphics bg = Graphics.FromImage(normalSymbol);
                    bg.SmoothingMode = category.Symbolizer.Smoothing ? SmoothingMode.AntiAlias : SmoothingMode.None;
                    Matrix trans = bg.Transform;
                    trans.Translate((float)size.Width/2, (float)size.Height/2);
                    bg.Transform = trans;
                    category.Symbolizer.Draw(bg, 1);


                    Size2D selSize = category.SelectionSymbolizer.GetSize();
                    if (selSize.Width * scaleSize < 1 || selSize.Height * scaleSize < 1) continue;

                    Bitmap selectedSymbol = new Bitmap((int)(size.Width * scaleSize), (int)(size.Height * scaleSize));
                    Graphics sg = Graphics.FromImage(selectedSymbol);
                    sg.SmoothingMode = category.SelectionSymbolizer.Smoothing ? SmoothingMode.AntiAlias : SmoothingMode.None;
                    Matrix trans2 = bg.Transform;
                    trans2.Translate((float)size.Width / 2, (float)size.Height / 2);
                    sg.Transform = trans2;
                    category.Symbolizer.Draw(sg, 1);


                    
                    foreach (int index in indices)
                    {
                        
                        FastDrawnState state = states[index];
                        if (!state.Visible) continue;
                        if (state.Category == null) continue;
                        IPointCategory pc = state.Category as IPointCategory;
                        if (pc == null) continue;
                        if (pc != category) continue;
                        Bitmap bmp = normalSymbol;
                        if (state.Selected)
                        {
                            bmp = selectedSymbol;
                        }
                        if (DataSet.FeatureType == FeatureTypes.Point)
                        {
                            System.Drawing.Point pt = new System.Drawing.Point();
                            pt.X = Convert.ToInt32((vertices[index * 2] - minX) * dx);
                            pt.Y = Convert.ToInt32((maxY - vertices[index * 2 + 1]) * dy);
                            
                            Matrix old = g.Transform;
                            Matrix shift = g.Transform;
                            shift.Translate(pt.X, pt.Y);
                            g.Transform = shift;
                            g.DrawImageUnscaled(bmp, -bmp.Width/2,-bmp.Height/2);
                            g.Transform = old;
                        }
                        else
                        {
                            ShapeRange range = DataSet.ShapeIndices[index];
                            for (int i = range.StartIndex; i <= range.EndIndex(); i++)
                            {
                                System.Drawing.Point pt = new System.Drawing.Point();
                                pt.X = Convert.ToInt32((vertices[i*2] - minX)*dx);
                                pt.Y = Convert.ToInt32((maxY - vertices[i*2 + 1])*dy);
                                
                                Matrix old = g.Transform;
                                Matrix shift = g.Transform;
                                shift.Translate(pt.X, pt.Y);
                                g.Transform = shift;
                                g.DrawImageUnscaled(bmp, -bmp.Width / 2, -bmp.Height / 2);
                                g.Transform = old;

                            }
                        }
                    }
                }

                if (e.Device == null) g.Dispose();

            }
            
        }
 private void BuildPaths(MapArgs e, IEnumerable<int> indices, out List<GraphicsPath> paths)
 {
     paths = new List<GraphicsPath>();     
     Extent drawExtents = new Extent(e.PixelToProj(_drawingBounds));
     Dictionary<FastDrawnState, GraphicsPath> borders = new Dictionary<FastDrawnState, GraphicsPath>();
     for (int selectState = 0; selectState < 2; selectState++)
     {
         foreach (IPolygonCategory category in Symbology.Categories)
         {
             FastDrawnState state = new FastDrawnState(selectState == 1, category);
             
             GraphicsPath border = new GraphicsPath();
             borders.Add(state, border);
             paths.Add(border);
         }
     }
     List<ShapeRange> shapes = DataSet.ShapeIndices;
     double[] vertices = DataSet.Vertex;
     if(!DrawnStatesNeeded)
     {
         FastDrawnState state = new FastDrawnState(false, Symbology.Categories[0]);
         foreach (int shp in indices)
         {
             ShapeRange shape = shapes[shp];
             if (!shape.Extent.Intersects(e.GeographicExtents)) continue;
             if(shp >= shapes.Count) continue;
             if (!borders.ContainsKey(state)) continue;
             if (drawExtents.Contains(shape.Extent))
             {
                 BuildPolygon(vertices, shapes[shp], borders[state], e, false);
             }
             else
             {
                 BuildPolygon(vertices, shapes[shp], borders[state], e, true);
             }
         }
     }
     else
     {
         FastDrawnState[] states = DrawnStates;
         foreach (int shp in indices)
         {
             if (shp >= shapes.Count) continue;
             if (shp >= states.Length)
             {
                 AssignFastDrawnStates();
                 states = DrawnStates;
             }
             if (states[shp].Visible == false) continue;
             ShapeRange shape = shapes[shp];
             if (!shape.Extent.Intersects(e.GeographicExtents)) continue;
             if (drawExtents.Contains(shape.Extent))
             {
                 FastDrawnState state = states[shp];
                 if (!borders.ContainsKey(state)) continue;
                 BuildPolygon(vertices, shapes[shp], borders[state], e, false);
             }
             else
             {
                 FastDrawnState state = states[shp];
                 if (!borders.ContainsKey(state)) continue;
                 BuildPolygon(vertices, shapes[shp], borders[state], e, true);
             }
             
         }
        
     }
     
 }