ThinkGeo.com    |     Documentation    |     Premium Support

Updating a feature's shape dynamically?

I'm attempting to update a lot of features on my map as new data comes in, hopefully in the most efficient manner I can find. I looked at the example of the moving plane and came up with the code below. I'm attempting to get the RectangleShape associated with the feature and change it's height based on the new data. The feature is found by the query, but the returned RectangleShape is null.


 


 
            //redraw the noise display
            InMemoryFeatureLayer receiversLayer = (InMemoryFeatureLayer)winformsMap1.FindFeatureLayer("ReceiversLayer");
            Overlay ReceiversOverlay = winformsMap1.Overlays["ReceiversOverlay"];
            String[] columns = { "SerialNumber", "Noise" };

            // Lock the overlay while we update the points
            ReceiversOverlay.Lock.EnterWriteLock();
            try
            {
                foreach (ReceiverUnit r in receivers.Values)
                {
                    receiversLayer.Open();
                    Feature f = receiversLayer.QueryTools.GetFeatureById(r.SerialNumber, columns);
                    receiversLayer.Close();
                    RectangleShape rectShape = f.GetShape() as RectangleShape; // why is this null?
                    rectShape.UpperLeftPoint.Y = r.LatLong.Y + r.Noise*.01;
                                                                     
                    f.ColumnValues["Noise"] = r.Noise.ToString();

                    receiversLayer.Open();
                    receiversLayer.EditTools.BeginTransaction();
                    //receiversLayer.EditTools.Update(f);
                    receiversLayer.EditTools.Update(rectShape);
                    receiversLayer.EditTools.CommitTransaction();
                    receiversLayer.Close();
                }
            }
            finally {
                // Release the lock on the overlay
                ReceiversOverlay.Lock.ExitWriteLock();
            }
            winformsMap1.Refresh();
        }
  


Apparently I'm doing this wrong, but I don't find any other examples of doing this. I have tried clearing  the features in the layer and creating new ones, which works, but at only 100 points, the updating is erratic, rather than smooth, and sometimes stops for a short moment. I will have many more than 100 points, so I'm looking at other methods.


Thanks for any help,


Janene


Wireless Seismic



 


Hi Janene,
 
Thanks for your post!
 
There are some errors in your code, and I also have some ideas to improve the performance of your application.
 
First of all, you can not get a RectangleShape from a feature; the RectangleShape is processed as PolygonShape when stored in a feature. That is why the returned RectangleShape is null. The code should be like this:
 


RectangleShape rectShape = f.GetBoundingBox();

 
Second, you don’t need to use the QueryTools and EditTools for an InMemoryFeatureLayer, just use the feature’s id to index the InternalFeatures in it. Your code could be like this:
 
When you add some feature to the InMemoryFeatureLayer, you can add the id as an index (in your application, the feature’s id should be same to SerialNumber):
 


receiversLayer.InternalFeatures.Add(f.Id, f);

 
Then you can query a feature by the indexed id:
 


Feature f = receiversLayer.InternalFeatures[r.SerialNumber];

 
You also can edit a feature like this:
 


receiversLayer.InternalFeatures[r.SerialNumber] = new Feature(rectShape);

 
You can have a try with these codes and hope this can help you.
 
Any more questions please let me know.
 
Thanks,
 
sun

Thank you, Sun, I've put these changes in and now it does work. 



Unfortunately, it's far too slow for what I need. When I increased my number of points (receivers) to 10,000, the display locked up. Eventually I will need the ability to have up to 60K-100K points.



The behavior I need is to be able to update/change the shape and color of each point as new data comes in, at about 4 times per second. I need the points to update in groups or individually, rather than the entire map at once. 



Any help with setting this up to be as efficient and fast as it can be would be helpful, and is part of my product evaluation criteria. 



Here's my current version. I've played around with where to put the layer open and close, the lock and unlock, etc. 



Janene



 



            InMemoryFeatureLayer receiversLayer = (InMemoryFeatureLayer)winformsMap1.FindFeatureLayer("ReceiversLayer");
            Overlay ReceiversOverlay = winformsMap1.Overlays["ReceiversOverlay"];

            try
            {
                // Lock the overlay while we update the points
                ReceiversOverlay.Lock.EnterWriteLock();
                receiversLayer.Open();
                foreach (ReceiverUnit r in receivers.Values)
                {
                    Feature f = receiversLayer.InternalFeatures[r.SerialNumber];
                    RectangleShape rectShape = f.GetBoundingBox(); 
                    rectShape.UpperLeftPoint.Y = r.LatLong.Y + r.Noise*.01;
                                                                     
                    Feature newFeat = new Feature(rectShape);
                    newFeat.ColumnValues["SerialNumber"] = r.SerialNumber;
                    newFeat.ColumnValues["Noise"] = r.Noise.ToString();

                    receiversLayer.InternalFeatures[r.SerialNumber] = newFeat;
                }
            } catch (Exception ex) {
                Console.WriteLine(ex.StackTrace);
            } finally {
                    // Release the lock on the overlay
                    receiversLayer.Close();  
                    ReceiversOverlay.Lock.ExitWriteLock();
                    winformsMap1.Refresh();            
            }


Janene,


So you mean you just want to update/change the shape and color for a few features when new data comes in? I think you can change the current extent to a small bounding box which just contains the modified features when you need to refresh the map. 
 
In addition, you’d better try the IndexedInMemoryFeatureLayer instead of InMemoryFeatureLayer when the count of points is larger than 10000, because it can improve the performance of finding the features to be drawn. You can find the code and get more information in the following link:
 
gis.thinkgeo.com/Support/Dis...fault.aspx
 
Any more questions please let me know.
 
Thanks,
 
Sun

Hi Sun,


I will need to change groups of features as the data comes in, probably 100-200 at a time, not just a few, but not the whole display of tens of thousands.


I was confused in the code that, while I wanted to edit the features only, I had to create new ones with the new rectangle, and then also had to add the custom data to the new features as well - this is a replace, not an edit, and as such is probably slower than it needs to be. 


I will look at the Indexed version, thanks. 


Janene



Janene,


I made a sample which is using the IndexedInMemoryFeatureLayer and update around 100 points (I create a random bounding box to get points from the tens of thousands points) each time. You can get the sample from the attachment and take a look.
 
About the feature editing, as the feature is a structure and is value type, so edit a feature is just create a new instance to replace the original one. 
 
Please let me know if you have any more questions.
 
Thanks,
 
sun  

979-Post6047Demo.zip (12.8 KB)