Finding ID from DBF After clicking on Shape

Topics: Data Access
Apr 23, 2012 at 4:32 AM

Hi Guys

So major noob here, just downloaded and installed Sharpmap today.

So far I've followed a few tutorials and am using a picture box to control my map.

Now all I need to do is get the ID of a column from it's associated DBF file when I click on a area of the map (I believe polygon might be the right terminology).

I've tried the How-To Section but it appears that it's not a picture box that the SHP file is in.

 

Any help would be grand

 

Coordinator
Apr 23, 2012 at 6:15 AM
Edited Apr 23, 2012 at 9:42 AM

The samples are using SharpMap.UI.Forms.MapBox (or .MapImage) control of the SharpMap.UI project.

Hth FObermaier

Apr 24, 2012 at 12:13 AM

Ahk, sweet.

As I can't find much documentation would you kindly point me in the right direction for it?

 

Thank you for your reply!

Coordinator
Apr 24, 2012 at 11:17 AM

There is not much documentation. Please evaluate the WinFormSamples project to see usage of MapBox and (deprecated) MapImage

Hth FObermaier

Apr 25, 2012 at 11:03 PM
Edited Apr 26, 2012 at 6:24 AM

Ahk sweet, would you be able to link me? Can't seem to find it... probably right under my nose somewhere....

Edit: I tried to do a MapBox but couldn't use my shapefile with it, as when I tried it gave me an error saying it's 'read only'.

Following the example in the How To with the MapImage I get these problems:

MapImg is the MapImage componant on the form. _SharpMap is the main layer

  • MapImg doesn't contain a definition for Layers so I added .Map. before it and then added Layer[0]
  • Now .DataSource No longer has  a definition. Not too sure what to do from here. My Code example is as follows

 

 

private void mapImg_MouseUp(SharpMap.Geometries.Point WorldPos, MouseEventArgs ImagePos)
{
 SharpMap.Geometries.Point p = _sharpMap.ImageToWorld(ImagePos.Location);
 _sharpMap.Center.X = p.X;
 _sharpMap.Center.Y = p.Y;
SharpMap.Data.FeatureDataSet ds = new SharpMap.Data.FeatureDataSet(); mapImg.Map.Layers[0].DataSource.ExecuteIntersectionQuery(p.GetBoundingBox(), ds); RefreshMap(); }

 

Help would be great as I just need to get the ID from the corresponding area and I've finished what I need to do

Coordinator
Apr 26, 2012 at 7:25 AM

Please use the source code and compile the project yourself.

Within the solution you'll find the WinFormSamples project.

Regarding your code snipplet:

private void mapImg_MouseUp(SharpMap.Geometries.Point WorldPos, MouseEventArgs ImagePos)
{
 SharpMap.Geometries.Point p = _sharpMap.ImageToWorld(ImagePos.Location);
 _sharpMap.Center.X = p.X;
 _sharpMap.Center.Y = p.Y;
SharpMap.Data.FeatureDataSet ds = new SharpMap.Data.FeatureDataSet();
var vl = mapImg.Map.Layers[0] as ICanQueryLayer;
if (vl != null)
{
vl.ExecuteIntersectionQuery(p.GetBoundingBox().Grow(2), ds);
//do sth with data in ds.Tables[0]
/*
...
*/
}
RefreshMap();

Hth FObermaier

Apr 26, 2012 at 11:52 PM
Edited Apr 27, 2012 at 1:22 AM

So close, got excited for a bit. It's throwing an exception at: var vl = mapImg.Map.Layers[0] as ICanQueryLayer;

Details:

ArugmentOutOfRangeException was unhandled

Index was out of range. Must be non-negative and less than the size of the collection.Parameter name: index

 

Any Suggestions?

Thanks =) 

 

Edit: Ok turns out it's because the the mapImg box doesn't have any layers, it was throwing an exception. So I've altered it to query _Sharpmap instead of the box. But just can't narrow in on where the actual data is stored in the var. I can find it through the Data Source but that will include all 250+ records.

I've also tried adding layers to the mapImg but it just un-renders the map, which I can try to sort out later. But when I run the line  "var vl = mapImg.Map.Layers[0] as ICanQueryLayer; " It will return false.

Coordinator
Apr 27, 2012 at 5:53 AM

What does your code look like now?

The ExecuteIntersectionQuery adds a new FeatureDataTable to the FeatureDataSet ds, if there were any matching results.

So, if you want to do sth with the results you simply have to browse through that table. I assume you are using Shapefile, therefore the object ID will be in the first column.

if (ds.Tables.Count > 0)
{
    var fdt = ds.Tables[ds.Tables.Count-1];
    var fdr = fdt.Rows[0];
    var fid = (uint)fdr[0];
    //...
}
Hth FObermaier

May 1, 2012 at 10:50 PM
Edited May 2, 2012 at 3:08 AM

Hey sorry for the late reply,

My code is  now this:

        private void mapImg_MouseUp(SharpMap.Geometries.Point WorldPos, MouseEventArgs e)
        {
            SharpMap.Geometries.Point p = _sharpMap.ImageToWorld(e.Location);
            SharpMap.Data.FeatureDataSet ds = new SharpMap.Data.FeatureDataSet();
            var vl = _sharpMap.Layers[0] as ICanQueryLayer;
            var bindingbox = p.GetBoundingBox();
            if (vl != null)
            {
                vl.ExecuteIntersectionQuery(bindingbox.Grow(2), ds);
                if (ds.Tables.Count > 0)
                {
                    var fdt = ds.Tables[0];
                    var fdr = fdt.Rows[0];
                    var fid = fdr.ItemArray[0];
                }
            }            
            _sharpMap.Center.X = p.X;
            _sharpMap.Center.Y = p.Y;
            RefreshMap();
        }
Made a minor change just to get the ID, but for every area of the map I click on it gives me the same ID. I assume it's due to the query not selecting the area properly...
How can I make this so it will get me a different value for each area (/polygon) I click on? Just to give you a visual understanding too, each area inside the boarder has an ID. That's what I'm trying to find.
Heres the Image: http://www.imageurlhost.com/images/h8tf8k3ijgrezvaby1q.jpg
Thanks for your help so far, getting so close!
Coordinator
May 2, 2012 at 8:09 AM

It may be that I'm mistaken and the object id is not part of the returned DataTable (I don't use ShapeFile at all).

What you get is the data that is defined in the associated dbase file for the queried feature.

If you only care for the ID, simply call

var oids = vl.GetObjectIdsInView(WorldPos.GetBoundingBox());

The call to Grow(2) is not necessary since you only want to test if the point is within any polygon.

You do need to do true intersection testing using NTS on the returned features, since sharpmap only checks for bounding boxes.

Hth FObermaier

May 2, 2012 at 10:41 PM

Got an assembly error with GetObjectIdsInView

But you were right about Grow, that is what was causing the whole problem. Works now! =D

Thank you so much!