Deleting Selected Features

Developer
Nov 15, 2010 at 9:24 PM

Hello,

Can anyone advise me on the right way to delete a feature that is identified in the FeatureSet.Selection collection.
That is: i have used the SelectMapFunction to select a feature.  It is highlighted in the map view correctly.
Then I want to do somethinglike this
ISelection selection = layer.Selection;

foreach (IFeature deleteThis in selection.ToFeatureList())
{

    layer.DataSet.Features.Remove(deleteThis);

}
delete Tis is the correct feature but it seems that the feature added to the selection collection is a clone of the original feature because 
This:
layer.DataSet.Features.IndexOf( deleteThis );
returns -1;
So, how can I find the original feature that is added to the selection collection in order to delete it?
Thanks,
Garth
Developer
Nov 15, 2010 at 9:41 PM
uh oh. This may be something that bears looking into for us to fix at a deeper level. Until then I think Features support an FID tag that isn't being used internally for anything significant. If it is not already set to anything you can simply cycle through your features during loading, label the FID value yourself. It may be that it is already primed with a value. You could number your features with FID before selection occurs and then use it to track it in both cases as a work around.

Ted


On Mon, Nov 15, 2010 at 2:24 PM, keenedge <notifications@codeplex.com> wrote:

From: keenedge

Hello,

Can anyone advise me on the right way to delete a feature that is identified in the FeatureSet.Selection collection.
That is: i have used the SelectMapFunction to select a feature. It is highlighted in the map view correctly.
Then I want to do somethinglike this
ISelection selection = layer.Selection;

foreach (IFeature deleteThis in selection.ToFeatureList())
{

    layer.DataSet.Features.Remove(deleteThis);

}
delete Tis is the correct feature but it seems that the feature added to the selection collection is a clone of the original feature because
This:
layer.DataSet.Features.IndexOf( deleteThis );
returns -1;
So, how can I find the original feature that is added to the selection collection in order to delete it?
Thanks,
Garth

Read the full discussion online.

To add a post to this discussion, reply to this email (DotSpatial@discussions.codeplex.com)

To start a new discussion for this project, email DotSpatial@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


Developer
Nov 15, 2010 at 10:21 PM

Using fid regresses to the same condition

public virtual int Fid

{

        get            

{

                if (_parentFeatureSet.AttributesPopulated == false)

                {                    

return _recordNumber;

                }

                return _parentFeatureSet.Features.IndexOf(this);

            }

        }

 

}

Inthis case "this" is not a member of _parentFeatureSet.Features.

Developer
Nov 15, 2010 at 11:06 PM
Woops... forgot all about that "clever" work around. Not so helpful that. Is there a "Tag" object on the feature somewhere that we could use to host a tracking index? I can't remember now. It might not be on IFeature anyway though. Maybe we need to think more about how to prevent the crisis from happening in the first place by having the same object be used in the selection rather than a copy. I don't think it should be a problem to do that, we just have to tweak the code that is making the duplicates so that it passes references around instead. If the extent bugs are fixed when I get home tonight I will take a serious look at this because I had originally planned on tracking the edit mode features around by object precisely so that you could add and remove features from the list without too much breakage.

Ted


On Mon, Nov 15, 2010 at 3:21 PM, keenedge <notifications@codeplex.com> wrote:

From: keenedge

Using fid regresses to the same condition

public virtual int Fid

{

get

{

if (_parentFeatureSet.AttributesPopulated == false)

{

return _recordNumber;

}

return _parentFeatureSet.Features.IndexOf(this);

}

}

}

Inthis case "this" is not a member of _parentFeatureSet.Features.

Read the full discussion online.

To add a post to this discussion, reply to this email (DotSpatial@discussions.codeplex.com)

To start a new discussion for this project, email DotSpatial@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com


Developer
Nov 15, 2010 at 11:12 PM
Oh and also if your dataset is in "indexMode" there are no features at all, and removal etc should be index based. But in that case, you should have had an indexSelection. If you have an IndexSelection then you cant remove based on feature, but you should be able to get the integer index. If you check the "IndexMode" property on the FeatureSet and it is true, then try casting the Selection object into an IndexSelection instead. The IndexSelection should give you super powers to help figure out what index you are actually working with and tie it back to the correct index in the FeatureSet. In Index mode, any feature you work with is created on the fly from a shape object.
Ted


