Salome HOME
Merge from BR_V5_DEV 16Feb09
[modules/visu.git] / src / PIPELINE / VISU_CutPlanesPL.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 //  VISU OBJECT : interactive object for VISU entities implementation
23 // File:    VISU_PipeLine.cxx
24 // Author:  Alexey PETROV
25 // Module : VISU
26 //
27 #include "VISU_CutPlanesPL.hxx"
28 #include "VISU_FieldTransform.hxx"
29 #include "VISU_PipeLineUtils.hxx"
30 #include "VTKViewer_GeometryFilter.h"
31 #include "VISU_MapperHolder.hxx"
32 #include "VISU_DeformationPL.hxx"
33
34 #include <vtkAppendPolyData.h>
35 #include <vtkCutter.h>
36 #include <vtkPlane.h>
37
38 //#include <vtkUnstructuredGrid.h>
39
40 static vtkFloatingPointType EPS = 1.0E-3;
41
42 #ifdef _DEBUG_
43 static int MYDEBUG = 0;
44 #else
45 static int MYDEBUG = 0;
46 #endif
47
48
49 //----------------------------------------------------------------------------
50 vtkStandardNewMacro(VISU_CutPlanesPL);
51
52
53 //----------------------------------------------------------------------------
54 VISU_CutPlanesPL
55 ::VISU_CutPlanesPL():
56   VISU_OptionalDeformationPL()
57 {
58   if(MYDEBUG) MESSAGE("VISU_CutPlanesPL()::VISU_CutPlanesPL() - "<<this);
59   
60   SetIsShrinkable(false);
61   SetIsFeatureEdgesAllowed(false);
62
63   SetElnoDisassembleState( true );
64
65   myAppendPolyData = vtkAppendPolyData::New();
66
67   myNbParts = 10;
68
69   myBasePlane[0] = YZ;
70   myBasePlane[0] = XY;
71
72   myDisplacement[0] = myDisplacement[1] = 0.5;
73
74   myAng[0][0] = myAng[0][1] = myAng[0][2] = 0.0;
75   myAng[1][0] = myAng[1][1] = myAng[1][2] = 0.0;
76   UseDeformation(false);
77 }
78
79
80 //----------------------------------------------------------------------------
81 VISU_CutPlanesPL
82 ::~VISU_CutPlanesPL()
83 {
84   if(MYDEBUG) MESSAGE("VISU_CutPlanesPL()::~VISU_CutPlanesPL() - "<<this);
85   myAppendPolyData->Delete();
86   myAppendPolyData = NULL;
87 }
88
89
90 //----------------------------------------------------------------------------
91 unsigned long int 
92 VISU_CutPlanesPL
93 ::GetMTime()
94 {
95   unsigned long int aTime = Superclass::GetMTime();
96   
97   if(IsDeformed()) {
98     aTime = std::max(aTime, VISU_OptionalDeformationPL::GetMTime());
99   }
100   
101   aTime = std::max(aTime, myAppendPolyData->GetMTime());
102
103   return aTime;
104 }
105
106
107 //----------------------------------------------------------------------------
108 void
109 VISU_CutPlanesPL
110 ::DoShallowCopy(VISU_PipeLine *thePipeLine,
111                 bool theIsCopyInput)
112 {
113   Superclass::DoShallowCopy(thePipeLine, theIsCopyInput);
114
115   if(VISU_CutPlanesPL *aPipeLine = dynamic_cast<VISU_CutPlanesPL*>(thePipeLine)){
116
117     SetOrientation(aPipeLine->GetPlaneOrientation(),
118                    aPipeLine->GetRotateX(),
119                    aPipeLine->GetRotateY());
120
121     SetDisplacement(aPipeLine->GetDisplacement());
122
123     SetNbParts(aPipeLine->GetNbParts());
124     for (int i = 0, iEnd = GetNbParts(); i < iEnd; i++)
125       if(!aPipeLine->IsPartDefault(i))  
126         SetPartPosition(i, aPipeLine->GetPartPosition(i));
127   }
128 }
129
130
131 //----------------------------------------------------------------------------
132 void
133 VISU_CutPlanesPL
134 ::Init()
135 {
136   Superclass::Init();
137   SetNbParts(10);
138   myBasePlane[0] = YZ;
139   myDisplacement[0] = 0.5;
140   myAng[0][0] = myAng[0][1] = myAng[0][2] = 0.0;
141   SetScale(VISU_DeformationPL::GetDefaultScaleFactor(this));
142 }
143
144
145 //----------------------------------------------------------------------------
146 vtkDataSet* 
147 VISU_CutPlanesPL
148 ::InsertCustomPL()
149 {
150   return GetWarpVectorOutput();
151 }
152
153
154 //----------------------------------------------------------------------------
155 void
156 VISU_CutPlanesPL
157 ::Update()
158 {
159   ClearAppendPolyData(myAppendPolyData);
160
161
162   if(!myVectorialField || !IsDeformed()){
163     SetMergeFilterInput(GetMergedInput(),GetMergedInput());
164   }
165   
166
167   if(VISU::IsDataOnCells(GetMergedInput()))
168     GetMapper()->SetScalarModeToUseCellData();
169   else
170     GetMapper()->SetScalarModeToUsePointData();
171
172   SetPartPosition();
173   
174   vtkFloatingPointType aDir[3];
175   GetDir(aDir, 
176          myAng[0], 
177          myBasePlane[0]);
178   
179   vtkFloatingPointType aBounds[6];
180
181   vtkDataSet* aFilterOutput = GetMergeFilterOutput();
182   
183   aFilterOutput->GetBounds(aBounds);
184
185   CutWithPlanes(myAppendPolyData,
186                 aFilterOutput,
187                 myNbParts,
188                 aDir,
189                 aBounds,
190                 myPartPosition, 
191                 myPartCondition, 
192                 myDisplacement[0]);
193
194   
195
196   SetWarpVectorInput(myAppendPolyData->GetOutput());
197   Superclass::Update();
198 }
199
200
201 //----------------------------------------------------------------------------
202 unsigned long int
203 VISU_CutPlanesPL
204 ::GetMemorySize()
205 {
206   unsigned long int aSize = Superclass::GetMemorySize();
207
208   if(vtkDataSet* aDataSet = myAppendPolyData->GetOutput())
209     aSize += aDataSet->GetActualMemorySize() * 1024;
210   
211   int anEnd = myAppendPolyData->GetNumberOfInputConnections(0);
212   for(int anId = 0; anId < anEnd; anId++)
213     if(vtkDataSet* aDataSet = myAppendPolyData->GetInput(anId))
214       aSize += aDataSet->GetActualMemorySize() * 1024;
215
216   return aSize;
217 }
218
219
220 //----------------------------------------------------------------------------
221 void
222 VISU_CutPlanesPL
223 ::SetPartPosition(int theNum)
224 {
225   for(int i = 0; i < myNbParts; i++)
226     myPartPosition[i] = GetPartPosition(i,theNum);
227 }
228
229 void
230 VISU_CutPlanesPL
231 ::ClearAppendPolyData(vtkAppendPolyData *theAppendPolyData)
232 {
233   theAppendPolyData->RemoveAllInputs();
234 }
235
236
237 //----------------------------------------------------------------------------
238 vtkFloatingPointType* 
239 VISU_CutPlanesPL::
240 GetRx(vtkFloatingPointType theRx[3][3], 
241       vtkFloatingPointType thaAng)
242 {
243   theRx[0][0] = 1.0;            theRx[0][1] = 0.0;            theRx[0][2] = 0.0;
244   theRx[1][0] = 0.0;            theRx[1][1] = cos(thaAng);    theRx[1][2] = -sin(thaAng);
245   theRx[2][0] = 0.0;            theRx[2][1] = sin(thaAng);    theRx[2][2] = cos(thaAng);
246   return theRx[0];
247 }
248
249
250
251 //----------------------------------------------------------------------------
252 vtkFloatingPointType* 
253 VISU_CutPlanesPL
254 ::GetRy(vtkFloatingPointType theRy[3][3], 
255         vtkFloatingPointType thaAng)
256 {
257   theRy[0][0] = cos(thaAng);    theRy[0][1] = 0.0;            theRy[0][2] = sin(thaAng);
258   theRy[1][0] = 0.0;            theRy[1][1] = 1.0;            theRy[1][2] = 0.0;
259   theRy[2][0] = -sin(thaAng);   theRy[2][1] = 0.0;            theRy[2][2] = cos(thaAng);
260   return theRy[0];
261 }
262
263
264 //----------------------------------------------------------------------------
265 vtkFloatingPointType* 
266 VISU_CutPlanesPL
267 ::GetRz(vtkFloatingPointType theRz[3][3], 
268         vtkFloatingPointType thaAng)
269 {
270   theRz[0][0] = cos(thaAng);    theRz[0][1] = -sin(thaAng);   theRz[0][2] = 0.0;
271   theRz[1][0] = sin(thaAng);    theRz[1][1] = cos(thaAng);    theRz[1][2] = 0.0;
272   theRz[2][0] = 0.0;            theRz[2][1] = 0.0;            theRz[2][2] = 1.0;
273   return theRz[0];
274 }
275
276
277 //----------------------------------------------------------------------------
278 void
279 VISU_CutPlanesPL
280 ::CorrectPnt(vtkFloatingPointType thePnt[3], 
281              const vtkFloatingPointType BoundPrj[6])
282 {
283   for(int i = 0, j = 0; i < 3; ++i, j=2*i){
284     if(thePnt[i] < BoundPrj[j]) thePnt[i] = BoundPrj[j];
285     if(thePnt[i] > BoundPrj[j+1]) thePnt[i] = BoundPrj[j+1];
286   }
287 }
288
289
290 //----------------------------------------------------------------------------
291 void
292 VISU_CutPlanesPL
293 ::GetBoundProject(vtkFloatingPointType BoundPrj[3], 
294                   const vtkFloatingPointType BoundBox[6], 
295                   const vtkFloatingPointType Dir[3])
296 {
297   vtkFloatingPointType BoundPoints[8][3] = { {BoundBox[0],BoundBox[2],BoundBox[4]},
298                                              {BoundBox[1],BoundBox[2],BoundBox[4]},
299                                              {BoundBox[0],BoundBox[3],BoundBox[4]},
300                                              {BoundBox[1],BoundBox[3],BoundBox[4]},
301                                              {BoundBox[0],BoundBox[2],BoundBox[5]},
302                                              {BoundBox[1],BoundBox[2],BoundBox[5]},
303                                              {BoundBox[0],BoundBox[3],BoundBox[5]},
304                                              {BoundBox[1],BoundBox[3],BoundBox[5]}};
305   BoundPrj[0] = vtkMath::Dot(Dir,BoundPoints[0]), BoundPrj[1] = BoundPrj[0];
306   for(int i = 1; i < 8; i++){
307     vtkFloatingPointType tmp = vtkMath::Dot(Dir,BoundPoints[i]);
308     if(BoundPrj[1] < tmp) BoundPrj[1] = tmp;
309     if(BoundPrj[0] > tmp) BoundPrj[0] = tmp;
310   }
311   BoundPrj[2] = BoundPrj[1] - BoundPrj[0];
312   BoundPrj[1] = BoundPrj[0] + (1.0 - EPS)*BoundPrj[2];
313   BoundPrj[0] = BoundPrj[0] + EPS*BoundPrj[2];
314   BoundPrj[2] = BoundPrj[1] - BoundPrj[0];
315 }
316
317
318 //----------------------------------------------------------------------------
319 void
320 VISU_CutPlanesPL
321 ::SetOrientation(const VISU_CutPlanesPL::PlaneOrientation& theOrient,
322                  vtkFloatingPointType theXAng, 
323                  vtkFloatingPointType theYAng, 
324                  int theNum)
325 {
326   myBasePlane[theNum] = theOrient;
327   switch(myBasePlane[theNum]){
328   case XY: myAng[theNum][0] = theXAng; break;
329   case YZ: myAng[theNum][1] = theXAng; break;
330   case ZX: myAng[theNum][2] = theXAng; break;
331   }
332   switch(myBasePlane[theNum]){
333   case XY: myAng[theNum][1] = theYAng; break;
334   case YZ: myAng[theNum][2] = theYAng; break;
335   case ZX: myAng[theNum][0] = theYAng; break;
336   }
337 }
338
339
340 //----------------------------------------------------------------------------
341 const VISU_CutPlanesPL::PlaneOrientation& 
342 VISU_CutPlanesPL
343 ::GetPlaneOrientation(int theNum)
344 {
345   return myBasePlane[theNum];
346 }
347
348 vtkFloatingPointType 
349 VISU_CutPlanesPL
350 ::GetRotateX(int theNum)
351 {
352   switch(myBasePlane[theNum]){
353   case XY: return myAng[theNum][0];
354   case YZ: return myAng[theNum][1];
355   case ZX: return myAng[theNum][2];
356   }
357   return 0;
358 }
359
360
361 //----------------------------------------------------------------------------
362 vtkFloatingPointType 
363 VISU_CutPlanesPL
364 ::GetRotateY(int theNum)
365 {
366   switch(myBasePlane[theNum]){
367   case XY: return myAng[theNum][1];
368   case YZ: return myAng[theNum][2];
369   case ZX: return myAng[theNum][0];
370   }
371   return 0;
372 }
373
374
375 //----------------------------------------------------------------------------
376 vtkFloatingPointType 
377 VISU_CutPlanesPL
378 ::GetDisplacement(int theNum)
379 {
380   return myDisplacement[theNum];
381 }
382
383
384 //----------------------------------------------------------------------------
385 void
386 VISU_CutPlanesPL
387 ::SetDisplacement(vtkFloatingPointType theDisp, 
388                   int theNum) 
389 {
390   if(VISU::CheckIsSameValue(myDisplacement[theNum], theDisp))
391     return;
392
393   myDisplacement[theNum] = theDisp;
394   Modified();
395 }
396
397
398 //----------------------------------------------------------------------------
399 void
400 VISU_CutPlanesPL
401 ::SetNbParts(int theNbParts) 
402 {
403   if(theNbParts > 0 && GetNbParts() != theNbParts){
404     myPartPosition.resize(theNbParts);
405     myPartCondition.resize(theNbParts, 1);
406     myNbParts = theNbParts;
407     Modified();
408   }
409 }
410
411
412 //----------------------------------------------------------------------------
413 int
414 VISU_CutPlanesPL
415 ::GetNbParts() 
416 {
417   return myPartPosition.size();
418 }
419
420
421 //----------------------------------------------------------------------------
422 void
423 VISU_CutPlanesPL
424 ::SetPartPosition(int thePartNumber, 
425                   vtkFloatingPointType thePartPosition)
426 {
427   if(thePartNumber >= myNbParts) 
428     return;
429
430   bool anIsSameValue = VISU::CheckIsSameValue(myPartPosition[thePartNumber], thePartPosition);
431   anIsSameValue &= VISU::CheckIsSameValue(myPartCondition[thePartNumber], 0);
432   if(anIsSameValue)
433     return;
434
435   myPartPosition[thePartNumber] = thePartPosition;
436   myPartCondition[thePartNumber] = 0;
437   Modified();
438 }
439
440
441 //----------------------------------------------------------------------------
442 vtkFloatingPointType 
443 VISU_CutPlanesPL
444 ::GetPartPosition(int thePartNumber, 
445                   int theNum)
446 {
447   if(thePartNumber >= myNbParts) 
448     return 0;
449
450   vtkFloatingPointType aPosition = myPartPosition[thePartNumber];
451   if(myPartCondition[thePartNumber]){
452       vtkFloatingPointType aDir[3], aBounds[6], aBoundPrj[3];
453       if(!IsDeformed()) 
454         GetMergedInput()->GetBounds(aBounds);
455       else
456         GetMergeFilterOutput()->GetBounds(aBounds);
457
458
459       GetDir(aDir,
460              myAng[theNum],
461              myBasePlane[theNum]);
462
463       GetBoundProject(aBoundPrj,
464                       aBounds,
465                       aDir);
466
467       if(myNbParts > 1){
468         vtkFloatingPointType aDBoundPrj = aBoundPrj[2]/(myNbParts - 1);
469         vtkFloatingPointType aDisplacement = aDBoundPrj * myDisplacement[theNum];
470         vtkFloatingPointType aStartPosition = aBoundPrj[0] - 0.5*aDBoundPrj + aDisplacement;
471         aPosition = aStartPosition + thePartNumber*aDBoundPrj;
472       }else
473         aPosition = aBoundPrj[0] + aBoundPrj[2]*myDisplacement[theNum];
474   }
475
476   return aPosition;
477 }
478
479
480 //----------------------------------------------------------------------------
481 void
482 VISU_CutPlanesPL
483 ::SetPartDefault(int thePartNumber)
484 {
485   if(thePartNumber >= myNbParts) 
486     return;
487
488   bool anIsSameValue = VISU::CheckIsSameValue(myPartPosition[thePartNumber], GetPartPosition(thePartNumber));
489   anIsSameValue &= VISU::CheckIsSameValue(myPartCondition[thePartNumber], 1);
490   if(anIsSameValue)
491     return;
492
493   myPartPosition[thePartNumber] = GetPartPosition(thePartNumber);
494   myPartCondition[thePartNumber] = 1;
495   Modified();
496 }
497
498
499 //----------------------------------------------------------------------------
500 int
501 VISU_CutPlanesPL
502 ::IsPartDefault(int thePartNumber)
503 {
504   if(thePartNumber >= myNbParts) 
505     return 1;
506
507   return myPartCondition[thePartNumber];
508 }
509
510
511 //----------------------------------------------------------------------------
512 void
513 VISU_CutPlanesPL
514 ::GetDir(vtkFloatingPointType theDir[3],
515          const vtkFloatingPointType theAng[3],
516          const PlaneOrientation& theBasePlane)
517 {
518   int iPlane = 0;
519   vtkFloatingPointType aRx[3][3], aRy[3][3], aRz[3][3], aRotation[3][3];
520   switch(theBasePlane){
521   case XY:
522     if(fabs(theAng[0]) > EPS) GetRx(aRx,theAng[0]); else vtkMath::Identity3x3(aRx);
523     if(fabs(theAng[1]) > EPS) GetRy(aRy,theAng[1]); else vtkMath::Identity3x3(aRy);
524     vtkMath::Multiply3x3(aRx,aRy,aRotation);
525     iPlane = 2;
526     break;
527   case YZ:
528     if(fabs(theAng[1]) > EPS) GetRy(aRy,theAng[1]); else vtkMath::Identity3x3(aRy);
529     if(fabs(theAng[2]) > EPS) GetRz(aRz,theAng[2]); else vtkMath::Identity3x3(aRz);
530     vtkMath::Multiply3x3(aRy,aRz,aRotation);
531     iPlane = 0;
532     break;
533   case ZX:
534     if(fabs(theAng[2]) > EPS) GetRz(aRz,theAng[2]); else vtkMath::Identity3x3(aRz);
535     if(fabs(theAng[0]) > EPS) GetRx(aRx,theAng[0]); else vtkMath::Identity3x3(aRx);
536     vtkMath::Multiply3x3(aRz,aRx,aRotation);
537     iPlane = 1;
538     break;
539   }
540
541   for(int i = 0; i < 3; i++)
542     theDir[i] = aRotation[i][iPlane];
543 }
544
545
546 //----------------------------------------------------------------------------
547 void
548 VISU_CutPlanesPL
549 ::CutWithPlane(vtkAppendPolyData* theAppendPolyData,
550                vtkDataSet* theDataSet,
551                vtkFloatingPointType theDir[3], 
552                vtkFloatingPointType theOrig[3])
553 {
554   vtkCutter *aCutPlane = vtkCutter::New();
555   aCutPlane->SetInput(theDataSet);
556   vtkPlane *aPlane = vtkPlane::New();
557   aPlane->SetOrigin(theOrig);
558
559   aPlane->SetNormal(theDir);
560   aCutPlane->SetCutFunction(aPlane);
561   aPlane->Delete();
562   theAppendPolyData->AddInput(aCutPlane->GetOutput());
563   aCutPlane->Delete();
564 }
565
566
567 //----------------------------------------------------------------------------
568 void
569 VISU_CutPlanesPL
570 ::CutWithPlanes(vtkAppendPolyData* theAppendPolyData, 
571                 vtkDataSet* theDataSet,
572                 int theNbPlanes, 
573                 vtkFloatingPointType theDir[3], 
574                 vtkFloatingPointType theBounds[6],
575                 const std::vector<vtkFloatingPointType>& thePlanePosition,
576                 const std::vector<int>& thePlaneCondition,
577                 vtkFloatingPointType theDisplacement)
578 {
579   vtkFloatingPointType aBoundPrj[3], aOrig[3], aPosition;
580   GetBoundProject(aBoundPrj, theBounds, theDir);
581   if(theNbPlanes > 1){
582     vtkFloatingPointType aDBoundPrj = aBoundPrj[2]/(theNbPlanes - 1);
583     vtkFloatingPointType aDisplacement = aDBoundPrj*theDisplacement;
584     vtkFloatingPointType aStartPosition = aBoundPrj[0] - 0.5*aDBoundPrj + aDisplacement;
585     for (int i = 0; i < theNbPlanes; i++){
586       aPosition = aStartPosition + i*aDBoundPrj;
587       if(thePlaneCondition[i]){
588         aPosition = aStartPosition + i*aDBoundPrj;
589       }else
590         aPosition = thePlanePosition[i];
591       VISU::Mul(theDir,aPosition,aOrig);
592       CutWithPlane(theAppendPolyData,theDataSet,theDir,aOrig);
593     }
594   }else{
595     if(thePlaneCondition[0])
596       aPosition = aBoundPrj[0] + aBoundPrj[2]*theDisplacement;
597     else
598       aPosition = thePlanePosition[0];
599     VISU::Mul(theDir,aPosition,aOrig);
600     CutWithPlane(theAppendPolyData,theDataSet,theDir,aOrig);
601   }
602   vtkPolyData *aPolyData = theAppendPolyData->GetOutput();
603   aPolyData->Update();
604   theAppendPolyData->Update();
605 }
606
607
608 //----------------------------------------------------------------------------
609 void
610 VISU_CutPlanesPL::SetVectorialField(VISU::PUnstructuredGridIDMapper theMapper)
611 {  
612   if(myVectorialField == theMapper)
613     return;
614
615   if(CheckCanDeformate(theMapper->GetOutput())){
616     myVectorialField = theMapper;
617     
618     SetMergeFilterInput(GetMergedInput(),theMapper->GetOutput());
619   }
620   else
621     UseDeformation(false);
622   
623   Modified();
624 }
625
626 //----------------------------------------------------------------------------
627 VISU::PUnstructuredGridIDMapper VISU_CutPlanesPL::
628 getVectorialField()
629 {
630   return myVectorialField;
631 }
632
633 //----------------------------------------------------------------------------
634 void VISU_CutPlanesPL::SetMapScale(vtkFloatingPointType theMapScale){
635   Superclass::SetMapScale(theMapScale);
636   if(IsDeformed())
637     VISU_OptionalDeformationPL::SetMapScale(theMapScale);
638 }