]> SALOME platform Git repositories - modules/visu.git/blob - src/VISU_I/VISU_ResultUtils.cc
Salome HOME
Merge from V5_1_main 14/05/2010
[modules/visu.git] / src / VISU_I / VISU_ResultUtils.cc
1 //  Copyright (C) 2007-2010  CEA/DEN, EDF R&D, OPEN CASCADE
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.
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
20 //  VISU OBJECT : interactive object for VISU entities implementation
21 //  File   : VISU_ResultUtils.cc
22 //  Author : Alexey PETROV
23 //  Module : VISU
24 //
25 #include "VISU_ResultUtils.hh"
26
27 #include "SUIT_Session.h"
28 #include "SALOME_Event.h"
29 #include "SalomeApp_Study.h"
30 #include "SalomeApp_Application.h"
31
32 #include "VISU_Convertor.hxx"
33 #include "VISU_ConvertorUtils.hxx"
34
35 #include <QFileInfo>
36 #include <QFile>
37 #include <QDir>
38
39 #include <boost/thread/recursive_mutex.hpp>
40 #include <boost/thread/thread.hpp>
41 #include <boost/bind.hpp>
42
43 #ifdef _DEBUG_
44 static int MYTIMEDEBUG = 0;
45 #else
46 static int MYTIMEDEBUG = 0;
47 #endif
48
49 using namespace std;
50
51 namespace VISU
52 {
53   //----------------------------------------------------------------------------
54   typedef boost::recursive_mutex TMutex;
55   typedef TMutex::scoped_lock TLock;
56
57   static TMutex myMutex;
58
59   //----------------------------------------------------------------------------
60   TResultManager
61   ::TResultManager(Result_i* theResult):
62     myResult(theResult)
63   {
64     myResult->Register();
65   }
66
67
68   //----------------------------------------------------------------------------
69   TResultManager
70   ::~TResultManager()
71   {
72     myResult->Destroy();
73   }
74
75
76   //----------------------------------------------------------------------------
77   TTransactionManager
78   ::TTransactionManager(_PTR(Study) theStudyDocument):
79     myStudyBuilder(theStudyDocument->NewBuilder())
80   {
81     TLock aLock(myMutex);
82     myStudyBuilder->NewCommand();
83   }
84
85
86   //----------------------------------------------------------------------------
87   TTransactionManager
88   ::~TTransactionManager()
89   {
90     TLock aLock(myMutex);
91     myStudyBuilder->CommitCommand();
92   }
93
94
95   //----------------------------------------------------------------------------
96   TUpdateObjBrowser
97   ::TUpdateObjBrowser(const int theStudyId, CORBA::Boolean* theIsDone):
98     myStudyId(theStudyId),
99     myIsDone(theIsDone)
100   {}
101     
102   
103   //----------------------------------------------------------------------------
104   void
105   TUpdateObjBrowser
106   ::Execute()
107   {
108     TLock aLock(myMutex);
109     SUIT_Session* aSession = SUIT_Session::session();
110     QList<SUIT_Application*> anApplications = aSession->applications();
111     QListIterator<SUIT_Application*> anIter (anApplications);
112     while (anIter.hasNext()) {
113       SUIT_Application* aSApp = anIter.next();
114       if(SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>(aSApp)){
115         if (SalomeApp_Study* aStudy = dynamic_cast<SalomeApp_Study*>(anApp->activeStudy())) {
116           if (_PTR(Study) aCStudy = aStudy->studyDS()) {
117             if (myStudyId == aCStudy->StudyId()) {
118               TTimerLog aTimerLog(MYTIMEDEBUG,"Result_i::updateObjectBrowser");
119               anApp->updateObjectBrowser();
120               *myIsDone = true;
121               break;
122             }
123           }
124         }
125       }
126     }
127   }
128
129
130   //----------------------------------------------------------------------------
131   QString
132   GenerateName(const std::string& theName)
133   {
134     TLock aLock(myMutex);
135
136     typedef std::map<std::string, int> TNameMap;
137     static TNameMap aMap;
138
139     TNameMap::const_iterator anIter = aMap.find(theName);
140     QString aResult;
141     if (anIter == aMap.end()) {
142       aMap[theName] = 0;
143       aResult = theName.c_str();
144     } else {
145       aResult = GenerateName(theName,++aMap[theName]);
146     }
147     return aResult;
148   }
149   
150
151   //----------------------------------------------------------------------------
152   bool
153   SplitName(const std::string& theName,
154             std::string& theBase,
155             std::string& theSuffix,
156             char theDelimeter)
157   {
158     size_t aPosition = theName.rfind(theDelimeter);
159     if(aPosition == std::string::npos){
160       theBase = theName;
161       theSuffix = "";
162       return false;
163     }
164
165     theBase = theName.substr(0, aPosition);
166     theSuffix = theName.substr(aPosition);
167     return true;
168   }
169   
170
171   //----------------------------------------------------------------------------
172   std::string
173   MakeFileName(const std::string& theName,
174                const void* thePointer)
175   {
176     std::ostringstream aStream;    
177     aStream<<theName<<"_"<<thePointer;
178     return aStream.str();
179   }
180   
181
182   //----------------------------------------------------------------------------
183   QString 
184   GenerateFieldName(const std::string& theName, 
185                     const std::string& theUnits)
186   {
187     QString aName;
188     const string tmp (theUnits.size(),' ');
189     if (theUnits == "" || theUnits == tmp)
190       aName = QString("%1, -").arg(theName.c_str());
191     else
192       aName = QString("%1, %2").arg(theName.c_str()).arg(theUnits.c_str());
193     aName = aName.simplified();
194     return aName;
195   }
196
197
198   //----------------------------------------------------------------------------
199   void
200   CreateReference(_PTR(Study) theStudyDocument,
201                   const std::string& theFatherEntry, 
202                   const std::string& theRefEntry)
203   {
204     _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
205     _PTR(SObject) aFather = theStudyDocument->FindObjectID(theFatherEntry);
206     _PTR(SObject) aNewObj = aStudyBuilder->NewObject(aFather);
207     _PTR(SObject) aRefSObj = theStudyDocument->FindObjectID(theRefEntry);
208     aStudyBuilder->Addreference(aNewObj,aRefSObj);
209   }
210
211
212   //----------------------------------------------------------------------------
213   void 
214   RemoveSObject(_PTR(Study) theStudyDocument,
215                 const string& theEntry)
216   {
217     _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
218     _PTR(SObject) aSObject = theStudyDocument->FindObjectID(theEntry);
219     aStudyBuilder->RemoveObject(aSObject);
220   }
221
222
223   //----------------------------------------------------------------------------
224   void
225   BuildEntities(Result_i* theResult,
226                 Result_i::PInput theInput,
227                 CORBA::Boolean* theIsDone,
228                 const std::string& theResultEntry,
229                 CORBA::Boolean theIsAtOnce,
230                 CORBA::Boolean theIsBuildGroups,
231                 CORBA::Boolean theIsBuildFields,
232                 CORBA::Boolean theIsBuildParts,
233                 _PTR(Study) theStudy)
234   {
235     if(*theIsDone)
236       return;
237
238     TTimerLog aTimerLog(MYTIMEDEBUG,"Result_i::BuildEntities");
239     TResultManager aResultManager(theResult);
240     TTransactionManager aTransactionManager(theStudy);
241
242     {
243       TTimerLog aTimerLog(MYTIMEDEBUG,"theInput->BuildEntities");
244       theInput->BuildEntities();
245     }
246
247     QString aComment,aTmp;
248     const TMeshMap& aMeshMap = theInput->GetMeshMap();
249     TMeshMap::const_iterator aMeshMapIter = aMeshMap.begin();
250     for(; aMeshMapIter != aMeshMap.end(); aMeshMapIter++){
251       const string& aMeshName = aMeshMapIter->first;
252       const PMesh& aMesh = aMeshMapIter->second;
253       const TMeshOnEntityMap& aMeshOnEntityMap = aMesh->myMeshOnEntityMap;
254       if(aMeshOnEntityMap.empty()) 
255         continue;
256       aComment = QString("myComment=MESH;myName=%1;myDim=%2");
257       aComment = aComment.arg(aMeshName.c_str());
258       aComment = aComment.arg(aMesh->myDim);
259       aMesh->myEntry = 
260         CreateAttributes(theStudy,
261                          theResultEntry,
262                          NO_ICON,
263                          NO_IOR,
264                          aMeshName,
265                          NO_PERFSITENT_REF,
266                          aComment.toLatin1().data(),
267                          true);
268     
269       aComment = QString("myComment=FAMILIES;myMeshName=%1").arg(aMeshName.c_str());
270       std::string aSubMeshesEntry = 
271         CreateAttributes(theStudy,
272                          aMesh->myEntry,
273                          NO_ICON,
274                          NO_IOR,
275                          "Families",
276                          NO_PERFSITENT_REF,
277                          aComment.toLatin1().data(),
278                          true);
279
280       if(theIsBuildGroups){
281         aMesh->myGroupsEntry =
282           CreateAttributes(theStudy,
283                            aMesh->myEntry,
284                            NO_ICON,
285                            NO_IOR,
286                            NO_NAME,
287                            NO_PERFSITENT_REF,
288                            NO_COMMENT,
289                            true);
290       }
291         
292       if(theIsBuildFields){
293         aMesh->myFieldsEntry =
294           CreateAttributes(theStudy,
295                            aMesh->myEntry,
296                            NO_ICON,
297                            NO_IOR,
298                            NO_NAME,
299                            NO_PERFSITENT_REF,
300                            NO_COMMENT,
301                            true);
302       }
303
304       if(theIsBuildParts){
305         aMesh->myPartsEntry =
306           CreateAttributes(theStudy,
307                            aMesh->myEntry,
308                            NO_ICON,
309                            NO_IOR,
310                            NO_NAME,
311                            NO_PERFSITENT_REF,
312                            NO_COMMENT,
313                            true);
314       }
315
316       //Import entities
317       TMeshOnEntityMap::const_iterator aMeshOnEntityMapIter = aMeshOnEntityMap.begin();
318       for(; aMeshOnEntityMapIter != aMeshOnEntityMap.end(); aMeshOnEntityMapIter++){
319         const TEntity& anEntity = aMeshOnEntityMapIter->first;
320         const PMeshOnEntity& aMeshOnEntity = aMeshOnEntityMapIter->second;
321         
322         string anEntityName;
323         switch(anEntity){
324         case NODE_ENTITY: 
325           anEntityName = "onNodes"; 
326           break;
327         case EDGE_ENTITY: 
328           anEntityName = "onEdges"; 
329           break;
330         case FACE_ENTITY: 
331           anEntityName = "onFaces"; 
332           break;
333         case CELL_ENTITY: 
334           anEntityName = "onCells"; 
335           break;
336         default:
337         continue;
338         }
339         
340         aComment = QString("myComment=ENTITY;myMeshName=%1;myId=%2");
341         aComment = aComment.arg(aMeshName.c_str());
342         aComment = aComment.arg(anEntity);
343         
344         aMeshOnEntity->myEntry = 
345           CreateAttributes(theStudy, 
346                            aSubMeshesEntry, 
347                            NO_ICON,
348                            NO_IOR,
349                            anEntityName.c_str(),
350                            NO_PERFSITENT_REF,
351                            aComment.toLatin1().data(), 
352                            true);
353       }
354     }
355     
356     ProcessVoidEvent(new TUpdateObjBrowser(theStudy->StudyId(),theIsDone));
357   }
358
359
360   //----------------------------------------------------------------------------
361   void
362   BuildGroups(Result_i* theResult,
363               Result_i::PInput theInput,
364               CORBA::Boolean* theIsDone,
365               CORBA::Boolean theIsBuild,
366               CORBA::Boolean theIsAtOnce,
367               _PTR(Study) theStudy)
368   {
369     if(!theIsBuild || *theIsDone)
370       return;
371
372     TTimerLog aTimerLog(MYTIMEDEBUG,"Result_i::BuildGroups");
373     TResultManager aResultManager(theResult);
374     TTransactionManager aTransactionManager(theStudy);
375     
376     {
377       TTimerLog aTimerLog(MYTIMEDEBUG,"theInput->BuildGroups");
378       theInput->BuildGroups();
379     }
380
381     QString aComment,aTmp;
382     const TMeshMap& aMeshMap = theInput->GetMeshMap();
383     TMeshMap::const_iterator aMeshMapIter = aMeshMap.begin();
384     for(; aMeshMapIter != aMeshMap.end(); aMeshMapIter++){
385       const string& aMeshName = aMeshMapIter->first;
386       const PMesh& aMesh = aMeshMapIter->second;
387       
388       const TMeshOnEntityMap& aMeshOnEntityMap = aMesh->myMeshOnEntityMap;
389       if(aMeshOnEntityMap.empty()) 
390         continue;
391       
392       TMeshOnEntityMap::const_iterator aMeshOnEntityMapIter = aMeshOnEntityMap.begin();
393       for(; aMeshOnEntityMapIter != aMeshOnEntityMap.end(); aMeshOnEntityMapIter++){
394         const TEntity& anEntity = aMeshOnEntityMapIter->first;
395         const PMeshOnEntity& aMeshOnEntity = aMeshOnEntityMapIter->second;
396         
397         const TFamilyMap& aFamilyMap = aMeshOnEntity->myFamilyMap;
398         TFamilyMap::const_iterator aFamilyMapIter = aFamilyMap.begin();
399         for(; aFamilyMapIter != aFamilyMap.end(); aFamilyMapIter++){
400           const string& aFamilyName = aFamilyMapIter->first;
401           const PFamily& aFamily = aFamilyMapIter->second;
402           aComment=QString("myComment=FAMILY;myMeshName=%1;myEntityId=%2;myName=%3");
403           aComment=aComment.arg(aMeshName.c_str());
404           aComment=aComment.arg(anEntity);
405           aComment=aComment.arg(aFamilyName.c_str());
406           aFamily->myEntry =
407             CreateAttributes(theStudy,
408                              aMeshOnEntity->myEntry,
409                              NO_ICON,
410                              NO_IOR,
411                              aFamilyName,
412                              NO_PERFSITENT_REF,
413                              aComment.toLatin1().data(),
414                              true);
415         }
416       }
417       //Importing groups
418       const TGroupMap& aGroupMap = aMesh->myGroupMap;
419       if(!aGroupMap.empty()){
420         aComment = QString("myComment=GROUPS;myMeshName=%1").arg(aMeshName.c_str());
421         
422         CreateAttributes(theStudy,
423                          aMesh->myGroupsEntry,
424                          NO_ICON,
425                          NO_IOR,
426                          "Groups",
427                          NO_PERFSITENT_REF,
428                          aComment.toLatin1().data(),
429                          false);
430
431         TGroupMap::const_iterator aGroupMapIter = aGroupMap.begin();
432         for(; aGroupMapIter != aGroupMap.end(); aGroupMapIter++){
433           const string& aGroupName = aGroupMapIter->first;
434           const PGroup& aGroup = aGroupMapIter->second;
435           aComment = QString("myComment=GROUP;myMeshName=%1;myName=%2").arg(aMeshName.c_str()).arg(aGroupName.c_str());
436           aGroup->myEntry = 
437             CreateAttributes(theStudy,
438                              aMesh->myGroupsEntry,
439                              NO_ICON,
440                              NO_IOR,
441                              aGroupName,
442                              NO_PERFSITENT_REF,
443                              aComment.toLatin1().data(),
444                              true);
445           const TFamilySet& aFamilySet = aGroup->myFamilySet;
446           TFamilySet::const_iterator aFamilyIter = aFamilySet.begin();
447           for(; aFamilyIter != aFamilySet.end(); aFamilyIter++){
448             const PFamily& aFamily = (*aFamilyIter).second;
449             CreateReference(theStudy,
450                             aGroup->myEntry,
451                             aFamily->myEntry);
452           }
453         }
454       }else if(!theIsAtOnce)
455         RemoveSObject(theStudy,
456                       aMesh->myGroupsEntry);
457     }
458     
459     ProcessVoidEvent(new TUpdateObjBrowser(theStudy->StudyId(),theIsDone));
460   }
461
462
463   //----------------------------------------------------------------------------
464   void
465   BuildFields(Result_i* theResult,
466               Result_i::PInput theInput,
467               CORBA::Boolean* theIsDone,
468               CORBA::Boolean theIsBuild,
469               CORBA::Boolean theIsAtOnce,
470               _PTR(Study) theStudy)
471   {
472     if(!theIsBuild || *theIsDone)
473       return;
474
475     TTimerLog aTimerLog(MYTIMEDEBUG,"Result_i::BuildFields");
476     TResultManager aResultManager(theResult);
477     TTransactionManager aTransactionManager(theStudy);
478
479     {
480       TTimerLog aTimerLog(MYTIMEDEBUG,"theInput->BuildFields");
481       theInput->BuildFields();
482     }
483
484     QString aComment,aTmp;
485     const TMeshMap& aMeshMap = theInput->GetMeshMap();
486     TMeshMap::const_iterator aMeshMapIter = aMeshMap.begin();
487
488     for(; aMeshMapIter != aMeshMap.end(); aMeshMapIter++)
489     {
490       const string& aMeshName = aMeshMapIter->first;
491       const PMesh& aMesh = aMeshMapIter->second;
492
493       const TMeshOnEntityMap& aMeshOnEntityMap = aMesh->myMeshOnEntityMap;
494       if(aMeshOnEntityMap.empty()) 
495         continue;
496
497       //Import fields
498       bool anIsFieldsEntryUpdated = false;
499       TMeshOnEntityMap::const_iterator aMeshOnEntityMapIter = aMeshOnEntityMap.begin();
500
501       for(; aMeshOnEntityMapIter != aMeshOnEntityMap.end(); aMeshOnEntityMapIter++)
502       {
503         const TEntity& anEntity = aMeshOnEntityMapIter->first;
504         const PMeshOnEntity& aMeshOnEntity = aMeshOnEntityMapIter->second;
505         const TFieldMap& aFieldMap = aMeshOnEntity->myFieldMap;
506         TFieldMap::const_iterator aFieldMapIter = aFieldMap.begin();
507
508         for(; aFieldMapIter != aFieldMap.end(); aFieldMapIter++)
509         {
510           if(!anIsFieldsEntryUpdated)
511           {
512             aComment = "";
513             aComment.append("myComment=FIELDS;");
514             aComment.append("myMeshName=");aComment.append(aMeshName.c_str());
515
516             CreateAttributes(theStudy,
517                              aMesh->myFieldsEntry,
518                              NO_ICON,
519                              NO_IOR,
520                              "Fields",
521                              NO_PERFSITENT_REF,
522                              aComment.toLatin1().data(),
523                              false);
524
525             anIsFieldsEntryUpdated = true;
526           }
527
528           const string& aFieldName = aFieldMapIter->first;
529           const PField& aField = aFieldMapIter->second;
530           const TValField& aValField = aField->myValField;
531           QString aFieldNameWithUnit = GenerateFieldName(aFieldName,aField->myUnitNames[0]);
532           aComment = QString("myComment=FIELD;myMeshName=%1;myEntityId=%2;myName=%3;myNbTimeStamps=%4;myNumComponent=%5");
533           aComment = aComment.arg(aMeshName.c_str());
534           aComment = aComment.arg(anEntity);
535           aComment = aComment.arg(aFieldName.c_str());
536           aComment = aComment.arg(aValField.size());
537           aComment = aComment.arg(aField->myNbComp);
538           
539           aField->myEntry = CreateAttributes(theStudy,
540                                              aMesh->myFieldsEntry,
541                                              NO_ICON,
542                                              NO_IOR,
543                                              aFieldNameWithUnit.toLatin1().data(),
544                                              NO_PERFSITENT_REF,
545                                              aComment.toLatin1().data(),
546                                              true);
547
548           CreateReference(theStudy,
549                           aField->myEntry,
550                           aMeshOnEntity->myEntry);
551
552           TValField::const_iterator aValFieldIter = aValField.begin();
553
554           for(; aValFieldIter != aValField.end(); aValFieldIter++)
555           {
556             int aTimeStamp = aValFieldIter->first;
557             const PValForTime& aValForTime = aValFieldIter->second;
558             aComment = QString("myComment=TIMESTAMP;myMeshName=%1;myEntityId=%2;myFieldName=%3;myTimeStampId=%4;myNumComponent=%5");
559             aComment = aComment.arg(aMeshName.c_str());
560             aComment = aComment.arg(anEntity);
561             aComment = aComment.arg(aFieldName.c_str());
562             aComment = aComment.arg(aTimeStamp);
563             aComment = aComment.arg(aField->myNbComp);
564
565             string aTimeStampId = VISU_Convertor::GenerateName(aValForTime->myTime);
566
567             aValForTime->myEntry = CreateAttributes(theStudy,
568                                                     aField->myEntry,
569                                                     NO_ICON,
570                                                     NO_IOR,
571                                                     aTimeStampId,
572                                                     NO_PERFSITENT_REF,
573                                                     aComment.toLatin1().data(),
574                                                     true);
575           }
576         }
577       }
578
579       if(!anIsFieldsEntryUpdated && !theIsAtOnce)
580         RemoveSObject(theStudy, aMesh->myFieldsEntry);
581     }
582
583     ProcessVoidEvent(new TUpdateObjBrowser(theStudy->StudyId(),theIsDone));
584   }
585
586
587   //----------------------------------------------------------------------------
588   void
589   BuildMinMax(Result_i* theResult,
590               Result_i::PInput theInput,
591               CORBA::Boolean* theIsDone,
592               CORBA::Boolean theIsBuild)
593   {
594     if(!theIsBuild || *theIsDone)
595       return;
596
597     TTimerLog aTimerLog(MYTIMEDEBUG,"Result_i::BuildMinMax");
598     TResultManager aResultManager(theResult);
599     
600     theInput->BuildMinMax();
601
602     *theIsDone = true;
603
604     theResult->UpdateObservers();
605   }
606
607
608   //----------------------------------------------------------------------------
609   void
610   BuildFieldDataTree(Result_i* theResult,
611                      Result_i::PInput theInput,
612                      CORBA::Boolean* theIsFieldsDone,
613                      CORBA::Boolean theIsBuildFields,
614                      CORBA::Boolean* theIsMinMaxDone,
615                      CORBA::Boolean theIsBuildMinMax,
616                      _PTR(Study) theStudy)
617   {
618     BuildFields(theResult,
619                 theInput,
620                 theIsFieldsDone,
621                 theIsBuildFields,
622                 false,
623                 theStudy);
624
625     BuildMinMax(theResult,
626                 theInput,
627                 theIsMinMaxDone,
628                 theIsBuildMinMax);
629   }
630
631
632   //----------------------------------------------------------------------------
633   bool
634   RemoveFile(const std::string& theFileName,
635              bool theRemoveEmptyDir)
636   {
637     QFileInfo aFileInfo(theFileName.c_str());
638     QFile(aFileInfo.absoluteFilePath()).remove();
639     
640     if(theRemoveEmptyDir)
641       QDir().rmdir(aFileInfo.absolutePath());
642
643     return aFileInfo.exists();
644   }
645
646
647   //----------------------------------------------------------------------------
648   bool
649   CopyFile(const std::string& theSourceFileName,
650            const std::string& theTargetFileName)
651   {
652     QFileInfo aSourceFileInfo(theSourceFileName.c_str());
653     QFileInfo aTargetFileInfo(theTargetFileName.c_str());
654     if(aSourceFileInfo.absoluteFilePath() == aTargetFileInfo.absoluteFilePath())
655       return true;
656
657     QString aCommand;
658     aCommand.sprintf("%s %s %s",
659                      COPY_COMMAND,
660                      aSourceFileInfo.filePath().toLatin1().data(),
661                      aTargetFileInfo.filePath().toLatin1().data());
662
663     return system(aCommand.toLatin1().data()) == 0;
664   }
665
666
667   //----------------------------------------------------------------------------
668 }