]> SALOME platform Git repositories - modules/paravis.git/blob - src/Plugins/MEDReader/plugin/MEDLoaderForPV/ExtractGroupHelper.cxx
Salome HOME
New 2 useful filters in MEDReader plugin : vtkUgSelectCellIds and vtkGroupAsMultiBlock
[modules/paravis.git] / src / Plugins / MEDReader / plugin / MEDLoaderForPV / ExtractGroupHelper.cxx
1 // Copyright (C) 2020  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (EDF R&D)
20
21 #include "ExtractGroupHelper.h"
22 #include "MEDFileFieldRepresentationTree.hxx"
23
24 #include "vtkInformation.h"
25 #include "vtkInformationDataObjectMetaDataKey.h"
26 #include "vtkAdjacentVertexIterator.h"
27 #include "vtkMutableDirectedGraph.h"
28 #include "vtkDataSetAttributes.h"
29 #include "vtkStringArray.h"
30
31 #include <cstring>
32
33 const char ExtractGroupGrp::START[]="GRP_";
34
35 const char ExtractGroupFam::START[]="FAM_";
36
37 ExtractGroupStatus::ExtractGroupStatus(const char *name):_status(false),_name(name)
38 {
39 }
40
41 void ExtractGroupStatus::printMySelf(std::ostream& os) const
42 {
43   os << "      -" << _ze_key_name << "(";
44   if(_status)
45     os << "X";
46   else
47     os << " ";
48   os << ")" << std::endl;
49 }
50
51 bool ExtractGroupStatus::isSameAs(const ExtractGroupStatus& other) const
52 {
53   return _name==other._name && _ze_key_name==other._ze_key_name;
54 }
55
56 bool ExtractGroupGrp::isSameAs(const ExtractGroupGrp& other) const
57 {
58   bool ret(ExtractGroupStatus::isSameAs(other));
59   if(ret)
60     return _fams==other._fams;
61   else
62     return false;
63 }
64
65 ExtractGroupFam::ExtractGroupFam(const char *name):ExtractGroupStatus(name),_id(0)
66 {
67   std::size_t pos(_name.find(MEDFileFieldRepresentationLeavesArrays::ZE_SEP));
68   std::string name0(_name.substr(0,pos)),name1(_name.substr(pos+strlen(MEDFileFieldRepresentationLeavesArrays::ZE_SEP)));
69   std::istringstream iss(name1);
70   iss >> _id;
71   std::ostringstream oss; oss << START << name; _ze_key_name=oss.str(); _name=name0;
72 }
73
74 bool ExtractGroupFam::isSameAs(const ExtractGroupFam& other) const
75 {
76   bool ret(ExtractGroupStatus::isSameAs(other));
77   if(ret)
78     return _id==other._id;
79   else
80     return false;
81 }
82
83 void ExtractGroupFam::printMySelf(std::ostream& os) const
84 {
85   os << "      -" << _ze_key_name << " famName : \"" << _name << "\" id : " << _id << " (";
86   if(_status)
87     os << "X";
88   else
89     os << " ";
90   os << ")" << std::endl;
91 }
92
93 void ExtractGroupFam::fillIdsToKeep(std::set<int>& s) const
94 {
95   s.insert(_id);
96 }
97 ///////////////////
98
99 bool ExtractGroupInternal::IndependantIsInformationOK(vtkInformationDataObjectMetaDataKey *medReaderMetaData, vtkInformation *info)
100 {
101   // Check the information contain meta data key
102   if(!info->Has(medReaderMetaData))
103     return false;
104
105   // Recover Meta Data
106   vtkMutableDirectedGraph *sil(vtkMutableDirectedGraph::SafeDownCast(info->Get(medReaderMetaData)));
107   if(!sil)
108     return false;
109   int idNames(0);
110   vtkAbstractArray *verticesNames(sil->GetVertexData()->GetAbstractArray("Names",idNames));
111   vtkStringArray *verticesNames2(vtkStringArray::SafeDownCast(verticesNames));
112   if(!verticesNames2)
113     return false;
114   for(int i=0;i<verticesNames2->GetNumberOfValues();i++)
115     {
116       vtkStdString &st(verticesNames2->GetValue(i));
117       if(st=="MeshesFamsGrps")
118         return true;
119     }
120   return false;
121 }
122
123 const char *ExtractGroupInternal::getMeshName() const
124 {
125   return this->_mesh_name.c_str();
126 }
127
128 void ExtractGroupInternal::loadFrom(vtkMutableDirectedGraph *sil)
129 {
130   std::vector<ExtractGroupGrp> oldGrps(_groups); _groups.clear();
131   std::vector<ExtractGroupFam> oldFams(_fams); _fams.clear();
132   int idNames(0);
133   vtkAbstractArray *verticesNames(sil->GetVertexData()->GetAbstractArray("Names",idNames));
134   vtkStringArray *verticesNames2(vtkStringArray::SafeDownCast(verticesNames));
135   vtkIdType id0;
136   bool found(false);
137   for(int i=0;i<verticesNames2->GetNumberOfValues();i++)
138     {
139       vtkStdString &st(verticesNames2->GetValue(i));
140       if(st=="MeshesFamsGrps")
141         {
142           id0=i;
143           found=true;
144         }
145     }
146   if(!found)
147     throw INTERP_KERNEL::Exception("There is an internal error ! The tree on server side has not the expected look !");
148   vtkAdjacentVertexIterator *it0(vtkAdjacentVertexIterator::New());
149   sil->GetAdjacentVertices(id0,it0);
150   int kk(0),ll(0);
151   while(it0->HasNext())
152     {
153       vtkIdType id1(it0->Next());
154       std::string meshName((const char *)verticesNames2->GetValue(id1));
155       this->_mesh_name=meshName;
156       vtkAdjacentVertexIterator *it1(vtkAdjacentVertexIterator::New());
157       sil->GetAdjacentVertices(id1,it1);
158       vtkIdType idZeGrps(it1->Next());//zeGroups
159       vtkAdjacentVertexIterator *itGrps(vtkAdjacentVertexIterator::New());
160       sil->GetAdjacentVertices(idZeGrps,itGrps);
161       while(itGrps->HasNext())
162         {
163           vtkIdType idg(itGrps->Next());
164           ExtractGroupGrp grp((const char *)verticesNames2->GetValue(idg));
165           vtkAdjacentVertexIterator *itGrps2(vtkAdjacentVertexIterator::New());
166           sil->GetAdjacentVertices(idg,itGrps2);
167           std::vector<std::string> famsOnGroup;
168           while(itGrps2->HasNext())
169             {
170               vtkIdType idgf(itGrps2->Next());
171               famsOnGroup.push_back(std::string((const char *)verticesNames2->GetValue(idgf)));
172             }
173           grp.setFamilies(famsOnGroup);
174           itGrps2->Delete();
175           _groups.push_back(grp);
176         }
177       itGrps->Delete();
178       vtkIdType idZeFams(it1->Next());//zeFams
179       it1->Delete();
180       vtkAdjacentVertexIterator *itFams(vtkAdjacentVertexIterator::New());
181       sil->GetAdjacentVertices(idZeFams,itFams);
182       while(itFams->HasNext())
183         {
184           vtkIdType idf(itFams->Next());
185           ExtractGroupFam fam((const char *)verticesNames2->GetValue(idf));
186           _fams.push_back(fam);
187         }
188       itFams->Delete();
189     }
190   it0->Delete();
191   //
192   std::size_t szg(_groups.size()),szf(_fams.size());
193   if(szg==oldGrps.size() && szf==oldFams.size())
194     {
195       bool isSame(true);
196       for(std::size_t i=0;i<szg && isSame;i++)
197         isSame=_groups[i].isSameAs(oldGrps[i]);
198       for(std::size_t i=0;i<szf && isSame;i++)
199         isSame=_fams[i].isSameAs(oldFams[i]);
200       if(isSame)
201         {
202           for(std::size_t i=0;i<szg;i++)
203             _groups[i].cpyStatusFrom(oldGrps[i]);
204           for(std::size_t i=0;i<szf;i++)
205             _fams[i].cpyStatusFrom(oldFams[i]);
206         }
207     }
208 }
209
210 int ExtractGroupInternal::getNumberOfEntries() const
211 {
212   std::size_t sz0(_groups.size()),sz1(_fams.size());
213   return (int)(sz0+sz1);
214 }
215
216 const char *ExtractGroupInternal::getKeyOfEntry(int i) const
217 {
218   int sz0((int)_groups.size());
219   if(i>=0 && i<sz0)
220     return _groups[i].getKeyOfEntry();
221   else
222     return _fams[i-sz0].getKeyOfEntry();
223 }
224
225 bool ExtractGroupInternal::getStatusOfEntryStr(const char *entry) const
226 {
227   const ExtractGroupStatus& elt(getEntry(entry));
228   return elt.getStatus();
229 }
230
231 void ExtractGroupInternal::setStatusOfEntryStr(const char *entry, bool status)
232 {
233   _selection.emplace_back(entry,status);
234 }
235
236 const ExtractGroupStatus& ExtractGroupInternal::getEntry(const char *entry) const
237 {
238   std::string entryCpp(entry);
239   for(std::vector<ExtractGroupGrp>::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
240     if(entryCpp==(*it0).getKeyOfEntry())
241       return *it0;
242   for(std::vector<ExtractGroupFam>::const_iterator it0=_fams.begin();it0!=_fams.end();it0++)
243     if(entryCpp==(*it0).getKeyOfEntry())
244       return *it0;
245   std::ostringstream oss; oss << "vtkExtractGroupInternal::getEntry : no such entry \"" << entry << "\"!";
246   throw INTERP_KERNEL::Exception(oss.str().c_str());
247 }
248
249 ExtractGroupStatus& ExtractGroupInternal::getEntry(const char *entry)
250 {
251   std::string entryCpp(entry);
252   for(std::vector<ExtractGroupGrp>::iterator it0=_groups.begin();it0!=_groups.end();it0++)
253     if(entryCpp==(*it0).getKeyOfEntry())
254       return *it0;
255   for(std::vector<ExtractGroupFam>::iterator it0=_fams.begin();it0!=_fams.end();it0++)
256     if(entryCpp==(*it0).getKeyOfEntry())
257       return *it0;
258   std::ostringstream oss; oss << "vtkExtractGroupInternal::getEntry : no such entry \"" << entry << "\"!";
259   throw INTERP_KERNEL::Exception(oss.str().c_str());
260 }
261
262 void ExtractGroupInternal::printMySelf(std::ostream& os) const
263 {
264   os << "Groups :" << std::endl;
265   for(std::vector<ExtractGroupGrp>::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
266     (*it0).printMySelf(os);
267   os << "Families :" << std::endl;
268   for(std::vector<ExtractGroupFam>::const_iterator it0=_fams.begin();it0!=_fams.end();it0++)
269     (*it0).printMySelf(os);
270 }
271
272 int ExtractGroupInternal::getIdOfFamily(const std::string& famName) const
273 {
274   for(std::vector<ExtractGroupFam>::const_iterator it=_fams.begin();it!=_fams.end();it++)
275     {
276       if((*it).getName()==famName)
277         return (*it).getId();
278     }
279   return std::numeric_limits<int>::max();
280 }
281
282 std::set<int> ExtractGroupInternal::getIdsToKeep() const
283 {
284   for(auto it: _selection)
285     {
286       const ExtractGroupStatus& elt(getEntry(it.first.c_str()));
287       elt.setStatus(it.second);
288     }
289   std::map<std::string,int> m(this->computeFamStrIdMap());
290   std::set<int> s;
291   for(std::vector<ExtractGroupGrp>::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
292     {
293       if((*it0).getStatus())
294         {
295           const std::vector<std::string>& fams((*it0).getFamiliesLyingOn());
296           for(std::vector<std::string>::const_iterator it1=fams.begin();it1!=fams.end();it1++)
297             {
298               std::map<std::string,int>::iterator it2(m.find((*it1)));
299               if(it2!=m.end())
300                 s.insert((*it2).second);
301             }
302         }
303      }
304   for(std::vector<ExtractGroupFam>::const_iterator it0=_fams.begin();it0!=_fams.end();it0++)
305     if((*it0).getStatus())
306       (*it0).fillIdsToKeep(s);
307   return s;
308 }
309
310 // see reference : https://en.cppreference.com/w/cpp/iterator/iterator
311 class FamilyIterator : public std::iterator< std::input_iterator_tag, long, long, int*, int >
312 {
313   long _num = 0;
314   const ExtractGroupInternal *_egi = nullptr;
315   const std::vector<std::string> *_fams = nullptr;
316 public:
317   explicit FamilyIterator(long num , const ExtractGroupInternal *egi, const std::vector<std::string>& fams) : _num(num),_egi(egi),_fams(&fams) {}
318   FamilyIterator& operator++() { ++_num; return *this;}
319   bool operator==(const FamilyIterator& other) const {return _num == other._num;}
320   bool operator!=(const FamilyIterator& other) const {return !(*this == other);}
321   reference operator*() const {return _egi->getIdOfFamily((*_fams)[_num]);}
322 };
323
324 std::vector< std::pair<std::string,std::vector<int> > > ExtractGroupInternal::getAllGroups() const
325 {
326     std::vector< std::pair<std::string,std::vector<int> > > ret;
327     for(const auto&  grp : _groups)
328     {
329         const std::vector<std::string>& fams(grp.getFamiliesLyingOn());
330         std::vector<int> famIds(FamilyIterator(0,this,fams),FamilyIterator(fams.size(),this,fams));
331         std::pair<std::string,std::vector<int> > elt(grp.getName(),std::move(famIds));
332         ret.emplace_back(std::move(elt));
333     }
334     return ret;
335 }
336
337 void ExtractGroupInternal::clearSelection() const
338 {
339   _selection.clear();
340   for(auto it : _groups)
341     it.resetStatus();
342   for(auto it : _fams)
343     it.resetStatus();
344 }
345
346 std::map<std::string,int> ExtractGroupInternal::computeFamStrIdMap() const
347 {
348   std::map<std::string,int> ret;
349   for(std::vector<ExtractGroupFam>::const_iterator it0=_fams.begin();it0!=_fams.end();it0++)
350     ret[(*it0).getName()]=(*it0).getId();
351   return ret;
352 }