On Mon, Nov 15, 2010 at 4:05 PM, Harold Dunsford <hadunsford@gmail.com> wrote:
Woops... forgot all about that "clever" work around. Not so helpful that. Is there a "Tag" object on the feature somewhere that we could use to host a tracking index? I can't remember now. It might not be on IFeature anyway though. Maybe we need to think more about how to prevent the crisis from happening in the first place by having the same object be used in the selection rather than a copy. I don't think it should be a problem to do that, we just have to tweak the code that is making the duplicates so that it passes references around instead. If the extent bugs are fixed when I get home tonight I will take a serious look at this because I had originally planned on tracking the edit mode features around by object precisely so that you could add and remove features from the list without too much breakage.

Ted



On Mon, Nov 15, 2010 at 3:21 PM, keenedge <notifications@codeplex.com> wrote:

From: keenedge

Using fid regresses to the same condition

public virtual int Fid

{

get

{

if (_parentFeatureSet.AttributesPopulated == false)

{

return _recordNumber;

}

return _parentFeatureSet.Features.IndexOf(this);

}

}

}

Inthis case "this" is not a member of _parentFeatureSet.Features.

Read the full discussion online.

To add a post to this discussion, reply to this email (DotSpatial@discussions.codeplex.com)

To start a new discussion for this project, email DotSpatial@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe or change your settings on codePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at codeplex.com



Developer
Nov 16, 2010 at 5:53 AM
This turned out to be a large can of worms. In a new branch in the repository, I have stored my new effort to try to make it easier to remove selected features, or features at various indices from a layer. However, I have managed to get myself into a tangle. The correct shapes are removed, there is no question of that. When working with the datagrid afterwards, everything appears to work. That is, selecting rows in the data table select shapes, and all rows in the data table select one and only one shape in the map. However, when I use my rectangle select, I get the strangest behavior. If the rectangle covers all the shapes, then all the shapes get selected. Some shapes, (probably the ones with index values lower than the deleted shapes) work as before. Many other shapes, however will only respond to selection if a different shape is in the rectangle. Selection in index mode should be using the FastDrawnState array, which is updated correctly and has the correct number of elements. However, somehow rectangle selection somewhere seems to be invoking an original FID when figuring out the extent, but I couldn't find it by the time it was time for bed. Maybe I'll have better luck figuring out this mystery tomorrow.
Developer
Nov 16, 2010 at 4:40 PM
Thanks for looking into this Ted, I already spend several days trying to get my head around it. I'm more baffled than ever.

However, I think you need to take a close look at this statement.

> "selection in index mode should be using the FastDrawnState array, which is updated correctly"

I have seen exactly the selection behavior you described. My fix was to make AssignFastDrawStates a public method and call it after deleting. This fixes many (but not all) problems related to deleting features.

So I guess somewhere in the fastdrawnstates there is an inconsistency.








On Mon, Nov 15, 2010 at 10:53 PM, Shade1974 <notifications@codeplex.com> wrote:

From: Shade1974

This turned out to be a large can of worms. In a new branch in the repository, I have stored my new effort to try to make it easier to remove selected features, or features at various indices from a layer. However, I have managed to get myself into a tangle. The correct shapes are removed, there is no question of that. When working with the datagrid afterwards, everything appears to work. That is, selecting rows in the data table select shapes, and all rows in the data table select one and only one shape in the map. However, when I use my rectangle select, I get the strangest behavior. If the rectangle covers all the shapes, then all the shapes get selected. Some shapes, (probably the ones with index values lower than the deleted shapes) work as before. Many other shapes, however will only respond to selection if a different shape is in the rectangle. Selection in index mode should be using the FastDrawnState array, which is updated correctly and has the correct number of elements. However, somehow rectangle selection somewhere seems to be invoking an original FID when figuring out the extent, but I couldn't find it by the time it was time for bed. Maybe I'll have better luck figuring out this mystery tomorrow.

Read the full discussion online.

To add a post to this discussion, reply to this email (DotSpatial@discussions.codeplex.com)

To start a new discussion for this project, email DotSpatial@discussions.codeplex.com

You are receiving this email because you subscribed to this discussion on CodePlex. You can unsubscribe on CodePlex.com.

Please note: Images and attachments will be removed from emails. Any posts to this discussion will also be available online at CodePlex.com




--
Garth Tissington
Developer
Nov 18, 2010 at 3:01 AM

