Salome HOME
sources v1.2c
[modules/visu.git] / src / VISU_I / VISU_TimeAnimation.cxx
1 //  Copyright (C) 2003  CEA/DEN, EDF R&D
2 //
3 //
4 //
5 //  File   : VISU_TimeAnimation.cxx
6 //  Author : Vitaly SMETANNIKOV
7 //  Module : VISU
8
9 #include "VISU_TimeAnimation.h"
10 #include "VISU_Result_i.hh"
11 #include "VISU_Prs3d_i.hh"
12 #include "VISU_Mesh_i.hh"
13 #include "VISU_ScalarMap_i.hh"
14 #include "VISU_IsoSurfaces_i.hh"
15 #include "VISU_DeformedShape_i.hh"
16 #include "VISU_CutPlanes_i.hh"
17 #include "VISU_CutLines_i.hh"
18 #include "VISU_Vectors_i.hh"
19 #include "VISU_StreamLines_i.hh"
20 #include "VISU_ViewManager_i.hh"
21 #include "VISU_ScalarBarActor.hxx"
22 #include "VISU_Actor.h"
23
24 #include "VTKViewer_ViewFrame.h"
25
26 #include "QAD_Config.h"
27
28 using namespace std;
29
30 //QWaitCondition myCondition;
31 static int MYDELAY = 1;
32
33 //************************************************************************
34 VISU_TimeAnimation::VISU_TimeAnimation(SALOMEDS::Study_var theStudy, VISU::View3D_ptr theView3D) {
35   myStudy = theStudy;
36   myIsActive = false;
37   myFrame = 0;
38   mySpeed = 1;
39   myProportional = false;
40   myView = 0;
41
42   if(!CORBA::is_nil(theView3D)){
43     VISU::View3D_i* pView = dynamic_cast<VISU::View3D_i*>(GetServant(theView3D));
44     QAD_StudyFrame* aStudyFrame = pView->GetStudyFrame();
45     myView = VISU::GetViewFrame(aStudyFrame);
46   }
47
48   myMaxVal = 0;
49   myMinVal = 0;
50   myTimeMin = 0;
51   myTimeMax = 0;
52   myLastError = "";
53   myCycling = false;
54 }
55
56
57 //************************************************************************
58 VISU_TimeAnimation::~VISU_TimeAnimation() {
59   for (int i = 0; i < getNbFields(); i++) {
60     clearData(myFieldsLst[i]);
61   }
62 }
63
64
65 //************************************************************************
66 void VISU_TimeAnimation::addField(SALOMEDS::SObject_ptr theField) {
67   FieldData aNewData;
68   aNewData.myField = SALOMEDS::SObject::_duplicate(theField);
69   aNewData.myNbFrames = 0;
70   aNewData.myPrs = 0;
71   aNewData.myActors = 0;
72   aNewData.myTiming = 0;
73   aNewData.myPrsType = VISU::TSCALARMAP;
74   VISU::Storable::TRestoringMap aMap = getMapOfValue(aNewData.myField);
75   aNewData.myNbTimes = VISU::Storable::FindValue(aMap,"myNbTimeStamps").toLong();
76   myFieldsLst.append(aNewData);
77
78   //find Min/Max timestamps
79   if ((myTimeMin == 0) && (myTimeMax == 0)) {
80     SALOMEDS::ChildIterator_var anIter = myStudy->NewChildIterator(theField);
81     SALOMEDS::SObject_var aTimeStamp;
82     anIter->Next(); // First is reference on support
83     myTimeMin = getTimeValue(anIter->Value());
84     for(; anIter->More(); anIter->Next()) {
85       myTimeMax = getTimeValue(anIter->Value());
86     }
87   }
88 }
89
90
91 //************************************************************************
92 void VISU_TimeAnimation::clearData(FieldData& theData) {
93   if (theData.myTiming) {
94     free(theData.myTiming);
95     theData.myTiming = 0;
96   }
97   vtkRenderer* aRen = myView->getRenderer();
98   if (theData.myActors) {
99     for (int i = 0; i < theData.myNbFrames; i++) {
100       if (theData.myActors[i] != 0) {
101         theData.myActors[i]->RemoveFromRender(aRen);
102         theData.myActors[i]->Delete();
103       }
104     }
105     free(theData.myActors);
106     theData.myActors = 0;
107   }
108   if (theData.myPrs) {
109     for (int i = 0; i < theData.myNbFrames; i++) 
110       theData.myPrs[i]->_remove_ref();
111     free(theData.myPrs);
112     theData.myPrs = 0;
113   }  
114   theData.myNbFrames = 0;
115   myView->update();
116 }
117
118
119 //************************************************************************
120 void VISU_TimeAnimation::generatePresentations(CORBA::Long theFieldNum) {
121   FieldData& aData = myFieldsLst[theFieldNum];
122
123   // Delete previous presentations
124   clearData(aData);
125
126   VISU::Result_i* pResult = createPresent(aData.myField); 
127   VISU::Storable::TRestoringMap aMap = getMapOfValue(aData.myField);
128   aData.myNbFrames = aData.myNbTimes;
129     //VISU::Storable::FindValue(aMap,"myNbTimeStamps").toLong();
130
131   aData.myPrs = (VISU::ScalarMap_i**) malloc(aData.myNbTimes * sizeof(VISU::ScalarMap_i*));
132   aData.myTiming = (double*) malloc(aData.myNbTimes * sizeof(double));
133
134   SALOMEDS::ChildIterator_var anIter = myStudy->NewChildIterator(aData.myField);
135   SALOMEDS::SObject_var aTimeStamp;
136   anIter->Next(); // First is reference on support
137   long i = 0;
138   double aMin = 0, aMax = 0;
139   for(;anIter->More();anIter->Next()) {
140     if (i == aData.myNbTimes) {
141       MESSAGE("There are extra timestamps in field");
142       return;
143     }
144     aTimeStamp = anIter->Value();
145     if (aTimeStamp->_is_nil()) continue;
146
147     aData.myTiming[i] = getTimeValue(aTimeStamp);
148     if (isRangeDefined()) {
149       if (aData.myTiming[i] < myMinVal) continue;
150       if (aData.myTiming[i] > myMaxVal) break;
151     }
152
153     VISU::Storable::TRestoringMap aTimeMap = getMapOfValue(aTimeStamp);
154     QString aMeshName = VISU::Storable::FindValue(aTimeMap,"myMeshName"); 
155     VISU::Entity anEntity = (VISU::Entity) VISU::Storable::FindValue(aTimeMap,"myEntityId").toInt(); 
156     QString aFieldName = VISU::Storable::FindValue(aTimeMap,"myFieldName"); 
157     int aTimeStampId = VISU::Storable::FindValue(aTimeMap,"myTimeStampId").toInt(); 
158     
159     switch (aData.myPrsType) {
160     case VISU::TSCALARMAP: // ScalarMap
161       {
162         VISU::ScalarMap_i* aPresent = new VISU::ScalarMap_i(pResult, false);
163         aPresent->Create(aMeshName.latin1(), anEntity, 
164                          aFieldName.latin1(), aTimeStampId);
165         //VISU::ScalarMap_var aTmp = aPresent->_this();
166         //aPresent->_remove_ref();
167         aData.myPrs[i] = aPresent;
168       }
169       break;
170       
171     case VISU::TISOSURFACE: // Iso Surfaces
172       {
173         VISU::IsoSurfaces_i* aPresent = new VISU::IsoSurfaces_i(pResult, false);
174         aPresent->Create(aMeshName.latin1(), anEntity, 
175                          aFieldName.latin1(), aTimeStampId);
176         //VISU::IsoSurfaces_var aTmp = aPresent->_this();
177         //aPresent->_remove_ref();
178         aData.myPrs[i] = aPresent;
179       }
180       break;
181     
182     case VISU::TCUTPLANES: // Cut Planes
183       {
184         VISU::CutPlanes_i* aPresent = new VISU::CutPlanes_i(pResult, false);
185         aPresent->Create(aMeshName.latin1(), anEntity, 
186                          aFieldName.latin1(), aTimeStampId);
187         //VISU::CutPlanes_var aTmp = aPresent->_this();
188         //aPresent->_remove_ref();
189         aData.myPrs[i] = aPresent;
190       }
191       break;
192       
193     case VISU::TDEFORMEDSHAPE: // Deformed Shape
194       {
195         VISU::DeformedShape_i* aPresent = new VISU::DeformedShape_i(pResult, false);
196         aPresent->Create(aMeshName.latin1(), anEntity, 
197                          aFieldName.latin1(), aTimeStampId);
198         //VISU::DeformedShape_var aTmp = aPresent->_this();
199         //aPresent->_remove_ref();
200         aData.myPrs[i] = aPresent;
201       }
202       break;
203       
204     case VISU::TVECTORS: // Vectors
205       {
206         VISU::Vectors_i* aPresent = new VISU::Vectors_i(pResult, false);
207         aPresent->Create(aMeshName.latin1(), anEntity,  
208                          aFieldName.latin1(), aTimeStampId);
209         //VISU::Vectors_var aTmp = aPresent->_this();
210         //aPresent->_remove_ref();
211         aData.myPrs[i] = aPresent;
212       }
213       break;
214       
215     case VISU::TSTREAMLINES: // Stream Lines
216       {
217         VISU::StreamLines_i* aPresent = new VISU::StreamLines_i(pResult, false);
218         aPresent->Create(aMeshName.latin1(), anEntity, 
219                          aFieldName.latin1(), aTimeStampId);
220         //VISU::StreamLines_var aTmp = aPresent->_this();
221         //aPresent->_remove_ref();
222         aData.myPrs[i] = aPresent;
223       }
224       break;
225     }
226     if (aData.myPrs[i]->GetMin() < aMin) aMin = aData.myPrs[i]->GetMin();
227     if (aData.myPrs[i]->GetMax() > aMax) aMax = aData.myPrs[i]->GetMax();
228     i++;
229   }
230   aData.myNbFrames = i;
231   QString aFixRange = QAD_CONFIG->getSetting("Visu:SBImposeRange");
232   if (aFixRange.compare("true") != 0) {
233     for (i = 0; i < aData.myNbFrames; i++) 
234       aData.myPrs[i]->SetRange(aMin, aMax);
235   }
236 }
237
238
239 //************************************************************************
240 CORBA::Boolean VISU_TimeAnimation::generateFrames() {
241   if (!myView) {
242     MESSAGE("Viewer is nod defined for animation");
243     return false;
244   }
245   myLastError = QString("Frame(s) for ");
246   bool aNoError = true;
247   VISU::Mutex mt(myMutex,qApp,MYDELAY);
248   clearView();
249   vtkRenderer* aRen = myView->getRenderer();
250   for (int i = 0; i < getNbFields(); i++) {
251     FieldData& aData = myFieldsLst[i];
252     aData.myActors = (VISU_Actor**) malloc(aData.myNbFrames * sizeof(VISU_Actor*));
253     for (long j = 0; j < aData.myNbFrames; j++) {
254       VISU_Actor* aActor = NULL;
255       try{
256         aActor = aData.myPrs[j]->CreateActor();
257         myView->AddActor(aActor);
258         if(j == 0)
259           aActor->VisibilityOn();
260         else
261           aActor->VisibilityOff();
262       }catch(std::runtime_error& exc){
263         aNoError = false;
264         myLastError += QString("%1 ").arg(aData.myTiming[j]);
265       }
266       aData.myActors[j] = aActor;
267     }
268   }
269   myFrame = 0;
270   myLastError += QString(" timestamp(s) cannot be created.");
271   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
272   myView->Repaint();
273   return aNoError;
274 }
275
276 //************************************************************************
277 void VISU_TimeAnimation::clearView() {
278   if (!myView) {
279     MESSAGE("Viewer is nod defined for animation");
280     return;
281   }
282   VISU::Mutex mt(myMutex,qApp,MYDELAY);
283   vtkRenderer* aRen = myView->getRenderer();
284   for (int i = 0; i < getNbFields(); i++) {
285     FieldData& aData = myFieldsLst[i];
286     if (aData.myActors) {
287       for (int i = 0; i < aData.myNbFrames; i++) {
288         if (aData.myActors[i] != 0) {
289           aData.myActors[i]->RemoveFromRender(aRen);
290           aData.myActors[i]->Delete();
291         }
292       } 
293       free(aData.myActors);
294       aData.myActors = 0;
295     }
296   }
297   myView->update();
298 }
299
300 //************************************************************************
301 void VISU_TimeAnimation::stopAnimation() {
302   myIsActive = false;
303 }
304
305 //************************************************************************
306 void VISU_TimeAnimation::startAnimation() {
307   if (!myIsActive) {
308     myIsActive = true;
309     QThread::start();
310   }
311 }
312
313 //************************************************************************
314 void VISU_TimeAnimation::nextFrame() {
315   stopAnimation();
316   if (myFrame < (myFieldsLst[0].myNbFrames-1)) {
317     int i;
318     for (i = 0; i < getNbFields(); i++) 
319       if (myFieldsLst[i].myActors[myFrame] != 0)
320         myFieldsLst[i].myActors[myFrame]->VisibilityOff();
321     myFrame++;
322     for (i = 0; i < getNbFields(); i++) 
323       if (myFieldsLst[i].myActors[myFrame] != 0)
324         myFieldsLst[i].myActors[myFrame]->VisibilityOn(); 
325
326     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
327     myView->Repaint();
328   }
329 }
330
331 //************************************************************************
332 void VISU_TimeAnimation::prevFrame() {
333   stopAnimation();
334   if (myFrame > 0) {
335     int i;
336     for (i = 0; i < getNbFields(); i++) 
337       if (myFieldsLst[i].myActors[myFrame] != 0)
338         myFieldsLst[i].myActors[myFrame]->VisibilityOff();
339     myFrame--;
340     for (i = 0; i < getNbFields(); i++) 
341       if (myFieldsLst[i].myActors[myFrame] != 0)
342         myFieldsLst[i].myActors[myFrame]->VisibilityOn();    
343
344     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
345     myView->Repaint();
346   }
347 }
348
349 //************************************************************************
350 void VISU_TimeAnimation::firstFrame() {
351   stopAnimation();
352   int i;
353   for (i = 0; i < getNbFields(); i++) 
354     if (myFieldsLst[i].myActors[myFrame] != 0)
355       myFieldsLst[i].myActors[myFrame]->VisibilityOff();
356   myFrame = 0;
357   for (i = 0; i < getNbFields(); i++) 
358     if (myFieldsLst[i].myActors[myFrame] != 0)
359       myFieldsLst[i].myActors[myFrame]->VisibilityOn();    
360
361   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
362   myView->Repaint();
363 }
364
365 //************************************************************************
366 void VISU_TimeAnimation::lastFrame() {
367   stopAnimation();
368   int i;
369   for (i = 0; i < getNbFields(); i++) 
370     if (myFieldsLst[i].myActors[myFrame] != 0)
371       myFieldsLst[i].myActors[myFrame]->VisibilityOff();
372   myFrame = myFieldsLst[0].myNbFrames-1;
373   for (i = 0; i < getNbFields(); i++) 
374     if (myFieldsLst[i].myActors[myFrame] != 0)
375       myFieldsLst[i].myActors[myFrame]->VisibilityOn();
376     
377   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
378   myView->Repaint();
379 }
380
381
382 //************************************************************************
383 // For Batchmode using
384 void VISU_TimeAnimation::gotoFrame(CORBA::Long theFrame) {
385   if ((theFrame < 0) || (theFrame > (getNbFrames()-1))) 
386     return;
387   stopAnimation();
388   qApp->lock();
389   qApp->syncX();
390   int i;
391   for (i = 0; i < getNbFields(); i++) 
392     if (myFieldsLst[i].myActors[myFrame] != 0)
393       myFieldsLst[i].myActors[myFrame]->VisibilityOff();
394   myFrame = theFrame;
395   for (i = 0; i < getNbFields(); i++) 
396     if (myFieldsLst[i].myActors[myFrame] != 0)
397       myFieldsLst[i].myActors[myFrame]->VisibilityOn();
398   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
399   myView->Repaint();
400   qApp->flushX(); 
401   qApp->processEvents(3);
402   qApp->unlock();
403 }
404
405
406 //************************************************************************
407 VISU::ScalarMap_ptr VISU_TimeAnimation::getPresentation(CORBA::Long theField, CORBA::Long theFrame) {
408   if ((theField > getNbFields()) || (theField < 0))
409     return VISU::ScalarMap::_nil();
410   if ((theFrame < 0) || (theFrame > (myFieldsLst[theField].myNbFrames - 1)))
411     return VISU::ScalarMap::_nil();
412   return myFieldsLst[theField].myPrs[theFrame]->_this();
413 }
414
415
416 //************************************************************************
417 CORBA::Long VISU_TimeAnimation::getNbFrames() { 
418   return (getNbFields() > 0)? myFieldsLst[0].myNbFrames : 0;
419 }
420
421
422 //************************************************************************
423 void VISU_TimeAnimation::run() {
424   if (!myView) {
425     MESSAGE("Viewer is nod defined for animation");
426     return;
427   }
428
429   double k=1;
430   double aOneVal;
431   bool isDumping = !myDumpPath.isEmpty();
432   aOneVal = (myFieldsLst[0].myNbFrames > 2) ?
433     myFieldsLst[0].myTiming[1] - myFieldsLst[0].myTiming[0] : 1;
434
435   qApp->lock();      
436   while (myIsActive) {
437     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
438     for (int i = 0; i < getNbFields(); i++) {
439       FieldData& aData = myFieldsLst[i];
440       if (myFrame > 0) {
441         if (aData.myActors[myFrame-1] != 0) 
442           aData.myActors[myFrame-1]->VisibilityOff();
443       } else { 
444         if (aData.myActors[aData.myNbFrames-1] != 0)
445           aData.myActors[aData.myNbFrames-1]->VisibilityOff();
446       }
447       if (aData.myActors[myFrame] != 0) {
448         aData.myActors[myFrame]->VisibilityOn();
449       }
450     }
451     myView->Repaint();
452     if (isDumping) {
453       QPixmap px = QPixmap::grabWindow(myView->getViewWidget()->winId());
454       QString aFile(myDumpPath);
455       QString aName = QString("%1").arg(myFieldsLst[0].myTiming[myFrame]);
456       int aPos = -1;
457       while ((aPos = aName.find(".")) > -1 )
458         aName.replace(aPos, 1, "_");
459       aFile += aName;
460       aFile += ".jpeg";
461       px.save(aFile, "JPEG");
462     }
463     if (!isDumping) {
464       if (myProportional) {
465         switch (myFrame) {
466         case 0:
467           k=1;
468           break;        
469         case 1:
470           if (myFieldsLst[0].myNbFrames > 2)
471             k = (myFieldsLst[0].myTiming[myFrame+1] - myFieldsLst[0].myTiming[myFrame])/aOneVal;
472           else
473             k = 1;
474           break;        
475         default:
476           k = (myFrame < (myFieldsLst[0].myNbFrames-1))? 
477             (myFieldsLst[0].myTiming[myFrame+1] - myFieldsLst[0].myTiming[myFrame])/aOneVal : 1;
478         }
479       } else
480         k = 1;
481       
482       qApp->unlock();
483       msleep((int)(1000.*k/mySpeed));
484       qApp->lock();
485     } else {
486       qApp->unlock();
487       msleep(100);
488       qApp->lock();
489     }
490     if (!myIsActive) break;
491
492     myFrame++;
493     if (myFrame == myFieldsLst[0].myNbFrames) {
494       if (!myCycling) {
495         myIsActive = false;
496         myFrame--;
497         break;
498       } else
499         myFrame = 0;
500     }
501   }
502   emit stopped();
503   qApp->unlock();
504   QThread::exit();
505 }
506
507 //************************************************************************
508 VISU::Result_i* VISU_TimeAnimation::createPresent(SALOMEDS::SObject_var theField) {
509   SALOMEDS::SObject_var aSObj = theField->GetFather();
510   aSObj = aSObj->GetFather();
511   aSObj = aSObj->GetFather();
512   CORBA::Object_var anObject = VISU::SObjectToObject(aSObj);
513   if(CORBA::is_nil(anObject)) return NULL;
514   return dynamic_cast<VISU::Result_i*>(VISU::GetServant(anObject));
515 }
516
517
518 //************************************************************************
519 VISU::Storable::TRestoringMap VISU_TimeAnimation::getMapOfValue(SALOMEDS::SObject_var theSObject) {
520   VISU::Storable::TRestoringMap aMap;
521   if(!theSObject->_is_nil()){
522     SALOMEDS::GenericAttribute_var anAttr;
523     if (theSObject->FindAttribute(anAttr, "AttributeComment")) {
524       SALOMEDS::AttributeComment_var aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
525       CORBA::String_var aString = aComment->Value();
526       QString strIn(aString.in());
527       VISU::Storable::StrToMap(strIn,aMap);
528     }
529   }
530   return aMap;
531 }
532
533 //************************************************************************
534 double VISU_TimeAnimation::getTimeValue(SALOMEDS::SObject_var theTimeStamp) {
535   SALOMEDS::GenericAttribute_var anAttr;
536   if(theTimeStamp->FindAttribute(anAttr, "AttributeName")) {
537     SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
538     QString aNameString(aName->Value());
539     return aNameString.toDouble();
540   }
541 }
542   
543 //************************************************************************
544 void VISU_TimeAnimation::setSpeed(CORBA::Long theSpeed) { 
545   mySpeed = (theSpeed<1)? 1 : theSpeed; 
546 }