1 // Copyright (C) 2010-2014 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 // Author : Anthony Geay
21 #include "vtkExtractGroup.h"
22 #include "MEDFileFieldRepresentationTree.hxx"
24 #include "vtkAdjacentVertexIterator.h"
25 #include "vtkIntArray.h"
26 #include "vtkCellData.h"
27 #include "vtkPointData.h"
29 #include "vtkStreamingDemandDrivenPipeline.h"
30 #include "vtkUnstructuredGrid.h"
31 #include "vtkMultiBlockDataSet.h"
33 #include "vtkInformationStringKey.h"
34 #include "vtkAlgorithmOutput.h"
35 #include "vtkObjectFactory.h"
36 #include "vtkMutableDirectedGraph.h"
37 #include "vtkMultiBlockDataSet.h"
38 #include "vtkDataSet.h"
39 #include "vtkInformationVector.h"
40 #include "vtkInformation.h"
41 #include "vtkDataArraySelection.h"
42 #include "vtkTimeStamp.h"
43 #include "vtkInEdgeIterator.h"
44 #include "vtkInformationDataObjectKey.h"
45 #include "vtkExecutive.h"
46 #include "vtkVariantArray.h"
47 #include "vtkStringArray.h"
48 #include "vtkDoubleArray.h"
49 #include "vtkCharArray.h"
50 #include "vtkUnsignedCharArray.h"
51 #include "vtkDataSetAttributes.h"
52 #include "vtkDemandDrivenPipeline.h"
53 #include "vtkDataObjectTreeIterator.h"
54 #include "vtkThreshold.h"
59 vtkStandardNewMacro(vtkExtractGroup);
61 vtkCxxSetObjectMacro(vtkExtractGroup, SIL, vtkMutableDirectedGraph);
65 class ExtractGroupStatus
68 ExtractGroupStatus():_status(false) { }
69 ExtractGroupStatus(const char *name);
70 bool getStatus() const { return _status; }
71 void setStatus(bool status) { _status=status; }
72 void cpyStatusFrom(const ExtractGroupStatus& other) { _status=other._status; }
73 std::string getName() const { return _name; }
74 const char *getKeyOfEntry() const { return _ze_key_name.c_str(); }
75 virtual void printMySelf(std::ostream& os) const;
76 virtual bool isSameAs(const ExtractGroupStatus& other) const;
80 std::string _ze_key_name;
83 class ExtractGroupGrp : public ExtractGroupStatus
86 ExtractGroupGrp(const char *name):ExtractGroupStatus(name) { std::ostringstream oss; oss << START << name; _ze_key_name=oss.str(); }
87 void setFamilies(const std::vector<std::string>& fams) { _fams=fams; }
88 const std::vector<std::string>& getFamiliesLyingOn() const { return _fams; }
89 bool isSameAs(const ExtractGroupGrp& other) const;
91 static const char START[];
92 std::vector<std::string> _fams;
95 class ExtractGroupFam : public ExtractGroupStatus
98 ExtractGroupFam(const char *name);
99 void printMySelf(std::ostream& os) const;
100 void fillIdsToKeep(std::set<int>& s) const;
101 int getId() const { return _id; }
102 bool isSameAs(const ExtractGroupFam& other) const;
104 static const char START[];
109 class vtkExtractGroup::vtkExtractGroupInternal
112 void loadFrom(vtkMutableDirectedGraph *sil);
113 int getNumberOfEntries() const;
114 const char *getKeyOfEntry(int i) const;
115 bool getStatusOfEntryStr(const char *entry) const;
116 void setStatusOfEntryStr(const char *entry, bool status);
117 void printMySelf(std::ostream& os) const;
118 std::set<int> getIdsToKeep() const;
119 int getIdOfFamily(const std::string& famName) const;
120 static bool IsInformationOK(vtkInformation *info);
122 std::map<std::string,int> computeFamStrIdMap() const;
123 const ExtractGroupStatus& getEntry(const char *entry) const;
124 ExtractGroupStatus& getEntry(const char *entry);
126 std::vector<ExtractGroupGrp> _groups;
127 std::vector<ExtractGroupFam> _fams;
130 const char ExtractGroupGrp::START[]="GRP_";
132 const char ExtractGroupFam::START[]="FAM_";
134 ExtractGroupStatus::ExtractGroupStatus(const char *name):_status(false),_name(name)
138 void ExtractGroupStatus::printMySelf(std::ostream& os) const
140 os << " -" << _ze_key_name << "(";
145 os << ")" << std::endl;
148 bool ExtractGroupStatus::isSameAs(const ExtractGroupStatus& other) const
150 return _name==other._name && _ze_key_name==other._ze_key_name;
153 bool ExtractGroupGrp::isSameAs(const ExtractGroupGrp& other) const
155 bool ret(ExtractGroupStatus::isSameAs(other));
157 return _fams==other._fams;
162 bool vtkExtractGroup::vtkExtractGroupInternal::IsInformationOK(vtkInformation *info)
164 if(!info->Has(vtkDataObject::SIL()))
166 vtkMutableDirectedGraph *sil(vtkMutableDirectedGraph::SafeDownCast(info->Get(vtkDataObject::SIL())));
170 vtkAbstractArray *verticesNames(sil->GetVertexData()->GetAbstractArray("Names",idNames));
171 vtkStringArray *verticesNames2(vtkStringArray::SafeDownCast(verticesNames));
174 for(int i=0;i<verticesNames2->GetNumberOfValues();i++)
176 vtkStdString &st(verticesNames2->GetValue(i));
177 if(st=="MeshesFamsGrps")
183 void vtkExtractGroup::vtkExtractGroupInternal::loadFrom(vtkMutableDirectedGraph *sil)
185 std::vector<ExtractGroupGrp> oldGrps(_groups); _groups.clear();
186 std::vector<ExtractGroupFam> oldFams(_fams); _fams.clear();
188 vtkAbstractArray *verticesNames(sil->GetVertexData()->GetAbstractArray("Names",idNames));
189 vtkStringArray *verticesNames2(vtkStringArray::SafeDownCast(verticesNames));
192 for(int i=0;i<verticesNames2->GetNumberOfValues();i++)
194 vtkStdString &st(verticesNames2->GetValue(i));
195 if(st=="MeshesFamsGrps")
202 throw INTERP_KERNEL::Exception("There is an internal error ! The tree on server side has not the expected look !");
203 vtkAdjacentVertexIterator *it0(vtkAdjacentVertexIterator::New());
204 sil->GetAdjacentVertices(id0,it0);
206 while(it0->HasNext())
208 vtkIdType id1(it0->Next());
209 std::string meshName((const char *)verticesNames2->GetValue(id1));
210 vtkAdjacentVertexIterator *it1(vtkAdjacentVertexIterator::New());
211 sil->GetAdjacentVertices(id1,it1);
212 vtkIdType idZeGrps(it1->Next());//zeGroups
213 vtkAdjacentVertexIterator *itGrps(vtkAdjacentVertexIterator::New());
214 sil->GetAdjacentVertices(idZeGrps,itGrps);
215 while(itGrps->HasNext())
217 vtkIdType idg(itGrps->Next());
218 ExtractGroupGrp grp((const char *)verticesNames2->GetValue(idg));
219 vtkAdjacentVertexIterator *itGrps2(vtkAdjacentVertexIterator::New());
220 sil->GetAdjacentVertices(idg,itGrps2);
221 std::vector<std::string> famsOnGroup;
222 while(itGrps2->HasNext())
224 vtkIdType idgf(itGrps2->Next());
225 famsOnGroup.push_back(std::string((const char *)verticesNames2->GetValue(idgf)));
227 grp.setFamilies(famsOnGroup);
229 _groups.push_back(grp);
232 vtkIdType idZeFams(it1->Next());//zeFams
234 vtkAdjacentVertexIterator *itFams(vtkAdjacentVertexIterator::New());
235 sil->GetAdjacentVertices(idZeFams,itFams);
236 while(itFams->HasNext())
238 vtkIdType idf(itFams->Next());
239 ExtractGroupFam fam((const char *)verticesNames2->GetValue(idf));
240 _fams.push_back(fam);
246 std::size_t szg(_groups.size()),szf(_fams.size());
247 if(szg==oldGrps.size() && szf==oldFams.size())
250 for(std::size_t i=0;i<szg && isSame;i++)
251 isSame=_groups[i].isSameAs(oldGrps[i]);
252 for(std::size_t i=0;i<szf && isSame;i++)
253 isSame=_fams[i].isSameAs(oldFams[i]);
256 for(std::size_t i=0;i<szg;i++)
257 _groups[i].cpyStatusFrom(oldGrps[i]);
258 for(std::size_t i=0;i<szf;i++)
259 _fams[i].cpyStatusFrom(oldFams[i]);
264 int vtkExtractGroup::vtkExtractGroupInternal::getNumberOfEntries() const
266 std::size_t sz0(_groups.size()),sz1(_fams.size());
267 return (int)(sz0+sz1);
270 const char *vtkExtractGroup::vtkExtractGroupInternal::getKeyOfEntry(int i) const
272 int sz0((int)_groups.size());
274 return _groups[i].getKeyOfEntry();
276 return _fams[i-sz0].getKeyOfEntry();
279 bool vtkExtractGroup::vtkExtractGroupInternal::getStatusOfEntryStr(const char *entry) const
281 const ExtractGroupStatus& elt(getEntry(entry));
282 return elt.getStatus();
285 void vtkExtractGroup::vtkExtractGroupInternal::setStatusOfEntryStr(const char *entry, bool status)
287 ExtractGroupStatus& elt(getEntry(entry));
288 elt.setStatus(status);
291 const ExtractGroupStatus& vtkExtractGroup::vtkExtractGroupInternal::getEntry(const char *entry) const
293 std::string entryCpp(entry);
294 for(std::vector<ExtractGroupGrp>::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
295 if(entryCpp==(*it0).getKeyOfEntry())
297 for(std::vector<ExtractGroupFam>::const_iterator it0=_fams.begin();it0!=_fams.end();it0++)
298 if(entryCpp==(*it0).getKeyOfEntry())
300 std::ostringstream oss; oss << "vtkExtractGroupInternal::getEntry : no such entry \"" << entry << "\"!";
301 throw INTERP_KERNEL::Exception(oss.str().c_str());
304 ExtractGroupStatus& vtkExtractGroup::vtkExtractGroupInternal::getEntry(const char *entry)
306 std::string entryCpp(entry);
307 for(std::vector<ExtractGroupGrp>::iterator it0=_groups.begin();it0!=_groups.end();it0++)
308 if(entryCpp==(*it0).getKeyOfEntry())
310 for(std::vector<ExtractGroupFam>::iterator it0=_fams.begin();it0!=_fams.end();it0++)
311 if(entryCpp==(*it0).getKeyOfEntry())
313 std::ostringstream oss; oss << "vtkExtractGroupInternal::getEntry : no such entry \"" << entry << "\"!";
314 throw INTERP_KERNEL::Exception(oss.str().c_str());
317 void vtkExtractGroup::vtkExtractGroupInternal::printMySelf(std::ostream& os) const
319 os << "Groups :" << std::endl;
320 for(std::vector<ExtractGroupGrp>::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
321 (*it0).printMySelf(os);
322 os << "Families :" << std::endl;
323 for(std::vector<ExtractGroupFam>::const_iterator it0=_fams.begin();it0!=_fams.end();it0++)
324 (*it0).printMySelf(os);
327 int vtkExtractGroup::vtkExtractGroupInternal::getIdOfFamily(const std::string& famName) const
329 for(std::vector<ExtractGroupFam>::const_iterator it=_fams.begin();it!=_fams.end();it++)
331 if((*it).getName()==famName)
332 return (*it).getId();
336 ExtractGroupFam::ExtractGroupFam(const char *name):ExtractGroupStatus(name),_id(0)
338 std::size_t pos(_name.find(MEDFileFieldRepresentationLeavesArrays::ZE_SEP));
339 std::string name0(_name.substr(0,pos)),name1(_name.substr(pos+strlen(MEDFileFieldRepresentationLeavesArrays::ZE_SEP)));
340 std::istringstream iss(name1);
342 std::ostringstream oss; oss << START << name; _ze_key_name=oss.str(); _name=name0;
345 bool ExtractGroupFam::isSameAs(const ExtractGroupFam& other) const
347 bool ret(ExtractGroupStatus::isSameAs(other));
349 return _id==other._id;
354 void ExtractGroupFam::printMySelf(std::ostream& os) const
356 os << " -" << _ze_key_name << " famName : \"" << _name << "\" id : " << _id << " (";
361 os << ")" << std::endl;
364 void ExtractGroupFam::fillIdsToKeep(std::set<int>& s) const
369 std::set<int> vtkExtractGroup::vtkExtractGroupInternal::getIdsToKeep() const
371 std::map<std::string,int> m(this->computeFamStrIdMap());
373 for(std::vector<ExtractGroupGrp>::const_iterator it0=_groups.begin();it0!=_groups.end();it0++)
375 if((*it0).getStatus())
377 const std::vector<std::string>& fams((*it0).getFamiliesLyingOn());
378 for(std::vector<std::string>::const_iterator it1=fams.begin();it1!=fams.end();it1++)
380 std::map<std::string,int>::iterator it2(m.find((*it1)));
382 s.insert((*it2).second);
386 for(std::vector<ExtractGroupFam>::const_iterator it0=_fams.begin();it0!=_fams.end();it0++)
387 if((*it0).getStatus())
388 (*it0).fillIdsToKeep(s);
392 std::map<std::string,int> vtkExtractGroup::vtkExtractGroupInternal::computeFamStrIdMap() const
394 std::map<std::string,int> ret;
395 for(std::vector<ExtractGroupFam>::const_iterator it0=_fams.begin();it0!=_fams.end();it0++)
396 ret[(*it0).getName()]=(*it0).getId();
402 vtkExtractGroup::vtkExtractGroup():SIL(NULL),Internal(new vtkExtractGroupInternal),InsideOut(0)
406 vtkExtractGroup::~vtkExtractGroup()
408 delete this->Internal;
411 void vtkExtractGroup::SetInsideOut(int val)
413 if(this->InsideOut!=val)
420 int vtkExtractGroup::RequestInformation(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector)
424 //std::cerr << "########################################## vtkExtractGroup::RequestInformation ##########################################" << std::endl;
425 vtkInformation *outInfo(outputVector->GetInformationObject(0));
426 vtkInformation *inputInfo(inputVector[0]->GetInformationObject(0));//unfortunately inputInfo->Has(vtkDataObject::SIL) returns false... use executive to find it !
428 vtkExecutive *exe(GetExecutive());
429 vtkAlgorithm *alg(this);
430 vtkInformation *infoOnSIL(alg->GetOutputInformation(0));
431 while(!vtkExtractGroup::vtkExtractGroupInternal::IsInformationOK(infoOnSIL))// skipping vtkPVPostFilter
433 if(exe->GetNumberOfInputConnections(0)<1)
435 vtkErrorMacro("No SIL Data available ! The source of this filter must be MEDReader !");
438 vtkExecutive *exe2(exe->GetInputExecutive(0,0));
440 alg=exe2->GetAlgorithm(); exe=exe2; infoOnSIL=alg->GetOutputInformation(0);
443 this->SetSIL(vtkMutableDirectedGraph::SafeDownCast(infoOnSIL->Get(vtkDataObject::SIL())));
444 this->Internal->loadFrom(this->SIL);
445 //this->Internal->printMySelf(std::cerr);
446 outInfo->Set(vtkDataObject::SIL(),this->SIL);
448 catch(INTERP_KERNEL::Exception& e)
450 std::cerr << "Exception has been thrown in vtkExtractGroup::RequestInformation : " << e.what() << std::endl;
456 template<class CellPointExtractor>
457 vtkDataSet *FilterFamilies(vtkDataSet *input, const std::set<int>& idsToKeep, bool insideOut, const char *arrNameOfFamilyField,
458 const char *associationForThreshold, bool& catchAll, bool& catchSmth)
460 static const int VTK_DATA_ARRAY_DELETE=vtkDataArrayTemplate<double>::VTK_DATA_ARRAY_DELETE;
461 static const char ZE_SELECTION_ARR_NAME[]="@@ZeSelection@@";
462 vtkDataSet *output(input->NewInstance());
463 output->ShallowCopy(input);
464 vtkSmartPointer<vtkThreshold> thres(vtkSmartPointer<vtkThreshold>::New());
465 thres->SetInputData(output);
466 vtkDataSetAttributes *dscIn(input->GetCellData()),*dscIn2(input->GetPointData());
467 vtkDataSetAttributes *dscOut(output->GetCellData()),*dscOut2(output->GetPointData());
469 double vMin(insideOut==0?1.:0.),vMax(insideOut==0?2.:1.);
470 thres->ThresholdBetween(vMin,vMax);
473 CellPointExtractor cpe2(input);
474 vtkDataArray *da(cpe2.Get()->GetScalars(arrNameOfFamilyField));
477 std::string daName(da->GetName());
478 vtkIntArray *dai(vtkIntArray::SafeDownCast(da));
479 if(daName!=arrNameOfFamilyField || !dai)
482 int nbOfTuples(dai->GetNumberOfTuples());
483 vtkCharArray *zeSelection(vtkCharArray::New());
484 zeSelection->SetName(ZE_SELECTION_ARR_NAME);
485 zeSelection->SetNumberOfComponents(1);
486 char *pt(new char[nbOfTuples]);
487 zeSelection->SetArray(pt,nbOfTuples,0,VTK_DATA_ARRAY_DELETE);
488 const int *inPtr(dai->GetPointer(0));
489 std::fill(pt,pt+nbOfTuples,0);
490 catchAll=true; catchSmth=false;
491 std::vector<bool> pt2(nbOfTuples,false);
492 for(std::set<int>::const_iterator it=idsToKeep.begin();it!=idsToKeep.end();it++)
494 bool catchFid(false);
495 for(int i=0;i<nbOfTuples;i++)
497 { pt2[i]=true; catchFid=true; }
503 for(int ii=0;ii<nbOfTuples;ii++)
506 CellPointExtractor cpe3(output);
507 int idx(cpe3.Get()->AddArray(zeSelection));
508 cpe3.Get()->SetActiveAttribute(idx,vtkDataSetAttributes::SCALARS);
509 cpe3.Get()->CopyScalarsOff();
510 zeSelection->Delete();
512 thres->SetInputArrayToProcess(idx,0,0,associationForThreshold,ZE_SELECTION_ARR_NAME);
514 vtkUnstructuredGrid *zeComputedOutput(thres->GetOutput());
515 CellPointExtractor cpe(zeComputedOutput);
516 cpe.Get()->RemoveArray(idx);
518 zeComputedOutput->Register(0);
519 return zeComputedOutput;
525 CellExtractor(vtkDataSet *ds):_ds(ds) { }
526 vtkDataSetAttributes *Get() { return _ds->GetCellData(); }
534 PointExtractor(vtkDataSet *ds):_ds(ds) { }
535 vtkDataSetAttributes *Get() { return _ds->GetPointData(); }
540 int vtkExtractGroup::RequestData(vtkInformation *request, vtkInformationVector **inputVector, vtkInformationVector *outputVector)
544 //std::cerr << "########################################## vtkExtractGroup::RequestData ##########################################" << std::endl;
545 vtkInformation* inputInfo=inputVector[0]->GetInformationObject(0);
546 vtkDataSet *input(vtkDataSet::SafeDownCast(inputInfo->Get(vtkDataObject::DATA_OBJECT())));
547 vtkInformation *info(input->GetInformation());
548 vtkInformation *outInfo(outputVector->GetInformationObject(0));
549 vtkDataSet *output(vtkDataSet::SafeDownCast(outInfo->Get(vtkDataObject::DATA_OBJECT())));
550 std::set<int> idsToKeep(this->Internal->getIdsToKeep());
551 // first shrink the input
552 bool catchAll,catchSmth;
553 vtkDataSet *tryOnCell(FilterFamilies<CellExtractor>(input,idsToKeep,this->InsideOut,
554 MEDFileFieldRepresentationLeavesArrays::FAMILY_ID_CELL_NAME,"vtkDataObject::FIELD_ASSOCIATION_CELLS",catchAll,catchSmth));
559 output->ShallowCopy(tryOnCell);
560 tryOnCell->Delete();//
567 vtkDataSet *tryOnNode(FilterFamilies<PointExtractor>(tryOnCell,idsToKeep,this->InsideOut,
568 MEDFileFieldRepresentationLeavesArrays::FAMILY_ID_NODE_NAME,"vtkDataObject::FIELD_ASSOCIATION_POINTS",catchAll,catchSmth));
569 if(tryOnNode && catchSmth)
571 output->ShallowCopy(tryOnNode);
573 tryOnNode->Delete();//
580 output->ShallowCopy(tryOnCell);
587 vtkDataSet *tryOnNode(FilterFamilies<PointExtractor>(input,idsToKeep,this->InsideOut,
588 MEDFileFieldRepresentationLeavesArrays::FAMILY_ID_NODE_NAME,"vtkDataObject::FIELD_ASSOCIATION_POINTS",catchAll,catchSmth));
592 output->ShallowCopy(tryOnNode);
598 output->ShallowCopy(tryOnCell);
607 vtkDataSet *tryOnNode(FilterFamilies<PointExtractor>(tryOnCell,idsToKeep,this->InsideOut,
608 MEDFileFieldRepresentationLeavesArrays::FAMILY_ID_NODE_NAME,"vtkDataObject::FIELD_ASSOCIATION_POINTS",catchAll,catchSmth));
611 output->ShallowCopy(tryOnNode);
612 tryOnNode->Delete();//
617 std::ostringstream oss; oss << "vtkExtractGroup::RequestData : The integer array with name \""<< MEDFileFieldRepresentationLeavesArrays::FAMILY_ID_CELL_NAME;
618 oss << "\" or \"" << MEDFileFieldRepresentationLeavesArrays::FAMILY_ID_NODE_NAME << "\" does not exist ! The extraction of group and/or family is not possible !";
619 if(this->HasObserver("ErrorEvent") )
620 this->InvokeEvent("ErrorEvent",const_cast<char *>(oss.str().c_str()));
622 vtkOutputWindowDisplayErrorText(const_cast<char *>(oss.str().c_str()));
623 vtkObject::BreakOnError();
628 catch(INTERP_KERNEL::Exception& e)
630 std::cerr << "Exception has been thrown in vtkExtractGroup::RequestData : " << e.what() << std::endl;
635 int vtkExtractGroup::GetSILUpdateStamp()
637 return this->SILTime;
640 void vtkExtractGroup::PrintSelf(ostream& os, vtkIndent indent)
642 this->Superclass::PrintSelf(os, indent);
645 int vtkExtractGroup::GetNumberOfGroupsFlagsArrays()
647 int ret(this->Internal->getNumberOfEntries());
648 //std::cerr << "vtkExtractGroup::GetNumberOfFieldsTreeArrays() -> " << ret << std::endl;
652 const char *vtkExtractGroup::GetGroupsFlagsArrayName(int index)
654 const char *ret(this->Internal->getKeyOfEntry(index));
655 //std::cerr << "vtkExtractGroup::GetFieldsTreeArrayName(" << index << ") -> " << ret << std::endl;
659 int vtkExtractGroup::GetGroupsFlagsArrayStatus(const char *name)
661 int ret((int)this->Internal->getStatusOfEntryStr(name));
662 //std::cerr << "vtkExtractGroup::GetGroupsFlagsArrayStatus(" << name << ") -> " << ret << std::endl;
666 void vtkExtractGroup::SetGroupsFlagsStatus(const char *name, int status)
668 //std::cerr << "vtkExtractGroup::SetFieldsStatus(" << name << "," << status << ")" << std::endl;
669 this->Internal->setStatusOfEntryStr(name,(bool)status);
670 if(std::string(name)==GetGroupsFlagsArrayName(GetNumberOfGroupsFlagsArrays()-1))
672 //this->Internal->printMySelf(std::cerr);