Best Practices For Adding Features
In today’s blog post, we will review a question that our support team encounters frequently - ‘How do I programmatically add new features to an existing layer?’
While the examples in this post reference the WPF edition, all classes are in the ThinkGeo.Core assembly, and the same code you see here will work the same in Winforms, Web-Api, Blazor and Xamarin
Option 1 - FeatureSource.AddFeature()
The recommended method for adding features to any layer is to use the AddFeature() function on the layer’s FeatureSource. There are a few benefits to using this method:
The spatial index is automatically rebuilt as you add features. This will improve rendering performance and also allow you to do spatial queries such as GetFeaturesInsideBoundingBox on the newly added features.
If your using a ProjectionConverter to convert your data to a different projection, you don’t have to worry about converting your feature when it’s added. You simply add the new feature in the same internal projection that the rest of your layer is using and the ProjectionConverter will handle the reprojection of your new features.
Every ThinkGeo FeatureLayer has a FeatureSource and will support the AddFeature() fuction.
Let’s walk through a quick code sample of adding a feature using this method. In the code below, we’re using an InMemoryFeatureLayer, but the same code would apply to any other FeatureLayer. The steps are pretty simple:
Instatiate a new InMemoryFeatureLayer and Open() the FeatureSource.
Call the BeginTransaction() function.
Add any new features you wish calling the AddFeature() function and passing in an x, y and optional id value. Note: the id will be used later if you need to Update or Delete the feature.
Call the CommitTransaction() function
// Create our InMemoryFeatureLayer and Open() the FeatureSource
InMemoryFeatureLayer inMemoryFeatureLayer = new InMemoryFeatureLayer();
inMemoryFeatureLayer.FeatureSource.Open();
// Begin the Transaction used any time you add/update/delete features.
inMemoryFeatureLayer.FeatureSource.BeginTransaction();
// Add a couple of features with a hard-coded x, y and name. Note: in practice, this will often be in a loop when reading from some data source.
inMemoryFeatureLayer.FeatureSource.AddFeature(new Feature(10, 20, "feature1_Id"));
inMemoryFeatureLayer.FeatureSource.AddFeature(new Feature(5, 10, "feature2_Id"));
// Finally, make sure to commit your transaction.
inMemoryFeatureLayer.FeatureSource.CommitTransaction();
And there are also methods to UpdateFeature() and DeleteFeature() that work in the same manner:
// Begin the Transaction used any time you add/update/delete features.
inMemoryFeatureLayer.FeatureSource.BeginTransaction();
// Update the 'x' value on feature1, and delete feature2.
inMemoryFeatureLayer.FeatureSource.UpdateFeature(new Feature(15, 20, "feature1_Id"));
inMemoryFeatureLayer.FeatureSource.DeleteFeature("feature2_Id");
// Finally, make sure to commit your transaction.
inMemoryFeatureLayer.FeatureSource.CommitTransaction();
Option 2 - Directly Adding to the InternalFeatures Property
If you want a simpler and more performant method to add features, you may want to just use the InternalFeatures property on the InMemoryFeatureLayer instead. The major advantage is improved performance when adding a large number of features, but there are a few caveats you should be aware of:
A spatial index is not created by default and you must manually call the BuildIndex() function. Without calling BuildIndex(), the features will still render but spatial queries will not recognize the new InternalFeatures.
If you’re reprojecting your layer, the features you add to the InternalFeatures property must be in the projected (external) projection.
The InternalFeatures property is only available on the InMemoryFeatureLayer.
Let’s walk through a quick code sample of adding features using this method:
// Add a couple of features with a hard-coded x, y and name. Note: in practice, this will often be in a loop when reading from some data source.
inMemoryFeatureLayer.InternalFeatures.Add(new Feature(154564879, 456123156489, "feature1_Id"));
inMemoryFeatureLayer.InternalFeatures.Add(new Feature(154789714, 456784478911, "feature2_Id"));
And that’s all there is to it. If you want to see this method in action, you can check out our WPF ‘HowDoI’ samples here and look at the ‘InMemoryFeaureLayer’ sample.
We hope today’s post has been helpful. If you want to experiment with the code above, sign up for a free evaluation!
If you have any questions or if you have a topic you would like to learn more about, please email sales@thinkgeo.com and we will cover it in a future post.