Okay, I think I have it solved.  In my case the problem was that I was updating the vertices, and even updated the selection using AssignFastDrawnStates(), what I had not done was cycle through each of the parts in the remaining shape indices and change the "Vertices" pointer.  They were all pointing to the old Vertex array!  This didn't affect rendering since with rendering it sort of ignores this pointer entirely and just uses the vertex array pointer in the FeatureSet itself.  But selection testing was using this, so my effort at selecting shapes was behaving wacky because it was looking at the new extent, but then if it passed that test, it was looking at the old vertex array for the detailed shape test.  The result was really hard to pin down.  Anyway, this has been fixed, and the DemoMap project now has a "remove" button that will remove shapes from the in-ram shapefiles.  I had to set it up to load the attributes in memory though, since the all important index based FID arrangement will no longer correspond to the file, and these features are not designed for the Non-ram based datasets.

Ted

May 13, 2011 at 10:54 AM

Hey Ted, I see you have been making great contributions the forum. Here my problem please, I hope you can help me?

Hey, have been reading your conversation. You two seem to have been working hard and doing alot. Please allow me to cut in here. I dont understand how the ISelection or Selection implementation works. Every time I use the selection tool to select a feature on the map (using either Mapwindow6 or Dotspacial), inside this event:

map1_SelectedIndexChange(obeject sender, EventArgs e)

{

[my code here:]

}

... I expect to get the index (or FID) of the selected feature. If the index I can use that to get the remaining attributes. Or, if I have the FID, I can use that to query an external database, which is my main goal. But the above event does not return any of that. Here is a snippet of what I wanna insert in the block above:

[my code here]:

MapWindow.Data.IFeature feat  = map1.GetFeatureLayers()[layer1].DataSet.GetFeature(index)

layer1 is layer am interested in.

index is the index of the selected feature, which the event does not seem to return.

I am stuck. Your kind help will be appreciated.... :)

 

Reagard

Dave

Oct 17, 2012 at 1:33 AM
Edited Oct 17, 2012 at 1:34 AM

My suggestion...

 

		Dim fLayer As FeatureLayer
		fLayer.DataSet.FillAttributes()
		fLayer.EditMode=True
		fLayer.ClearSelection()
		fLayer.SelectByAttribute("[ID] = 'N1'")
		fLayer.SelectByAttribute("[ID] = 'N12'")
		fLayer.SelectByAttribute("[ID] = 'N32'")
		If fLayer.Selection.Count>0 Then
			fLayer.RemoveSelectedFeatures()
			fLayer.DataSet.UpdateExtent()
			fLayer.DataSet.Save()
		End If
		fLayer.EditMode=False
I hope it serves
Mar 17, 2016 at 9:52 AM
I'm using DotSpatial 1.8 and still have problems (Index Out of Range Errors) after deleting features by using IFeatureLayer.RemoveSelectedFeatures().
What can be done to update the feature index after deleting features?
Claudia
Developer
Mar 17, 2016 at 12:21 PM
Hey Claudia,

please check whether calling the following code after pFLayer.RemoveSelectedFeatures works for you.
I had the index problem whenever I manipulated (add, delete, move) the featureset without calling this code afterwards. Since I added this code I don't have any problems anymore.
pFLayer.DataSet.UpdateExtent()
pFLayer.DataSet.InitializeVertices()
If pFLayer.LabelLayer IsNot Nothing Then pFLayer.LabelLayer.CreateLabels()

If save Then
      pFLayer.DataSet.Save()
      pFLayer.DataSet.Close()
End If

pFLayer.AssignFastDrawnStates()
If _map IsNot Nothing Then
     _map.Refresh()
     _map.ResetBuffer()
End If
pFLayer is an IFeatureLayer
_map is your DotSpatial.Controls.Map
Marked as answer by jany_ on 3/18/2016 at 5:54 AM
Mar 18, 2016 at 12:42 PM
Edited Mar 18, 2016 at 12:43 PM
Hi Jany,

I inserted your code and had a try - with the result that everytime I called pFLayer.RemoveSelectedFeatures all Features were deleted. But this was when I used it on the shapefile that I had modified before without updating the shapeindex. So that one was probably corrupt.

A try on a new shapefile worked perfectly!
Thank you!
Claudia
Developer
Mar 18, 2016 at 12:54 PM
Good to know it works for you and you're welcome.

And yes the other file was most probably corrupt. I remember my files being unuseable before I found the solution.