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