private void DrawFeatures(MapArgs e, IEnumerable<int> indices) { Graphics g; if (e.Device != null) { g = e.Device; // A device on the MapArgs is optional, but overrides the normal buffering behaviors. } else { g = Graphics.FromImage(_backBuffer); } // Only draw features that are currently visible. Extent drawExtents = new Extent(e.PixelToProj(_drawingBounds)); double minX = e.MinX; double maxY = e.MaxY; double dx = e.Dx; double dy = e.Dy; if(DrawnStatesNeeded) { FastDrawnState[] states = DrawnStates; for (int selectState = 0; selectState < 2; selectState++) { foreach (ILineCategory category in Symbology.Categories) { // Define the symbology based on the category and selection state ILineSymbolizer ls = category.Symbolizer; if (selectState == SELECTED) ls = category.SelectionSymbolizer; if (ls.Smoothing) { g.SmoothingMode = SmoothingMode.AntiAlias; } else { g.SmoothingMode = SmoothingMode.None; } // Determine the subset of the specified features that are visible and match the category ILineCategory lineCategory = category; int i = selectState; Func<FastDrawnState, bool> isMember = state => state.Category == lineCategory && state.Selected == (i == 1) && state.Visible == true; var drawnFeatures = from feature in indices where isMember(states[feature]) select feature; GraphicsPath graphPath = new GraphicsPath(); foreach (int shp in drawnFeatures) { ShapeRange shape = DataSet.ShapeIndices[shp]; if (drawExtents.Contains(shape.Extent)) { // This optimization only works if we are zoomed out far enough // that the whole linestring fits in the short integer // drawing window. Otherwise, we need to crop the line. FastBuildLine(graphPath, DataSet.Vertex, shape, minX, maxY, dx, dy); } else { for (int iPart = 0; iPart < shape.Parts.Count; iPart++) { IBasicGeometry geom = DataSet.GetFeature(shp).GetBasicGeometryN(iPart); if (drawExtents.Contains(shape.Extent) == false) { geom = e.GeographicExtents.Intersection(geom); } // Cropped geometries can be either linestrings or multi-linestrings IBasicLineString bls = geom as IBasicLineString; if (bls != null) { // the result is definitely in the linestring category BuildLineString(graphPath, bls, minX, maxY, dx, dy); } else { IMultiLineString intersect = geom as MultiLineString; if (intersect == null) continue; for (int iLine = 0; iLine < intersect.NumGeometries; iLine++) { BuildLineString(graphPath, intersect.GetBasicGeometryN(iLine) as IBasicLineString, minX, maxY, dx, dy); } } } } } double scale = 1; if (ls.ScaleMode == ScaleModes.Geographic) { scale = e.ImageRectangle.Width / e.GeographicExtents.Width; } foreach (IStroke stroke in ls.Strokes) { stroke.DrawPath(g, graphPath, scale); } graphPath.Dispose(); } } } else { // Selection state is disabled // Category is only the very first category ILineCategory category = Symbology.Categories[0]; ILineSymbolizer ls = category.Symbolizer; if (ls.Smoothing) { g.SmoothingMode = SmoothingMode.AntiAlias; } else { g.SmoothingMode = SmoothingMode.None; } // Determine the subset of the specified features that are visible and match the category ILineCategory lineCategory = category; GraphicsPath graphPath = new GraphicsPath(); foreach (int shp in indices) { ShapeRange shape = DataSet.ShapeIndices[shp]; if (drawExtents.Contains(shape.Extent)) { // This optimization only works if we are zoomed out far enough // that the whole linestring fits in the short integer // drawing window. Otherwise, we need to crop the line. FastBuildLine(graphPath, DataSet.Vertex, shape, minX, maxY, dx, dy); } else { for (int iPart = 0; iPart < shape.Parts.Count; iPart++) { IBasicGeometry geom = DataSet.GetFeature(shp).GetBasicGeometryN(iPart); if (drawExtents.Contains(shape.Extent) == false) { geom = e.GeographicExtents.Intersection(geom); } // Cropped geometries can be either linestrings or multi-linestrings IBasicLineString bls = geom as IBasicLineString; if (bls != null) { // the result is definitely in the linestring category BuildLineString(graphPath, bls, minX, maxY, dx, dy); } else { IMultiLineString intersect = geom as MultiLineString; if (intersect == null) continue; for (int iLine = 0; iLine < intersect.NumGeometries; iLine++) { BuildLineString(graphPath, intersect.GetBasicGeometryN(iLine) as IBasicLineString, minX, maxY, dx, dy); } } } } } double scale = 1; if (ls.ScaleMode == ScaleModes.Geographic) { scale = e.ImageRectangle.Width / e.GeographicExtents.Width; } foreach (IStroke stroke in ls.Strokes) { stroke.DrawPath(g, graphPath, scale); } graphPath.Dispose(); } 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); } } } }