Selection hightlight

Topics: SharpMap v0.9 / v1.x
Feb 10, 2012 at 8:00 AM



I would like to Hightlight the selected object in a vector layer (shapefile) , to to this I copy the object in a tempory layer. That works but it time consuming:

I do an executeIntersectionQuery to get the selected object and

I copy it in the tempory layer, these operations take 2 or 3 seconds for huge layer (about 10000 objects).

Does somebody has a faster solution ?




Feb 11, 2012 at 4:45 PM


you can use executeIntersectionQuery  and get dataset then dataset.Tables[0] return geometry of selection then add new layer with new color

		SharpMap.Data.FeatureDataTable data = dataset.Tables[0];
		SharpMap.Layers.VectorLayer laySelected = new SharpMap.Layers.VectorLayer("-*highLight");
                laySelected.DataSource = new SharpMap.Data.Providers.GeometryProvider(data);
                laySelected.Style.Fill = new System.Drawing.SolidBrush(System.Drawing.Color.Gold);
                laySelected.Style.Outline = new System.Drawing.Pen(System.Drawing.Color.Gold);
                laySelected.Style.PointColor = new System.Drawing.SolidBrush(System.Drawing.Color.Gold);

Feb 13, 2012 at 7:45 AM

Thanks for your answer

But I already do that.

That works well on small layer but on larger one it comes to slow .

The time consuming comes from:

1- the executeIntersectionQuery

2- the map refresh which redraw all layers (if we are on a large zoom, that redraw all the objects).

So , do you have a faster  method ?


Feb 13, 2012 at 8:04 AM
Edited Feb 13, 2012 at 8:05 AM

Eric, regarding ExecuteIntersectionQuery on shapefile you may want to try the shapefile provider in the SharpMap.Extension project. It uses NTS' prepared geometries and should perform better.

Regarding execute intersection query, I think we considered a VectorLayerCachingProxy (like the GdalRasterLayerCachingProxy). The idea behind it is to encapsulate the VectorLayer and render its contents to a bitmap. When no relevant property has changed, blit the rendered image, else update image and blit that.

Be sure you use an index!

Hth FObermaier

Feb 13, 2012 at 12:23 PM

Good inputs.

I'll perform some test.


Thank you



Feb 14, 2012 at 5:41 AM

working code:
SharpMap.Data.FeatureDataSet ds = new SharpMap.Data.FeatureDataSet(); SharpMap.Layers.VectorLayer layer = (SharpMap.Layers.VectorLayer)DisplayMap.Map.Layers[0]; //layers0 is current display layer layer.DataSource.Open(); layer.DataSource.ExecuteIntersectionQuery(worldPos.GetBoundingBox(), ds); //because I wrote this code in event "MapImage_MouseMove" so use WorldPos //if selected any object if (ds.Tables[0].Rows.Count > 0) { //create the selected layer SharpMap.Layers.VectorLayer laySelected = new SharpMap.Layers.VectorLayer("Selection"); laySelected.DataSource = new SharpMap.Data.Providers.GeometryProvider(ds.Tables[0]); laySelected.Style.Fill = new System.Drawing.SolidBrush(Color.HotPink); //SystemColor.Hightlight DisplayMap.Map.Layers.Add(laySelected); //map is a gloabal variable which type is "Map" DisplayMap.Refresh(); } layer.DataSource.Close();

Feb 16, 2012 at 9:30 AM


I've found a faster solution, the idea is not to draw the selected object on a layer but to draw it on the picture box . This solution avoid to redraw the map which takes time. It's possible to highlight the selection in less than 1 sec with huge layer

Now I ll try to speed up the intersection query, but I d'ont know how.


Sep 20, 2012 at 9:27 AM
Edited Sep 20, 2012 at 9:29 AM


Found another way to achieve highlighting; it was born after reading the reply of ronaldovn.

I do a query on the layer's data table with Linq - it gives me a list of fid's, loop that list and get the Geometries with ShapeFile.GetGeometryByID(fid), and put them in a List<Geometry> - to calculate the BoundingBox to zoom to.

I create a new VectorLayer "selection", with an empty DataSource (program will not work if you forget it) and a nice colored VectorStyle:

// declaration
 VectorLayer _selectionLayer;
// add selection layer
_selectionLayer = new VectorLayer("selection");
// datasource needs to be there
List<Geometry> tempList = new List<Geometry>();
_selectionLayer.DataSource = new GeometryProvider(tempList);
// style
VectorStyle lineStyle = new VectorStyle();
lineStyle.Line = new Pen(Color.Cyan, 2);
_selectionLayer.Style = lineStyle;
// coordinate transformations (if you need it)
_selectionLayer.CoordinateTransformation = .....;
_selectionLayer.ReverseCoordinateTransformation = .....;

Later on, when I want to highlight my selection, I zoom into the selection's BoundingBox, bind the "selection" layer's DataSource to my List<Geometry>, and do a Refresh:

List<Geometry> geometryList = new List<Geometry>();

... fill list with Geometries ...
_selectionLayer.DataSource = new GeometryProvider(geometryList);

Not tested on big layers or selections, but it doesn't use ExecuteIntersectionQuery.

Have a nice day,