Salome HOME
247f894302b0f541f6ff44f8608719b68834d69c
[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   vtkDataSet* aMergedInput = GetMergedInput();
160   if(VISU::IsQuadraticData(aMergedInput)) // Bug 0020123, note 0005343
161     throw std::runtime_error("Impossible to build presentation");
162
163   ClearAppendPolyData(myAppendPolyData);
164
165
166   if(!myVectorialField || !IsDeformed()){
167     SetMergeFilterInput(aMergedInput,aMergedInput);
168   }
169   
170
171   if(VISU::IsDataOnCells(aMergedInput))
172     GetMapper()->SetScalarModeToUseCellData();
173   else
174     GetMapper()->SetScalarModeToUsePointData();
175
176   SetPartPosition();
177   
178   vtkFloatingPointType aDir[3];
179   GetDir(aDir, 
180          myAng[0], 
181          myBasePlane[0]);
182   
183   vtkFloatingPointType aBounds[6];
184
185   vtkDataSet* aFilterOutput = GetMergeFilterOutput();
186   
187   aFilterOutput->GetBounds(aBounds);
188
189   CutWithPlanes(myAppendPolyData,
190                 aFilterOutput,
191                 myNbParts,
192                 aDir,
193                 aBounds,
194                 myPartPosition, 
195                 myPartCondition, 
196                 myDisplacement[0]);
197
198   
199
200   SetWarpVectorInput(myAppendPolyData->GetOutput());
201   Superclass::Update();
202 }
203
204
205 //----------------------------------------------------------------------------
206 unsigned long int
207 VISU_CutPlanesPL
208 ::GetMemorySize()
209 {
210   unsigned long int aSize = Superclass::GetMemorySize();
211
212   if(vtkDataSet* aDataSet = myAppendPolyData->GetOutput())
213     aSize += aDataSet->GetActualMemorySize() * 1024;
214   
215   int anEnd = myAppendPolyData->GetNumberOfInputConnections(0);
216   for(int anId = 0; anId < anEnd; anId++)
217     if(vtkDataSet* aDataSet = myAppendPolyData->GetInput(anId))
218       aSize += aDataSet->GetActualMemorySize() * 1024;
219
220   return aSize;
221 }
222
223
224 //----------------------------------------------------------------------------
225 void
226 VISU_CutPlanesPL
227 ::SetPartPosition(int theNum)
228 {
229   for(int i = 0; i < myNbParts; i++)
230     myPartPosition[i] = GetPartPosition(i,theNum);
231 }
232
233 void
234 VISU_CutPlanesPL
235 ::ClearAppendPolyData(vtkAppendPolyData *theAppendPolyData)
236 {
237   theAppendPolyData->RemoveAllInputs();
238 }
239
240
241 //----------------------------------------------------------------------------
242 vtkFloatingPointType* 
243 VISU_CutPlanesPL::
244 GetRx(vtkFloatingPointType theRx[3][3], 
245       vtkFloatingPointType thaAng)
246 {
247   theRx[0][0] = 1.0;            theRx[0][1] = 0.0;            theRx[0][2] = 0.0;
248   theRx[1][0] = 0.0;            theRx[1][1] = cos(thaAng);    theRx[1][2] = -sin(thaAng);
249   theRx[2][0] = 0.0;            theRx[2][1] = sin(thaAng);    theRx[2][2] = cos(thaAng);
250   return theRx[0];
251 }
252
253
254
255 //----------------------------------------------------------------------------
256 vtkFloatingPointType* 
257 VISU_CutPlanesPL
258 ::GetRy(vtkFloatingPointType theRy[3][3], 
259         vtkFloatingPointType thaAng)
260 {
261   theRy[0][0] = cos(thaAng);    theRy[0][1] = 0.0;            theRy[0][2] = sin(thaAng);
262   theRy[1][0] = 0.0;            theRy[1][1] = 1.0;            theRy[1][2] = 0.0;
263   theRy[2][0] = -sin(thaAng);   theRy[2][1] = 0.0;            theRy[2][2] = cos(thaAng);
264   return theRy[0];
265 }
266
267
268 //----------------------------------------------------------------------------
269 vtkFloatingPointType* 
270 VISU_CutPlanesPL
271 ::GetRz(vtkFloatingPointType theRz[3][3], 
272         vtkFloatingPointType thaAng)
273 {
274   theRz[0][0] = cos(thaAng);    theRz[0][1] = -sin(thaAng);   theRz[0][2] = 0.0;
275   theRz[1][0] = sin(thaAng);    theRz[1][1] = cos(thaAng);    theRz[1][2] = 0.0;
276   theRz[2][0] = 0.0;            theRz[2][1] = 0.0;            theRz[2][2] = 1.0;
277   return theRz[0];
278 }
279
280
281 //----------------------------------------------------------------------------
282 void
283 VISU_CutPlanesPL
284 ::CorrectPnt(vtkFloatingPointType thePnt[3], 
285              const vtkFloatingPointType BoundPrj[6])
286 {
287   for(int i = 0, j = 0; i < 3; ++i, j=2*i){
288     if(thePnt[i] < BoundPrj[j]) thePnt[i] = BoundPrj[j];
289     if(thePnt[i] > BoundPrj[j+1]) thePnt[i] = BoundPrj[j+1];
290   }
291 }
292
293
294 //----------------------------------------------------------------------------
295 void
296 VISU_CutPlanesPL
297 ::GetBoundProject(vtkFloatingPointType BoundPrj[3], 
298                   const vtkFloatingPointType BoundBox[6], 
299                   const vtkFloatingPointType Dir[3])
300 {
301   vtkFloatingPointType BoundPoints[8][3] = { {BoundBox[0],BoundBox[2],BoundBox[4]},
302                                              {BoundBox[1],BoundBox[2],BoundBox[4]},
303                                              {BoundBox[0],BoundBox[3],BoundBox[4]},
304                                              {BoundBox[1],BoundBox[3],BoundBox[4]},
305                                              {BoundBox[0],BoundBox[2],BoundBox[5]},
306                                              {BoundBox[1],BoundBox[2],BoundBox[5]},
307                                              {BoundBox[0],BoundBox[3],BoundBox[5]},
308                                              {BoundBox[1],BoundBox[3],BoundBox[5]}};
309   BoundPrj[0] = vtkMath::Dot(Dir,BoundPoints[0]), BoundPrj[1] = BoundPrj[0];
310   for(int i = 1; i < 8; i++){
311     vtkFloatingPointType tmp = vtkMath::Dot(Dir,BoundPoints[i]);
312     if(BoundPrj[1] < tmp) BoundPrj[1] = tmp;
313     if(BoundPrj[0] > tmp) BoundPrj[0] = tmp;
314   }
315   BoundPrj[2] = BoundPrj[1] - BoundPrj[0];
316   BoundPrj[1] = BoundPrj[0] + (1.0 - EPS)*BoundPrj[2];
317   BoundPrj[0] = BoundPrj[0] + EPS*BoundPrj[2];
318   BoundPrj[2] = BoundPrj[1] - BoundPrj[0];
319 }
320
321
322 //----------------------------------------------------------------------------
323 void
324 VISU_CutPlanesPL
325 ::SetOrientation(const VISU_CutPlanesPL::PlaneOrientation& theOrient,
326                  vtkFloatingPointType theXAng, 
327                  vtkFloatingPointType theYAng, 
328                  int theNum)
329 {
330   myBasePlane[theNum] = theOrient;
331   switch(myBasePlane[theNum]){
332   case XY: myAng[theNum][0] = theXAng; break;
333   case YZ: myAng[theNum][1] = theXAng; break;
334   case ZX: myAng[theNum][2] = theXAng; break;
335   }
336   switch(myBasePlane[theNum]){
337   case XY: myAng[theNum][1] = theYAng; break;
338   case YZ: myAng[theNum][2] = theYAng; break;
339   case ZX: myAng[theNum][0] = theYAng; break;
340   }
341 }
342
343
344 //----------------------------------------------------------------------------
345 const VISU_CutPlanesPL::PlaneOrientation& 
346 VISU_CutPlanesPL
347 ::GetPlaneOrientation(int theNum)
348 {
349   return myBasePlane[theNum];
350 }
351
352 vtkFloatingPointType 
353 VISU_CutPlanesPL
354 ::GetRotateX(int theNum)
355 {
356   switch(myBasePlane[theNum]){
357   case XY: return myAng[theNum][0];
358   case YZ: return myAng[theNum][1];
359   case ZX: return myAng[theNum][2];
360   }
361   return 0;
362 }
363
364
365 //----------------------------------------------------------------------------
366 vtkFloatingPointType 
367 VISU_CutPlanesPL
368 ::GetRotateY(int theNum)
369 {
370   switch(myBasePlane[theNum]){
371   case XY: return myAng[theNum][1];
372   case YZ: return myAng[theNum][2];
373   case ZX: return myAng[theNum][0];
374   }
375   return 0;
376 }
377
378
379 //----------------------------------------------------------------------------
380 vtkFloatingPointType 
381 VISU_CutPlanesPL
382 ::GetDisplacement(int theNum)
383 {
384   return myDisplacement[theNum];
385 }
386
387
388 //----------------------------------------------------------------------------
389 void
390 VISU_CutPlanesPL
391 ::SetDisplacement(vtkFloatingPointType theDisp, 
392                   int theNum) 
393 {
394   if(VISU::CheckIsSameValue(myDisplacement[theNum], theDisp))
395     return;
396
397   myDisplacement[theNum] = theDisp;
398   Modified();
399 }
400
401
402 //----------------------------------------------------------------------------
403 void
404 VISU_CutPlanesPL
405 ::SetNbParts(int theNbParts) 
406 {
407   if(theNbParts > 0 && GetNbParts() != theNbParts){
408     myPartPosition.resize(theNbParts);
409     myPartCondition.resize(theNbParts, 1);
410     myNbParts = theNbParts;
411     Modified();
412   }
413 }
414
415
416 //----------------------------------------------------------------------------
417 int
418 VISU_CutPlanesPL
419 ::GetNbParts() 
420 {
421   return myPartPosition.size();
422 }
423
424
425 //----------------------------------------------------------------------------
426 void
427 VISU_CutPlanesPL
428 ::SetPartPosition(int thePartNumber, 
429                   vtkFloatingPointType thePartPosition)
430 {
431   if(thePartNumber >= myNbParts) 
432     return;
433
434   bool anIsSameValue = VISU::CheckIsSameValue(myPartPosition[thePartNumber], thePartPosition);
435   anIsSameValue &= VISU::CheckIsSameValue(myPartCondition[thePartNumber], 0);
436   if(anIsSameValue)
437     return;
438
439   myPartPosition[thePartNumber] = thePartPosition;
440   myPartCondition[thePartNumber] = 0;
441   Modified();
442 }
443
444
445 //----------------------------------------------------------------------------
446 vtkFloatingPointType 
447 VISU_CutPlanesPL
448 ::GetPartPosition(int thePartNumber, 
449                   int theNum)
450 {
451   if(thePartNumber >= myNbParts) 
452     return 0;
453
454   vtkFloatingPointType aPosition = myPartPosition[thePartNumber];
455   if(myPartCondition[thePartNumber]){
456       vtkFloatingPointType aDir[3], aBounds[6], aBoundPrj[3];
457       if(!IsDeformed()) 
458         GetMergedInput()->GetBounds(aBounds);
459       else
460         GetMergeFilterOutput()->GetBounds(aBounds);
461
462
463       GetDir(aDir,
464              myAng[theNum],
465              myBasePlane[theNum]);
466
467       GetBoundProject(aBoundPrj,
468                       aBounds,
469                       aDir);
470
471       if(myNbParts > 1){
472         vtkFloatingPointType aDBoundPrj = aBoundPrj[2]/(myNbParts - 1);
473         vtkFloatingPointType aDisplacement = aDBoundPrj * myDisplacement[theNum];
474         vtkFloatingPointType aStartPosition = aBoundPrj[0] - 0.5*aDBoundPrj + aDisplacement;
475         aPosition = aStartPosition + thePartNumber*aDBoundPrj;
476       }else
477         aPosition = aBoundPrj[0] + aBoundPrj[2]*myDisplacement[theNum];
478   }
479
480   return aPosition;
481 }
482
483
484 //----------------------------------------------------------------------------
485 void
486 VISU_CutPlanesPL
487 ::SetPartDefault(int thePartNumber)
488 {
489   if(thePartNumber >= myNbParts) 
490     return;
491
492   bool anIsSameValue = VISU::CheckIsSameValue(myPartPosition[thePartNumber], GetPartPosition(thePartNumber));
493   anIsSameValue &= VISU::CheckIsSameValue(myPartCondition[thePartNumber], 1);
494   if(anIsSameValue)
495     return;
496
497   myPartPosition[thePartNumber] = GetPartPosition(thePartNumber);
498   myPartCondition[thePartNumber] = 1;
499   Modified();
500 }
501
502
503 //----------------------------------------------------------------------------
504 int
505 VISU_CutPlanesPL
506 ::IsPartDefault(int thePartNumber)
507 {
508   if(thePartNumber >= myNbParts) 
509     return 1;
510
511   return myPartCondition[thePartNumber];
512 }
513
514
515 //----------------------------------------------------------------------------
516 void
517 VISU_CutPlanesPL
518 ::GetDir(vtkFloatingPointType theDir[3],
519          const vtkFloatingPointType theAng[3],
520          const PlaneOrientation& theBasePlane)
521 {
522   int iPlane = 0;
523   vtkFloatingPointType aRx[3][3], aRy[3][3], aRz[3][3], aRotation[3][3];
524   switch(theBasePlane){
525   case XY:
526     if(fabs(theAng[0]) > EPS) GetRx(aRx,theAng[0]); else vtkMath::Identity3x3(aRx);
527     if(fabs(theAng[1]) > EPS) GetRy(aRy,theAng[1]); else vtkMath::Identity3x3(aRy);
528     vtkMath::Multiply3x3(aRx,aRy,aRotation);
529     iPlane = 2;
530     break;
531   case YZ:
532     if(fabs(theAng[1]) > EPS) GetRy(aRy,theAng[1]); else vtkMath::Identity3x3(aRy);
533     if(fabs(theAng[2]) > EPS) GetRz(aRz,theAng[2]); else vtkMath::Identity3x3(aRz);
534     vtkMath::Multiply3x3(aRy,aRz,aRotation);
535     iPlane = 0;
536     break;
537   case ZX:
538     if(fabs(theAng[2]) > EPS) GetRz(aRz,theAng[2]); else vtkMath::Identity3x3(aRz);
539     if(fabs(theAng[0]) > EPS) GetRx(aRx,theAng[0]); else vtkMath::Identity3x3(aRx);
540     vtkMath::Multiply3x3(aRz,aRx,aRotation);
541     iPlane = 1;
542     break;
543   }
544
545   for(int i = 0; i < 3; i++)
546     theDir[i] = aRotation[i][iPlane];
547 }
548
549
550 //----------------------------------------------------------------------------
551 void
552 VISU_CutPlanesPL
553 ::CutWithPlane(vtkAppendPolyData* theAppendPolyData,
554                vtkDataSet* theDataSet,
555                vtkFloatingPointType theDir[3], 
556                vtkFloatingPointType theOrig[3])
557 {
558   vtkCutter *aCutPlane = vtkCutter::New();
559   aCutPlane->SetInput(theDataSet);
560   vtkPlane *aPlane = vtkPlane::New();
561   aPlane->SetOrigin(theOrig);
562
563   aPlane->SetNormal(theDir);
564   aCutPlane->SetCutFunction(aPlane);
565   aPlane->Delete();
566   theAppendPolyData->AddInput(aCutPlane->GetOutput());
567   aCutPlane->Delete();
568 }
569
570
571 //----------------------------------------------------------------------------
572 void
573 VISU_CutPlanesPL
574 ::CutWithPlanes(vtkAppendPolyData* theAppendPolyData, 
575                 vtkDataSet* theDataSet,
576                 int theNbPlanes, 
577                 vtkFloatingPointType theDir[3], 
578                 vtkFloatingPointType theBounds[6],
579                 const std::vector<vtkFloatingPointType>& thePlanePosition,
580                 const std::vector<int>& thePlaneCondition,
581                 vtkFloatingPointType theDisplacement)
582 {
583   vtkFloatingPointType aBoundPrj[3], aOrig[3], aPosition;
584   GetBoundProject(aBoundPrj, theBounds, theDir);
585   if(theNbPlanes > 1){
586     vtkFloatingPointType aDBoundPrj = aBoundPrj[2]/(theNbPlanes - 1);
587     vtkFloatingPointType aDisplacement = aDBoundPrj*theDisplacement;
588     vtkFloatingPointType aStartPosition = aBoundPrj[0] - 0.5*aDBoundPrj + aDisplacement;
589     for (int i = 0; i < theNbPlanes; i++){
590       aPosition = aStartPosition + i*aDBoundPrj;
591       if(thePlaneCondition[i]){
592         aPosition = aStartPosition + i*aDBoundPrj;
593       }else
594         aPosition = thePlanePosition[i];
595       VISU::Mul(theDir,aPosition,aOrig);
596       CutWithPlane(theAppendPolyData,theDataSet,theDir,aOrig);
597     }
598   }else{
599     if(thePlaneCondition[0])
600       aPosition = aBoundPrj[0] + aBoundPrj[2]*theDisplacement;
601     else
602       aPosition = thePlanePosition[0];
603     VISU::Mul(theDir,aPosition,aOrig);
604     CutWithPlane(theAppendPolyData,theDataSet,theDir,aOrig);
605   }
606   vtkPolyData *aPolyData = theAppendPolyData->GetOutput();
607   aPolyData->Update();
608   theAppendPolyData->Update();
609 }
610
611
612 //----------------------------------------------------------------------------
613 void
614 VISU_CutPlanesPL::SetVectorialField(VISU::PUnstructuredGridIDMapper theMapper)
615 {  
616   if(myVectorialField == theMapper)
617     return;
618
619   if(CheckCanDeformate(theMapper->GetOutput())){
620     myVectorialField = theMapper;
621     
622     SetMergeFilterInput(GetMergedInput(),theMapper->GetOutput());
623   }
624   else
625     UseDeformation(false);
626   
627   Modified();
628 }
629
630 //----------------------------------------------------------------------------
631 VISU::PUnstructuredGridIDMapper VISU_CutPlanesPL::
632 getVectorialField()
633 {
634   return myVectorialField;
635 }
636
637 //----------------------------------------------------------------------------
638 void VISU_CutPlanesPL::SetMapScale(vtkFloatingPointType theMapScale){
639   Superclass::SetMapScale(theMapScale);
640   if(IsDeformed())
641     VISU_OptionalDeformationPL::SetMapScale(theMapScale);
642 }