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