ThinkGeo.com    |     Documentation    |     Premium Support

GetFeaturesContaining with several layers in overlay

 


Hi,
 
I have an overlaylayer with 6 layers.
When the user clicks on a feature, I add this feature in a Inmemorylayer to consider this feature as selected and ,I want to know to which layer belongs the feature. (ie the code below).
So i do a foreach, and it's slow when i click on a feature.
 
Is there a way to optimize this code or do it differently ?
 
Thanks.
 
Regards.
 
Steph.
 
 
 
    foreach (FeatureLayer rr in ((LayerOverlay)_wpfMap.Overlays[ConstantsMap.NOMOVERLAYDYNAMIC + "_KEY"]).Layers)
            {
                if (rr.Name != ConstantsMap.NOMINMEMORYLAYERSELECT && rr.IsVisible == true)
                {
 
                    if (rr.IsOpen == false)
                        rr.Open();                     
                                 
                    ftsQuery = rr.QueryTools.GetFeaturesContaining(clickLocation, ReturningColumnsType.AllColumns);
 
                    if (ftsQuery.Count > 0)
                    {

                       foreach (Feature ftQuery in ftsQuery)
                        {
                            //Si colonne attributaire "TypeDetourage" n'existe pas alors ajout                           
                            if (ftQuery.ColumnValues.ContainsKey("TypeDetourage") == false)
                            {
                                tyDt = _vm.LayersMapConfig.Where(p => p.NomLayer == rr.Name).First().RangModaTypeDt;
                                ftQuery.ColumnValues.Add("TypeDetourage", tyDt.ToString());
                            }
                            ftQuery.ColumnValues.Add("LayerEnCours", rr.Name);
 
                            dejaSlc = _inMemFeatureLayerEnCours.InternalFeatures.Where(ii =>                           ii.ColumnValues.SequenceEqual(ftQuery.ColumnValues)).Count() > 0 ? true : false;
                            //Sélection
                            if (dejaSlc == false)
                            {
                                _inMemFeatureLayerEnCours.InternalFeatures.Add(ftQuery);
 
                            }
                            //Dé-sélection
                            else
                            {
                                _inMemFeatureLayerEnCours.InternalFeatures.Remove(ftQuery);
                                _vm.LstSourceAsso = null;
                            }
                            ftFind = true;
 

          if (ftFind == true)
            {
                _wpfMap.Overlays[ConstantsMap.NOMOVERLAYDYNAMIC + "_KEY"].Refresh();

                        }
                    }

 
 

Hi Steph,


I think the problem is caused by the large number of features in your layers and you used lots of foreach(inside Linq operation similar to foreach also exists), try to use parallel.foreach, and Plinq, that elevates the speed a lot, here is the new code I revised based on your code:



            foreach (FeatureLayer rr in ((LayerOverlay)_wpfMap.Overlays[ConstantsMap.NOMOVERLAYDYNAMIC + "_KEY"]).Layers)
            {
                if (rr.Name != ConstantsMap.NOMINMEMORYLAYERSELECT && rr.IsVisible == true)
                {
                    if (rr.IsOpen == false) rr.Open();
                    Collection<Feature> ftsQuery = rr.QueryTools.GetFeaturesContaining(clickLocation, ReturningColumnsType.AllColumns);
                    if (ftsQuery.Count > 0)
                    {
                        ftFind = true;
                        if (!ftQuery[0].ColumnValues.ContainsKey("TypeDetourage")) //Si colonne attributaire "TypeDetourage" n'existe pas alors ajout   
                        {
                            Parallel.ForEach<Feature>(ftsQuery, ftQuery =>
                            {
                                tyDt = _vm.LayersMapConfig.Where(p => p.NomLayer == rr.Name).First().RangModaTypeDt;
                                ftQuery.ColumnValues.Add("TypeDetourage", tyDt.ToString());

                                ftQuery.ColumnValues.Add("LayerEnCours", rr.Name);

                                dejaSlc = _inMemFeatureLayerEnCours.InternalFeatures.AsParallel<features>().Where<Feature>(ii => ii.ColumnValues.SequenceEqual(ftQuery.ColumnValues)).Count() > 0 ? true : false;
                                //Sélection
                                if (dejaSlc == false)
                                {
                                    _inMemFeatureLayerEnCours.InternalFeatures.Add(ftQuery);
                                }
                                //Dé-sélection
                                else
                                {
                                    _inMemFeatureLayerEnCours.InternalFeatures.Remove(ftQuery);
                                    _vm.LstSourceAsso = null;
                                }
                            });
                        }
                        else
                        {
                            Parallel.ForEach<Feature>(ftsQuery, ftQuery =>
                            {
                                ftQuery.ColumnValues.Add("LayerEnCours", rr.Name);

                                dejaSlc = _inMemFeatureLayerEnCours.InternalFeatures.AsParallel<features>().Where<Feature>(ii => ii.ColumnValues.SequenceEqual(ftQuery.ColumnValues)).Count() > 0 ? true : false;
                                //Sélection
                                if (dejaSlc == false)
                                {
                                    _inMemFeatureLayerEnCours.InternalFeatures.Add(ftQuery);
                                }
                                //Dé-sélection
                                else
                                {
                                    _inMemFeatureLayerEnCours.InternalFeatures.Remove(ftQuery);
                                    _vm.LstSourceAsso = null;
                                }
                            });
                        }
                    }
                    if (ftFind)
                    {
                        _wpfMap.Overlays[ConstantsMap.NOMOVERLAYDYNAMIC + "_KEY"].Refresh();
                    }
                }
            }

Hope it helps,


Edgar


 

 



Hi Edgar,  
  
 Thanks.  
 I did and the performance is not very good. 
 What I want to do is to select a feature on the click of the map.  
 May be, my method is not very good.  
 Is there a better way to do ? 
  
 For example, copy the features which are displayed in a MemoryFeatureLayer. And when the user pan or zoom, update the features displayed ? 
 I’am afraid that the copy takes a lot of memory … ? 
 Have you an other idea ? 
  
 Thanks a lot. 
 Regards. 
  
 Steph. 


Hi edgar, 
  
 And I forgot to say how is organized the overlay  
 There are 6 layers :  
 Layer 1 has 7 features with the condition WHERECLAUSE / 35209 without the condition WHERECLAUSE 
 Layer 2 has 205 features with the condition WHERECLAUSE / 35209 without the condition WHERECLAUSE 
 Layer 3 has 9 features with the condition WHERECLAUSE / 35209 without the condition WHERECLAUSE 
 Layer 4 has 23 features with the condition WHERECLAUSE / 50162 without the condition WHERECLAUSE 
 Layer 5 has 43 Features with the condition WHERECLAUSE / 59034 without the condition WHERECLAUSE 
 Layer 6 has 31 features with the condition WHERECLAUSE / 35989 without the condition WHERECLAUSE 
  
 When I test the number of features for each layers (querytools.getcount() ), I have the number with the whereclause, so I deduct from it that the getfeaturescontaining takes into account the "WHERECLAUSE" . 
 So the number of the features is not so high as it … 
  
 Thanks again for your help. 
  
 Regards. 
  
 Steph. 
  
  


Steph,


Here is the code I wrote, please get it and have a try. I think the performance will be great.


Regards,


Edgar



post10854.txt (2.16 KB)

Hi Edgar,


I have a question about the performance GetFeaturesContaining() on a mssqlFeatureLayer


I have a layer which has 1 000 000 features. The features appears from a certain threshold of zoom. 


So there is 50000 visible features on the screen.


The querytools GetFeatureContaining makes a request on 1 000 000 features or the 50000 visible features in the screen ?


When I did a queryTools with GetCount, the number is 1 000 000 .. so I'm afraid the request is on the 1 000 000 features ;-(


And the problem is that there is a time out.


So is there a way to do the GetFeatureContaining only on the features visible in the screen ?


Thanks a lot for your help.


Regards.


Stéph.


 


 


 


 


 


 


 


 


 


 


 


 


 


 



Hi Steph, 
  
 You can use GetFeaturesInsideBoundingBox first, and add the result features into an InMemoryFeatureLayer and then call the GetFeaturesContaining. 
  
 Regards, 
 Edgar

 Hi Edgar, 


Thanks for your help.


We did  some tests from our part.


With my PC (windows 7 8go RAM) and a table which contains 890000 polygons => I can zoom, pan etc ....


With a VM ( a much less powerful config  : Windows XP 1go RAM) and a table which contains 890000 polygons => can zoom , pan etc ..


So the problem doesn' come from the GetFeatureContaining.


The time out problem comes from a pc of our customers. We are going to continue our research.


 


Thanks for your help.


Regards.


Steph.



Hello Steph, 
  
 You are welcome, please feel free to let us know if you have any more questions. 
  
 Regards, 
  
 Gary