Salome HOME
SMH: 3.0.0 preparation - merged and adopted version (POLYWORK+HEAD)
[modules/visu.git] / src / PIPELINE / VISU_CutPlanesPL.cxx
1 //  VISU OBJECT : interactive object for VISU entities implementation
2 //
3 //  Copyright (C) 2003  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.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org 
21 //
22 //
23 // File:    VISU_PipeLine.cxx
24 // Author:  Alexey PETROV
25 // Module : VISU
26
27
28 #include "VISU_CutPlanesPL.hxx"
29 #include "VISU_PipeLineUtils.hxx"
30 #include "VTKViewer_GeometryFilter.h"
31
32 #include <vtkAppendPolyData.h>
33 #include <vtkCutter.h>
34 #include <vtkPlane.h>
35
36 using namespace std;
37
38 static float EPS = 1.0E-3;
39
40 vtkStandardNewMacro(VISU_CutPlanesPL);
41
42 VISU_CutPlanesPL::VISU_CutPlanesPL(){
43   myAppendPolyData = vtkAppendPolyData::New();
44 }
45
46 VISU_CutPlanesPL::~VISU_CutPlanesPL(){
47   myAppendPolyData->Delete();
48 }
49
50 void VISU_CutPlanesPL::ShallowCopy(VISU_PipeLine *thePipeLine){
51   VISU_ScalarMapPL::ShallowCopy(thePipeLine);
52   if(VISU_CutPlanesPL *aPipeLine = dynamic_cast<VISU_CutPlanesPL*>(thePipeLine)){
53     SetOrientation(aPipeLine->GetPlaneOrientation(),
54                    aPipeLine->GetRotateX(),aPipeLine->GetRotateY());
55     SetDisplacement(aPipeLine->GetDisplacement());
56     SetNbParts(aPipeLine->GetNbParts());
57     for (int i = 0, iend = GetNbParts(); i < iend; i++)
58       if(!aPipeLine->IsPartDefault(i))  SetPartPosition(i, aPipeLine->GetPartPosition(i));
59   }
60 }
61
62 void VISU_CutPlanesPL::Init(){
63   VISU_ScalarMapPL::Init();
64
65   SetNbParts(10);
66   myBasePlane[0] = YZ;
67   myDisplacement[0] = 0.5;
68   myAng[0][0] = myAng[0][1] = myAng[0][2] = 0.0;
69 }
70
71 VISU_ScalarMapPL::THook* VISU_CutPlanesPL::DoHook(){
72   return myAppendPolyData->GetOutput();
73 }
74
75 void VISU_CutPlanesPL::Update(){
76   ClearAppendPolyData(myAppendPolyData);
77   SetPartPosition();
78   float aDir[3];
79   GetDir(aDir,myAng[0],myBasePlane[0]);
80   float aBounds[6];
81   myInput->GetBounds(aBounds);
82   vtkDataSet* aDataSet = myFieldTransform->GetUnstructuredGridOutput();
83   CutWithPlanes(myAppendPolyData,aDataSet,myNbParts,aDir,aBounds,
84                 myPartPosition,myPartCondition,myDisplacement[0]);
85
86   VISU_ScalarMapPL::Update();
87 }
88
89 void VISU_CutPlanesPL::SetPartPosition(int theNum){
90   for(int i = 0; i < myNbParts; i++)
91     myPartPosition[i] = GetPartPosition(i,theNum);
92 }
93
94 void VISU_CutPlanesPL::ClearAppendPolyData(vtkAppendPolyData *theAppendPolyData){
95   int iEnd = theAppendPolyData->GetNumberOfInputs();
96   for(int i = iEnd-1; i >= 0; i--)
97     theAppendPolyData->RemoveInput(theAppendPolyData->GetInput(i));
98 }
99
100 float* VISU_CutPlanesPL::GetRx(float theRx[3][3], float thaAng){
101   theRx[0][0] = 1.0;            theRx[0][1] = 0.0;            theRx[0][2] = 0.0;
102   theRx[1][0] = 0.0;            theRx[1][1] = cos(thaAng);    theRx[1][2] = -sin(thaAng);
103   theRx[2][0] = 0.0;            theRx[2][1] = sin(thaAng);    theRx[2][2] = cos(thaAng);
104   return theRx[0];
105 }
106
107
108 float* VISU_CutPlanesPL::GetRy(float theRy[3][3], float thaAng){
109   theRy[0][0] = cos(thaAng);    theRy[0][1] = 0.0;            theRy[0][2] = sin(thaAng);
110   theRy[1][0] = 0.0;            theRy[1][1] = 1.0;            theRy[1][2] = 0.0;   
111   theRy[2][0] = -sin(thaAng);   theRy[2][1] = 0.0;            theRy[2][2] = cos(thaAng);   
112   return theRy[0];
113 }
114
115
116 float* VISU_CutPlanesPL::GetRz(float theRz[3][3], float thaAng){
117   theRz[0][0] = cos(thaAng);    theRz[0][1] = -sin(thaAng);   theRz[0][2] = 0.0;
118   theRz[1][0] = sin(thaAng);    theRz[1][1] = cos(thaAng);    theRz[1][2] = 0.0;   
119   theRz[2][0] = 0.0;            theRz[2][1] = 0.0;            theRz[2][2] = 1.0;   
120   return theRz[0];
121 }
122
123
124 void VISU_CutPlanesPL::CorrectPnt(float thePnt[3], const float BoundPrj[6]){
125   for(int i = 0, j = 0; i < 3; ++i, j=2*i){
126     if(thePnt[i] < BoundPrj[j]) thePnt[i] = BoundPrj[j];
127     if(thePnt[i] > BoundPrj[j+1]) thePnt[i] = BoundPrj[j+1];
128   }
129 }
130
131 void VISU_CutPlanesPL::GetBoundProject(float BoundPrj[3], const float BoundBox[6], const float Dir[3]){
132   float BoundPoints[8][3] = { {BoundBox[0],BoundBox[2],BoundBox[4]},
133                               {BoundBox[1],BoundBox[2],BoundBox[4]},
134                               {BoundBox[0],BoundBox[3],BoundBox[4]},
135                               {BoundBox[1],BoundBox[3],BoundBox[4]},
136                               {BoundBox[0],BoundBox[2],BoundBox[5]},
137                               {BoundBox[1],BoundBox[2],BoundBox[5]}, 
138                               {BoundBox[0],BoundBox[3],BoundBox[5]}, 
139                               {BoundBox[1],BoundBox[3],BoundBox[5]}};
140   BoundPrj[0] = vtkMath::Dot(Dir,BoundPoints[0]), BoundPrj[1] = BoundPrj[0];
141   for(int i = 1; i < 8; i++){
142     float tmp = vtkMath::Dot(Dir,BoundPoints[i]);
143     if(BoundPrj[1] < tmp) BoundPrj[1] = tmp;
144     if(BoundPrj[0] > tmp) BoundPrj[0] = tmp;
145   }
146   BoundPrj[2] = BoundPrj[1] - BoundPrj[0];
147   BoundPrj[1] = BoundPrj[0] + (1.0 - EPS)*BoundPrj[2];
148   BoundPrj[0] = BoundPrj[0] + EPS*BoundPrj[2];
149   BoundPrj[2] = BoundPrj[1] - BoundPrj[0];
150 }
151
152
153 void VISU_CutPlanesPL::SetOrientation(const VISU_CutPlanesPL::PlaneOrientation& theOrient, 
154                                       float theXAng, float theYAng, int theNum)
155
156   myBasePlane[theNum] = theOrient;
157   switch(myBasePlane[theNum]){
158   case XY: myAng[theNum][0] = theXAng; break;
159   case YZ: myAng[theNum][1] = theXAng; break;
160   case ZX: myAng[theNum][2] = theXAng; break;
161   }
162   switch(myBasePlane[theNum]){
163   case XY: myAng[theNum][1] = theYAng; break;
164   case YZ: myAng[theNum][2] = theYAng; break;
165   case ZX: myAng[theNum][0] = theYAng; break;
166   }
167 }
168
169
170 const VISU_CutPlanesPL::PlaneOrientation& VISU_CutPlanesPL::GetPlaneOrientation(int theNum){ 
171   return myBasePlane[theNum];
172 }
173
174 float VISU_CutPlanesPL::GetRotateX(int theNum){
175   switch(myBasePlane[theNum]){
176   case XY: return myAng[theNum][0];
177   case YZ: return myAng[theNum][1];
178   case ZX: return myAng[theNum][2];
179   }
180   return 0;
181 }
182
183 float VISU_CutPlanesPL::GetRotateY(int theNum){
184   switch(myBasePlane[theNum]){
185   case XY: return myAng[theNum][1];
186   case YZ: return myAng[theNum][2];
187   case ZX: return myAng[theNum][0];
188   }
189   return 0;
190 }
191
192
193 void VISU_CutPlanesPL::SetNbParts(int theNb) { 
194   myNbParts = theNb;
195   myPartPosition.resize(myNbParts);
196   myPartCondition.resize(myNbParts,1);
197   Modified();
198 }
199
200
201 void VISU_CutPlanesPL::SetPartPosition(int thePartNumber, float thePartPosition){
202   if(thePartNumber >= myNbParts) return;
203   myPartPosition[thePartNumber] = thePartPosition;
204   myPartCondition[thePartNumber] = 0;
205   Modified();
206 }
207 float VISU_CutPlanesPL::GetPartPosition(int thePartNumber, int theNum){
208   if(thePartNumber >= myNbParts) return 0;
209   float aPosition = myPartPosition[thePartNumber];
210   if(myPartCondition[thePartNumber]){
211       float aDir[3], aBounds[6], aBoundPrj[3];
212       myInput->GetBounds(aBounds);
213       GetDir(aDir,myAng[theNum],myBasePlane[theNum]);
214       GetBoundProject(aBoundPrj,aBounds,aDir);
215       if (myNbParts > 1){
216         float aDBoundPrj = aBoundPrj[2]/(myNbParts - 1);
217         float aDisplacement = aDBoundPrj * myDisplacement[theNum];
218         float aStartPosition = aBoundPrj[0] - 0.5*aDBoundPrj + aDisplacement;
219         aPosition = aStartPosition + thePartNumber*aDBoundPrj;
220       }else
221         aPosition = aBoundPrj[0] + aBoundPrj[2]*myDisplacement[theNum];    
222   }
223   return aPosition;
224 }
225
226
227 void VISU_CutPlanesPL::SetPartDefault(int thePartNumber){
228   if(thePartNumber >= myNbParts) return;
229   myPartPosition[thePartNumber] = GetPartPosition(thePartNumber);
230   myPartCondition[thePartNumber] = 1;
231   Modified();
232 }
233 int VISU_CutPlanesPL::IsPartDefault(int thePartNumber){
234   if(thePartNumber >= myNbParts) return 1;
235   return myPartCondition[thePartNumber];
236 }
237
238
239 void VISU_CutPlanesPL::GetDir(float theDir[3], float theAng[3], const PlaneOrientation& theBasePlane){
240   int iPlane = 0;
241   float aRx[3][3], aRy[3][3], aRz[3][3], aRotation[3][3];
242   switch(theBasePlane){
243   case XY: 
244     if(fabs(theAng[0]) > EPS) GetRx(aRx,theAng[0]); else vtkMath::Identity3x3(aRx);
245     if(fabs(theAng[1]) > EPS) GetRy(aRy,theAng[1]); else vtkMath::Identity3x3(aRy);
246     vtkMath::Multiply3x3(aRx,aRy,aRotation);
247     iPlane = 2;
248     break;
249   case YZ: 
250     if(fabs(theAng[1]) > EPS) GetRy(aRy,theAng[1]); else vtkMath::Identity3x3(aRy);
251     if(fabs(theAng[2]) > EPS) GetRz(aRz,theAng[2]); else vtkMath::Identity3x3(aRz);
252     vtkMath::Multiply3x3(aRy,aRz,aRotation);
253     iPlane = 0;
254     break;
255   case ZX: 
256     if(fabs(theAng[2]) > EPS) GetRz(aRz,theAng[2]); else vtkMath::Identity3x3(aRz);
257     if(fabs(theAng[0]) > EPS) GetRx(aRx,theAng[0]); else vtkMath::Identity3x3(aRx);
258     vtkMath::Multiply3x3(aRz,aRx,aRotation);
259     iPlane = 1;
260     break;
261   }
262   for(int i = 0; i < 3; i++)  
263     theDir[i] = aRotation[i][iPlane];
264 }
265
266
267 void VISU_CutPlanesPL::CutWithPlane(vtkAppendPolyData* theAppendPolyData, 
268                                     vtkDataSet* theDataSet,
269                                     float theDir[3], float theOrig[3])
270 {
271   vtkCutter *aCutPlane = vtkCutter::New();
272   aCutPlane->SetInput(theDataSet);
273   vtkPlane *aPlane = vtkPlane::New();
274   aPlane->SetOrigin(theOrig);
275   
276   aPlane->SetNormal(theDir);
277   aCutPlane->SetCutFunction(aPlane);
278   aPlane->Delete();
279   theAppendPolyData->AddInput(aCutPlane->GetOutput());
280   aCutPlane->Register(theAppendPolyData);
281   aCutPlane->Delete();
282 }
283
284
285 void VISU_CutPlanesPL::CutWithPlanes(vtkAppendPolyData* theAppendPolyData, vtkDataSet* theDataSet,
286                                      int theNbPlanes, float theDir[3], float theBounds[6], 
287                                      const vector<float>& thePlanePosition, 
288                                      const vector<int>& thePlaneCondition,
289                                      float theDisplacement)
290 {
291   float aBoundPrj[3], aOrig[3], aPosition;
292   GetBoundProject(aBoundPrj, theBounds, theDir);
293   if(theNbPlanes > 1){
294     float aDBoundPrj = aBoundPrj[2]/(theNbPlanes - 1);
295     float aDisplacement = aDBoundPrj*theDisplacement;
296     float aStartPosition = aBoundPrj[0] - 0.5*aDBoundPrj + aDisplacement;
297     for (int i = 0; i < theNbPlanes; i++){
298       aPosition = aStartPosition + i*aDBoundPrj;
299       if(thePlaneCondition[i]){
300         aPosition = aStartPosition + i*aDBoundPrj;
301       }else
302         aPosition = thePlanePosition[i];
303       VISU::Mul(theDir,aPosition,aOrig);
304       CutWithPlane(theAppendPolyData,theDataSet,theDir,aOrig);
305     }
306   }else{
307     if(thePlaneCondition[0])
308       aPosition = aBoundPrj[0] + aBoundPrj[2]*theDisplacement;
309     else
310       aPosition = thePlanePosition[0];
311     VISU::Mul(theDir,aPosition,aOrig);
312     CutWithPlane(theAppendPolyData,theDataSet,theDir,aOrig);
313   }
314   vtkPolyData *aPolyData = theAppendPolyData->GetOutput();
315   aPolyData->Update();
316   theAppendPolyData->Update();
317 }