Salome HOME
MPV: Merge V1_2d
[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).in());
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 = VTK_LARGE_FLOAT, aMax = -VTK_LARGE_FLOAT;
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     if(aData.myPrsType == VISU::TISOSURFACE)
236       for (i = 0; i < aData.myNbFrames; i++) 
237         if(VISU::IsoSurfaces_i* aPrs = dynamic_cast<VISU::IsoSurfaces_i*>(aData.myPrs[i]))
238            aPrs->SetSubRange(aMin, aMax);
239   }
240 }
241
242
243 //************************************************************************
244 CORBA::Boolean VISU_TimeAnimation::generateFrames() {
245   if (!myView) {
246     MESSAGE("Viewer is nod defined for animation");
247     return false;
248   }
249   myLastError = QString("Frame(s) for ");
250   bool aNoError = true;
251   VISU::Mutex mt(myMutex,qApp,MYDELAY);
252   clearView();
253   vtkRenderer* aRen = myView->getRenderer();
254   for (int i = 0; i < getNbFields(); i++) {
255     FieldData& aData = myFieldsLst[i];
256     aData.myActors = (VISU_Actor**) malloc(aData.myNbFrames * sizeof(VISU_Actor*));
257     for (long j = 0; j < aData.myNbFrames; j++) {
258       VISU_Actor* aActor = NULL;
259       try{
260         aActor = aData.myPrs[j]->CreateActor();
261         myView->AddActor(aActor);
262         if(j == 0)
263           aActor->VisibilityOn();
264         else
265           aActor->VisibilityOff();
266       }catch(std::runtime_error& exc){
267         aNoError = false;
268         myLastError += QString("%1 ").arg(aData.myTiming[j]);
269       }
270       aData.myActors[j] = aActor;
271     }
272   }
273   myFrame = 0;
274   myLastError += QString(" timestamp(s) cannot be created.");
275   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
276   myView->Repaint();
277   return aNoError;
278 }
279
280 //************************************************************************
281 void VISU_TimeAnimation::clearView() {
282   if (!myView) {
283     MESSAGE("Viewer is nod defined for animation");
284     return;
285   }
286   VISU::Mutex mt(myMutex,qApp,MYDELAY);
287   vtkRenderer* aRen = myView->getRenderer();
288   for (int i = 0; i < getNbFields(); i++) {
289     FieldData& aData = myFieldsLst[i];
290     if (aData.myActors) {
291       for (int i = 0; i < aData.myNbFrames; i++) {
292         if (aData.myActors[i] != 0) {
293           aData.myActors[i]->RemoveFromRender(aRen);
294           aData.myActors[i]->Delete();
295         }
296       } 
297       free(aData.myActors);
298       aData.myActors = 0;
299     }
300   }
301   myView->update();
302 }
303
304 //************************************************************************
305 void VISU_TimeAnimation::stopAnimation() {
306   myIsActive = false;
307 }
308
309 //************************************************************************
310 void VISU_TimeAnimation::startAnimation() {
311   if (!myIsActive) {
312     myIsActive = true;
313     QThread::start();
314   }
315 }
316
317 //************************************************************************
318 void VISU_TimeAnimation::nextFrame() {
319   stopAnimation();
320   if (myFrame < (myFieldsLst[0].myNbFrames-1)) {
321     int i;
322     for (i = 0; i < getNbFields(); i++) 
323       if (myFieldsLst[i].myActors[myFrame] != 0)
324         myFieldsLst[i].myActors[myFrame]->VisibilityOff();
325     myFrame++;
326     for (i = 0; i < getNbFields(); i++) 
327       if (myFieldsLst[i].myActors[myFrame] != 0)
328         myFieldsLst[i].myActors[myFrame]->VisibilityOn(); 
329
330     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
331     myView->Repaint();
332   }
333 }
334
335 //************************************************************************
336 void VISU_TimeAnimation::prevFrame() {
337   stopAnimation();
338   if (myFrame > 0) {
339     int i;
340     for (i = 0; i < getNbFields(); i++) 
341       if (myFieldsLst[i].myActors[myFrame] != 0)
342         myFieldsLst[i].myActors[myFrame]->VisibilityOff();
343     myFrame--;
344     for (i = 0; i < getNbFields(); i++) 
345       if (myFieldsLst[i].myActors[myFrame] != 0)
346         myFieldsLst[i].myActors[myFrame]->VisibilityOn();    
347
348     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
349     myView->Repaint();
350   }
351 }
352
353 //************************************************************************
354 void VISU_TimeAnimation::firstFrame() {
355   stopAnimation();
356   int i;
357   for (i = 0; i < getNbFields(); i++) 
358     if (myFieldsLst[i].myActors[myFrame] != 0)
359       myFieldsLst[i].myActors[myFrame]->VisibilityOff();
360   myFrame = 0;
361   for (i = 0; i < getNbFields(); i++) 
362     if (myFieldsLst[i].myActors[myFrame] != 0)
363       myFieldsLst[i].myActors[myFrame]->VisibilityOn();    
364
365   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
366   myView->Repaint();
367 }
368
369 //************************************************************************
370 void VISU_TimeAnimation::lastFrame() {
371   stopAnimation();
372   int i;
373   for (i = 0; i < getNbFields(); i++) 
374     if (myFieldsLst[i].myActors[myFrame] != 0)
375       myFieldsLst[i].myActors[myFrame]->VisibilityOff();
376   myFrame = myFieldsLst[0].myNbFrames-1;
377   for (i = 0; i < getNbFields(); i++) 
378     if (myFieldsLst[i].myActors[myFrame] != 0)
379       myFieldsLst[i].myActors[myFrame]->VisibilityOn();
380     
381   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
382   myView->Repaint();
383 }
384
385
386 //************************************************************************
387 // For Batchmode using
388 void VISU_TimeAnimation::gotoFrame(CORBA::Long theFrame) {
389   if ((theFrame < 0) || (theFrame > (getNbFrames()-1))) 
390     return;
391   stopAnimation();
392   qApp->lock();
393   qApp->syncX();
394   int i;
395   for (i = 0; i < getNbFields(); i++) 
396     if (myFieldsLst[i].myActors[myFrame] != 0)
397       myFieldsLst[i].myActors[myFrame]->VisibilityOff();
398   myFrame = theFrame;
399   for (i = 0; i < getNbFields(); i++) 
400     if (myFieldsLst[i].myActors[myFrame] != 0)
401       myFieldsLst[i].myActors[myFrame]->VisibilityOn();
402   emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
403   myView->Repaint();
404   qApp->flushX(); 
405   qApp->processEvents(3);
406   qApp->unlock();
407 }
408
409
410 //************************************************************************
411 VISU::ScalarMap_ptr VISU_TimeAnimation::getPresentation(CORBA::Long theField, CORBA::Long theFrame) {
412   if ((theField > getNbFields()) || (theField < 0))
413     return VISU::ScalarMap::_nil();
414   if ((theFrame < 0) || (theFrame > (myFieldsLst[theField].myNbFrames - 1)))
415     return VISU::ScalarMap::_nil();
416   return myFieldsLst[theField].myPrs[theFrame]->_this();
417 }
418
419
420 //************************************************************************
421 CORBA::Long VISU_TimeAnimation::getNbFrames() { 
422   return (getNbFields() > 0)? myFieldsLst[0].myNbFrames : 0;
423 }
424
425
426 //************************************************************************
427 void VISU_TimeAnimation::run() {
428   if (!myView) {
429     MESSAGE("Viewer is nod defined for animation");
430     return;
431   }
432
433   double k=1;
434   double aOneVal;
435   bool isDumping = !myDumpPath.isEmpty();
436   aOneVal = (myFieldsLst[0].myNbFrames > 2) ?
437     myFieldsLst[0].myTiming[1] - myFieldsLst[0].myTiming[0] : 1;
438
439   qApp->lock();      
440   while (myIsActive) {
441     emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
442     for (int i = 0; i < getNbFields(); i++) {
443       FieldData& aData = myFieldsLst[i];
444       if (myFrame > 0) {
445         if (aData.myActors[myFrame-1] != 0) 
446           aData.myActors[myFrame-1]->VisibilityOff();
447       } else { 
448         if (aData.myActors[aData.myNbFrames-1] != 0)
449           aData.myActors[aData.myNbFrames-1]->VisibilityOff();
450       }
451       if (aData.myActors[myFrame] != 0) {
452         aData.myActors[myFrame]->VisibilityOn();
453       }
454     }
455     myView->Repaint(false);
456     if (isDumping) {
457       QPixmap px = QPixmap::grabWindow(myView->getViewWidget()->winId());
458       QString aFile(myDumpPath);
459       QString aName = QString("%1").arg(myFieldsLst[0].myTiming[myFrame]);
460       int aPos = -1;
461       while ((aPos = aName.find(".")) > -1 )
462         aName.replace(aPos, 1, "_");
463       aFile += aName;
464       aFile += ".jpeg";
465       px.save(aFile, "JPEG");
466     }
467     if (!isDumping) {
468       if (myProportional) {
469         switch (myFrame) {
470         case 0:
471           k=1;
472           break;        
473         case 1:
474           if (myFieldsLst[0].myNbFrames > 2)
475             k = (myFieldsLst[0].myTiming[myFrame+1] - myFieldsLst[0].myTiming[myFrame])/aOneVal;
476           else
477             k = 1;
478           break;        
479         default:
480           k = (myFrame < (myFieldsLst[0].myNbFrames-1))? 
481             (myFieldsLst[0].myTiming[myFrame+1] - myFieldsLst[0].myTiming[myFrame])/aOneVal : 1;
482         }
483       } else
484         k = 1;
485       
486       qApp->unlock();
487       msleep((int)(1000.*k/mySpeed));
488       qApp->lock();
489     } else {
490       qApp->unlock();
491       msleep(100);
492       qApp->lock();
493     }
494     if (!myIsActive) break;
495
496     myFrame++;
497     if (myFrame == myFieldsLst[0].myNbFrames) {
498       if (!myCycling) {
499         myIsActive = false;
500         myFrame--;
501         break;
502       } else
503         myFrame = 0;
504     }
505   }
506   emit stopped();
507   qApp->unlock();
508   QThread::exit();
509 }
510
511 //************************************************************************
512 VISU::Result_i* VISU_TimeAnimation::createPresent(SALOMEDS::SObject_var theField) {
513   SALOMEDS::SObject_var aSObj = theField->GetFather();
514   aSObj = aSObj->GetFather();
515   aSObj = aSObj->GetFather();
516   CORBA::Object_var anObject = VISU::SObjectToObject(aSObj);
517   if(CORBA::is_nil(anObject)) return NULL;
518   return dynamic_cast<VISU::Result_i*>(VISU::GetServant(anObject).in());
519 }
520
521
522 //************************************************************************
523 VISU::Storable::TRestoringMap VISU_TimeAnimation::getMapOfValue(SALOMEDS::SObject_var theSObject) {
524   VISU::Storable::TRestoringMap aMap;
525   if(!theSObject->_is_nil()){
526     SALOMEDS::GenericAttribute_var anAttr;
527     if (theSObject->FindAttribute(anAttr, "AttributeComment")) {
528       SALOMEDS::AttributeComment_var aComment = SALOMEDS::AttributeComment::_narrow(anAttr);
529       CORBA::String_var aString = aComment->Value();
530       QString strIn(aString.in());
531       VISU::Storable::StrToMap(strIn,aMap);
532     }
533   }
534   return aMap;
535 }
536
537 //************************************************************************
538 double VISU_TimeAnimation::getTimeValue(SALOMEDS::SObject_var theTimeStamp) {
539   SALOMEDS::GenericAttribute_var anAttr;
540   if(theTimeStamp->FindAttribute(anAttr, "AttributeName")) {
541     SALOMEDS::AttributeName_var aName = SALOMEDS::AttributeName::_narrow(anAttr);
542     QString aNameString(aName->Value());
543     return aNameString.toDouble();
544   }
545 }
546   
547 //************************************************************************
548 void VISU_TimeAnimation::setSpeed(CORBA::Long theSpeed) { 
549   mySpeed = (theSpeed<1)? 1 : theSpeed; 
550 }