1 // Copyright (C) 2003 CEA/DEN, EDF R&D
5 // File : VISU_TimeAnimation.cxx
6 // Author : Vitaly SMETANNIKOV
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"
24 #include "VTKViewer_ViewFrame.h"
26 #include "QAD_Config.h"
30 //QWaitCondition myCondition;
31 static int MYDELAY = 1;
33 //************************************************************************
34 VISU_TimeAnimation::VISU_TimeAnimation(SALOMEDS::Study_var theStudy, VISU::View3D_ptr theView3D) {
39 myProportional = false;
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);
57 //************************************************************************
58 VISU_TimeAnimation::~VISU_TimeAnimation() {
59 for (int i = 0; i < getNbFields(); i++) {
60 clearData(myFieldsLst[i]);
65 //************************************************************************
66 void VISU_TimeAnimation::addField(SALOMEDS::SObject_ptr theField) {
68 aNewData.myField = SALOMEDS::SObject::_duplicate(theField);
69 aNewData.myNbFrames = 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);
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());
91 //************************************************************************
92 void VISU_TimeAnimation::clearData(FieldData& theData) {
93 if (theData.myTiming) {
94 free(theData.myTiming);
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();
105 free(theData.myActors);
106 theData.myActors = 0;
109 for (int i = 0; i < theData.myNbFrames; i++)
110 theData.myPrs[i]->_remove_ref();
114 theData.myNbFrames = 0;
119 //************************************************************************
120 void VISU_TimeAnimation::generatePresentations(CORBA::Long theFieldNum) {
121 FieldData& aData = myFieldsLst[theFieldNum];
123 // Delete previous presentations
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();
131 aData.myPrs = (VISU::ScalarMap_i**) malloc(aData.myNbTimes * sizeof(VISU::ScalarMap_i*));
132 aData.myTiming = (double*) malloc(aData.myNbTimes * sizeof(double));
134 SALOMEDS::ChildIterator_var anIter = myStudy->NewChildIterator(aData.myField);
135 SALOMEDS::SObject_var aTimeStamp;
136 anIter->Next(); // First is reference on support
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");
144 aTimeStamp = anIter->Value();
145 if (aTimeStamp->_is_nil()) continue;
147 aData.myTiming[i] = getTimeValue(aTimeStamp);
148 if (isRangeDefined()) {
149 if (aData.myTiming[i] < myMinVal) continue;
150 if (aData.myTiming[i] > myMaxVal) break;
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();
159 switch (aData.myPrsType) {
160 case VISU::TSCALARMAP: // ScalarMap
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;
171 case VISU::TISOSURFACE: // Iso Surfaces
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;
182 case VISU::TCUTPLANES: // Cut Planes
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;
193 case VISU::TDEFORMEDSHAPE: // Deformed Shape
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;
204 case VISU::TVECTORS: // Vectors
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;
215 case VISU::TSTREAMLINES: // Stream Lines
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;
226 if (aData.myPrs[i]->GetMin() < aMin) aMin = aData.myPrs[i]->GetMin();
227 if (aData.myPrs[i]->GetMax() > aMax) aMax = aData.myPrs[i]->GetMax();
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);
243 //************************************************************************
244 CORBA::Boolean VISU_TimeAnimation::generateFrames() {
246 MESSAGE("Viewer is nod defined for animation");
249 myLastError = QString("Frame(s) for ");
250 bool aNoError = true;
251 VISU::Mutex mt(myMutex,qApp,MYDELAY);
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;
260 aActor = aData.myPrs[j]->CreateActor();
261 myView->AddActor(aActor);
263 aActor->VisibilityOn();
265 aActor->VisibilityOff();
266 }catch(std::runtime_error& exc){
268 myLastError += QString("%1 ").arg(aData.myTiming[j]);
270 aData.myActors[j] = aActor;
274 myLastError += QString(" timestamp(s) cannot be created.");
275 emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
280 //************************************************************************
281 void VISU_TimeAnimation::clearView() {
283 MESSAGE("Viewer is nod defined for animation");
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();
297 free(aData.myActors);
304 //************************************************************************
305 void VISU_TimeAnimation::stopAnimation() {
309 //************************************************************************
310 void VISU_TimeAnimation::startAnimation() {
317 //************************************************************************
318 void VISU_TimeAnimation::nextFrame() {
320 if (myFrame < (myFieldsLst[0].myNbFrames-1)) {
322 for (i = 0; i < getNbFields(); i++)
323 if (myFieldsLst[i].myActors[myFrame] != 0)
324 myFieldsLst[i].myActors[myFrame]->VisibilityOff();
326 for (i = 0; i < getNbFields(); i++)
327 if (myFieldsLst[i].myActors[myFrame] != 0)
328 myFieldsLst[i].myActors[myFrame]->VisibilityOn();
330 emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
335 //************************************************************************
336 void VISU_TimeAnimation::prevFrame() {
340 for (i = 0; i < getNbFields(); i++)
341 if (myFieldsLst[i].myActors[myFrame] != 0)
342 myFieldsLst[i].myActors[myFrame]->VisibilityOff();
344 for (i = 0; i < getNbFields(); i++)
345 if (myFieldsLst[i].myActors[myFrame] != 0)
346 myFieldsLst[i].myActors[myFrame]->VisibilityOn();
348 emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
353 //************************************************************************
354 void VISU_TimeAnimation::firstFrame() {
357 for (i = 0; i < getNbFields(); i++)
358 if (myFieldsLst[i].myActors[myFrame] != 0)
359 myFieldsLst[i].myActors[myFrame]->VisibilityOff();
361 for (i = 0; i < getNbFields(); i++)
362 if (myFieldsLst[i].myActors[myFrame] != 0)
363 myFieldsLst[i].myActors[myFrame]->VisibilityOn();
365 emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
369 //************************************************************************
370 void VISU_TimeAnimation::lastFrame() {
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();
381 emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
386 //************************************************************************
387 // For Batchmode using
388 void VISU_TimeAnimation::gotoFrame(CORBA::Long theFrame) {
389 if ((theFrame < 0) || (theFrame > (getNbFrames()-1)))
395 for (i = 0; i < getNbFields(); i++)
396 if (myFieldsLst[i].myActors[myFrame] != 0)
397 myFieldsLst[i].myActors[myFrame]->VisibilityOff();
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]);
405 qApp->processEvents(3);
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();
420 //************************************************************************
421 CORBA::Long VISU_TimeAnimation::getNbFrames() {
422 return (getNbFields() > 0)? myFieldsLst[0].myNbFrames : 0;
426 //************************************************************************
427 void VISU_TimeAnimation::run() {
429 MESSAGE("Viewer is nod defined for animation");
435 bool isDumping = !myDumpPath.isEmpty();
436 aOneVal = (myFieldsLst[0].myNbFrames > 2) ?
437 myFieldsLst[0].myTiming[1] - myFieldsLst[0].myTiming[0] : 1;
441 emit frameChanged(myFrame, myFieldsLst[0].myTiming[myFrame]);
442 for (int i = 0; i < getNbFields(); i++) {
443 FieldData& aData = myFieldsLst[i];
445 if (aData.myActors[myFrame-1] != 0)
446 aData.myActors[myFrame-1]->VisibilityOff();
448 if (aData.myActors[aData.myNbFrames-1] != 0)
449 aData.myActors[aData.myNbFrames-1]->VisibilityOff();
451 if (aData.myActors[myFrame] != 0) {
452 aData.myActors[myFrame]->VisibilityOn();
455 myView->Repaint(false);
457 QPixmap px = QPixmap::grabWindow(myView->getViewWidget()->winId());
458 QString aFile(myDumpPath);
459 QString aName = QString("%1").arg(myFieldsLst[0].myTiming[myFrame]);
461 while ((aPos = aName.find(".")) > -1 )
462 aName.replace(aPos, 1, "_");
465 px.save(aFile, "JPEG");
468 if (myProportional) {
474 if (myFieldsLst[0].myNbFrames > 2)
475 k = (myFieldsLst[0].myTiming[myFrame+1] - myFieldsLst[0].myTiming[myFrame])/aOneVal;
480 k = (myFrame < (myFieldsLst[0].myNbFrames-1))?
481 (myFieldsLst[0].myTiming[myFrame+1] - myFieldsLst[0].myTiming[myFrame])/aOneVal : 1;
487 msleep((int)(1000.*k/mySpeed));
494 if (!myIsActive) break;
497 if (myFrame == myFieldsLst[0].myNbFrames) {
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());
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);
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();
547 //************************************************************************
548 void VISU_TimeAnimation::setSpeed(CORBA::Long theSpeed) {
549 mySpeed = (theSpeed<1)? 1 : theSpeed;