Salome HOME
72faaef41480c10d0d518c0543ece404e61a541c
[modules/visu.git] / src / OBJECT / VISU_GaussPtsDeviceActor.cxx
1 //  Copyright (C) 2007-2008  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 //  Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 //  CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 //  This library is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU Lesser General Public
8 //  License as published by the Free Software Foundation; either
9 //  version 2.1 of the License.
10 //
11 //  This library is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 //  Lesser General Public License for more details.
15 //
16 //  You should have received a copy of the GNU Lesser General Public
17 //  License along with this library; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 //  See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 //  SMESH OBJECT : interactive object for SMESH visualization
23 //  File   :
24 //  Author : 
25 //  Module :
26 //  $Header$
27 //
28 #include "VISU_GaussPtsDeviceActor.h"
29
30 #include "VISU_GaussPointsPL.hxx"
31 #include "VISU_OpenGLPointSpriteMapper.hxx"
32
33 #include "VTKViewer_Transform.h"
34 #include "VTKViewer_TransformFilter.h"
35 #include <SALOME_ExtractPolyDataGeometry.h>
36
37 #include <vtkObjectFactory.h>
38 #include <vtkPolyData.h>
39 #include <vtkRenderer.h>
40 #include <vtkTextProperty.h>
41 #include <vtkProperty.h>
42 #include <vtkTexture.h>
43 #include <vtkPassThroughFilter.h>
44 #include <vtkImageData.h>
45
46 #include <QFileInfo>
47
48 #include "utilities.h"
49 #include "VISU_PipeLineUtils.hxx"
50
51 #ifdef _DEBUG_
52 static int MYDEBUG = 0;
53 #else
54 static int MYDEBUG = 0;
55 #endif
56
57
58 //----------------------------------------------------------------
59 namespace VISU
60 {
61   inline
62   std::string
63   Image2VTI(const std::string& theImageFileName)
64   {
65     QFileInfo aFileInfo( theImageFileName.c_str() );
66     QString aFormat = aFileInfo.suffix();
67 #ifdef WIN32
68     QString aTmpDir = getenv( "TEMP" );
69 #else
70     QString aTmpDir = QString( "/tmp/" ) + getenv("USER");
71 #endif
72     QString aVTIName = aTmpDir + "-" + aFileInfo.completeBaseName() + ".vti";
73     QString aCommand = QString( "VISU_img2vti " ) + aFormat + " " +  theImageFileName.c_str() + " " + aVTIName;
74
75     if ( system( aCommand.toLatin1().data() ) == 0 )
76       return aVTIName.toLatin1().data();
77
78     return "";
79   }
80
81   inline
82   void
83   RemoveFile(const std::string& theFileName)
84   {
85     if( theFileName != "" ){
86 #ifndef WNT
87       QString aCommand = QString( "rm -fr " ) + theFileName.c_str();
88 #else
89       QString aCommand = QString( "del /F " ) + theFileName.c_str();
90 #endif
91       system( aCommand.toLatin1().data() );
92     }
93   }
94   
95   
96   TTextureValue
97   GetTexture(const std::string& theMainTexture, 
98              const std::string& theAlphaTexture)
99   {
100     typedef std::pair<std::string,std::string> TTextureKey;
101     typedef std::map<TTextureKey,TTextureValue> TTextureMap;
102     
103     static TTextureMap aTextureMap;
104     
105     TTextureValue aTextureValue;
106     TTextureKey aTextureKey( theMainTexture.c_str(), theAlphaTexture.c_str() );
107     TTextureMap::const_iterator anIter = aTextureMap.find( aTextureKey );
108     if ( anIter != aTextureMap.end() ) {
109       aTextureValue = anIter->second;
110     } else {
111       QString aMainTextureVTI = Image2VTI(theMainTexture).c_str();
112       QString anAlphaTextureVTI = Image2VTI(theAlphaTexture).c_str();
113       
114       if( !aMainTextureVTI.isNull() && !anAlphaTextureVTI.isNull() ){
115         aTextureValue =
116           VISU_GaussPointsPL::MakeTexture( aMainTextureVTI.toLatin1().data(), 
117                                            anAlphaTextureVTI.toLatin1().data() );
118
119         if( aTextureValue.GetPointer() )
120           aTextureMap[aTextureKey] = aTextureValue;
121       }
122
123       RemoveFile(aMainTextureVTI.toLatin1().data());
124       RemoveFile(anAlphaTextureVTI.toLatin1().data());
125     }
126
127     return aTextureValue;
128   }
129 }
130
131
132 //----------------------------------------------------------------
133 vtkStandardNewMacro(VISU_GaussDeviceActorBase);
134
135
136 VISU_GaussDeviceActorBase
137 ::VISU_GaussDeviceActorBase():
138   myTransformFilter(VTKViewer_TransformFilter::New()),
139   myPolyDataExtractor(0)
140 {
141   if(MYDEBUG) MESSAGE("VISU_GaussDeviceActorBase - "<<this);
142
143   myTransformFilter->Delete();
144
145   for(int i = 0; i < 3; i++){
146     PPassThroughFilter aFilter(vtkPassThroughFilter::New());
147     myPassFilter.push_back(aFilter);
148     aFilter->Delete();
149   }
150 }
151
152
153 VISU_GaussDeviceActorBase
154 ::~VISU_GaussDeviceActorBase()
155 {
156   if(MYDEBUG) MESSAGE("~VISU_GaussDeviceActorBase - "<<this);
157 }
158
159
160 //----------------------------------------------------------------
161 void
162 VISU_GaussDeviceActorBase
163 ::Render(vtkRenderer *ren, vtkMapper *vtkNotUsed(m))
164 {
165   if (this->Mapper == NULL)
166     {
167     vtkErrorMacro("No mapper for actor.");
168     return;
169     }
170   
171   // render the property
172   if (!this->Property)
173     {
174     // force creation of a property
175     this->GetProperty();
176     }
177   this->Property->Render(this, ren);
178   if (this->BackfaceProperty)
179     {
180     this->BackfaceProperty->BackfaceRender(this, ren);
181     this->Device->SetBackfaceProperty(this->BackfaceProperty);
182     }
183   this->Device->SetProperty(this->Property);  
184   
185   // render the texture
186   if (this->Texture)
187     {
188     this->Texture->Render(ren);
189     }
190   
191   // make sure the device has the same matrix
192   vtkMatrix4x4 *matrix = this->Device->GetUserMatrix();
193   this->GetMatrix(matrix);
194   
195   this->Device->Render(ren,Mapper);  
196   this->EstimatedRenderTime = Mapper->GetTimeToDraw();
197 }
198
199
200 //----------------------------------------------------------------
201 void
202 VISU_GaussDeviceActorBase
203 ::SetTransform(VTKViewer_Transform* theTransform)
204 {
205   myTransformFilter->SetTransform(theTransform);
206 }
207
208 //----------------------------------------------------------------
209 void
210 VISU_GaussDeviceActorBase
211 ::SetPointSpriteMapper(VISU_OpenGLPointSpriteMapper* theMapper) 
212 {
213   vtkPolyData* aDataSet = theMapper->GetInput();
214   myMapper = theMapper;
215
216   int anId = 0;
217   if (myPolyDataExtractor) {
218     myPolyDataExtractor->SetInput(aDataSet);
219     myPassFilter[ anId ]->SetInput( myPolyDataExtractor->GetOutput() ); 
220   } else {
221     myPassFilter[ anId ]->SetInput( aDataSet ); 
222   }
223   myPassFilter[ anId + 1 ]->SetInput( myPassFilter[ anId ]->GetOutput() );
224
225   anId++;
226   myTransformFilter->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
227   
228   anId++;
229   myPassFilter[ anId ]->SetInput( myTransformFilter->GetOutput() );
230   
231   myMapper->SetInput( myPassFilter[ anId ]->GetPolyDataOutput() );
232   
233   Superclass::SetMapper( theMapper );
234 }
235
236 void
237 VISU_GaussDeviceActorBase
238 ::DoMapperShallowCopy( vtkMapper* theMapper,
239                        bool theIsCopyInput )
240 {
241   VISU::CopyMapper( GetMapper(), theMapper, theIsCopyInput );
242 }
243
244 VISU_OpenGLPointSpriteMapper*
245 VISU_GaussDeviceActorBase
246 ::GetPointSpriteMapper()
247 {
248   return myMapper.GetPointer();
249 }
250
251 //----------------------------------------------------------------------------
252 unsigned long int
253 VISU_GaussDeviceActorBase
254 ::GetMemorySize()
255 {
256   vtkDataSet* aDataSet = GetMapper()->GetInput();
257   return aDataSet->GetActualMemorySize() * 1024;
258 }
259
260
261
262 //----------------------------------------------------------------
263 vtkStandardNewMacro(VISU_GaussPtsDeviceActor);
264
265
266 VISU_GaussPtsDeviceActor
267 ::VISU_GaussPtsDeviceActor()
268 {}
269
270
271 VISU_GaussPtsDeviceActor
272 ::~VISU_GaussPtsDeviceActor()
273 {}
274
275
276 //----------------------------------------------------------------------------
277 void
278 VISU_GaussPtsDeviceActor
279 ::AddToRender(vtkRenderer* theRenderer)
280 {
281   theRenderer->AddActor(this);
282 }
283
284 void 
285 VISU_GaussPtsDeviceActor
286 ::RemoveFromRender(vtkRenderer* theRenderer)
287 {
288   theRenderer->RemoveActor(this);
289 }
290
291
292 //----------------------------------------------------------------------------
293 void
294 VISU_GaussPtsDeviceActor
295 ::SetPipeLine(VISU_GaussPointsPL* thePipeLine) 
296 {
297   SetPointSpriteMapper( thePipeLine->GetPointSpriteMapper() );
298
299   myPipeLine = thePipeLine;
300 }
301
302 VISU_GaussPointsPL* 
303 VISU_GaussPtsDeviceActor
304 ::GetPipeLine() 
305
306   return myPipeLine.GetPointer();
307 }
308
309 void
310 VISU_GaussPtsDeviceActor
311 ::ShallowCopyPL(VISU_GaussPointsPL* thePipeLine)
312 {
313   myPipeLine->ShallowCopy(thePipeLine, true);
314 }
315
316
317 //----------------------------------------------------------------------------
318 int
319 VISU_GaussPtsDeviceActor
320 ::GetPickable()
321 {
322   if(Superclass::GetPickable()){
323     if(vtkMapper* aMapper = GetMapper()){
324       if(vtkDataSet* aDataSet= aMapper->GetInput()){
325         aDataSet->Update();
326         return aDataSet->GetNumberOfCells() > 0;
327       }
328     }
329   }
330
331   return false;
332 }
333
334
335 //----------------------------------------------------------------------------
336 unsigned long int
337 VISU_GaussPtsDeviceActor
338 ::GetMemorySize()
339 {
340   unsigned long int aSize = Superclass::GetMemorySize();
341
342   aSize += GetPipeLine()->GetMemorySize();
343
344   return aSize;
345 }
346
347
348
349 //============================================================================
350 #include <vtkActor.h>
351 #include <vtkProperty.h>
352 #include <vtkConeSource.h>
353 #include <vtkAppendPolyData.h>
354 #include <vtkPolyDataMapper.h>
355
356
357 //----------------------------------------------------------------------------
358 vtkStandardNewMacro(VISU_CursorPyramid);
359
360 //----------------------------------------------------------------------------
361 VISU_CursorPyramid
362 ::VISU_CursorPyramid():
363   myHeight(10.0),
364   myRadius(5.0),
365   myMagnification(1.0),
366   myClamp(256.0),
367   myNbCones(6),
368   myAppendFilter(vtkAppendPolyData::New()),
369   myMapper(vtkPolyDataMapper::New())
370 {
371   myAppendFilter->Delete();
372   myMapper->Delete();
373
374   myMapper->SetInput(myAppendFilter->GetOutput());
375
376   for(int i = 0; i < myNbCones; i++){
377     vtkConeSource* aConeSource = vtkConeSource::New();
378     myAppendFilter->AddInput(aConeSource->GetOutput());
379     aConeSource->SetResolution(4);
380     mySources[i] = aConeSource;
381     aConeSource->Delete();
382   }
383 }
384
385
386 //----------------------------------------------------------------------------
387 void
388 VISU_CursorPyramid
389 ::Render(vtkRenderer *ren, vtkMapper *vtkNotUsed(m))
390 {
391   if (ren == NULL)
392     {
393     vtkErrorMacro("No mapper for actor.");
394     return;
395     }
396
397   this->SetScale(1.0);
398   vtkFloatingPointType aMRadius = myRadius*myMagnification;
399   Init(myHeight,aMRadius*myCursorSize);
400
401   if(myClamp > 0.0f){
402     vtkFloatingPointType aPoint1[3] = {0.0, 0.0, 0.0};
403     ren->SetDisplayPoint(aPoint1);
404     ren->DisplayToWorld();
405     ren->GetWorldPoint(aPoint1);
406
407     vtkFloatingPointType aPoint2[3] = {0.0, myClamp, 0.0};
408     ren->SetDisplayPoint(aPoint2);
409     ren->DisplayToWorld();
410     ren->GetWorldPoint(aPoint2);
411     
412     vtkFloatingPointType aWorldClamp = 
413       (aPoint2[0] - aPoint1[0])*(aPoint2[0] - aPoint1[0]) + 
414       (aPoint2[1] - aPoint1[1])*(aPoint2[1] - aPoint1[1]) + 
415       (aPoint2[2] - aPoint1[2])*(aPoint2[2] - aPoint1[2]); 
416     
417     aWorldClamp = sqrt(aWorldClamp);
418     vtkFloatingPointType aMDiameter = 2.0 * aMRadius;
419     vtkFloatingPointType aCoeff = aWorldClamp / aMDiameter;
420
421     if(aCoeff < 1.0){
422       this->SetScale(aCoeff);
423       //Init(myHeight/aCoeff,aMRadius*aCoeff);
424     }
425   }
426
427   if (this->Mapper == NULL)
428     {
429     vtkErrorMacro("No mapper for actor.");
430     return;
431     }
432   
433   // render the property
434   if (!this->Property)
435     {
436     // force creation of a property
437     this->GetProperty();
438     }
439   this->Property->Render(this, ren);
440   if (this->BackfaceProperty)
441     {
442     this->BackfaceProperty->BackfaceRender(this, ren);
443     this->Device->SetBackfaceProperty(this->BackfaceProperty);
444     }
445   this->Device->SetProperty(this->Property);  
446   
447   // render the texture
448   if (this->Texture)
449     {
450     this->Texture->Render(ren);
451     }
452   
453   // make sure the device has the same matrix
454   vtkMatrix4x4 *matrix = this->Device->GetUserMatrix();
455   this->GetMatrix(matrix);
456   
457   this->Device->Render(ren,Mapper);  
458   this->EstimatedRenderTime = Mapper->GetTimeToDraw();
459 }
460
461
462 //----------------------------------------------------------------------------
463 void
464 VISU_CursorPyramid
465 ::AddToRender(vtkRenderer* theRenderer)
466
467   theRenderer->AddActor(this);
468 }
469
470 void
471 VISU_CursorPyramid
472 ::RemoveFromRender(vtkRenderer* theRenderer)
473
474   theRenderer->RemoveActor(this);
475 }
476
477 //----------------------------------------------------------------------------
478 void 
479 VISU_CursorPyramid
480 ::SetPreferences(vtkFloatingPointType theHeight,
481                  vtkFloatingPointType theCursorSize)
482 {
483   Init(theHeight, theCursorSize, myRadius, myMagnification, myClamp, GetPosition(), GetProperty()->GetColor());
484 }
485
486 //----------------------------------------------------------------------------
487 void
488 VISU_CursorPyramid
489 ::Init(vtkFloatingPointType theHeight,
490        vtkFloatingPointType theCursorSize,
491        vtkFloatingPointType theRadius,
492        vtkFloatingPointType theMagnification,
493        vtkFloatingPointType theClamp,
494        vtkFloatingPointType thePos[3],
495        vtkFloatingPointType theColor[3])
496 {
497   Init(theHeight,theRadius*theMagnification*theCursorSize);
498   SetPosition(thePos[0],thePos[1],thePos[2]);
499   GetProperty()->SetColor(theColor);
500   SetMapper(myMapper.GetPointer());
501
502   myHeight = theHeight;
503   myCursorSize = theCursorSize;
504
505   myRadius = theRadius;
506   myMagnification = theMagnification;
507
508   myClamp = theClamp;
509 }
510
511
512 void
513 VISU_CursorPyramid
514 ::Init(vtkFloatingPointType theHeight,
515        vtkFloatingPointType theRadius)
516 {
517   for(int i = 0; i < myNbCones; ++i){
518     vtkConeSource* aSource = mySources[i].GetPointer();
519     aSource->SetHeight(theHeight);
520     // Set the angle of the cone. As a side effect, the angle plus height sets 
521     // the base radius of the cone.
522     aSource->SetAngle(20.0);
523   }
524   
525   vtkFloatingPointType aDisplacement = -0.5*theHeight - theRadius;
526   
527   // X
528   mySources[0]->SetDirection(1.0, 0.0, 0.0);
529   mySources[0]->SetCenter(aDisplacement, 0.0, 0.0);
530
531   // It is impossible to inverse direction around X axis (VTK bug)
532   mySources[1]->SetDirection(-VTK_LARGE_FLOAT, 1.0, 0.0); // A workaround
533   mySources[1]->SetCenter(-aDisplacement, 0.0, 0.0);
534   
535   // Y
536   mySources[2]->SetDirection(0.0, 1.0, 0.0);
537   mySources[2]->SetCenter(0.0, aDisplacement, 0.0);
538   
539   mySources[3]->SetDirection(0.0, -1.0, 0.0); 
540   mySources[3]->SetCenter(0.0, -aDisplacement, 0.0);
541   
542   // Z
543   mySources[4]->SetDirection(0.0, 0.0, 1.0); 
544   mySources[4]->SetCenter(0.0, 0.0, aDisplacement);
545   
546   mySources[5]->SetDirection(0.0, 0.0, -1.0); 
547   mySources[5]->SetCenter(0.0, 0.0, -aDisplacement);
548 }
549